• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "absl/strings/substitute.h"
16 
17 #include <cstdint>
18 #include <vector>
19 
20 #include "gtest/gtest.h"
21 #include "absl/strings/str_cat.h"
22 
23 namespace {
24 
TEST(SubstituteTest,Substitute)25 TEST(SubstituteTest, Substitute) {
26   // Basic.
27   EXPECT_EQ("Hello, world!", absl::Substitute("$0, $1!", "Hello", "world"));
28 
29   // Non-char* types.
30   EXPECT_EQ("123 0.2 0.1 foo true false x",
31             absl::Substitute("$0 $1 $2 $3 $4 $5 $6", 123, 0.2, 0.1f,
32                              std::string("foo"), true, false, 'x'));
33 
34   // All int types.
35   EXPECT_EQ(
36       "-32767 65535 "
37       "-1234567890 3234567890 "
38       "-1234567890 3234567890 "
39       "-1234567890123456789 9234567890123456789",
40       absl::Substitute(
41           "$0 $1 $2 $3 $4 $5 $6 $7",
42           static_cast<short>(-32767),          // NOLINT(runtime/int)
43           static_cast<unsigned short>(65535),  // NOLINT(runtime/int)
44           -1234567890, 3234567890U, -1234567890L, 3234567890UL,
45           -int64_t{1234567890123456789}, uint64_t{9234567890123456789u}));
46 
47   // Hex format
48   EXPECT_EQ("0 1 f ffff0ffff 0123456789abcdef",
49             absl::Substitute("$0$1$2$3$4 $5",  //
50                              absl::Hex(0), absl::Hex(1, absl::kSpacePad2),
51                              absl::Hex(0xf, absl::kSpacePad2),
52                              absl::Hex(int16_t{-1}, absl::kSpacePad5),
53                              absl::Hex(int16_t{-1}, absl::kZeroPad5),
54                              absl::Hex(0x123456789abcdef, absl::kZeroPad16)));
55 
56   // Dec format
57   EXPECT_EQ("0 115   -1-0001 81985529216486895",
58             absl::Substitute("$0$1$2$3$4 $5",  //
59                              absl::Dec(0), absl::Dec(1, absl::kSpacePad2),
60                              absl::Dec(0xf, absl::kSpacePad2),
61                              absl::Dec(int16_t{-1}, absl::kSpacePad5),
62                              absl::Dec(int16_t{-1}, absl::kZeroPad5),
63                              absl::Dec(0x123456789abcdef, absl::kZeroPad16)));
64 
65   // Pointer.
66   const int* int_p = reinterpret_cast<const int*>(0x12345);
67   std::string str = absl::Substitute("$0", int_p);
68   EXPECT_EQ(absl::StrCat("0x", absl::Hex(int_p)), str);
69 
70   // Volatile Pointer.
71   // Like C++ streamed I/O, such pointers implicitly become bool
72   volatile int vol = 237;
73   volatile int *volatile volptr = &vol;
74   str = absl::Substitute("$0", volptr);
75   EXPECT_EQ("true", str);
76 
77   // null is special. StrCat prints 0x0. Substitute prints NULL.
78   const uint64_t* null_p = nullptr;
79   str = absl::Substitute("$0", null_p);
80   EXPECT_EQ("NULL", str);
81 
82   // char* is also special.
83   const char* char_p = "print me";
84   str = absl::Substitute("$0", char_p);
85   EXPECT_EQ("print me", str);
86 
87   char char_buf[16];
88   strncpy(char_buf, "print me too", sizeof(char_buf));
89   str = absl::Substitute("$0", char_buf);
90   EXPECT_EQ("print me too", str);
91 
92   // null char* is "doubly" special. Represented as the empty string.
93   char_p = nullptr;
94   str = absl::Substitute("$0", char_p);
95   EXPECT_EQ("", str);
96 
97   // Out-of-order.
98   EXPECT_EQ("b, a, c, b", absl::Substitute("$1, $0, $2, $1", "a", "b", "c"));
99 
100   // Literal $
101   EXPECT_EQ("$", absl::Substitute("$$"));
102 
103   EXPECT_EQ("$1", absl::Substitute("$$1"));
104 
105   // Test all overloads.
106   EXPECT_EQ("a", absl::Substitute("$0", "a"));
107   EXPECT_EQ("a b", absl::Substitute("$0 $1", "a", "b"));
108   EXPECT_EQ("a b c", absl::Substitute("$0 $1 $2", "a", "b", "c"));
109   EXPECT_EQ("a b c d", absl::Substitute("$0 $1 $2 $3", "a", "b", "c", "d"));
110   EXPECT_EQ("a b c d e",
111             absl::Substitute("$0 $1 $2 $3 $4", "a", "b", "c", "d", "e"));
112   EXPECT_EQ("a b c d e f", absl::Substitute("$0 $1 $2 $3 $4 $5", "a", "b", "c",
113                                             "d", "e", "f"));
114   EXPECT_EQ("a b c d e f g", absl::Substitute("$0 $1 $2 $3 $4 $5 $6", "a", "b",
115                                               "c", "d", "e", "f", "g"));
116   EXPECT_EQ("a b c d e f g h",
117             absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7", "a", "b", "c", "d", "e",
118                              "f", "g", "h"));
119   EXPECT_EQ("a b c d e f g h i",
120             absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8", "a", "b", "c", "d",
121                              "e", "f", "g", "h", "i"));
122   EXPECT_EQ("a b c d e f g h i j",
123             absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9", "a", "b", "c",
124                              "d", "e", "f", "g", "h", "i", "j"));
125   EXPECT_EQ("a b c d e f g h i j b0",
126             absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $10", "a", "b", "c",
127                              "d", "e", "f", "g", "h", "i", "j"));
128 
129   const char* null_cstring = nullptr;
130   EXPECT_EQ("Text: ''", absl::Substitute("Text: '$0'", null_cstring));
131 }
132 
TEST(SubstituteTest,SubstituteAndAppend)133 TEST(SubstituteTest, SubstituteAndAppend) {
134   std::string str = "Hello";
135   absl::SubstituteAndAppend(&str, ", $0!", "world");
136   EXPECT_EQ("Hello, world!", str);
137 
138   // Test all overloads.
139   str.clear();
140   absl::SubstituteAndAppend(&str, "$0", "a");
141   EXPECT_EQ("a", str);
142   str.clear();
143   absl::SubstituteAndAppend(&str, "$0 $1", "a", "b");
144   EXPECT_EQ("a b", str);
145   str.clear();
146   absl::SubstituteAndAppend(&str, "$0 $1 $2", "a", "b", "c");
147   EXPECT_EQ("a b c", str);
148   str.clear();
149   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3", "a", "b", "c", "d");
150   EXPECT_EQ("a b c d", str);
151   str.clear();
152   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4", "a", "b", "c", "d", "e");
153   EXPECT_EQ("a b c d e", str);
154   str.clear();
155   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5", "a", "b", "c", "d", "e",
156                             "f");
157   EXPECT_EQ("a b c d e f", str);
158   str.clear();
159   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6", "a", "b", "c", "d",
160                             "e", "f", "g");
161   EXPECT_EQ("a b c d e f g", str);
162   str.clear();
163   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6 $7", "a", "b", "c", "d",
164                             "e", "f", "g", "h");
165   EXPECT_EQ("a b c d e f g h", str);
166   str.clear();
167   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6 $7 $8", "a", "b", "c",
168                             "d", "e", "f", "g", "h", "i");
169   EXPECT_EQ("a b c d e f g h i", str);
170   str.clear();
171   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3 $4 $5 $6 $7 $8 $9", "a", "b",
172                             "c", "d", "e", "f", "g", "h", "i", "j");
173   EXPECT_EQ("a b c d e f g h i j", str);
174 }
175 
TEST(SubstituteTest,VectorBoolRef)176 TEST(SubstituteTest, VectorBoolRef) {
177   std::vector<bool> v = {true, false};
178   const auto& cv = v;
179   EXPECT_EQ("true false true false",
180             absl::Substitute("$0 $1 $2 $3", v[0], v[1], cv[0], cv[1]));
181 
182   std::string str = "Logic be like: ";
183   absl::SubstituteAndAppend(&str, "$0 $1 $2 $3", v[0], v[1], cv[0], cv[1]);
184   EXPECT_EQ("Logic be like: true false true false", str);
185 }
186 
TEST(SubstituteTest,Enums)187 TEST(SubstituteTest, Enums) {
188   enum UnscopedEnum { kEnum0 = 0, kEnum1 = 1 };
189   EXPECT_EQ("0 1", absl::Substitute("$0 $1", UnscopedEnum::kEnum0,
190                                     UnscopedEnum::kEnum1));
191 
192   enum class ScopedEnum { kEnum0 = 0, kEnum1 = 1 };
193   EXPECT_EQ("0 1",
194             absl::Substitute("$0 $1", ScopedEnum::kEnum0, ScopedEnum::kEnum1));
195 
196   enum class ScopedEnumInt32 : int32_t { kEnum0 = 989, kEnum1 = INT32_MIN };
197   EXPECT_EQ("989 -2147483648",
198             absl::Substitute("$0 $1", ScopedEnumInt32::kEnum0,
199                              ScopedEnumInt32::kEnum1));
200 
201   enum class ScopedEnumUInt32 : uint32_t { kEnum0 = 1, kEnum1 = UINT32_MAX };
202   EXPECT_EQ("1 4294967295", absl::Substitute("$0 $1", ScopedEnumUInt32::kEnum0,
203                                              ScopedEnumUInt32::kEnum1));
204 
205   enum class ScopedEnumInt64 : int64_t { kEnum0 = -1, kEnum1 = 42949672950 };
206   EXPECT_EQ("-1 42949672950", absl::Substitute("$0 $1", ScopedEnumInt64::kEnum0,
207                                                ScopedEnumInt64::kEnum1));
208 
209   enum class ScopedEnumUInt64 : uint64_t { kEnum0 = 1, kEnum1 = 42949672950 };
210   EXPECT_EQ("1 42949672950", absl::Substitute("$0 $1", ScopedEnumUInt64::kEnum0,
211                                               ScopedEnumUInt64::kEnum1));
212 
213   enum class ScopedEnumChar : signed char { kEnum0 = -1, kEnum1 = 1 };
214   EXPECT_EQ("-1 1", absl::Substitute("$0 $1", ScopedEnumChar::kEnum0,
215                                      ScopedEnumChar::kEnum1));
216 
217   enum class ScopedEnumUChar : unsigned char {
218     kEnum0 = 0,
219     kEnum1 = 1,
220     kEnumMax = 255
221   };
222   EXPECT_EQ("0 1 255", absl::Substitute("$0 $1 $2", ScopedEnumUChar::kEnum0,
223                                         ScopedEnumUChar::kEnum1,
224                                         ScopedEnumUChar::kEnumMax));
225 
226   enum class ScopedEnumInt16 : int16_t { kEnum0 = -100, kEnum1 = 10000 };
227   EXPECT_EQ("-100 10000", absl::Substitute("$0 $1", ScopedEnumInt16::kEnum0,
228                                            ScopedEnumInt16::kEnum1));
229 
230   enum class ScopedEnumUInt16 : uint16_t { kEnum0 = 0, kEnum1 = 10000 };
231   EXPECT_EQ("0 10000", absl::Substitute("$0 $1", ScopedEnumUInt16::kEnum0,
232                                         ScopedEnumUInt16::kEnum1));
233 }
234 
235 #ifdef GTEST_HAS_DEATH_TEST
236 
TEST(SubstituteDeathTest,SubstituteDeath)237 TEST(SubstituteDeathTest, SubstituteDeath) {
238   EXPECT_DEBUG_DEATH(
239       static_cast<void>(absl::Substitute(absl::string_view("-$2"), "a", "b")),
240       "Invalid absl::Substitute\\(\\) format string: asked for \"\\$2\", "
241       "but only 2 args were given.");
242   EXPECT_DEBUG_DEATH(
243       static_cast<void>(absl::Substitute(absl::string_view("-$z-"))),
244       "Invalid absl::Substitute\\(\\) format string: \"-\\$z-\"");
245   EXPECT_DEBUG_DEATH(
246       static_cast<void>(absl::Substitute(absl::string_view("-$"))),
247       "Invalid absl::Substitute\\(\\) format string: \"-\\$\"");
248 }
249 
250 #endif  // GTEST_HAS_DEATH_TEST
251 
252 }  // namespace
253