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