diff options
author | Greg Falcon <gfalcon@google.com> | 2023-06-05 14:27:37 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-06-05 14:28:21 -0700 |
commit | 66406fdf1553de6ad672576167e7cc7ca2d764cb (patch) | |
tree | 086ef19347c945aa8115a8a4279d00427eda3791 /absl/strings | |
parent | 7a74153a05aa8bacb8cb9ae3fa707e5407adc2c9 (diff) |
Add a unit test that captures the current behavior of formatting of char types and char-backed enum types through StrCat(), StrFormat("%v"), and Substitute().
This test allows us to modify the behavior in this space without introducing undesired changes elsewhere.
PiperOrigin-RevId: 537981963
Change-Id: Icda91b66efcc0dc8c263011b137e130a3db2dc19
Diffstat (limited to 'absl/strings')
-rw-r--r-- | absl/strings/BUILD.bazel | 12 | ||||
-rw-r--r-- | absl/strings/CMakeLists.txt | 14 | ||||
-rw-r--r-- | absl/strings/char_formatting_test.cc | 189 |
3 files changed, 215 insertions, 0 deletions
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index bd33c533..4a111b5a 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -1319,3 +1319,15 @@ cc_binary( "//absl/types:optional", ], ) + +cc_test( + name = "char_formatting_test", + srcs = [ + "char_formatting_test.cc", + ], + deps = [ + ":str_format", + ":strings", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 9aaa7932..2ad052a3 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -548,6 +548,20 @@ absl_cc_test( GTest::gmock_main ) +absl_cc_test( + NAME + char_formatting_test + SRCS + "char_formatting_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::str_format + absl::strings + GTest::gmock_main +) + # Internal-only target, do not depend on directly. absl_cc_library( NAME diff --git a/absl/strings/char_formatting_test.cc b/absl/strings/char_formatting_test.cc new file mode 100644 index 00000000..60416af3 --- /dev/null +++ b/absl/strings/char_formatting_test.cc @@ -0,0 +1,189 @@ +// Copyright 2023 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <cstddef> + +#include "gtest/gtest.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/substitute.h" + +namespace { + +TEST(CharFormatting, Char) { + const char v = 'A'; + + // Desired behavior: does not compile: + // EXPECT_EQ(absl::StrCat(v, "B"), "AB"); + // EXPECT_EQ(absl::StrFormat("%vB", v), "AB"); + + // Legacy behavior: format as char: + EXPECT_EQ(absl::Substitute("$0B", v), "AB"); +} + +enum CharEnum : char {}; +TEST(CharFormatting, CharEnum) { + auto v = static_cast<CharEnum>('A'); + + // Desired behavior: format as decimal + // (No APIs do this today.) + + // BUG: internally fails + EXPECT_EQ(absl::StrFormat("%vB", v), ""); + + // Legacy behavior: does not compile: + // EXPECT_EQ(absl::StrCat(ch, "B"), "AB"); + + // Legacy behavior: format as character: + + // Some older versions of gcc behave differently in this one case. +#if !defined(__GNUC__) || defined(__clang__) + EXPECT_EQ(absl::Substitute("$0B", v), "AB"); +#endif +} + +enum class CharEnumClass: char {}; +TEST(CharFormatting, CharEnumClass) { + auto v = static_cast<CharEnumClass>('A'); + + // Desired behavior: format as decimal + // (No APIs do this today.) + + // BUG: internally fails + EXPECT_EQ(absl::StrFormat("%vB", v), ""); + + // Legacy behavior: does not compile: + // EXPECT_EQ(absl::StrCat(ch, "B"), "AB"); + + // Legacy behavior: format as character: + EXPECT_EQ(absl::Substitute("$0B", v), "AB"); +} + +TEST(CharFormatting, UnsignedChar) { + const unsigned char v = 'A'; + + // Desired behavior: format as decimal: + EXPECT_EQ(absl::StrCat(v, "B"), "65B"); + EXPECT_EQ(absl::Substitute("$0B", v), "65B"); + + // Legacy behavior: does not compile: + // EXPECT_EQ(absl::StrFormat("%vB", v), "65B"); + + // Signedness check + const unsigned char w = 255; + EXPECT_EQ(absl::StrCat(w, "B"), "255B"); + EXPECT_EQ(absl::Substitute("$0B", w), "255B"); + // EXPECT_EQ(absl::StrFormat("%vB", v), "255B"); +} + +TEST(CharFormatting, SignedChar) { + const signed char v = 'A'; + + // Desired behavior: format as decimal: + EXPECT_EQ(absl::StrCat(v, "B"), "65B"); + EXPECT_EQ(absl::Substitute("$0B", v), "65B"); + + // Legacy behavior: does not compile: + // EXPECT_EQ(absl::StrFormat("%vB", v), "AB"); + + // Signedness check + const signed char w = -128; + EXPECT_EQ(absl::StrCat(w, "B"), "-128B"); + EXPECT_EQ(absl::Substitute("$0B", w), "-128B"); +} + +enum UnsignedCharEnum : unsigned char {}; +TEST(CharFormatting, UnsignedCharEnum) { + auto v = static_cast<UnsignedCharEnum>('A'); + + // Desired behavior: format as decimal: + EXPECT_EQ(absl::StrCat(v, "B"), "65B"); + EXPECT_EQ(absl::Substitute("$0B", v), "65B"); + + // BUG: internally fails + EXPECT_EQ(absl::StrFormat("%vB", v), ""); + + // Signedness check + auto w = static_cast<UnsignedCharEnum>(255); + EXPECT_EQ(absl::StrCat(w, "B"), "255B"); + EXPECT_EQ(absl::Substitute("$0B", w), "255B"); +} + +enum SignedCharEnum : signed char {}; +TEST(CharFormatting, SignedCharEnum) { + auto v = static_cast<SignedCharEnum>('A'); + + // Desired behavior: format as decimal: + EXPECT_EQ(absl::StrCat(v, "B"), "65B"); + EXPECT_EQ(absl::Substitute("$0B", v), "65B"); + + // BUG: internally fails + EXPECT_EQ(absl::StrFormat("%vB", v), ""); + + // Signedness check + auto w = static_cast<SignedCharEnum>(-128); + EXPECT_EQ(absl::StrCat(w, "B"), "-128B"); + EXPECT_EQ(absl::Substitute("$0B", w), "-128B"); +} + +enum class UnsignedCharEnumClass : unsigned char {}; +TEST(CharFormatting, UnsignedCharEnumClass) { + auto v = static_cast<UnsignedCharEnumClass>('A'); + + // Desired behavior: format as decimal: + EXPECT_EQ(absl::StrCat(v, "B"), "65B"); + EXPECT_EQ(absl::Substitute("$0B", v), "65B"); + + // BUG: internally fails + EXPECT_EQ(absl::StrFormat("%vB", v), ""); + + // Signedness check + auto w = static_cast<UnsignedCharEnumClass>(255); + EXPECT_EQ(absl::StrCat(w, "B"), "255B"); + EXPECT_EQ(absl::Substitute("$0B", w), "255B"); +} + +enum SignedCharEnumClass : signed char {}; +TEST(CharFormatting, SignedCharEnumClass) { + auto v = static_cast<SignedCharEnumClass>('A'); + + // Desired behavior: format as decimal: + EXPECT_EQ(absl::StrCat(v, "B"), "65B"); + EXPECT_EQ(absl::Substitute("$0B", v), "65B"); + + // BUG: internally fails + EXPECT_EQ(absl::StrFormat("%vB", v), ""); + + // Signedness check + auto w = static_cast<SignedCharEnumClass>(-128); + EXPECT_EQ(absl::StrCat(w, "B"), "-128B"); + EXPECT_EQ(absl::Substitute("$0B", w), "-128B"); +} + +#ifdef __cpp_lib_byte +TEST(CharFormatting, StdByte) { + auto v = static_cast<std::byte>('A'); + // Desired behavior: format as 0xff + // (No APIs do this today.) + + // BUG: internally fails + EXPECT_EQ(absl::StrFormat("%vB", v), ""); + + // Legacy behavior: format as decimal: + EXPECT_EQ(absl::StrCat(v, "B"), "65B"); + EXPECT_EQ(absl::Substitute("$0B", v), "65B"); +} +#endif // _cpp_lib_byte + +} // namespace |