Copy //third_party/quic string libraries to //third_party/quiche * quic_str_cat_lib -> quiche_str_cat_lib * quic_string_piece_lib -> quiche_string_piece_lib * quic_text_utils -> quiche_text_utils To keep CLs small, a series of followup CLs will modify consumers of these libraries to use the quiche variant. A final followup CL will remove the originals from //third_party/quic. The motivation is to expose base64 functions to our HTTPSSVC parsing library, which will eventually land in //third_party and be shared with Chromium via //third_party/quiche. PiperOrigin-RevId: 284975905 Change-Id: I78d0b65f7a3afb5613d8f9de1c98b4e3bfd9ed8e
diff --git a/common/platform/api/quiche_str_cat.h b/common/platform/api/quiche_str_cat.h new file mode 100644 index 0000000..36d054f --- /dev/null +++ b/common/platform/api/quiche_str_cat.h
@@ -0,0 +1,28 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_ + +#include <string> +#include <utility> + +#include "net/quiche/common/platform/impl/quiche_str_cat_impl.h" + +namespace quiche { + +// Merges given strings or numbers with no delimiter. +template <typename... Args> +inline std::string QuicheStrCat(const Args&... args) { + return quiche::QuicheStrCatImpl(std::forward<const Args&>(args)...); +} + +template <typename... Args> +inline std::string QuicheStringPrintf(const Args&... args) { + return QuicheStringPrintfImpl(std::forward<const Args&>(args)...); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_STR_CAT_H_
diff --git a/common/platform/api/quiche_str_cat_test.cc b/common/platform/api/quiche_str_cat_test.cc new file mode 100644 index 0000000..7085b8a --- /dev/null +++ b/common/platform/api/quiche_str_cat_test.cc
@@ -0,0 +1,169 @@ +// Copyright (c) 2016 The Chromium 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 "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h" + +#include <string> + +#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_test.h" + +namespace quiche { +namespace test { +namespace { + +class QuicheStrCatTest : public QuicheTest {}; + +TEST_F(QuicheStrCatTest, Ints) { + const int16_t s = -1; + const uint16_t us = 2; + const int i = -3; + const uint32_t ui = 4; + const int64_t l = -5; + const uint64_t ul = 6; + const ptrdiff_t ptrdiff = -7; + const size_t size = 8; + const intptr_t intptr = -9; + const uintptr_t uintptr = 10; + std::string answer; + answer = QuicheStrCat(s, us); + EXPECT_EQ(answer, "-12"); + answer = QuicheStrCat(i, ui); + EXPECT_EQ(answer, "-34"); + answer = QuicheStrCat(l, ul); + EXPECT_EQ(answer, "-56"); + answer = QuicheStrCat(ptrdiff, size); + EXPECT_EQ(answer, "-78"); + answer = QuicheStrCat(size, intptr); + EXPECT_EQ(answer, "8-9"); + answer = QuicheStrCat(uintptr, 0); + EXPECT_EQ(answer, "100"); +} + +TEST_F(QuicheStrCatTest, Basics) { + std::string result; + + std::string strs[] = {"Hello", "Cruel", "World"}; + + QuicheStringPiece pieces[] = {"Hello", "Cruel", "World"}; + + const char* c_strs[] = {"Hello", "Cruel", "World"}; + + int32_t i32s[] = {'H', 'C', 'W'}; + uint64_t ui64s[] = {12345678910LL, 10987654321LL}; + + result = QuicheStrCat(false, true, 2, 3); + EXPECT_EQ(result, "0123"); + + result = QuicheStrCat(-1); + EXPECT_EQ(result, "-1"); + + result = QuicheStrCat(0.5); + EXPECT_EQ(result, "0.5"); + + result = QuicheStrCat(strs[1], pieces[2]); + EXPECT_EQ(result, "CruelWorld"); + + result = QuicheStrCat(strs[0], ", ", pieces[2]); + EXPECT_EQ(result, "Hello, World"); + + result = QuicheStrCat(strs[0], ", ", strs[1], " ", strs[2], "!"); + EXPECT_EQ(result, "Hello, Cruel World!"); + + result = QuicheStrCat(pieces[0], ", ", pieces[1], " ", pieces[2]); + EXPECT_EQ(result, "Hello, Cruel World"); + + result = QuicheStrCat(c_strs[0], ", ", c_strs[1], " ", c_strs[2]); + EXPECT_EQ(result, "Hello, Cruel World"); + + result = QuicheStrCat("ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!"); + EXPECT_EQ(result, "ASCII 72, 67 87!"); + + result = QuicheStrCat(ui64s[0], ", ", ui64s[1], "!"); + EXPECT_EQ(result, "12345678910, 10987654321!"); + + std::string one = "1"; + result = QuicheStrCat("And a ", one.size(), " and a ", + &result[2] - &result[0], " and a ", one, " 2 3 4", "!"); + EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!"); + + result = + QuicheStrCat("To output a char by ASCII/numeric value, use +: ", '!' + 0); + EXPECT_EQ(result, "To output a char by ASCII/numeric value, use +: 33"); + + float f = 10000.5; + result = QuicheStrCat("Ten K and a half is ", f); + EXPECT_EQ(result, "Ten K and a half is 10000.5"); + + double d = 99999.9; + result = QuicheStrCat("This double number is ", d); + EXPECT_EQ(result, "This double number is 99999.9"); + + result = QuicheStrCat(1, 22, 333, 4444, 55555, 666666, 7777777, 88888888, + 999999999); + EXPECT_EQ(result, "122333444455555666666777777788888888999999999"); +} + +TEST_F(QuicheStrCatTest, MaxArgs) { + std::string result; + // Test 10 up to 26 arguments, the current maximum + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a"); + EXPECT_EQ(result, "123456789a"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b"); + EXPECT_EQ(result, "123456789ab"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c"); + EXPECT_EQ(result, "123456789abc"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d"); + EXPECT_EQ(result, "123456789abcd"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e"); + EXPECT_EQ(result, "123456789abcde"); + result = + QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"); + EXPECT_EQ(result, "123456789abcdef"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g"); + EXPECT_EQ(result, "123456789abcdefg"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h"); + EXPECT_EQ(result, "123456789abcdefgh"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i"); + EXPECT_EQ(result, "123456789abcdefghi"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j"); + EXPECT_EQ(result, "123456789abcdefghij"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k"); + EXPECT_EQ(result, "123456789abcdefghijk"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l"); + EXPECT_EQ(result, "123456789abcdefghijkl"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m"); + EXPECT_EQ(result, "123456789abcdefghijklm"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n"); + EXPECT_EQ(result, "123456789abcdefghijklmn"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", "o"); + EXPECT_EQ(result, "123456789abcdefghijklmno"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"); + EXPECT_EQ(result, "123456789abcdefghijklmnop"); + result = QuicheStrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q"); + EXPECT_EQ(result, "123456789abcdefghijklmnopq"); + // No limit thanks to C++11's variadic templates + result = QuicheStrCat( + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c", "d", "e", "f", "g", "h", + "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", + "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", + "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"); + EXPECT_EQ(result, + "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); +} + +} // namespace +} // namespace test +} // namespace quiche
diff --git a/common/platform/api/quiche_string_piece.h b/common/platform/api/quiche_string_piece.h new file mode 100644 index 0000000..9def942 --- /dev/null +++ b/common/platform/api/quiche_string_piece.h
@@ -0,0 +1,16 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_ + +#include "net/quiche/common/platform/impl/quiche_string_piece_impl.h" + +namespace quiche { + +using QuicheStringPiece = quiche::QuicheStringPieceImpl; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
diff --git a/common/platform/api/quiche_text_utils.h b/common/platform/api/quiche_text_utils.h new file mode 100644 index 0000000..c58c676 --- /dev/null +++ b/common/platform/api/quiche_text_utils.h
@@ -0,0 +1,133 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_ + +#include <string> + +#include "net/third_party/quiche/src/common/platform/api/quiche_export.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" +#include "net/quiche/common/platform/impl/quiche_text_utils_impl.h" + +namespace quiche { + +// Various utilities for manipulating text. +class QUICHE_EXPORT QuicheTextUtils { + public: + // Returns true if |data| starts with |prefix|, case sensitively. + static bool StartsWith(quiche::QuicheStringPiece data, + quiche::QuicheStringPiece prefix) { + return quiche::QuicheTextUtilsImpl::StartsWith(data, prefix); + } + + // Returns true if |data| ends with |suffix|, case insensitively. + static bool EndsWithIgnoreCase(quiche::QuicheStringPiece data, + quiche::QuicheStringPiece suffix) { + return quiche::QuicheTextUtilsImpl::EndsWithIgnoreCase(data, suffix); + } + + // Returns a new string in which |data| has been converted to lower case. + static std::string ToLower(quiche::QuicheStringPiece data) { + return quiche::QuicheTextUtilsImpl::ToLower(data); + } + + // Removes leading and trailing whitespace from |data|. + static void RemoveLeadingAndTrailingWhitespace( + quiche::QuicheStringPiece* data) { + quiche::QuicheTextUtilsImpl::RemoveLeadingAndTrailingWhitespace(data); + } + + // Returns true if |in| represents a valid uint64, and stores that value in + // |out|. + static bool StringToUint64(quiche::QuicheStringPiece in, uint64_t* out) { + return quiche::QuicheTextUtilsImpl::StringToUint64(in, out); + } + + // Returns true if |in| represents a valid int, and stores that value in + // |out|. + static bool StringToInt(quiche::QuicheStringPiece in, int* out) { + return quiche::QuicheTextUtilsImpl::StringToInt(in, out); + } + + // Returns true if |in| represents a valid uint32, and stores that value in + // |out|. + static bool StringToUint32(quiche::QuicheStringPiece in, uint32_t* out) { + return quiche::QuicheTextUtilsImpl::StringToUint32(in, out); + } + + // Returns true if |in| represents a valid size_t, and stores that value in + // |out|. + static bool StringToSizeT(quiche::QuicheStringPiece in, size_t* out) { + return quiche::QuicheTextUtilsImpl::StringToSizeT(in, out); + } + + // Returns a new string representing |in|. + static std::string Uint64ToString(uint64_t in) { + return quiche::QuicheTextUtilsImpl::Uint64ToString(in); + } + + // This converts |length| bytes of binary to a 2*|length|-character + // hexadecimal representation. + // Return value: 2*|length| characters of ASCII string. + static std::string HexEncode(const char* data, size_t length) { + return HexEncode(quiche::QuicheStringPiece(data, length)); + } + + // This converts |data.length()| bytes of binary to a + // 2*|data.length()|-character hexadecimal representation. + // Return value: 2*|data.length()| characters of ASCII string. + static std::string HexEncode(quiche::QuicheStringPiece data) { + return quiche::QuicheTextUtilsImpl::HexEncode(data); + } + + // This converts a uint32 into an 8-character hexidecimal + // representation. Return value: 8 characters of ASCII string. + static std::string Hex(uint32_t v) { + return quiche::QuicheTextUtilsImpl::Hex(v); + } + + // Converts |data| from a hexadecimal ASCII string to a binary string + // that is |data.length()/2| bytes long. + static std::string HexDecode(quiche::QuicheStringPiece data) { + return quiche::QuicheTextUtilsImpl::HexDecode(data); + } + + // Base64 encodes with no padding |data_len| bytes of |data| into |output|. + static void Base64Encode(const uint8_t* data, + size_t data_len, + std::string* output) { + return quiche::QuicheTextUtilsImpl::Base64Encode(data, data_len, output); + } + + // Returns a string containing hex and ASCII representations of |binary|, + // side-by-side in the style of hexdump. Non-printable characters will be + // printed as '.' in the ASCII output. + // For example, given the input "Hello, QUIC!\01\02\03\04", returns: + // "0x0000: 4865 6c6c 6f2c 2051 5549 4321 0102 0304 Hello,.QUIC!...." + static std::string HexDump(quiche::QuicheStringPiece binary_data) { + return quiche::QuicheTextUtilsImpl::HexDump(binary_data); + } + + // Returns true if |data| contains any uppercase characters. + static bool ContainsUpperCase(quiche::QuicheStringPiece data) { + return quiche::QuicheTextUtilsImpl::ContainsUpperCase(data); + } + + // Returns true if |data| contains only decimal digits. + static bool IsAllDigits(quiche::QuicheStringPiece data) { + return quiche::QuicheTextUtilsImpl::IsAllDigits(data); + } + + // Splits |data| into a vector of pieces delimited by |delim|. + static std::vector<quiche::QuicheStringPiece> Split( + quiche::QuicheStringPiece data, + char delim) { + return quiche::QuicheTextUtilsImpl::Split(data, delim); + } +}; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEXT_UTILS_H_
diff --git a/common/platform/api/quiche_text_utils_test.cc b/common/platform/api/quiche_text_utils_test.cc new file mode 100644 index 0000000..1ca75d2 --- /dev/null +++ b/common/platform/api/quiche_text_utils_test.cc
@@ -0,0 +1,231 @@ +// Copyright 2016 The Chromium 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 "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h" + +#include <string> + +#include "net/third_party/quiche/src/common/platform/api/quiche_test.h" + +namespace quiche { +namespace test { + +class QuicheTextUtilsTest : public QuicheTest {}; + +TEST_F(QuicheTextUtilsTest, StartsWith) { + EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith("hello world", "hello")); + EXPECT_TRUE( + quiche::QuicheTextUtils::StartsWith("hello world", "hello world")); + EXPECT_TRUE(quiche::QuicheTextUtils::StartsWith("hello world", "")); + EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "Hello")); + EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "world")); + EXPECT_FALSE(quiche::QuicheTextUtils::StartsWith("hello world", "bar")); +} + +TEST_F(QuicheTextUtilsTest, EndsWithIgnoreCase) { + EXPECT_TRUE( + quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "world")); + EXPECT_TRUE(quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", + "hello world")); + EXPECT_TRUE(quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "")); + EXPECT_TRUE( + quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "WORLD")); + EXPECT_FALSE( + quiche::QuicheTextUtils::EndsWithIgnoreCase("hello world", "hello")); +} + +TEST_F(QuicheTextUtilsTest, ToLower) { + EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("LOWER")); + EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lower")); + EXPECT_EQ("lower", quiche::QuicheTextUtils::ToLower("lOwEr")); + EXPECT_EQ("123", quiche::QuicheTextUtils::ToLower("123")); + EXPECT_EQ("", quiche::QuicheTextUtils::ToLower("")); +} + +TEST_F(QuicheTextUtilsTest, RemoveLeadingAndTrailingWhitespace) { + std::string input; + + for (auto* input : {"text", " text", " text", "text ", "text ", " text ", + " text ", "\r\n\ttext", "text\n\r\t"}) { + quiche::QuicheStringPiece piece(input); + quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&piece); + EXPECT_EQ("text", piece); + } +} + +TEST_F(QuicheTextUtilsTest, StringToNumbers) { + const std::string kMaxInt32Plus1 = "2147483648"; + const std::string kMinInt32Minus1 = "-2147483649"; + const std::string kMaxUint32Plus1 = "4294967296"; + + { + // StringToUint64 + uint64_t uint64_val = 0; + EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint64("123", &uint64_val)); + EXPECT_EQ(123u, uint64_val); + EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint64("1234", &uint64_val)); + EXPECT_EQ(1234u, uint64_val); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint64("", &uint64_val)); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint64("-123", &uint64_val)); + EXPECT_FALSE( + quiche::QuicheTextUtils::StringToUint64("-123.0", &uint64_val)); + EXPECT_TRUE( + quiche::QuicheTextUtils::StringToUint64(kMaxUint32Plus1, &uint64_val)); + EXPECT_EQ(4294967296u, uint64_val); + } + + { + // StringToint + int int_val = 0; + EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("123", &int_val)); + EXPECT_EQ(123, int_val); + EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("1234", &int_val)); + EXPECT_EQ(1234, int_val); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToInt("", &int_val)); + EXPECT_TRUE(quiche::QuicheTextUtils::StringToInt("-123", &int_val)); + EXPECT_EQ(-123, int_val); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToInt("-123.0", &int_val)); + if (sizeof(int) > 4) { + EXPECT_TRUE( + quiche::QuicheTextUtils::StringToInt(kMinInt32Minus1, &int_val)); + EXPECT_EQ(-2147483649ll, int_val); + EXPECT_TRUE( + quiche::QuicheTextUtils::StringToInt(kMaxInt32Plus1, &int_val)); + EXPECT_EQ(2147483648ll, int_val); + } else { + EXPECT_FALSE( + quiche::QuicheTextUtils::StringToInt(kMinInt32Minus1, &int_val)); + EXPECT_FALSE( + quiche::QuicheTextUtils::StringToInt(kMaxInt32Plus1, &int_val)); + } + } + + { + // StringToUint32 + uint32_t uint32_val = 0; + EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint32("123", &uint32_val)); + EXPECT_EQ(123u, uint32_val); + EXPECT_TRUE(quiche::QuicheTextUtils::StringToUint32("1234", &uint32_val)); + EXPECT_EQ(1234u, uint32_val); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint32("", &uint32_val)); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToUint32("-123", &uint32_val)); + EXPECT_FALSE( + quiche::QuicheTextUtils::StringToUint32("-123.0", &uint32_val)); + EXPECT_FALSE( + quiche::QuicheTextUtils::StringToUint32(kMaxUint32Plus1, &uint32_val)); + } + + { + // StringToSizeT + size_t size_t_val = 0; + EXPECT_TRUE(quiche::QuicheTextUtils::StringToSizeT("123", &size_t_val)); + EXPECT_EQ(123u, size_t_val); + EXPECT_TRUE(quiche::QuicheTextUtils::StringToSizeT("1234", &size_t_val)); + EXPECT_EQ(1234u, size_t_val); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("", &size_t_val)); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("-123", &size_t_val)); + EXPECT_FALSE(quiche::QuicheTextUtils::StringToSizeT("-123.0", &size_t_val)); + if (sizeof(size_t) > 4) { + EXPECT_TRUE( + quiche::QuicheTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val)); + EXPECT_EQ(4294967296ull, size_t_val); + } else { + EXPECT_FALSE( + quiche::QuicheTextUtils::StringToSizeT(kMaxUint32Plus1, &size_t_val)); + } + } +} + +TEST_F(QuicheTextUtilsTest, Uint64ToString) { + EXPECT_EQ("123", quiche::QuicheTextUtils::Uint64ToString(123)); + EXPECT_EQ("1234", quiche::QuicheTextUtils::Uint64ToString(1234)); +} + +TEST_F(QuicheTextUtilsTest, HexEncode) { + EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello", 5)); + EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello World", 5)); + EXPECT_EQ("48656c6c6f", quiche::QuicheTextUtils::HexEncode("Hello")); + EXPECT_EQ("0102779cfa", + quiche::QuicheTextUtils::HexEncode("\x01\x02\x77\x9c\xfa")); +} + +TEST_F(QuicheTextUtilsTest, HexDecode) { + EXPECT_EQ("Hello", quiche::QuicheTextUtils::HexDecode("48656c6c6f")); + EXPECT_EQ("", quiche::QuicheTextUtils::HexDecode("")); + EXPECT_EQ("\x01\x02\x77\x9c\xfa", + quiche::QuicheTextUtils::HexDecode("0102779cfa")); +} + +TEST_F(QuicheTextUtilsTest, HexDump) { + // Verify output of the HexDump method is as expected. + char packet[] = { + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x51, 0x55, 0x49, 0x43, 0x21, + 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c, + 0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74, + 0x6f, 0x20, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x01, 0x02, 0x03, 0x00, + }; + EXPECT_EQ( + quiche::QuicheTextUtils::HexDump(packet), + "0x0000: 4865 6c6c 6f2c 2051 5549 4321 2054 6869 Hello,.QUIC!.Thi\n" + "0x0010: 7320 7374 7269 6e67 2073 686f 756c 6420 s.string.should.\n" + "0x0020: 6265 206c 6f6e 6720 656e 6f75 6768 2074 be.long.enough.t\n" + "0x0030: 6f20 7370 616e 206d 756c 7469 706c 6520 o.span.multiple.\n" + "0x0040: 6c69 6e65 7320 6f66 206f 7574 7075 742e lines.of.output.\n" + "0x0050: 0102 03 ...\n"); + // Verify that 0x21 and 0x7e are printable, 0x20 and 0x7f are not. + EXPECT_EQ("0x0000: 2021 7e7f .!~.\n", + quiche::QuicheTextUtils::HexDump( + quiche::QuicheTextUtils::HexDecode("20217e7f"))); + // Verify that values above numeric_limits<unsigned char>::max() are formatted + // properly on platforms where char is unsigned. + EXPECT_EQ("0x0000: 90aa ff ...\n", + quiche::QuicheTextUtils::HexDump( + quiche::QuicheTextUtils::HexDecode("90aaff"))); +} + +TEST_F(QuicheTextUtilsTest, Base64Encode) { + std::string output; + std::string input = "Hello"; + quiche::QuicheTextUtils::Base64Encode( + reinterpret_cast<const uint8_t*>(input.data()), input.length(), &output); + EXPECT_EQ("SGVsbG8", output); + + input = + "Hello, QUIC! This string should be long enough to span" + "multiple lines of output\n"; + quiche::QuicheTextUtils::Base64Encode( + reinterpret_cast<const uint8_t*>(input.data()), input.length(), &output); + EXPECT_EQ( + "SGVsbG8sIFFVSUMhIFRoaXMgc3RyaW5nIHNob3VsZCBiZSBsb25n" + "IGVub3VnaCB0byBzcGFubXVsdGlwbGUgbGluZXMgb2Ygb3V0cHV0Cg", + output); +} + +TEST_F(QuicheTextUtilsTest, ContainsUpperCase) { + EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("abc")); + EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("")); + EXPECT_FALSE(quiche::QuicheTextUtils::ContainsUpperCase("123")); + EXPECT_TRUE(quiche::QuicheTextUtils::ContainsUpperCase("ABC")); + EXPECT_TRUE(quiche::QuicheTextUtils::ContainsUpperCase("aBc")); +} + +TEST_F(QuicheTextUtilsTest, Split) { + EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}), + quiche::QuicheTextUtils::Split("a,b,c", ',')); + EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}), + quiche::QuicheTextUtils::Split("a:b:c", ':')); + EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a:b:c"}), + quiche::QuicheTextUtils::Split("a:b:c", ',')); + // Leading and trailing whitespace is preserved. + EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({"a", "b", "c"}), + quiche::QuicheTextUtils::Split("a,b,c", ',')); + EXPECT_EQ(std::vector<quiche::QuicheStringPiece>({" a", "b ", " c "}), + quiche::QuicheTextUtils::Split(" a:b : c ", ':')); +} + +} // namespace test +} // namespace quiche