1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
// Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <config.h>

#include <dhcp/opaque_data_tuple.h>
#include <util/buffer.h>

#include <gtest/gtest.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <algorithm><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <sstream><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <vector><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

using namespace isc;
using namespace isc::dhcp;
using namespace isc::util;

namespace {

struct OpaqueDataTupleLenientParsing : ::testing::Test {
    void SetUp() final override {
        // Retain the current setting for future restoration.
        previous_ = Option::lenient_parsing_;

        // Enable lenient parsing.
        Option::lenient_parsing_ = true;
    }

    void TearDown() final override {
        // Restore.
        Option::lenient_parsing_ = previous_;
    }

    bool previous_;
};

// This test checks that when the default constructor is called, the data buffer
// is empty.
TEST(OpaqueDataTuple, constructor) {<--- syntax error
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // There should be no data in the tuple.
    EXPECT_EQ(0, tuple.getLength());
    EXPECT_TRUE(tuple.getData().empty());
    EXPECT_TRUE(tuple.getText().empty());
}

// Test that the constructor which takes the buffer as argument parses the
// wire data.
TEST(OpaqueDataTuple, constructorParse1Byte) {
    OpaqueDataTuple::Buffer wire_data = {
        0x0B,                               // Length is 11
        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
        0x77, 0x6F, 0x72, 0x6C, 0x64        // world
    };

    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE, wire_data.begin(),
                          wire_data.end());

    EXPECT_EQ(11, tuple.getLength());
    EXPECT_EQ("Hello world", tuple.getText());
}

// Test that the constructor which takes the buffer as argument parses the
// wire data.
TEST(OpaqueDataTuple, constructorParse2Bytes) {
    OpaqueDataTuple::Buffer wire_data = {
        0x00, 0x0B,                         // Length is 11
        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
        0x77, 0x6F, 0x72, 0x6C, 0x64        // world
    };

    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES, wire_data.begin(),
                          wire_data.end());

    EXPECT_EQ(11, tuple.getLength());
    EXPECT_EQ("Hello world", tuple.getText());
}


// This test checks that it is possible to set the tuple data using raw buffer.
TEST(OpaqueDataTuple, assignData) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Initially the tuple buffer should be empty.
    OpaqueDataTuple::Buffer buf = tuple.getData();
    ASSERT_TRUE(buf.empty());
    // Prepare some input data and assign to the tuple.
    OpaqueDataTuple::Buffer data1 = {
        0xCA, 0xFE, 0xBE, 0xEF
    };
    tuple.assign(data1.begin(), data1.size());
    // Tuple should now hold the data we assigned.
    ASSERT_EQ(data1.size(), tuple.getLength());
    buf = tuple.getData();
    EXPECT_EQ(buf, data1);

    // Prepare the other set of data and assign to the tuple.
    OpaqueDataTuple::Buffer data2 = {
        1, 2, 3, 4, 5, 6
    };
    tuple.assign(data2.begin(), data2.size());
    // The new data should have replaced the old data.
    ASSERT_EQ(data2.size(), tuple.getLength());
    buf = tuple.getData();
    EXPECT_EQ(buf, data2);
}

// This test checks that it is possible to append the data to the tuple using
// raw buffer.
TEST(OpaqueDataTuple, appendData) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Initially the tuple buffer should be empty.
    OpaqueDataTuple::Buffer buf = tuple.getData();
    ASSERT_TRUE(buf.empty());
    // Prepare some input data and append to the empty tuple.
    OpaqueDataTuple::Buffer data1 = {
        0xCA, 0xFE, 0xBE, 0xEF
    };
    tuple.append(data1.begin(), data1.size());
    // The tuple should now hold only the data we appended.
    ASSERT_EQ(data1.size(), tuple.getLength());
    buf = tuple.getData();
    EXPECT_EQ(buf, data1);
    // Prepare the new set of data and append.
    OpaqueDataTuple::Buffer data2 = {
        1, 2, 3, 4, 5, 6
    };
    tuple.append(data2.begin(), data2.size());
    // We expect that the tuple now has both sets of data we appended. In order
    // to verify that, we have to concatenate the input data1 and data2.
    OpaqueDataTuple::Buffer data12(data1.begin(), data1.end());
    data12.insert(data12.end(), data2.begin(), data2.end());
    // The size of the tuple should be a sum of data1 and data2 lengths.
    ASSERT_EQ(data1.size() + data2.size(), tuple.getLength());
    buf = tuple.getData();
    EXPECT_EQ(buf, data12);
}

