1 // Copyright 2023 The Abseil Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <cstddef>
16
17 #include "gtest/gtest.h"
18 #include "absl/strings/str_cat.h"
19 #include "absl/strings/str_format.h"
20 #include "absl/strings/substitute.h"
21
22 namespace {
23
TEST(CharFormatting,Char)24 TEST(CharFormatting, Char) {
25 const char v = 'A';
26
27 // Desired behavior: does not compile:
28 // EXPECT_EQ(absl::StrCat(v, "B"), "AB");
29 // EXPECT_EQ(absl::StrFormat("%vB", v), "AB");
30
31 // Legacy behavior: format as char:
32 EXPECT_EQ(absl::Substitute("$0B", v), "AB");
33 }
34
35 enum CharEnum : char {};
TEST(CharFormatting,CharEnum)36 TEST(CharFormatting, CharEnum) {
37 auto v = static_cast<CharEnum>('A');
38
39 // Desired behavior: format as decimal
40 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
41 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
42
43 // Legacy behavior: format as character:
44
45 // Some older versions of gcc behave differently in this one case
46 #if !defined(__GNUC__) || defined(__clang__)
47 EXPECT_EQ(absl::Substitute("$0B", v), "AB");
48 #endif
49 }
50
51 enum class CharEnumClass: char {};
TEST(CharFormatting,CharEnumClass)52 TEST(CharFormatting, CharEnumClass) {
53 auto v = static_cast<CharEnumClass>('A');
54
55 // Desired behavior: format as decimal:
56 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
57 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
58
59 // Legacy behavior: format as character:
60 EXPECT_EQ(absl::Substitute("$0B", v), "AB");
61 }
62
TEST(CharFormatting,UnsignedChar)63 TEST(CharFormatting, UnsignedChar) {
64 const unsigned char v = 'A';
65
66 // Desired behavior: format as decimal:
67 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
68 EXPECT_EQ(absl::Substitute("$0B", v), "65B");
69 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
70
71 // Signedness check
72 const unsigned char w = 255;
73 EXPECT_EQ(absl::StrCat(w, "B"), "255B");
74 EXPECT_EQ(absl::Substitute("$0B", w), "255B");
75 // EXPECT_EQ(absl::StrFormat("%vB", v), "255B");
76 }
77
TEST(CharFormatting,SignedChar)78 TEST(CharFormatting, SignedChar) {
79 const signed char v = 'A';
80
81 // Desired behavior: format as decimal:
82 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
83 EXPECT_EQ(absl::Substitute("$0B", v), "65B");
84 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
85
86 // Signedness check
87 const signed char w = -128;
88 EXPECT_EQ(absl::StrCat(w, "B"), "-128B");
89 EXPECT_EQ(absl::Substitute("$0B", w), "-128B");
90 }
91
92 enum UnsignedCharEnum : unsigned char {};
TEST(CharFormatting,UnsignedCharEnum)93 TEST(CharFormatting, UnsignedCharEnum) {
94 auto v = static_cast<UnsignedCharEnum>('A');
95
96 // Desired behavior: format as decimal:
97 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
98 EXPECT_EQ(absl::Substitute("$0B", v), "65B");
99 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
100
101 // Signedness check
102 auto w = static_cast<UnsignedCharEnum>(255);
103 EXPECT_EQ(absl::StrCat(w, "B"), "255B");
104 EXPECT_EQ(absl::Substitute("$0B", w), "255B");
105 EXPECT_EQ(absl::StrFormat("%vB", w), "255B");
106 }
107
108 enum SignedCharEnum : signed char {};
TEST(CharFormatting,SignedCharEnum)109 TEST(CharFormatting, SignedCharEnum) {
110 auto v = static_cast<SignedCharEnum>('A');
111
112 // Desired behavior: format as decimal:
113 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
114 EXPECT_EQ(absl::Substitute("$0B", v), "65B");
115 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
116
117 // Signedness check
118 auto w = static_cast<SignedCharEnum>(-128);
119 EXPECT_EQ(absl::StrCat(w, "B"), "-128B");
120 EXPECT_EQ(absl::Substitute("$0B", w), "-128B");
121 EXPECT_EQ(absl::StrFormat("%vB", w), "-128B");
122 }
123
124 enum class UnsignedCharEnumClass : unsigned char {};
TEST(CharFormatting,UnsignedCharEnumClass)125 TEST(CharFormatting, UnsignedCharEnumClass) {
126 auto v = static_cast<UnsignedCharEnumClass>('A');
127
128 // Desired behavior: format as decimal:
129 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
130 EXPECT_EQ(absl::Substitute("$0B", v), "65B");
131 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
132
133 // Signedness check
134 auto w = static_cast<UnsignedCharEnumClass>(255);
135 EXPECT_EQ(absl::StrCat(w, "B"), "255B");
136 EXPECT_EQ(absl::Substitute("$0B", w), "255B");
137 EXPECT_EQ(absl::StrFormat("%vB", w), "255B");
138 }
139
140 enum SignedCharEnumClass : signed char {};
TEST(CharFormatting,SignedCharEnumClass)141 TEST(CharFormatting, SignedCharEnumClass) {
142 auto v = static_cast<SignedCharEnumClass>('A');
143
144 // Desired behavior: format as decimal:
145 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
146 EXPECT_EQ(absl::Substitute("$0B", v), "65B");
147 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
148
149 // Signedness check
150 auto w = static_cast<SignedCharEnumClass>(-128);
151 EXPECT_EQ(absl::StrCat(w, "B"), "-128B");
152 EXPECT_EQ(absl::Substitute("$0B", w), "-128B");
153 EXPECT_EQ(absl::StrFormat("%vB", w), "-128B");
154 }
155
156 #ifdef __cpp_lib_byte
TEST(CharFormatting,StdByte)157 TEST(CharFormatting, StdByte) {
158 auto v = static_cast<std::byte>('A');
159 // Desired behavior: format as 0xff
160 // (No APIs do this today.)
161
162 // Legacy behavior: format as decimal:
163 EXPECT_EQ(absl::StrCat(v, "B"), "65B");
164 EXPECT_EQ(absl::Substitute("$0B", v), "65B");
165 EXPECT_EQ(absl::StrFormat("%vB", v), "65B");
166 }
167 #endif // _cpp_lib_byte
168
169 } // namespace
170