1 // Copyright (C) 2011-2020 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 #include <config.h>
8
9 #include <exceptions/exceptions.h>
10 #include <util/strutil.h>
11 #include <util/encode/hex.h>
12
13 #include <gtest/gtest.h>
14
15 #include <stdint.h>
16 #include <string>
17
18 using namespace isc;
19 using namespace isc::util;
20 using namespace isc::util::str;
21 using namespace std;
22
23 namespace {
24
25 // Check for slash replacement
26
TEST(StringUtilTest,Slash)27 TEST(StringUtilTest, Slash) {
28
29 string instring = "";
30 isc::util::str::normalizeSlash(instring);
31 EXPECT_EQ("", instring);
32
33 instring = "C:\\A\\B\\C.D";
34 isc::util::str::normalizeSlash(instring);
35 EXPECT_EQ("C:/A/B/C.D", instring);
36
37 instring = "// \\ //";
38 isc::util::str::normalizeSlash(instring);
39 EXPECT_EQ("// / //", instring);
40 }
41
42 // Check that leading and trailing space trimming works
43
TEST(StringUtilTest,Trim)44 TEST(StringUtilTest, Trim) {
45
46 // Empty and full string.
47 EXPECT_EQ("", isc::util::str::trim(""));
48 EXPECT_EQ("abcxyz", isc::util::str::trim("abcxyz"));
49
50 // Trim right-most blanks
51 EXPECT_EQ("ABC", isc::util::str::trim("ABC "));
52 EXPECT_EQ("ABC", isc::util::str::trim("ABC\t\t \n\t"));
53
54 // Left-most blank trimming
55 EXPECT_EQ("XYZ", isc::util::str::trim(" XYZ"));
56 EXPECT_EQ("XYZ", isc::util::str::trim("\t\t \tXYZ"));
57
58 // Right and left, with embedded spaces
59 EXPECT_EQ("MN \t OP", isc::util::str::trim("\t\tMN \t OP \t"));
60 }
61
62 // Check tokenization. Note that ASSERT_EQ is used to check the size of the
63 // returned vector; if not as expected, the following references may be invalid
64 // so should not be used.
65
TEST(StringUtilTest,Tokens)66 TEST(StringUtilTest, Tokens) {
67 vector<string> result;
68
69 // Default delimiters
70
71 // Degenerate cases
72 result = isc::util::str::tokens(""); // Empty string
73 EXPECT_EQ(0, result.size());
74
75 result = isc::util::str::tokens(" \n "); // String is all delimiters
76 EXPECT_EQ(0, result.size());
77
78 result = isc::util::str::tokens("abc"); // String has no delimiters
79 ASSERT_EQ(1, result.size());
80 EXPECT_EQ(string("abc"), result[0]);
81
82 // String containing leading and/or trailing delimiters, no embedded ones.
83 result = isc::util::str::tokens("\txyz"); // One leading delimiter
84 ASSERT_EQ(1, result.size());
85 EXPECT_EQ(string("xyz"), result[0]);
86
87 result = isc::util::str::tokens("\t \nxyz"); // Multiple leading delimiters
88 ASSERT_EQ(1, result.size());
89 EXPECT_EQ(string("xyz"), result[0]);
90
91 result = isc::util::str::tokens("xyz\n"); // One trailing delimiter
92 ASSERT_EQ(1, result.size());
93 EXPECT_EQ(string("xyz"), result[0]);
94
95 result = isc::util::str::tokens("xyz \t"); // Multiple trailing
96 ASSERT_EQ(1, result.size());
97 EXPECT_EQ(string("xyz"), result[0]);
98
99 result = isc::util::str::tokens("\t xyz \n"); // Leading and trailing
100 ASSERT_EQ(1, result.size());
101 EXPECT_EQ(string("xyz"), result[0]);
102
103 // Embedded delimiters
104 result = isc::util::str::tokens("abc\ndef"); // 2 tokens, one separator
105 ASSERT_EQ(2, result.size());
106 EXPECT_EQ(string("abc"), result[0]);
107 EXPECT_EQ(string("def"), result[1]);
108
109 result = isc::util::str::tokens("abc\t\t\ndef"); // 2 tokens, 3 separators
110 ASSERT_EQ(2, result.size());
111 EXPECT_EQ(string("abc"), result[0]);
112 EXPECT_EQ(string("def"), result[1]);
113
114 result = isc::util::str::tokens("abc\n \tdef\t\tghi");
115 ASSERT_EQ(3, result.size()); // Multiple tokens, many delims
116 EXPECT_EQ(string("abc"), result[0]);
117 EXPECT_EQ(string("def"), result[1]);
118 EXPECT_EQ(string("ghi"), result[2]);
119
120 // Embedded and non-embedded delimiters
121
122 result = isc::util::str::tokens("\t\t \nabc\n \tdef\t\tghi \n\n");
123 ASSERT_EQ(3, result.size()); // Multiple tokens, many delims
124 EXPECT_EQ(string("abc"), result[0]);
125 EXPECT_EQ(string("def"), result[1]);
126 EXPECT_EQ(string("ghi"), result[2]);
127
128 // Non-default delimiter
129 result = isc::util::str::tokens("alpha/beta/ /gamma//delta/epsilon/", "/");
130 ASSERT_EQ(6, result.size());
131 EXPECT_EQ(string("alpha"), result[0]);
132 EXPECT_EQ(string("beta"), result[1]);
133 EXPECT_EQ(string(" "), result[2]);
134 EXPECT_EQ(string("gamma"), result[3]);
135 EXPECT_EQ(string("delta"), result[4]);
136 EXPECT_EQ(string("epsilon"), result[5]);
137
138 // Non-default delimiters (plural)
139 result = isc::util::str::tokens("+*--alpha*beta+ -gamma**delta+epsilon-+**",
140 "*+-");
141 ASSERT_EQ(6, result.size());
142 EXPECT_EQ(string("alpha"), result[0]);
143 EXPECT_EQ(string("beta"), result[1]);
144 EXPECT_EQ(string(" "), result[2]);
145 EXPECT_EQ(string("gamma"), result[3]);
146 EXPECT_EQ(string("delta"), result[4]);
147 EXPECT_EQ(string("epsilon"), result[5]);
148
149 // Escaped delimiter
150 result = isc::util::str::tokens("foo\\,bar", ",", true);
151 EXPECT_EQ(1, result.size());
152 EXPECT_EQ(string("foo,bar"), result[0]);
153
154 // Escaped escape
155 result = isc::util::str::tokens("foo\\\\,bar", ",", true);
156 ASSERT_EQ(2, result.size());
157 EXPECT_EQ(string("foo\\"), result[0]);
158 EXPECT_EQ(string("bar"), result[1]);
159
160 // Double escapes
161 result = isc::util::str::tokens("foo\\\\\\\\,\\bar", ",", true);
162 ASSERT_EQ(2, result.size());
163 EXPECT_EQ(string("foo\\\\"), result[0]);
164 EXPECT_EQ(string("\\bar"), result[1]);
165
166 // Escaped standard character
167 result = isc::util::str::tokens("fo\\o,bar", ",", true);
168 ASSERT_EQ(2, result.size());
169 EXPECT_EQ(string("fo\\o"), result[0]);
170 EXPECT_EQ(string("bar"), result[1]);
171
172 // Escape at the end
173 result = isc::util::str::tokens("foo,bar\\", ",", true);
174 ASSERT_EQ(2, result.size());
175 EXPECT_EQ(string("foo"), result[0]);
176 EXPECT_EQ(string("bar\\"), result[1]);
177
178 // Escape opening a token
179 result = isc::util::str::tokens("foo,\\,,bar", ",", true);
180 ASSERT_EQ(3, result.size());
181 EXPECT_EQ(string("foo"), result[0]);
182 EXPECT_EQ(string(","), result[1]);
183 EXPECT_EQ(string("bar"), result[2]);
184 }
185
186 // Changing case
187
TEST(StringUtilTest,ChangeCase)188 TEST(StringUtilTest, ChangeCase) {
189 string mixed("abcDEFghiJKLmno123[]{=+--+]}");
190 string upper("ABCDEFGHIJKLMNO123[]{=+--+]}");
191 string lower("abcdefghijklmno123[]{=+--+]}");
192
193 string test = mixed;
194 isc::util::str::lowercase(test);
195 EXPECT_EQ(lower, test);
196
197 test = mixed;
198 isc::util::str::uppercase(test);
199 EXPECT_EQ(upper, test);
200 }
201
202 // Formatting
203
TEST(StringUtilTest,Formatting)204 TEST(StringUtilTest, Formatting) {
205
206 vector<string> args;
207 args.push_back("arg1");
208 args.push_back("arg2");
209 args.push_back("arg3");
210
211 string format1 = "This is a string with no tokens";
212 EXPECT_EQ(format1, isc::util::str::format(format1, args));
213
214 string format2 = ""; // Empty string
215 EXPECT_EQ(format2, isc::util::str::format(format2, args));
216
217 string format3 = " "; // Empty string
218 EXPECT_EQ(format3, isc::util::str::format(format3, args));
219
220 string format4 = "String with %d non-string tokens %lf";
221 EXPECT_EQ(format4, isc::util::str::format(format4, args));
222
223 string format5 = "String with %s correct %s number of tokens %s";
224 string result5 = "String with arg1 correct arg2 number of tokens arg3";
225 EXPECT_EQ(result5, isc::util::str::format(format5, args));
226
227 string format6 = "String with %s too %s few tokens";
228 string result6 = "String with arg1 too arg2 few tokens";
229 EXPECT_EQ(result6, isc::util::str::format(format6, args));
230
231 string format7 = "String with %s too %s many %s tokens %s !";
232 string result7 = "String with arg1 too arg2 many arg3 tokens %s !";
233 EXPECT_EQ(result7, isc::util::str::format(format7, args));
234
235 string format8 = "String with embedded%s%s%stokens";
236 string result8 = "String with embeddedarg1arg2arg3tokens";
237 EXPECT_EQ(result8, isc::util::str::format(format8, args));
238
239 // Handle an empty vector
240 args.clear();
241 string format9 = "%s %s";
242 EXPECT_EQ(format9, isc::util::str::format(format9, args));
243 }
244
TEST(StringUtilTest,getToken)245 TEST(StringUtilTest, getToken) {
246 string s("a b c");
247 istringstream ss(s);
248 EXPECT_EQ("a", isc::util::str::getToken(ss));
249 EXPECT_EQ("b", isc::util::str::getToken(ss));
250 EXPECT_EQ("c", isc::util::str::getToken(ss));
251 EXPECT_THROW(isc::util::str::getToken(ss), isc::util::str::StringTokenError);
252 }
253
tokenToNumCall_32_16(const string & token)254 int32_t tokenToNumCall_32_16(const string& token) {
255 return isc::util::str::tokenToNum<int32_t, 16>(token);
256 }
257
tokenToNumCall_16_8(const string & token)258 int16_t tokenToNumCall_16_8(const string& token) {
259 return isc::util::str::tokenToNum<int16_t, 8>(token);
260 }
261
TEST(StringUtilTest,tokenToNum)262 TEST(StringUtilTest, tokenToNum) {
263 uint32_t num32 = tokenToNumCall_32_16("0");
264 EXPECT_EQ(0, num32);
265 num32 = tokenToNumCall_32_16("123");
266 EXPECT_EQ(123, num32);
267 num32 = tokenToNumCall_32_16("65535");
268 EXPECT_EQ(65535, num32);
269
270 EXPECT_THROW(tokenToNumCall_32_16(""),
271 isc::util::str::StringTokenError);
272 EXPECT_THROW(tokenToNumCall_32_16("a"),
273 isc::util::str::StringTokenError);
274 EXPECT_THROW(tokenToNumCall_32_16("-1"),
275 isc::util::str::StringTokenError);
276 EXPECT_THROW(tokenToNumCall_32_16("65536"),
277 isc::util::str::StringTokenError);
278 EXPECT_THROW(tokenToNumCall_32_16("1234567890"),
279 isc::util::str::StringTokenError);
280 EXPECT_THROW(tokenToNumCall_32_16("-1234567890"),
281 isc::util::str::StringTokenError);
282
283 uint16_t num16 = tokenToNumCall_16_8("123");
284 EXPECT_EQ(123, num16);
285 num16 = tokenToNumCall_16_8("0");
286 EXPECT_EQ(0, num16);
287 num16 = tokenToNumCall_16_8("255");
288 EXPECT_EQ(255, num16);
289
290 EXPECT_THROW(tokenToNumCall_16_8(""),
291 isc::util::str::StringTokenError);
292 EXPECT_THROW(tokenToNumCall_16_8("a"),
293 isc::util::str::StringTokenError);
294 EXPECT_THROW(tokenToNumCall_16_8("-1"),
295 isc::util::str::StringTokenError);
296 EXPECT_THROW(tokenToNumCall_16_8("256"),
297 isc::util::str::StringTokenError);
298 EXPECT_THROW(tokenToNumCall_16_8("1234567890"),
299 isc::util::str::StringTokenError);
300 EXPECT_THROW(tokenToNumCall_16_8("-1234567890"),
301 isc::util::str::StringTokenError);
302
303 }
304
305 /// @brief Convenience function which calls quotedStringToBinary
306 /// and converts returned vector back to string.
307 ///
308 /// @param s Input string.
309 /// @return String holding a copy of a vector returned by the
310 /// quotedStringToBinary.
testQuoted(const std::string & s)311 std::string testQuoted(const std::string& s) {
312 std::vector<uint8_t> vec = str::quotedStringToBinary(s);
313 std::string s2(vec.begin(), vec.end());
314 return (s2);
315 }
316
TEST(StringUtilTest,quotedStringToBinary)317 TEST(StringUtilTest, quotedStringToBinary) {
318 // No opening or closing quote should result in empty string.
319 EXPECT_TRUE(str::quotedStringToBinary("'").empty());
320 EXPECT_TRUE(str::quotedStringToBinary("").empty());
321 EXPECT_TRUE(str::quotedStringToBinary(" ").empty());
322 EXPECT_TRUE(str::quotedStringToBinary("'circuit id").empty());
323 EXPECT_TRUE(str::quotedStringToBinary("circuit id'").empty());
324
325 // If there is only opening and closing quote, an empty
326 // vector should be returned.
327 EXPECT_TRUE(str::quotedStringToBinary("''").empty());
328
329 // Both opening and ending quote is present.
330 EXPECT_EQ("circuit id", testQuoted("'circuit id'"));
331 EXPECT_EQ("remote id", testQuoted(" ' remote id'"));
332 EXPECT_EQ("duid", testQuoted(" ' duid'"));
333 EXPECT_EQ("duid", testQuoted("'duid ' "));
334 EXPECT_EQ("remote'id", testQuoted(" ' remote'id '"));
335 EXPECT_EQ("remote id'", testQuoted("'remote id''"));
336 EXPECT_EQ("'remote id", testQuoted("''remote id'"));
337
338 // Multiple quotes.
339 EXPECT_EQ("'", testQuoted("'''"));
340 EXPECT_EQ("''", testQuoted("''''"));
341 }
342
343 /// @brief Test that hex string with colons can be decoded.
344 ///
345 /// @param input Input string to be decoded.
346 /// @param reference A string without colons representing the
347 /// decoded data.
testColonSeparated(const std::string & input,const std::string & reference)348 void testColonSeparated(const std::string& input,
349 const std::string& reference) {
350 // Create a reference vector.
351 std::vector<uint8_t> reference_vector;
352 ASSERT_NO_THROW(encode::decodeHex(reference, reference_vector));
353
354 // Fill the output vector with some garbage to make sure that
355 // the data is erased when a string is decoded successfully.
356 std::vector<uint8_t> decoded(1, 10);
357 ASSERT_NO_THROW(decodeColonSeparatedHexString(input, decoded));
358
359 // Get the string representation of the decoded data for logging
360 // purposes.
361 std::string encoded;
362 ASSERT_NO_THROW(encoded = encode::encodeHex(decoded));
363
364 // Check if the decoded data matches the reference.
365 EXPECT_TRUE(decoded == reference_vector)
366 << "decoded data don't match the reference, input='"
367 << input << "', reference='" << reference << "'"
368 ", decoded='" << encoded << "'";
369 }
370
TEST(StringUtilTest,decodeColonSeparatedHexString)371 TEST(StringUtilTest, decodeColonSeparatedHexString) {
372 // Test valid strings.
373 testColonSeparated("A1:02:C3:d4:e5:F6", "A102C3D4E5F6");
374 testColonSeparated("A:02:3:d:E5:F6", "0A02030DE5F6");
375 testColonSeparated("A:B:C:D", "0A0B0C0D");
376 testColonSeparated("1", "01");
377 testColonSeparated("1e", "1E");
378 testColonSeparated("", "");
379
380 // Test invalid strings.
381 std::vector<uint8_t> decoded;
382 // Whitespaces.
383 EXPECT_THROW(decodeColonSeparatedHexString(" ", decoded),
384 isc::BadValue);
385 // Whitespace before digits.
386 EXPECT_THROW(decodeColonSeparatedHexString(" A1", decoded),
387 isc::BadValue);
388 // Two consecutive colons.
389 EXPECT_THROW(decodeColonSeparatedHexString("A::01", decoded),
390 isc::BadValue);
391 // Three consecutive colons.
392 EXPECT_THROW(decodeColonSeparatedHexString("A:::01", decoded),
393 isc::BadValue);
394 // Whitespace within a string.
395 EXPECT_THROW(decodeColonSeparatedHexString("A :01", decoded),
396 isc::BadValue);
397 // Terminating colon.
398 EXPECT_THROW(decodeColonSeparatedHexString("0A:01:", decoded),
399 isc::BadValue);
400 // Opening colon.
401 EXPECT_THROW(decodeColonSeparatedHexString(":0A:01", decoded),
402 isc::BadValue);
403 // Three digits before the colon.
404 EXPECT_THROW(decodeColonSeparatedHexString("0A1:B1", decoded),
405 isc::BadValue);
406 }
407
testFormatted(const std::string & input,const std::string & reference)408 void testFormatted(const std::string& input,
409 const std::string& reference) {
410 // Create a reference vector.
411 std::vector<uint8_t> reference_vector;
412 ASSERT_NO_THROW(encode::decodeHex(reference, reference_vector));
413
414 // Fill the output vector with some garbage to make sure that
415 // the data is erased when a string is decoded successfully.
416 std::vector<uint8_t> decoded(1, 10);
417 ASSERT_NO_THROW(decodeFormattedHexString(input, decoded));
418
419 // Get the string representation of the decoded data for logging
420 // purposes.
421 std::string encoded;
422 ASSERT_NO_THROW(encoded = encode::encodeHex(decoded));
423
424 // Check if the decoded data matches the reference.
425 EXPECT_TRUE(decoded == reference_vector)
426 << "decoded data don't match the reference, input='"
427 << input << "', reference='" << reference << "'"
428 ", decoded='" << encoded << "'";
429 }
430
TEST(StringUtilTest,decodeFormattedHexString)431 TEST(StringUtilTest, decodeFormattedHexString) {
432 // Colon separated.
433 testFormatted("1:A7:B5:4:23", "01A7B50423");
434 // Space separated.
435 testFormatted("1 A7 B5 4 23", "01A7B50423");
436 // No colons, even number of digits.
437 testFormatted("17a534", "17A534");
438 // Odd number of digits.
439 testFormatted("A3A6f78", "0A3A6F78");
440 // '0x' prefix.
441 testFormatted("0xA3A6f78", "0A3A6F78");
442 // '0x' prefix with a special value of 0.
443 testFormatted("0x0", "00");
444 // Empty string.
445 testFormatted("", "");
446
447 std::vector<uint8_t> decoded;
448 // Dangling colon.
449 EXPECT_THROW(decodeFormattedHexString("0a:", decoded),
450 isc::BadValue);
451 // Dangling space.
452 EXPECT_THROW(decodeFormattedHexString("0a ", decoded),
453 isc::BadValue);
454 // '0x' prefix and spaces.
455 EXPECT_THROW(decodeFormattedHexString("x01 02", decoded),
456 isc::BadValue);
457 // '0x' prefix and colons.
458 EXPECT_THROW(decodeFormattedHexString("0x01:02", decoded),
459 isc::BadValue);
460 // colon and spaces mixed
461 EXPECT_THROW(decodeFormattedHexString("01:02 03", decoded),
462 isc::BadValue);
463 // Missing colon.
464 EXPECT_THROW(decodeFormattedHexString("01:0203", decoded),
465 isc::BadValue);
466 // Missing space.
467 EXPECT_THROW(decodeFormattedHexString("01 0203", decoded),
468 isc::BadValue);
469 // Invalid prefix.
470 EXPECT_THROW(decodeFormattedHexString("x0102", decoded),
471 isc::BadValue);
472 // Invalid prefix again.
473 EXPECT_THROW(decodeFormattedHexString("1x0102", decoded),
474 isc::BadValue);
475 }
476
477 /// @brief Function used to test StringSantitizer
478 /// @param original - string to sanitize
479 /// @param char_set - regular expression string describing invalid
480 /// characters
481 /// @param char_replacement - character(s) which replace invalid
482 /// characters
483 /// @param expected - expected sanitized string
sanitizeStringTest(const std::string & original,const std::string & char_set,const std::string & char_replacement,const std::string & expected)484 void sanitizeStringTest(
485 const std::string& original,
486 const std::string& char_set,
487 const std::string& char_replacement,
488 const std::string& expected) {
489
490 StringSanitizerPtr ss;
491 std::string sanitized;
492
493 try {
494 ss.reset(new StringSanitizer(char_set, char_replacement));
495 } catch (const std::exception& ex) {
496 ADD_FAILURE() << "Could not construct sanitizer:" << ex.what();
497 return;
498 }
499
500 try {
501 sanitized = ss->scrub(original);
502 } catch (const std::exception& ex) {
503 ADD_FAILURE() << "Could not scrub string:" << ex.what();
504 return;
505 }
506
507 EXPECT_EQ(sanitized, expected);
508 }
509
510 // Verifies StringSantizer class
TEST(StringUtilTest,stringSanitizer)511 TEST(StringUtilTest, stringSanitizer) {
512 // Bad regular expression should throw.
513 StringSanitizerPtr ss;
514 ASSERT_THROW(ss.reset(new StringSanitizer("[bogus-regex","")), BadValue);
515
516 std::string good_data(StringSanitizer::MAX_DATA_SIZE, '0');
517 std::string bad_data(StringSanitizer::MAX_DATA_SIZE + 1, '0');
518
519 ASSERT_NO_THROW(ss.reset(new StringSanitizer(good_data, good_data)));
520
521 ASSERT_THROW(ss.reset(new StringSanitizer(bad_data, "")), BadValue);
522 ASSERT_THROW(ss.reset(new StringSanitizer("", bad_data)), BadValue);
523
524 // List of invalid chars should work: (b,c,2 are invalid)
525 sanitizeStringTest("abc.123", "[b-c2]", "*",
526 "a**.1*3");
527 // Inverted list of valid chars should work: (b,c,2 are valid)
528 sanitizeStringTest("abc.123", "[^b-c2]", "*",
529 "*bc**2*");
530
531 // A string of all valid chars should return an identical string.
532 sanitizeStringTest("-_A--B__Cabc34567_-", "[^A-Ca-c3-7_-]", "x",
533 "-_A--B__Cabc34567_-");
534
535 // Replacing with a character should work.
536 sanitizeStringTest("A[b]c\12JoE3-_x!B$Y#e", "[^A-Za-z0-9_]", "*",
537 "A*b*c*JoE3*_x*B*Y*e");
538
539 // Removing (i.e.replacing with an "empty" string) should work.
540 sanitizeStringTest("A[b]c\12JoE3-_x!B$Y#e", "[^A-Za-z0-9_]", "",
541 "AbcJoE3_xBYe");
542
543 // More than one non-matching in a row should work.
544 sanitizeStringTest("%%A%%B%%C%%", "[^A-Za-z0-9_]", "x",
545 "xxAxxBxxCxx");
546
547 // Removing more than one non-matching in a row should work.
548 sanitizeStringTest("%%A%%B%%C%%", "[^A-Za-z0-9_]", "",
549 "ABC");
550
551 // Replacing with a string should work.
552 sanitizeStringTest("%%A%%B%%C%%", "[^A-Za-z0-9_]", "xyz",
553 "xyzxyzAxyzxyzBxyzxyzCxyzxyz");
554
555 // Dots as valid chars work.
556 sanitizeStringTest("abc.123", "[^A-Za-z0-9_.]", "*",
557 "abc.123");
558
559 std::string withNulls("\000ab\000c.12\0003",10);
560 sanitizeStringTest(withNulls, "[^A-Za-z0-9_.]", "*",
561 "*ab*c.12*3");
562 }
563
564 // Verifies templated buffer iterator seekTrimmed() function
TEST(StringUtilTest,seekTrimmed)565 TEST(StringUtilTest, seekTrimmed) {
566
567 // Empty buffer should be fine.
568 std::vector<uint8_t> buffer;
569 auto begin = buffer.end();
570 auto end = buffer.end();
571 ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
572 EXPECT_EQ(0, std::distance(begin, end));
573
574 // Buffer of only trim values, should be fine.
575 buffer = { 1, 1 };
576 begin = buffer.begin();
577 end = buffer.end();
578 ASSERT_NO_THROW(end = seekTrimmed(begin, end, 1));
579 EXPECT_EQ(0, std::distance(begin, end));
580
581 // One trailing null should trim off.
582 buffer = {'o', 'n', 'e', 0 };
583 begin = buffer.begin();
584 end = buffer.end();
585 ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
586 EXPECT_EQ(3, std::distance(begin, end));
587
588 // More than one trailing null should trim off.
589 buffer = { 't', 'h', 'r', 'e', 'e', 0, 0, 0 };
590 begin = buffer.begin();
591 end = buffer.end();
592 ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
593 EXPECT_EQ(5, std::distance(begin, end));
594
595 // Embedded null should be left in place.
596 buffer = { 'e', 'm', 0, 'b', 'e', 'd' };
597 begin = buffer.begin();
598 end = buffer.end();
599 ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
600 EXPECT_EQ(6, std::distance(begin, end));
601
602 // Leading null should be left in place.
603 buffer = { 0, 'l', 'e', 'a', 'd', 'i', 'n', 'g' };
604 begin = buffer.begin();
605 end = buffer.end();
606 ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
607 EXPECT_EQ(8, std::distance(begin, end));
608 }
609
610 // Verifies isPrintable predicate on strings.
TEST(StringUtilTest,stringIsPrintable)611 TEST(StringUtilTest, stringIsPrintable) {
612 string content;
613
614 // Empty is printable.
615 EXPECT_TRUE(isPrintable(content));
616
617 // Check Abcd.
618 content = "Abcd";
619 EXPECT_TRUE(isPrintable(content));
620
621 // Add a control character (not printable).
622 content += "\a";
623 EXPECT_FALSE(isPrintable(content));
624 }
625
626 // Verifies isPrintable predicate on byte vectors.
TEST(StringUtilTest,vectorIsPrintable)627 TEST(StringUtilTest, vectorIsPrintable) {
628 vector<uint8_t> content;
629
630 // Empty is printable.
631 EXPECT_TRUE(isPrintable(content));
632
633 // Check Abcd.
634 content = { 0x41, 0x62, 0x63, 0x64 };
635 EXPECT_TRUE(isPrintable(content));
636
637 // Add a control character (not printable).
638 content.push_back('\a');
639 EXPECT_FALSE(isPrintable(content));
640 }
641
642 } // end of anonymous namespace
643