buffer_unittest.cc 10.2 KB
Newer Older
1
// Copyright (C) 2009-2018 Internet Systems Consortium, Inc. ("ISC")
2
//
3
4
5
// 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/.
6

7
8
#include <config.h>

9
10
#include <gtest/gtest.h>

11
12
#include <exceptions/exceptions.h>

13
#ifdef EXPECT_DEATH
14
#include <util/unittests/resource.h>
15
#include <util/unittests/check_valgrind.h>
16
#endif /* EXPECT_DEATH */
17

18
#include <util/buffer.h>
19
20
21
22
23

using namespace isc;

namespace {

24
25
using isc::util::InputBuffer;
using isc::util::OutputBuffer;
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

class BufferTest : public ::testing::Test {
protected:
    BufferTest() : ibuffer(testdata, sizeof(testdata)), obuffer(0),
                   expected_size(0)
    {
        data16 = (2 << 8) | 3;
        data32 = (4 << 24) | (5 << 16) | (6 << 8) | 7;
        memset(vdata, 0, sizeof(testdata));
    }

    InputBuffer ibuffer;
    OutputBuffer obuffer;
    static const uint8_t testdata[5];
    uint8_t vdata[sizeof(testdata)];
    size_t expected_size;
    uint16_t data16;
    uint32_t data32;
};

const uint8_t BufferTest::testdata[5] = {1, 2, 3, 4, 5};

TEST_F(BufferTest, inputBufferRead) {
    EXPECT_EQ(5, ibuffer.getLength());
    EXPECT_EQ(1, ibuffer.readUint8());
    EXPECT_EQ(1, ibuffer.getPosition());
    data16 = ibuffer.readUint16();
    EXPECT_EQ((2 << 8) | 3, data16);
    EXPECT_EQ(3, ibuffer.getPosition());
    ibuffer.setPosition(1);
    EXPECT_EQ(1, ibuffer.getPosition());
    data32 = ibuffer.readUint32();
    EXPECT_EQ((2 << 24) | (3 << 16) | (4 << 8) | 5, data32);
    ibuffer.setPosition(0);
    memset(vdata, 0, sizeof(vdata));
    ibuffer.readData(vdata, sizeof(vdata));
    EXPECT_EQ(0, memcmp(vdata, testdata, sizeof(testdata)));
}

TEST_F(BufferTest, inputBufferException) {
66
    EXPECT_THROW(ibuffer.setPosition(6), isc::util::InvalidBufferPosition);
67
68

    ibuffer.setPosition(sizeof(testdata));
69
    EXPECT_THROW(ibuffer.readUint8(), isc::util::InvalidBufferPosition);
70
71

    ibuffer.setPosition(sizeof(testdata) - 1);
72
    EXPECT_THROW(ibuffer.readUint16(), isc::util::InvalidBufferPosition);
73
74

    ibuffer.setPosition(sizeof(testdata) - 3);
75
    EXPECT_THROW(ibuffer.readUint32(), isc::util::InvalidBufferPosition);
76
77
78

    ibuffer.setPosition(sizeof(testdata) - 4);
    EXPECT_THROW(ibuffer.readData(vdata, sizeof(vdata)),
79
                 isc::util::InvalidBufferPosition);
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
}

TEST_F(BufferTest, outputBufferExtend) {
    EXPECT_EQ(0, obuffer.getCapacity());
    EXPECT_EQ(0, obuffer.getLength());
    obuffer.writeUint8(10);
    EXPECT_LT(0, obuffer.getCapacity());
    EXPECT_EQ(1, obuffer.getLength());
}

TEST_F(BufferTest, outputBufferWrite) {
    const uint8_t* cp;

    obuffer.writeUint8(1);
    expected_size += sizeof(uint8_t);
    EXPECT_EQ(expected_size, obuffer.getLength());
    cp = static_cast<const uint8_t*>(obuffer.getData());
    EXPECT_EQ(1, *cp);

    obuffer.writeUint16(data16);
    expected_size += sizeof(data16);
    cp = static_cast<const uint8_t*>(obuffer.getData());
    EXPECT_EQ(expected_size, obuffer.getLength());
    EXPECT_EQ(2, *(cp + 1));
    EXPECT_EQ(3, *(cp + 2));

    obuffer.writeUint32(data32);
    expected_size += sizeof(data32);
    cp = static_cast<const uint8_t*>(obuffer.getData());
    EXPECT_EQ(expected_size, obuffer.getLength());
    EXPECT_EQ(4, *(cp + 3));
    EXPECT_EQ(5, *(cp + 4));
    EXPECT_EQ(6, *(cp + 5));
    EXPECT_EQ(7, *(cp + 6));

    obuffer.writeData(testdata, sizeof(testdata));
    expected_size += sizeof(testdata);
    EXPECT_EQ(expected_size, obuffer.getLength());
    cp = static_cast<const uint8_t*>(obuffer.getData());
    EXPECT_EQ(0, memcmp(cp + 7, testdata, sizeof(testdata)));
}

TEST_F(BufferTest, outputBufferWriteat) {
    obuffer.writeUint32(data32);
    expected_size += sizeof(data32);

    // overwrite 2nd byte
    obuffer.writeUint8At(4, 1);
    EXPECT_EQ(expected_size, obuffer.getLength()); // length shouldn't change
    const uint8_t* cp = static_cast<const uint8_t*>(obuffer.getData());
    EXPECT_EQ(4, *(cp + 1));

    // overwrite 2nd and 3rd bytes
    obuffer.writeUint16At(data16, 1);
    EXPECT_EQ(expected_size, obuffer.getLength()); // length shouldn't change
    cp = static_cast<const uint8_t*>(obuffer.getData());
    EXPECT_EQ(2, *(cp + 1));
    EXPECT_EQ(3, *(cp + 2));

    // overwrite 3rd and 4th bytes
    obuffer.writeUint16At(data16, 2);
    EXPECT_EQ(expected_size, obuffer.getLength());
    cp = static_cast<const uint8_t*>(obuffer.getData());
    EXPECT_EQ(2, *(cp + 2));
    EXPECT_EQ(3, *(cp + 3));

    EXPECT_THROW(obuffer.writeUint8At(data16, 5),
147
                 isc::util::InvalidBufferPosition);
148
    EXPECT_THROW(obuffer.writeUint8At(data16, 4),
149
                 isc::util::InvalidBufferPosition);
150
    EXPECT_THROW(obuffer.writeUint16At(data16, 3),
151
                 isc::util::InvalidBufferPosition);
152
    EXPECT_THROW(obuffer.writeUint16At(data16, 4),
153
                 isc::util::InvalidBufferPosition);
154
    EXPECT_THROW(obuffer.writeUint16At(data16, 5),
155
                 isc::util::InvalidBufferPosition);
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
}

TEST_F(BufferTest, outputBufferSkip) {
    obuffer.skip(4);
    EXPECT_EQ(4, obuffer.getLength());

    obuffer.skip(2);
    EXPECT_EQ(6, obuffer.getLength());
}

TEST_F(BufferTest, outputBufferTrim) {
    obuffer.writeData(testdata, sizeof(testdata));
    EXPECT_EQ(5, obuffer.getLength());

    obuffer.trim(1);
    EXPECT_EQ(4, obuffer.getLength());

    obuffer.trim(2);
    EXPECT_EQ(2, obuffer.getLength());

    EXPECT_THROW(obuffer.trim(3), OutOfRange);
}

Francis Dupont's avatar
Francis Dupont committed
179
TEST_F(BufferTest, outputBufferReadAt) {
180
181
182
183
    obuffer.writeData(testdata, sizeof(testdata));
    for (int i = 0; i < sizeof(testdata); i ++) {
        EXPECT_EQ(testdata[i], obuffer[i]);
    }
184
185
#ifdef EXPECT_DEATH
    // We use assert now, so we check it dies
186
187
188
189
190
191
192
193
194
195
196
197
    if (!isc::util::unittests::runningOnValgrind()) {
        EXPECT_DEATH({
            isc::util::unittests::dontCreateCoreDumps();

            try {
                obuffer[sizeof(testdata)];
            } catch (...) {
                // Prevent exceptions killing the application, we need
                // to make sure it dies the real hard way
            }
            }, "");
    }
198
#endif
199
200
201
}

TEST_F(BufferTest, outputBufferClear) {
202
203
    const uint8_t* cp;

204
    obuffer.writeData(testdata, sizeof(testdata));
205
    cp = static_cast<const uint8_t*>(obuffer.getData());
206
207
    obuffer.clear();
    EXPECT_EQ(0, obuffer.getLength());
208
209
210
211
212
213
214
215
216
217
218
    EXPECT_EQ(*cp, 1);
}

TEST_F(BufferTest, outputBufferWipe) {
    const uint8_t* cp;

    obuffer.writeData(testdata, sizeof(testdata));
    cp = static_cast<const uint8_t*>(obuffer.getData());
    obuffer.wipe();
    EXPECT_EQ(0, obuffer.getLength());
    EXPECT_EQ(*cp, 0);
219
}
220

221
222
223
224
225
TEST_F(BufferTest, emptyOutputBufferWipe) {
    ASSERT_NO_THROW(obuffer.wipe());
    EXPECT_EQ(0, obuffer.getLength());
}

226
227
228
229
230
231
TEST_F(BufferTest, outputBufferCopy) {
    obuffer.writeData(testdata, sizeof(testdata));

    EXPECT_NO_THROW({
        OutputBuffer copy(obuffer);
        ASSERT_EQ(sizeof(testdata), copy.getLength());
232
        ASSERT_NE(obuffer.getData(), copy.getData());
233
234
235
236
237
238
239
240
241
242
243
244
        for (int i = 0; i < sizeof(testdata); i ++) {
            EXPECT_EQ(testdata[i], copy[i]);
            if (i + 1 < sizeof(testdata)) {
                obuffer.writeUint16At(0, i);
            }
            EXPECT_EQ(testdata[i], copy[i]);
        }
        obuffer.clear();
        ASSERT_EQ(sizeof(testdata), copy.getLength());
    });
}

245
246
247
248
249
250
251
TEST_F(BufferTest, outputEmptyBufferCopy) {
    EXPECT_NO_THROW({
        OutputBuffer copy(obuffer);
        ASSERT_EQ(0, copy.getLength());
    });
}

252
253
254
255
256
257
258
259
TEST_F(BufferTest, outputBufferAssign) {
    OutputBuffer another(0);
    another.clear();
    obuffer.writeData(testdata, sizeof(testdata));

    EXPECT_NO_THROW({
        another = obuffer;
        ASSERT_EQ(sizeof(testdata), another.getLength());
260
        ASSERT_NE(obuffer.getData(), another.getData());
261
262
263
264
265
266
267
268
269
270
271
272
        for (int i = 0; i < sizeof(testdata); i ++) {
            EXPECT_EQ(testdata[i], another[i]);
            if (i + 1 < sizeof(testdata)) {
                obuffer.writeUint16At(0, i);
            }
            EXPECT_EQ(testdata[i], another[i]);
        }
        obuffer.clear();
        ASSERT_EQ(sizeof(testdata), another.getLength());
    });
}

273
TEST_F(BufferTest, outputEmptyBufferAssign) {
274
275
    OutputBuffer copy(0);
    ASSERT_NO_THROW({
276
277
        copy = obuffer;
    });
278
279
    ASSERT_EQ(0, copy.getLength());
    EXPECT_EQ(NULL, copy.getData());
280
281
}

282
283
284
285
286
// Check assign to self doesn't break stuff
TEST_F(BufferTest, outputBufferAssignSelf) {
    EXPECT_NO_THROW(obuffer = obuffer);
}

287
288
289
290
291
TEST_F(BufferTest, outputBufferZeroSize) {
    // Some OSes might return NULL on malloc for 0 size, so check it works
    EXPECT_NO_THROW({
        OutputBuffer first(0);
        OutputBuffer copy(first);
292
293
        OutputBuffer second(0);
        second = first;
294
295
296
    });
}

297
TEST_F(BufferTest, inputBufferReadVectorAll) {
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
    std::vector<uint8_t> vec;

    // check that vector can read the whole buffer
    ibuffer.readVector(vec, 5);

    ASSERT_EQ(5, vec.size());
    EXPECT_EQ(0, memcmp(&vec[0], testdata, 5));

    // ibuffer is 5 bytes long. Can't read past it.
    EXPECT_THROW(
        ibuffer.readVector(vec, 1),
        isc::util::InvalidBufferPosition
    );
}

313
TEST_F(BufferTest, inputBufferReadVectorChunks) {
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
    std::vector<uint8_t> vec;

    // check that vector can read the whole buffer
    ibuffer.readVector(vec, 3);
    EXPECT_EQ(3, vec.size());

    EXPECT_EQ(0, memcmp(&vec[0], testdata, 3));

    EXPECT_NO_THROW(
        ibuffer.readVector(vec, 2)
    );

    EXPECT_EQ(0, memcmp(&vec[0], testdata+3, 2));
}

329
330
331
332
333
334
335
336
337
338
339
340
341
342
// Tests whether uint64 can be written properly.
TEST_F(BufferTest, writeUint64) {

    uint64_t val1 = 0x0102030405060708ul;
    uint64_t val2 = 0xfffffffffffffffful;

    uint8_t exp_val1[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    uint8_t exp_val2[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

    const uint8_t* cp;

    obuffer.writeUint64(val1);
    ASSERT_EQ(sizeof(uint64_t), obuffer.getLength());
    cp = static_cast<const uint8_t*>(obuffer.getData());
343
    EXPECT_TRUE(cp);
344
345
346
347
348
349
350
    EXPECT_FALSE(memcmp(exp_val1, obuffer.getData(), sizeof(uint64_t)));

    EXPECT_NO_THROW(obuffer.clear());

    obuffer.writeUint64(val2);
    ASSERT_EQ(sizeof(uint64_t), obuffer.getLength());
    cp = static_cast<const uint8_t*>(obuffer.getData());
351
    EXPECT_TRUE(cp);
352
353
354
    EXPECT_FALSE(memcmp(exp_val2, obuffer.getData(), sizeof(uint64_t)));
}

355
}