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