1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6
7 #include <fbl/name.h>
8
9 #include <lib/unittest/unittest.h>
10
11 namespace {
12
13 constexpr char fill = 0x7f;
14
buffer_invariants_hold(const char * buf,size_t size)15 bool buffer_invariants_hold(const char* buf, size_t size) {
16 // The buffer should start with zero or more non-NUL bytes followed
17 // by a NUL.
18 unsigned int idx = 0;
19 while (buf[idx] != 0) {
20 idx++;
21 if (idx == size) {
22 unittest_printf("No NUL byte found\n");
23 return false;
24 }
25 }
26 idx++; // Skip the NUL
27 // The rest of the buffer should be filled with the NUL byte
28 // to ensure stale data isn't leaked.
29 while (idx < size) {
30 if (buf[idx] != '\0') {
31 unsigned int byte = buf[idx];
32 unittest_printf(
33 "buf[%u] 0x%02x != 0x00\n", idx, byte);
34 return false;
35 }
36 idx++;
37 }
38 return true;
39 }
40
41 template <size_t Size>
empty_ctor()42 bool empty_ctor() {
43 BEGIN_TEST;
44
45 // Note on |out| sizes: most tests use Size * 2 to ensure the out buffer is
46 // more than big enough to read the entire name with room to spare.
47 char out[Size * 2];
48 memset(out, fill, sizeof(out));
49
50 fbl::Name<Size> name;
51 name.get(sizeof(out), out);
52
53 EXPECT_EQ(out[0], 0, "");
54 EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), "");
55
56 END_TEST;
57 }
58
59 template <size_t Size>
named_ctor_empty()60 bool named_ctor_empty() {
61 BEGIN_TEST;
62
63 char out[Size * 2];
64 memset(out, fill, sizeof(out));
65
66 fbl::Name<Size> name("", 1);
67 name.get(sizeof(out), out);
68
69 EXPECT_EQ(out[0], 0, "");
70 EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), "");
71
72 END_TEST;
73 }
74
75 template <size_t Size>
named_ctor_small()76 bool named_ctor_small() {
77 BEGIN_TEST;
78
79 char out[Size * 2];
80 memset(out, fill, sizeof(out));
81
82 fbl::Name<Size> name("a", 2);
83 name.get(sizeof(out), out);
84
85 EXPECT_EQ(out[0], 'a', "");
86 EXPECT_EQ(out[1], 0, "");
87 EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), "");
88
89 END_TEST;
90 }
91
92 template <size_t Size>
named_ctor_exact()93 bool named_ctor_exact() {
94 BEGIN_TEST;
95
96 char out[Size * 2];
97 memset(out, fill, sizeof(out));
98
99 char expected_name[Size];
100 memset(expected_name, 'z', Size - 1);
101 expected_name[Size - 1] = 0;
102
103 fbl::Name<Size> name(expected_name, Size);
104 name.get(sizeof(out), out);
105
106 for (size_t idx = 0; idx < Size - 1; ++idx) {
107 EXPECT_EQ(out[idx], 'z', "");
108 }
109 EXPECT_EQ(out[Size - 1], 0, "");
110 EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), "");
111
112 END_TEST;
113 }
114
115 template <size_t Size>
named_ctor_overflow()116 bool named_ctor_overflow() {
117 BEGIN_TEST;
118
119 constexpr size_t overflow_size = 2 * Size;
120
121 char out[overflow_size * 2];
122 memset(out, fill, sizeof(out));
123
124 char expected_name[overflow_size];
125 memset(expected_name, 'z', overflow_size - 1);
126 expected_name[overflow_size - 1] = 0;
127
128 fbl::Name<Size> name(expected_name, overflow_size);
129 name.get(sizeof(out), out);
130
131 for (size_t idx = 0; idx < Size - 1; ++idx) {
132 EXPECT_EQ(out[idx], 'z', "");
133 }
134 EXPECT_EQ(out[Size - 1], 0, "");
135 EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), "");
136
137 END_TEST;
138 }
139
140 template <size_t Size>
zero_sized_output_buffer()141 bool zero_sized_output_buffer() {
142 BEGIN_TEST;
143
144 // Neither of these bytes should be touched.
145 char out[2] = {fill, fill};
146
147 fbl::Name<Size> name("a", 2);
148 name.get(0, out);
149
150 EXPECT_EQ(out[0], fill, "");
151 EXPECT_EQ(out[1], fill, "");
152
153 END_TEST;
154 }
155
156 template <size_t NameSize, size_t OutSize>
output_buffer_size()157 bool output_buffer_size() {
158 static_assert(OutSize > 0, ""); // |OutSize - 1| below would fail.
159
160 BEGIN_TEST;
161
162 // Longest name possible.
163 char expected_name[NameSize];
164 memset(expected_name, 'z', NameSize - 1);
165 expected_name[NameSize - 1] = 0;
166
167 char out[OutSize + 2]; // Extra fill at the end.
168 memset(out, fill, sizeof(out));
169
170 fbl::Name<NameSize> name(expected_name, sizeof(expected_name));
171 name.get(OutSize, out);
172
173 // Check that the name fits in the size we passed to Name::get().
174 for (size_t idx = 0; idx < OutSize - 1; ++idx) {
175 char msg[32];
176 snprintf(msg, sizeof(msg), "idx=%zu", idx);
177 EXPECT_EQ(out[idx], 'z', msg);
178 }
179 EXPECT_EQ(out[OutSize - 1], 0, "");
180
181 // Check that the extra fill is intact.
182 EXPECT_TRUE(buffer_invariants_hold(out, OutSize), "");
183 EXPECT_EQ(out[OutSize], fill, "");
184 EXPECT_EQ(out[OutSize+1], fill, "");
185
186 END_TEST;
187 }
188
189 // Test the smallest size and a typical size.
190 constexpr size_t kSmallestNameSize = 2;
191 constexpr size_t kTypicalNameSize = 32;
192
193 } // namespace
194
195 #define NAME_UNITTEST(fname) UNITTEST(#fname, fname)
196
197 UNITTEST_START_TESTCASE(name_tests)
198
199 NAME_UNITTEST(empty_ctor<kSmallestNameSize>)
200 NAME_UNITTEST(empty_ctor<kTypicalNameSize>)
201
202 NAME_UNITTEST(named_ctor_empty<kSmallestNameSize>)
203 NAME_UNITTEST(named_ctor_empty<kTypicalNameSize>)
204
205 NAME_UNITTEST(named_ctor_small<kSmallestNameSize>)
206 NAME_UNITTEST(named_ctor_small<kTypicalNameSize>)
207
208 NAME_UNITTEST(named_ctor_exact<kSmallestNameSize>)
209 NAME_UNITTEST(named_ctor_exact<kTypicalNameSize>)
210
211 NAME_UNITTEST(named_ctor_overflow<kSmallestNameSize>)
212 NAME_UNITTEST(named_ctor_overflow<kTypicalNameSize>)
213
214 NAME_UNITTEST(zero_sized_output_buffer<kSmallestNameSize>)
215 NAME_UNITTEST(zero_sized_output_buffer<kTypicalNameSize>)
216
217 // Output buffer only contains NUL.
218 NAME_UNITTEST((output_buffer_size<kTypicalNameSize, 1>))
219
220 // Smallest useful output buffer.
221 NAME_UNITTEST((output_buffer_size<kTypicalNameSize, 2>))
222
223 // Edge cases around exactly matching the Name length.
224 NAME_UNITTEST((output_buffer_size<kTypicalNameSize, kTypicalNameSize - 2>))
225 NAME_UNITTEST((output_buffer_size<kTypicalNameSize, kTypicalNameSize - 1>))
226 NAME_UNITTEST((output_buffer_size<kTypicalNameSize, kTypicalNameSize>))
227 // Don't bother testing a larger output buffer, since most of the
228 // earlier tests use larger output buffers.
229
230 UNITTEST_END_TESTCASE(name_tests, "nametests", "Name test");
231