// This test checks that it is possible to assign the string to the tuple.
TEST(OpaqueDataTuple, assignString) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Initially, the tuple should be empty.
    ASSERT_EQ(0, tuple.getLength());
    // Assign some string data.
    tuple.assign("Some string");
    // Verify that the data has been assigned.
    EXPECT_EQ(11, tuple.getLength());
    EXPECT_EQ("Some string", tuple.getText());
    // Assign some other string.
    tuple.assign("Different string");
    // The new string should have replaced the old string.
    EXPECT_EQ(16, tuple.getLength());
    EXPECT_EQ("Different string", tuple.getText());
}

// This test checks that it is possible to append the string to the tuple.
TEST(OpaqueDataTuple, appendString) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Initially the tuple should be empty.
    ASSERT_EQ(0, tuple.getLength());
    // Append the string to it.
    tuple.append("First part");
    ASSERT_EQ(10, tuple.getLength());
    ASSERT_EQ("First part", tuple.getText());
    // Now append the other string.
    tuple.append(" and second part");
    EXPECT_EQ(26, tuple.getLength());
    // The resulting data in the tuple should be a concatenation of both
    // strings.
    EXPECT_EQ("First part and second part", tuple.getText());
}

// This test verifies that equals function correctly checks that the tuple
// holds a given string but it doesn't hold the other. This test also
// checks the assignment operator for the tuple.
TEST(OpaqueDataTuple, equals) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Tuple is supposed to be empty so it is not equal xyz.
    EXPECT_FALSE(tuple.equals("xyz"));
    // Assign xyz.
    EXPECT_NO_THROW(tuple = "xyz");
    // The tuple should be equal xyz, but not abc.
    EXPECT_FALSE(tuple.equals("abc"));
    EXPECT_TRUE(tuple.equals("xyz"));
    // Assign abc to the tuple.
    EXPECT_NO_THROW(tuple = "abc");
    // It should be now opposite.
    EXPECT_TRUE(tuple.equals("abc"));
    EXPECT_FALSE(tuple.equals("xyz"));
}

// This test checks that the conversion of the data in the tuple to the string
// is performed correctly.
TEST(OpaqueDataTuple, getText) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Initially the tuple should be empty.
    ASSERT_TRUE(tuple.getText().empty());
    // ASCII representation of 'Hello world'.
    const char as_ascii[] = {
        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
        0x77, 0x6F, 0x72, 0x6C, 0x64        // world
    };
    // Assign it to the tuple.
    tuple.assign(as_ascii, sizeof(as_ascii));
    // Conversion to string should give as the original text.
    EXPECT_EQ("Hello world", tuple.getText());
}

// This test verifies the behavior of (in)equality and assignment operators.
TEST(OpaqueDataTuple, operators) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Tuple should be empty initially.
    ASSERT_EQ(0, tuple.getLength());
    // Check assignment.
    EXPECT_NO_THROW(tuple = "Hello World");
    EXPECT_EQ(11, tuple.getLength());
    EXPECT_TRUE(tuple == "Hello World");
    EXPECT_TRUE(tuple != "Something else");
    // Assign something else to make sure it affects the tuple.
    EXPECT_NO_THROW(tuple = "Something else");
    EXPECT_EQ(14, tuple.getLength());
    EXPECT_TRUE(tuple == "Something else");
    EXPECT_TRUE(tuple != "Hello World");
}

