1 // Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 /// \brief Test of asiolink utilities
8 ///
9 /// Tests the functionality of the asiolink utilities code by comparing them
10 /// with the equivalent methods in isc::dns::[Input/Output]Buffer.
11 
12 #include <config.h>
13 
14 #include <cstddef>
15 
16 #include <arpa/inet.h>
17 #include <gtest/gtest.h>
18 
19 #include <util/buffer.h>
20 #include <util/io_utilities.h>
21 
22 using namespace isc::util;
23 
TEST(asioutil,readUint16)24 TEST(asioutil, readUint16) {
25 
26     // Reference buffer
27     uint8_t data[2] = {0, 0};
28     InputBuffer buffer(data, sizeof(data));
29 
30     // Avoid possible compiler warnings by only setting uint8_t variables to
31     // uint8_t values.
32     uint8_t i8 = 0;
33     uint8_t j8 = 0;
34     for (int i = 0; i < (2 << 8); ++i, ++i8) {
35         for (int j = 0; j < (2 << 8); ++j, ++j8) {
36             data[0] = i8;
37             data[1] = j8;
38             buffer.setPosition(0);
39             EXPECT_EQ(buffer.readUint16(), readUint16(data, sizeof(data)));
40         }
41     }
42 }
43 
TEST(asioutil,readUint16OutOfRange)44 TEST(asioutil, readUint16OutOfRange) {
45     uint8_t data;
46     EXPECT_THROW(readUint16(&data, sizeof(data)), isc::OutOfRange);
47 }
48 
TEST(asioutil,writeUint16)49 TEST(asioutil, writeUint16) {
50 
51     // Reference buffer
52     OutputBuffer buffer(2);
53     uint8_t test[2];
54 
55     // Avoid possible compiler warnings by only setting uint16_t variables to
56     // uint16_t values.
57     uint16_t i16 = 0;
58     for (uint32_t i = 0; i < (2 << 16); ++i, ++i16) {
59 
60         // Write the reference data
61         buffer.clear();
62         buffer.writeUint16(i16);
63 
64         // ... and the test data
65         writeUint16(i16, test, sizeof(test));
66 
67         // ... and compare
68         const uint8_t* ref = static_cast<const uint8_t*>(buffer.getData());
69         EXPECT_EQ(ref[0], test[0]);
70         EXPECT_EQ(ref[1], test[1]);
71     }
72 }
73 
TEST(asioutil,writeUint16OutOfRange)74 TEST(asioutil, writeUint16OutOfRange) {
75     uint16_t i16 = 42;
76     uint8_t data;
77     EXPECT_THROW(writeUint16(i16, &data, sizeof(data)), isc::OutOfRange);
78 }
79 
80 // test data shared amount readUint32 and writeUint32 tests
81 const static uint32_t test32[] = {
82     0,
83     1,
84     2000,
85     0x80000000,
86     0xffffffff
87 };
88 
TEST(asioutil,readUint32)89 TEST(asioutil, readUint32) {
90     uint8_t data[8];
91 
92     // make sure that we can read data, regardless of
93     // the memory alignment. That' why we need to repeat
94     // it 4 times.
95     for (int offset=0; offset < 4; offset++) {
96         for (int i=0; i < sizeof(test32)/sizeof(uint32_t); i++) {
97             uint32_t tmp = htonl(test32[i]);
98             memcpy(&data[offset], &tmp, sizeof(uint32_t));
99 
100             EXPECT_EQ(test32[i], readUint32(&data[offset], sizeof(uint32_t)));
101         }
102     }
103 }
104 
TEST(asioutil,readUint32OutOfRange)105 TEST(asioutil, readUint32OutOfRange) {
106     uint8_t data[3];
107     EXPECT_THROW(readUint32(data, sizeof(data)), isc::OutOfRange);
108 }
109 
TEST(asioutil,writeUint32)110 TEST(asioutil, writeUint32) {
111     uint8_t data[8];
112 
113     // make sure that we can write data, regardless of
114     // the memory alignment. That's why we need to repeat
115     // it 4 times.
116     for (int offset=0; offset < 4; offset++) {
117         for (int i=0; i < sizeof(test32)/sizeof(uint32_t); i++) {
118             uint8_t* ptr = writeUint32(test32[i], &data[offset],
119                                        sizeof(uint32_t));
120 
121             EXPECT_EQ(&data[offset]+sizeof(uint32_t), ptr);
122 
123             uint32_t tmp = htonl(test32[i]);
124 
125             EXPECT_EQ(0, memcmp(&tmp, &data[offset], sizeof(uint32_t)));
126         }
127     }
128 }
129 
TEST(asioutil,writeUint32OutOfRange)130 TEST(asioutil, writeUint32OutOfRange) {
131     uint32_t i32 = 28;
132     uint8_t data[3];
133     EXPECT_THROW(writeUint32(i32, data, sizeof(data)), isc::OutOfRange);
134 }
135 
136 // Tests whether uint64 can be read from a buffer properly.
TEST(asioutil,readUint64)137 TEST(asioutil, readUint64) {
138 
139     uint8_t buf[8];
140     for (int offset = 0; offset < sizeof(buf); offset++) {
141         buf[offset] = offset+1;
142     }
143 
144     // Let's do some simple sanity checks first.
145     EXPECT_THROW(readUint64(NULL, 0), isc::OutOfRange);
146     EXPECT_THROW(readUint64(buf, 7), isc::OutOfRange);
147 
148     // Now check if a real value could be read.
149     const uint64_t exp_val = 0x0102030405060708ul;
150     uint64_t val;
151 
152     EXPECT_NO_THROW(val = readUint64(buf, 8));
153     EXPECT_EQ(val, exp_val);
154 
155     // Now check if there are no buffer overflows.
156     memset(buf, 0xff, 8);
157 
158     EXPECT_NO_THROW(val = readUint64(buf, 8));
159     EXPECT_EQ(0xfffffffffffffffful, val);
160 }
161