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