// This test verifies that the tuple is inserted in the textual format to the
// output stream.
TEST(OpaqueDataTuple, operatorOutputStream) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // The tuple should be empty initially.
    ASSERT_EQ(0, tuple.getLength());
    // The tuple is empty, so assigning its content to the output stream should
    // be no-op and result in the same text in the stream.
    std::ostringstream s;
    s << "Some text";
    EXPECT_NO_THROW(s << tuple);
    EXPECT_EQ("Some text", s.str());
    // Now, let's assign some text to the tuple and call operator again.
    // The new text should be added to the stream.
    EXPECT_NO_THROW(tuple = " and some other text");
    EXPECT_NO_THROW(s << tuple);
    EXPECT_EQ(s.str(), "Some text and some other text");
}

// This test verifies that the value of the tuple can be initialized from the
// input stream.
TEST(OpaqueDataTuple, operatorInputStream) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // The tuple should be empty initially.
    ASSERT_EQ(0, tuple.getLength());
    // The input stream has some text. This text should be appended to the
    // tuple.
    std::istringstream s;
    s.str("Some text");
    EXPECT_NO_THROW(s >> tuple);
    EXPECT_EQ("Some text", tuple.getText());
    // Now, let's assign some other text to the stream. This new text should be
    // assigned to the tuple.
    s.str("And some other");
    EXPECT_NO_THROW(s >> tuple);
    EXPECT_EQ("And some other", tuple.getText());
}

// This test checks that the tuple is correctly encoded in the wire format when
// the size of the length field is 1 byte.
TEST(OpaqueDataTuple, pack1Byte) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
    // Initially, the tuple should be empty.
    ASSERT_EQ(0, tuple.getLength());
    // It turns out that Option 124 can be sent with 0 length Opaque Data
    // See #2021 for more details
    OutputBuffer out_buf(10);
    ASSERT_NO_THROW(tuple.pack(out_buf));
    ASSERT_EQ(1, out_buf.getLength());
    const uint8_t* zero_len = out_buf.getData();
    ASSERT_EQ(0, *zero_len);
    // Reset the output buffer for another test.
    out_buf.clear();
    // Set the data for tuple.
    std::vector<uint8_t> data;
    for (uint8_t i = 0; i < 100; ++i) {
        data.push_back(i);
    }
    tuple.assign(data.begin(), data.size());
    // Packing the data should succeed.
    ASSERT_NO_THROW(tuple.pack(out_buf));
    // The rendered buffer should be 101 bytes long - 1 byte for length,
    // 100 bytes for the actual data.
    ASSERT_EQ(101, out_buf.getLength());
    // Get the rendered data into the vector for convenience.
    std::vector<uint8_t>
        render_data(out_buf.getData(), out_buf.getData() + 101);
    // The first byte is a length byte. It should hold the length of 100.
    EXPECT_EQ(100, render_data[0]);
    // Verify that the rendered data is correct.
    EXPECT_TRUE(std::equal(render_data.begin() + 1, render_data.end(),
                           data.begin()));
    // Reset the output buffer for another test.
    out_buf.clear();
    // Fill in the tuple buffer so as it reaches maximum allowed length. The
    // maximum length is 255 when the size of the length field is one byte.
    for (uint8_t i = 100; i < 255; ++i) {
        data.push_back(i);
    }
    ASSERT_EQ(255, data.size());
    tuple.assign(data.begin(), data.size());
    // The pack() should be successful again.
    ASSERT_NO_THROW(tuple.pack(out_buf));
    // The rendered buffer should be 256 bytes long. The first byte holds the
    // opaque data length, the remaining bytes hold the actual data.
    ASSERT_EQ(256, out_buf.getLength());
    // Check that the data is correct.
    render_data.assign(out_buf.getData(), out_buf.getData() + 256);
    EXPECT_EQ(255, render_data[0]);
    EXPECT_TRUE(std::equal(render_data.begin() + 1, render_data.end(),
                           data.begin()));
    // Clear output buffer for another test.
    out_buf.clear();
    // Add one more value to the tuple. Now, the resulting buffer should exceed
    // the maximum length. An attempt to pack() should fail.
    data.push_back(255);
    tuple.assign(data.begin(), data.size());
    EXPECT_THROW(tuple.pack(out_buf), OpaqueDataTupleError);
}

