// Copyright 2017 The Fuchsia Authors // // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT #include #include namespace { constexpr char fill = 0x7f; bool buffer_invariants_hold(const char* buf, size_t size) { // The buffer should start with zero or more non-NUL bytes followed // by a NUL. unsigned int idx = 0; while (buf[idx] != 0) { idx++; if (idx == size) { unittest_printf("No NUL byte found\n"); return false; } } idx++; // Skip the NUL // The rest of the buffer should be filled with the NUL byte // to ensure stale data isn't leaked. while (idx < size) { if (buf[idx] != '\0') { unittest_printf( "buf[%d] 0x%02x != 0x00\n", idx, buf[idx]); return false; } idx++; } return true; } template bool empty_ctor() { BEGIN_TEST; // Note on |out| sizes: most tests use Size * 2 to ensure the out buffer is // more than big enough to read the entire name with room to spare. char out[Size * 2]; memset(out, fill, sizeof(out)); fbl::Name name; name.get(sizeof(out), out); EXPECT_EQ(out[0], 0, ""); EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), ""); END_TEST; } template bool named_ctor_empty() { BEGIN_TEST; char out[Size * 2]; memset(out, fill, sizeof(out)); fbl::Name name("", 1); name.get(sizeof(out), out); EXPECT_EQ(out[0], 0, ""); EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), ""); END_TEST; } template bool named_ctor_small() { BEGIN_TEST; char out[Size * 2]; memset(out, fill, sizeof(out)); fbl::Name name("a", 2); name.get(sizeof(out), out); EXPECT_EQ(out[0], 'a', ""); EXPECT_EQ(out[1], 0, ""); EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), ""); END_TEST; } template bool named_ctor_exact() { BEGIN_TEST; char out[Size * 2]; memset(out, fill, sizeof(out)); char expected_name[Size]; memset(expected_name, 'z', Size - 1); expected_name[Size - 1] = 0; fbl::Name name(expected_name, Size); name.get(sizeof(out), out); for (size_t idx = 0; idx < Size - 1; ++idx) { EXPECT_EQ(out[idx], 'z', ""); } EXPECT_EQ(out[Size - 1], 0, ""); EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), ""); END_TEST; } template bool named_ctor_overflow() { BEGIN_TEST; constexpr size_t overflow_size = 2 * Size; char out[overflow_size * 2]; memset(out, fill, sizeof(out)); char expected_name[overflow_size]; memset(expected_name, 'z', overflow_size - 1); expected_name[overflow_size - 1] = 0; fbl::Name name(expected_name, overflow_size); name.get(sizeof(out), out); for (size_t idx = 0; idx < Size - 1; ++idx) { EXPECT_EQ(out[idx], 'z', ""); } EXPECT_EQ(out[Size - 1], 0, ""); EXPECT_TRUE(buffer_invariants_hold(out, sizeof(out)), ""); END_TEST; } template bool zero_sized_output_buffer() { BEGIN_TEST; // Neither of these bytes should be touched. char out[2] = {fill, fill}; fbl::Name name("a", 2); name.get(0, out); EXPECT_EQ(out[0], fill, ""); EXPECT_EQ(out[1], fill, ""); END_TEST; } template bool output_buffer_size() { static_assert(OutSize > 0, ""); // |OutSize - 1| below would fail. BEGIN_TEST; // Longest name possible. char expected_name[NameSize]; memset(expected_name, 'z', NameSize - 1); expected_name[NameSize - 1] = 0; char out[OutSize + 2]; // Extra fill at the end. memset(out, fill, sizeof(out)); fbl::Name name(expected_name, sizeof(expected_name)); name.get(OutSize, out); // Check that the name fits in the size we passed to Name::get(). for (size_t idx = 0; idx < OutSize - 1; ++idx) { char msg[32]; snprintf(msg, sizeof(msg), "idx=%zu", idx); EXPECT_EQ(out[idx], 'z', msg); } EXPECT_EQ(out[OutSize - 1], 0, ""); // Check that the extra fill is intact. EXPECT_TRUE(buffer_invariants_hold(out, OutSize), ""); EXPECT_EQ(out[OutSize], fill, ""); EXPECT_EQ(out[OutSize+1], fill, ""); END_TEST; } // Test the smallest size and a typical size. constexpr size_t kSmallestNameSize = 2; constexpr size_t kTypicalNameSize = 32; } // namespace #define NAME_UNITTEST(fname) UNITTEST(#fname, fname) UNITTEST_START_TESTCASE(name_tests) NAME_UNITTEST(empty_ctor) NAME_UNITTEST(empty_ctor) NAME_UNITTEST(named_ctor_empty) NAME_UNITTEST(named_ctor_empty) NAME_UNITTEST(named_ctor_small) NAME_UNITTEST(named_ctor_small) NAME_UNITTEST(named_ctor_exact) NAME_UNITTEST(named_ctor_exact) NAME_UNITTEST(named_ctor_overflow) NAME_UNITTEST(named_ctor_overflow) NAME_UNITTEST(zero_sized_output_buffer) NAME_UNITTEST(zero_sized_output_buffer) // Output buffer only contains NUL. NAME_UNITTEST((output_buffer_size)) // Smallest useful output buffer. NAME_UNITTEST((output_buffer_size)) // Edge cases around exactly matching the Name length. NAME_UNITTEST((output_buffer_size)) NAME_UNITTEST((output_buffer_size)) NAME_UNITTEST((output_buffer_size)) // Don't bother testing a larger output buffer, since most of the // earlier tests use larger output buffers. UNITTEST_END_TESTCASE(name_tests, "nametests", "Name test");