// Copyright 2022 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/base/string-format.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest-support.h" namespace v8::base { // Some hard-coded assumptions. constexpr int kMaxPrintedIntLen = 11; constexpr int kMaxPrintedUint32Len = 10; constexpr int kMaxPrintedUint64Len = 20; constexpr int kMaxPrintedSizetLen = sizeof(size_t) == sizeof(uint32_t) ? kMaxPrintedUint32Len : kMaxPrintedUint64Len; TEST(FormattedStringTest, Empty) { auto empty = FormattedString{}; EXPECT_EQ("", decltype(empty)::kFormat); EXPECT_EQ(1, decltype(empty)::kMaxLen); EXPECT_EQ('\0', empty.PrintToArray()[0]); } TEST(FormattedStringTest, SingleString) { auto message = FormattedString{} << "foo"; EXPECT_EQ("%s", decltype(message)::kFormat); constexpr std::array kExpectedOutput{'f', 'o', 'o', '\0'}; EXPECT_EQ(kExpectedOutput, message.PrintToArray()); } TEST(FormattedStringTest, Int) { auto message = FormattedString{} << 42; EXPECT_EQ("%d", decltype(message)::kFormat); // +1 for null-termination. EXPECT_EQ(kMaxPrintedIntLen + 1, decltype(message)::kMaxLen); EXPECT_THAT(message.PrintToArray().data(), ::testing::StrEq("42")); } TEST(FormattedStringTest, MaxInt) { auto message = FormattedString{} << std::numeric_limits::max(); auto result_arr = message.PrintToArray(); // We *nearly* used the full reserved array size (the minimum integer is still // one character longer).. EXPECT_EQ(size_t{decltype(message)::kMaxLen}, result_arr.size()); EXPECT_THAT(result_arr.data(), ::testing::StrEq("2147483647")); } TEST(FormattedStringTest, MinInt) { auto message = FormattedString{} << std::numeric_limits::min(); auto result_arr = message.PrintToArray(); // We used the full reserved array size. EXPECT_EQ(size_t{decltype(message)::kMaxLen}, result_arr.size()); EXPECT_THAT(result_arr.data(), ::testing::StrEq("-2147483648")); } TEST(FormattedStringTest, SizeT) { auto message = FormattedString{} << size_t{42}; EXPECT_EQ(sizeof(size_t) == sizeof(uint32_t) ? "%" PRIu32 : "%" PRIu64, decltype(message)::kFormat); // +1 for null-termination. EXPECT_EQ(kMaxPrintedSizetLen + 1, decltype(message)::kMaxLen); EXPECT_THAT(message.PrintToArray().data(), ::testing::StrEq("42")); } TEST(FormattedStringTest, MaxSizeT) { auto message = FormattedString{} << std::numeric_limits::max(); auto result_arr = message.PrintToArray(); // We used the full reserved array size. EXPECT_EQ(size_t{decltype(message)::kMaxLen}, result_arr.size()); constexpr const char* kMaxSizeTStr = sizeof(size_t) == 4 ? "4294967295" : "18446744073709551615"; EXPECT_THAT(result_arr.data(), ::testing::StrEq(kMaxSizeTStr)); } TEST(FormattedStringTest, Combination) { auto message = FormattedString{} << "Expected " << 11 << " got " << size_t{42} << "!"; EXPECT_EQ(sizeof(size_t) == sizeof(uint32_t) ? "%s%d%s%" PRIu32 "%s" : "%s%d%s%" PRIu64 "%s", decltype(message)::kFormat); size_t expected_array_len = strlen("Expected got !") + kMaxPrintedIntLen + kMaxPrintedSizetLen + 1; EXPECT_EQ(expected_array_len, size_t{decltype(message)::kMaxLen}); EXPECT_THAT(message.PrintToArray().data(), ::testing::StrEq("Expected 11 got 42!")); } TEST(FormattedStringTest, Uint32AndUint64) { auto message = FormattedString{} << uint32_t{1} << " != " << uint64_t{2}; EXPECT_EQ("%" PRIu32 "%s%" PRIu64, decltype(message)::kFormat); size_t expected_array_len = kMaxPrintedUint32Len + 4 + kMaxPrintedUint64Len + 1; EXPECT_EQ(expected_array_len, size_t{decltype(message)::kMaxLen}); EXPECT_THAT(message.PrintToArray().data(), ::testing::StrEq("1 != 2")); } } // namespace v8::base