// This test checks that the tuple is correctly encoded in the wire format when
// the size of the length field is 2 bytes.
TEST(OpaqueDataTuple, pack2Bytes) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Initially, the tuple should be empty.
    ASSERT_EQ(0, tuple.getLength());
    // It turns out that Option 124 can be sent with 0 length Opaque Data
    // See #2021 for more details
    OutputBuffer out_buf(10);
    ASSERT_NO_THROW(tuple.pack(out_buf));
    ASSERT_EQ(2, out_buf.getLength());
    const uint8_t* out_data = out_buf.getData();
    ASSERT_LE(sizeof(uint16_t), out_buf.getLength());
    ASSERT_EQ(0, out_data[0]);
    ASSERT_EQ(0, out_data[1]);
    // Reset the output buffer for another test.
    out_buf.clear();
    // Set the data for tuple.
    std::vector<uint8_t> data;
    for (unsigned i = 0; i < 512; ++i) {
        data.push_back(i & 0xff);
    }
    tuple.assign(data.begin(), data.size());
    // Packing the data should succeed.
    ASSERT_NO_THROW(tuple.pack(out_buf));
    // The rendered buffer should be 514 bytes long - 2 bytes for length,
    // 512 bytes for the actual data.
    ASSERT_EQ(514, out_buf.getLength());
    // Get the rendered data into the vector for convenience.
    std::vector<uint8_t>
        render_data(out_buf.getData(), out_buf.getData() + 514);
    // The first two bytes hold the length of 512.
    uint16_t len = (render_data[0] << 8) + render_data[1];
    EXPECT_EQ(512, len);
    // Verify that the rendered data is correct.
    EXPECT_TRUE(std::equal(render_data.begin() + 2, render_data.end(),
                           data.begin()));

    // Without clearing the output buffer, try to do it again. The pack should
    // append the data to the current buffer.
    ASSERT_NO_THROW(tuple.pack(out_buf));
    EXPECT_EQ(1028, out_buf.getLength());

    // Check that we can render the buffer of the maximal allowed size.
    data.assign(65535, 1);
    ASSERT_NO_THROW(tuple.assign(data.begin(), data.size()));
    ASSERT_NO_THROW(tuple.pack(out_buf));

    out_buf.clear();

    // Append one additional byte. The total length of the tuple now exceeds
    // the maximal value. An attempt to render it should throw an exception.
    data.assign(1, 1);
    ASSERT_NO_THROW(tuple.append(data.begin(), data.size()));
    EXPECT_THROW(tuple.pack(out_buf), OpaqueDataTupleError);
}

// This test verifies that the tuple is decoded from the wire format.
TEST(OpaqueDataTuple, unpack1Byte) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
    OpaqueDataTuple::Buffer wire_data = {
        0x0B,                               // Length is 11
        0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
        0x77, 0x6F, 0x72, 0x6C, 0x64        // world
    };

    ASSERT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));
    EXPECT_EQ(11, tuple.getLength());
    EXPECT_EQ("Hello world", tuple.getText());
}

// This test verifies that the tuple having a length of 0, is decoded from
// the wire format.
TEST(OpaqueDataTuple, unpack1ByteZeroLength) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
    EXPECT_NO_THROW(tuple = "Hello world");
    ASSERT_NE(tuple.getLength(), 0);

    OpaqueDataTuple::Buffer wire_data = {
        0
    };
    ASSERT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));

    EXPECT_EQ(0, tuple.getLength());
}

// This test verifies that the tuple having a length of 0, followed by no
// data, is decoded from the wire format.
TEST(OpaqueDataTuple, unpack1ByteZeroLengthNoData) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
    OpaqueDataTuple::Buffer wire_data = {0};
    ASSERT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));
}

// This test verifies that the tuple having a length of 0, followed by no
// data, is decoded from the wire format.
TEST(OpaqueDataTuple, unpack2ByteZeroLengthNoData) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    OpaqueDataTuple::Buffer wire_data = {0, 0};
    ASSERT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));
}

// This test verifies that exception is thrown if the empty buffer is being
// parsed.
TEST(OpaqueDataTuple, unpack1ByteEmptyBuffer) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
    OpaqueDataTuple::Buffer wire_data = {};
    EXPECT_THROW(tuple.unpack(wire_data.begin(), wire_data.end()),
                 OpaqueDataTupleError);
}

// This test verifies that exception is thrown when parsing truncated buffer.
TEST(OpaqueDataTuple, unpack1ByteTruncatedBuffer) {
   OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
    OpaqueDataTuple::Buffer wire_data = {
        10, 2, 3
    };
    EXPECT_THROW(tuple.unpack(wire_data.begin(), wire_data.end()),
                 OpaqueDataTupleError);
}

// This test verifies that the tuple is decoded from the wire format.
TEST(OpaqueDataTuple, unpack2Byte) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    OpaqueDataTuple::Buffer wire_data;
    // Set tuple length to 400 (0x190).
    wire_data.push_back(1);
    wire_data.push_back(0x90);
    // Fill in the buffer with some data.
    for (int i = 0; i < 400; ++i) {
        wire_data.push_back(i);
    }
    // The unpack should succeed.
    ASSERT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));
    // The decoded length should be 400.
    ASSERT_EQ(400, tuple.getLength());
    // And the data should match.
    EXPECT_TRUE(std::equal(wire_data.begin() + 2, wire_data.end(),
                           tuple.getData().begin()));
}

// This test verifies that the tuple having a length of 0, is decoded from
// the wire format.
TEST(OpaqueDataTuple, unpack2ByteZeroLength) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Set some data for the tuple.
    EXPECT_NO_THROW(tuple = "Hello world");
    ASSERT_NE(tuple.getLength(), 0);
    // The buffer holds just a length field with the value of 0.
    OpaqueDataTuple::Buffer wire_data = {
        0, 0
    };
    // The empty tuple should be successfully decoded.
    ASSERT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));
    // The data should be replaced with an empty buffer.
    EXPECT_EQ(0, tuple.getLength());
}

// This test verifies that exception is thrown if the empty buffer is being
// parsed.
TEST(OpaqueDataTuple, unpack2ByteEmptyBuffer) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    OpaqueDataTuple::Buffer wire_data = {};
    // Pass empty buffer (first iterator equal to second iterator).
    // This should not be accepted.
    EXPECT_THROW(tuple.unpack(wire_data.begin(), wire_data.end()),
                 OpaqueDataTupleError);
}

// This test verifies that exception is thrown when parsing truncated buffer.
TEST(OpaqueDataTuple, unpack2ByteTruncatedBuffer) {
   OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
   // Specify the data with the length of 10, but limit the buffer size to
   // 2 bytes.
   OpaqueDataTuple::Buffer wire_data = {
       0, 10, 2, 3
   };
   // This should fail because the buffer is truncated.
   EXPECT_THROW(tuple.unpack(wire_data.begin(), wire_data.end()),
                OpaqueDataTupleError);
}

// Test that an exception is not thrown when parsing in lenient mode.
TEST_F(OpaqueDataTupleLenientParsing, unpack) {
    OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
    // Specify the data with the length of 10, but limit the buffer size to 2.
   OpaqueDataTuple::Buffer wire_data = {
        0, 10, 2, 3
    };
    EXPECT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));
    EXPECT_EQ(tuple.getData(), OpaqueDataTuple::Buffer({2, 3}));
}

} // anonymous namespace