Adds PrettyPrint, PrettyPrintWithSeparator and EscapeForPrinting.
This commit is contained in:
15
BUILD
15
BUILD
@@ -20,3 +20,18 @@ cc_test(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "pretty_print",
|
||||
srcs = ["pretty_print.cpp"],
|
||||
hdrs = ["pretty_print.h"],
|
||||
includes = ["pretty_print.h"],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "pretty_print_test",
|
||||
srcs = ["pretty_print_test.cpp"],
|
||||
deps = [
|
||||
":pretty_print",
|
||||
"@tinytest",
|
||||
],
|
||||
)
|
||||
|
||||
13
pretty_print.cpp
Normal file
13
pretty_print.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
/***************************************************************************************
|
||||
* @file pretty_print.cpp *
|
||||
* *
|
||||
* @brief Defines functions for printing objects in a frendlier manner. *
|
||||
* @copyright *
|
||||
* Copyright 2023 Tom Hicks *
|
||||
* Licensed under the MIT license see the LICENSE file for details. *
|
||||
***************************************************************************************/
|
||||
#include "pretty_print.h"
|
||||
|
||||
namespace CPPUtils {
|
||||
// Nothing here.
|
||||
} // namespace CPPUtils
|
||||
331
pretty_print.h
Normal file
331
pretty_print.h
Normal file
@@ -0,0 +1,331 @@
|
||||
#ifndef CPP_UTILS_pretty_print_h__
|
||||
#define CPP_UTILS_pretty_print_h__
|
||||
/***************************************************************************************
|
||||
* @file pretty_print.cpp *
|
||||
* *
|
||||
* @brief Defines functions for printing objects in a frendlier manner. *
|
||||
* @copyright *
|
||||
* Copyright 2023 Tom Hicks *
|
||||
* Licensed under the MIT license see the LICENSE file for details. *
|
||||
***************************************************************************************/
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <queue>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
/** \addtogroup Pretty Print
|
||||
* @{
|
||||
*/
|
||||
namespace CPPUtils {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper templates - These are not directly tested.
|
||||
template <typename TChar>
|
||||
struct StringTraits;
|
||||
|
||||
template <>
|
||||
struct StringTraits<char> {
|
||||
static constexpr const char* Literal(const char* narrow, const wchar_t* wide) { return narrow; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringTraits<wchar_t> {
|
||||
static constexpr const wchar_t* Literal(const char* narrow, const wchar_t* wide) { return wide; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_container {
|
||||
template <typename U>
|
||||
static constexpr bool test(decltype(std::begin(std::declval<U>()))*) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static constexpr bool test(...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr bool value = test<T>(nullptr);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Forward Declarations
|
||||
|
||||
// const char* and const wchar_t*
|
||||
template <typename TChar>
|
||||
std::basic_string<TChar> EscapeForPrinting(const TChar* text);
|
||||
|
||||
// std::string and std::wstring
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string<TChar, TTraits>& text);
|
||||
|
||||
// std::string_view and std::wstring_view
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string_view<TChar, TTraits>& text);
|
||||
|
||||
// pointers
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const void* pointer);
|
||||
|
||||
// const char* and const wchar_t*
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const TChar* item);
|
||||
|
||||
// std::string and std::wstring
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string<TChar, TTraits>& item);
|
||||
|
||||
// std::string_view and std::wstring_view
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string_view<TChar, TTraits>& item);
|
||||
|
||||
// std::tuple
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::tuple<TArgs...>& tuple);
|
||||
|
||||
// Containers (anything with a begin and end iterator)
|
||||
template <typename TChar, typename TTraits, typename TContainer, typename, typename>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TContainer container);
|
||||
|
||||
// Initializer Lists
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::initializer_list<TItem> container);
|
||||
|
||||
// queues
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::queue<TItem> queue);
|
||||
|
||||
// pairs
|
||||
template <typename TChar, typename TTraits, typename TFirst, typename TSecond>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::pair<TFirst, TSecond> value);
|
||||
|
||||
// Catch-all for everything else. Just print it and hope that works.
|
||||
template <typename TChar,
|
||||
typename TTraits,
|
||||
typename TItem,
|
||||
typename std::enable_if<!is_container<TItem>::value>::type* = nullptr>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TItem item);
|
||||
|
||||
// Prints varargs with a const char* or const wchar_t* separator between each pair.
|
||||
template <typename TChar, typename TTraits, typename... Args>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os, const TChar* separator, Args&&... args);
|
||||
|
||||
// Prints varargs with a std::string or std::wstring separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
std::basic_string<TChar, TTraits> separator,
|
||||
TArgs&&... args);
|
||||
|
||||
// Prints varargs with a std::string_view or std::wstring_view separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
std::basic_string_view<TChar, TTraits> separator,
|
||||
TArgs&&... args);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Actual implementations
|
||||
|
||||
// const char*
|
||||
template <typename TChar>
|
||||
std::basic_string<TChar> EscapeForPrinting(const TChar* text) {
|
||||
std::regex regex = std::regex(StringTraits<TChar>::Literal("\033", L"\033"));
|
||||
const TChar* replace = StringTraits<TChar>::Literal("\\033", L"\\033");
|
||||
return std::regex_replace(text, regex, replace);
|
||||
}
|
||||
|
||||
// std::string
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string<TChar, TTraits>& text) {
|
||||
std::regex regex = std::regex(StringTraits<TChar>::Literal("\033", L"\033"));
|
||||
std::basic_string<TChar, TTraits> replace = StringTraits<TChar>::Literal("\\033", L"\\033");
|
||||
return std::regex_replace(text, regex, replace);
|
||||
}
|
||||
|
||||
// std::string_view
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string_view<TChar, TTraits>& text) {
|
||||
std::basic_string<TChar, TTraits> text_as_string = std::basic_string<TChar, TTraits>(text);
|
||||
std::regex regex = std::regex(StringTraits<TChar>::Literal("\033", L"\033"));
|
||||
std::basic_string<TChar, TTraits> replace = StringTraits<TChar>::Literal("\\033", L"\\033");
|
||||
return std::regex_replace(text_as_string, regex, replace);
|
||||
}
|
||||
|
||||
// pointers
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const void* pointer) {
|
||||
if (pointer == nullptr) {
|
||||
os << StringTraits<TChar>::Literal("null", L"null");
|
||||
} else {
|
||||
os << pointer;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
// const char*.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const TChar* item) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(item)
|
||||
<< StringTraits<TChar>::Literal("\"", L"\"");
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::string.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string<TChar, TTraits>& item) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(item)
|
||||
<< StringTraits<TChar>::Literal("\"", L"\"");
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::string_view.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string_view<TChar, TTraits>& item) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(item)
|
||||
<< StringTraits<TChar>::Literal("\"", L"\"");
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::tuple
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::tuple<TArgs...>& tuple) {
|
||||
std::apply(
|
||||
[&os](auto&&... args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]]");
|
||||
return;
|
||||
}
|
||||
size_t n = 0;
|
||||
os << StringTraits<TChar>::Literal("[ ", L"[ ");
|
||||
((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? StringTraits<TChar>::Literal(", ", L", ")
|
||||
: StringTraits<TChar>::Literal("", L""))),
|
||||
...);
|
||||
os << StringTraits<TChar>::Literal(" ]", L" ]");
|
||||
},
|
||||
tuple);
|
||||
return os;
|
||||
}
|
||||
|
||||
// Containers
|
||||
template <typename TChar,
|
||||
typename TTraits,
|
||||
typename TContainer,
|
||||
typename = decltype(std::begin(std::declval<TContainer>())),
|
||||
typename = decltype(std::end(std::declval<TContainer>())),
|
||||
typename = typename TContainer::value_type>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TContainer container) {
|
||||
if (container.size() <= 0) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]");
|
||||
} else {
|
||||
os << StringTraits<TChar>::Literal("[ ", L"[ ");
|
||||
for (auto it = std::begin(container); it != std::end(container); it++) {
|
||||
if (it != std::begin(container)) {
|
||||
os << StringTraits<TChar>::Literal(", ", L", ");
|
||||
}
|
||||
PrettyPrint(os, *it);
|
||||
}
|
||||
os << StringTraits<TChar>::Literal(" ]", L" ]");
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
// initializer_lists
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::initializer_list<TItem> container) {
|
||||
if (container.size() <= 0) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]");
|
||||
return os;
|
||||
}
|
||||
os << StringTraits<TChar>::Literal("[ ", L"[ ");
|
||||
for (auto it = std::begin(container); it != std::end(container); it++) {
|
||||
if (it != std::begin(container)) {
|
||||
os << StringTraits<TChar>::Literal(", ", L", ");
|
||||
}
|
||||
PrettyPrint(os, *it);
|
||||
}
|
||||
os << StringTraits<TChar>::Literal(" ]", L" ]");
|
||||
return os;
|
||||
}
|
||||
|
||||
// queues
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::queue<TItem> queue) {
|
||||
if (queue.empty()) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]");
|
||||
return os;
|
||||
}
|
||||
os << StringTraits<TChar>::Literal("[ ", L"[ ");
|
||||
PrettyPrint(os, queue.front());
|
||||
queue.pop();
|
||||
while (!queue.empty()) {
|
||||
os << StringTraits<TChar>::Literal(", ", L", ");
|
||||
PrettyPrint(os, queue.front());
|
||||
queue.pop();
|
||||
}
|
||||
os << StringTraits<TChar>::Literal(" ]", L" ]");
|
||||
return os;
|
||||
}
|
||||
|
||||
// pairs
|
||||
template <typename TChar, typename TTraits, typename TFirst, typename TSecond>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::pair<TFirst, TSecond> value) {
|
||||
os << StringTraits<TChar>::Literal("(", L"(");
|
||||
PrettyPrint(os, value.first);
|
||||
os << StringTraits<TChar>::Literal(", ", L", ");
|
||||
PrettyPrint(os, value.second);
|
||||
os << StringTraits<TChar>::Literal(")", L")");
|
||||
return os;
|
||||
}
|
||||
|
||||
// Catch-all for everything else.
|
||||
template <typename TChar, typename TTraits, typename TItem, typename std::enable_if<!is_container<TItem>::value>::type*>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TItem item) {
|
||||
os << item;
|
||||
return os;
|
||||
}
|
||||
|
||||
// Prints args with separator between them. const char* separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os, const TChar* separator, TArgs&&... args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("", L"");
|
||||
return os;
|
||||
}
|
||||
size_t n = 0;
|
||||
((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? separator : StringTraits<TChar>::Literal("", L""))), ...);
|
||||
return os;
|
||||
}
|
||||
|
||||
// Prints args with separator between them. std::string separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
std::basic_string<TChar, TTraits> separator,
|
||||
TArgs&&... args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("", L"");
|
||||
return os;
|
||||
}
|
||||
size_t n = 0;
|
||||
((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? separator : StringTraits<TChar>::Literal("", L""))), ...);
|
||||
return os;
|
||||
}
|
||||
|
||||
// Prints args with separator between them. std::string_view separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
std::basic_string_view<TChar, TTraits> separator,
|
||||
TArgs&&... args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("", L"");
|
||||
return os;
|
||||
}
|
||||
size_t n = 0;
|
||||
((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? separator : StringTraits<TChar>::Literal("", L""))), ...);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // End namespace CPPUtils
|
||||
|
||||
/** @}*/
|
||||
#endif // End !defined CPP_UTILS_pretty_print_h__
|
||||
427
pretty_print_test.cpp
Normal file
427
pretty_print_test.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
/***************************************************************************************
|
||||
* @file pretty_print_test.cpp *
|
||||
* *
|
||||
* @brief Defines tests for functions for printing objects in a frendlier manner. *
|
||||
* @copyright *
|
||||
* Copyright 2023 Tom Hicks *
|
||||
* Licensed under the MIT license see the LICENSE file for details. *
|
||||
***************************************************************************************/
|
||||
// clang-format off
|
||||
#include "pretty_print.h"
|
||||
#include "tinytest.h"
|
||||
// clang-format on
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace {
|
||||
using std::make_tuple;
|
||||
using std::ostringstream;
|
||||
using std::string;
|
||||
using std::string_view;
|
||||
using TinyTest::execute_suite;
|
||||
using TinyTest::make_test;
|
||||
using TinyTest::make_test_suite;
|
||||
using TinyTest::TestResults;
|
||||
using namespace CPPUtils;
|
||||
using std::wstring;
|
||||
} // End namespace
|
||||
|
||||
TestResults test_EscapeForPrintingWithAConstCharPointer() {
|
||||
TestResults results;
|
||||
auto escape_const_char_pointer = [](const char* value) -> string { return EscapeForPrinting(value); };
|
||||
results += execute_suite(make_test_suite(
|
||||
"CPPUtils::EscapeForPrinting(const char*)",
|
||||
escape_const_char_pointer,
|
||||
{
|
||||
make_test("should escape an empty string", (string) "", make_tuple("")),
|
||||
make_test("should esacpe a string with no special characters",
|
||||
(string) "This is a normal string.",
|
||||
make_tuple("This is a normal string.")),
|
||||
make_test("should escape the escape character by itself", (string) "\\033", make_tuple("\033")),
|
||||
make_test("should escape the escape character within a string",
|
||||
(string) "This string has an \\033 in it.",
|
||||
make_tuple("This string has an \033 in it.")),
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
|
||||
TestResults test_EscapeForPrintingWithAString() {
|
||||
TestResults results;
|
||||
auto escape_string = [](const string& value) -> string { return EscapeForPrinting(value); };
|
||||
results += execute_suite(make_test_suite(
|
||||
"CPPUtils::EscapeForPrinting(const std::string&)",
|
||||
escape_string,
|
||||
{
|
||||
make_test("should escape an empty string", (string) "", make_tuple((string) "")),
|
||||
make_test("should escape a string with no special characters",
|
||||
(string) "This is a normal string.",
|
||||
make_tuple((string) "This is a normal string.")),
|
||||
make_test("should escape the escape character by itself", (string) "\\033", make_tuple((string) "\033")),
|
||||
make_test("should escape the escape character within a string",
|
||||
(string) "This string has an \\033 in it.",
|
||||
make_tuple((string) "This string has an \033 in it.")),
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
|
||||
TestResults test_EscapeForPrintingWithAStringView() {
|
||||
auto escape_string_view = [](const string_view& value) -> string { return EscapeForPrinting(value); };
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::EscapeForPrinting(const std::string_view&)",
|
||||
escape_string_view,
|
||||
{
|
||||
make_test("should escape an empty string", (string) "", make_tuple((string_view) "")),
|
||||
make_test("should escape a string with no special characters",
|
||||
(string) "This is a normal string.",
|
||||
make_tuple((string_view) "This is a normal string.")),
|
||||
make_test("should escape the escape character by itself", (string) "\\033", make_tuple((string_view) "\033")),
|
||||
make_test("should escape the escape character within a string",
|
||||
(string) "This string has an \\033 in it.",
|
||||
make_tuple((string_view) "This string has an \033 in it.")),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithAConstCharPointer() {
|
||||
auto pretty_print = [](const char* value) -> string {
|
||||
ostringstream os;
|
||||
PrettyPrint(os, value);
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrint(std::ostream&, const char*)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print \"\" for an empty string", (string) "\"\"", make_tuple("")),
|
||||
make_test("should print \"hello world\"", (string) "\"hello world\"", make_tuple("hello world")),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithAString() {
|
||||
auto pretty_print = [](const string& value) -> string {
|
||||
ostringstream os;
|
||||
PrettyPrint(os, value);
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrint(std::ostream&, const std::string&)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print \"\" for an empty string", (string) "\"\"", make_tuple((string) "")),
|
||||
make_test("should print \"hello world\"", (string) "\"hello world\"", make_tuple((string) "hello world")),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithAStringView() {
|
||||
auto pretty_print = [](const std::string_view& value) -> string {
|
||||
ostringstream os;
|
||||
PrettyPrint(os, value);
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrint(std::ostream&, const std::string_view&)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print \"\" for an empty string", (string) "\"\"", make_tuple((string_view) "")),
|
||||
make_test(
|
||||
"should print \"hello world\"", (string) "\"hello world\"", make_tuple((string_view) "hello world")),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithATuple() {
|
||||
auto pretty_print = [](int i) -> string {
|
||||
ostringstream os;
|
||||
switch (i) {
|
||||
case 1:
|
||||
PrettyPrint(os, make_tuple(1, "hello", 9));
|
||||
break;
|
||||
case 2:
|
||||
PrettyPrint(os, make_tuple());
|
||||
break;
|
||||
case 3:
|
||||
PrettyPrint(os, make_tuple("one", "two", "three"));
|
||||
break;
|
||||
}
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrint(std::ostream&, std::tuple)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print a tuple of mixed types", (string) "[ 1, \"hello\", 9 ]", make_tuple(1)),
|
||||
make_test("should print an empty tuple", (string) "[]", make_tuple(2)),
|
||||
make_test("should print a tuple of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(3)),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithAnInitializerList() {
|
||||
auto pretty_print = [](int i) {
|
||||
ostringstream os;
|
||||
switch (i) {
|
||||
case 1:
|
||||
PrettyPrint(os, {"one", "two", "three"});
|
||||
break;
|
||||
case 2:
|
||||
PrettyPrint(os, (std::initializer_list<string>){});
|
||||
break;
|
||||
case 3:
|
||||
PrettyPrint(os, {1, 2, 3});
|
||||
break;
|
||||
case 4:
|
||||
PrettyPrint(os, {"one", "two", "three", "four"});
|
||||
break;
|
||||
case 5:
|
||||
PrettyPrint(os, {1.1, 2.2, 3.3});
|
||||
break;
|
||||
}
|
||||
return os.str();
|
||||
};
|
||||
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrint(std::ostream&, std::initializer_list)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test(
|
||||
"should print an initializer_list of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(1)),
|
||||
make_test("should print an empty initializer_list", (string) "[]", make_tuple(2)),
|
||||
make_test("should print an initializer_list of integers", (string) "[ 1, 2, 3 ]", make_tuple(3)),
|
||||
make_test("should print an initializer_list of strings with four elements",
|
||||
(string) "[ \"one\", \"two\", \"three\", \"four\" ]",
|
||||
make_tuple(4)),
|
||||
make_test("should print an initializer_list of doubles", (string) "[ 1.1, 2.2, 3.3 ]", make_tuple(5)),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithDifferentContainerTypes() {
|
||||
auto pretty_print = [](int i) {
|
||||
ostringstream os;
|
||||
switch (i) {
|
||||
case 1: {
|
||||
std::vector<int> v = {1, 2, 3};
|
||||
PrettyPrint(os, v);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
std::queue<int> q;
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
q.push(3);
|
||||
PrettyPrint(os, q);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
std::vector<string> v = {"one", "two", "three"};
|
||||
PrettyPrint(os, v);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
std::queue<string> q;
|
||||
q.push("one");
|
||||
q.push("two");
|
||||
q.push("three");
|
||||
PrettyPrint(os, q);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return os.str();
|
||||
};
|
||||
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrint(std::ostream&, TContainer)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print a vector of integers", (string) "[ 1, 2, 3 ]", make_tuple(1)),
|
||||
make_test("should print a queue of integers", (string) "[ 1, 2, 3 ]", make_tuple(2)),
|
||||
make_test("should print a vector of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(3)),
|
||||
make_test("should print a queue of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(4)),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithSimpleTypes() {
|
||||
TestResults results;
|
||||
|
||||
auto pretty_print_int = [](int value) -> string {
|
||||
ostringstream os;
|
||||
PrettyPrint(os, value);
|
||||
return os.str();
|
||||
};
|
||||
results += execute_suite(make_test_suite("CPPUtils::PrettyPrint(std::ostream&, const TItem&)",
|
||||
pretty_print_int,
|
||||
{
|
||||
make_test("should print 42 for an int", (string) "42", make_tuple(42)),
|
||||
}));
|
||||
|
||||
auto pretty_print_float = [](float value) -> string {
|
||||
ostringstream os;
|
||||
PrettyPrint(os, value);
|
||||
return os.str();
|
||||
};
|
||||
results +=
|
||||
execute_suite(make_test_suite("CPPUtils::PrettyPrint(std::ostream&, const TItem&)",
|
||||
pretty_print_float,
|
||||
{
|
||||
make_test("should print 3.14 for a float", (string) "3.14", make_tuple(3.14f)),
|
||||
}));
|
||||
|
||||
auto pretty_print_string = [](const string& value) -> string {
|
||||
ostringstream os;
|
||||
PrettyPrint(os, value);
|
||||
return os.str();
|
||||
};
|
||||
results += execute_suite(make_test_suite("CPPUtils::PrettyPrint(std::ostream&, const TItem&)",
|
||||
pretty_print_string,
|
||||
{
|
||||
make_test("should print \"hello world\" for a string",
|
||||
(string) "\"hello world\"",
|
||||
make_tuple((string) "hello world")),
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithAPair() {
|
||||
auto pretty_print = [](int id) -> string {
|
||||
ostringstream os;
|
||||
switch (id) {
|
||||
case 1:
|
||||
PrettyPrint(os, std::make_pair(1, 2));
|
||||
break;
|
||||
case 2:
|
||||
PrettyPrint(os, std::make_pair(3.14f, 42));
|
||||
break;
|
||||
case 3:
|
||||
PrettyPrint(os, std::make_pair((string) "hello", (string) "world"));
|
||||
break;
|
||||
}
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrint(std::ostream&, const std::pair<T1, T2>&)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print (1, 2) for a pair of ints", (string) "(1, 2)", make_tuple(1)),
|
||||
make_test("should print (3.14, 42) for a pair of float and int", (string) "(3.14, 42)", make_tuple(2)),
|
||||
make_test("should print (\"hello\", \"world\") for a pair of strings",
|
||||
(string) "(\"hello\", \"world\")",
|
||||
make_tuple(3)),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithSeparatorWithAConstCharPointer() {
|
||||
auto pretty_print = [](const char* separator, int id) -> string {
|
||||
ostringstream os;
|
||||
switch (id) {
|
||||
case 1:
|
||||
PrettyPrintWithSeparator(os, separator, 1, 2, 3);
|
||||
break;
|
||||
case 2:
|
||||
PrettyPrintWithSeparator(os, separator, 3.14f, 42, (string) "hello world");
|
||||
break;
|
||||
case 3:
|
||||
PrettyPrintWithSeparator(os, separator, (string) "hello", (string) "world");
|
||||
break;
|
||||
}
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(
|
||||
make_test_suite("CPPUtils::PrettyPrintWithSeparator(std::ostream&, const TChar*, Args&&...)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print 1, 2, 3 for a list of ints", (string) "1, 2, 3", make_tuple(", ", 1)),
|
||||
make_test("should print 3.14; 42; \"hello world\" for a list of float, int and string",
|
||||
(string) "3.14; 42; \"hello world\"",
|
||||
make_tuple("; ", 2)),
|
||||
make_test("should print \"hello\" \"world\" for a list of strings",
|
||||
(string) "\"hello\" \"world\"",
|
||||
make_tuple(" ", 3)),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithSeparatorWithAString() {
|
||||
auto pretty_print = [](const string& separator, int id) -> string {
|
||||
ostringstream os;
|
||||
switch (id) {
|
||||
case 1:
|
||||
PrettyPrintWithSeparator(os, separator, 1, 2, 3);
|
||||
break;
|
||||
case 2:
|
||||
PrettyPrintWithSeparator(os, separator, 3.14f, 42, (string) "hello world");
|
||||
break;
|
||||
case 3:
|
||||
PrettyPrintWithSeparator(os, separator, (string) "hello", (string) "world");
|
||||
break;
|
||||
}
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrintWithSeparator(std::ostream&, const TChar*, Args&&...)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test("should print 1 | 2 | 3 for a list of ints", (string) "1 | 2 | 3", make_tuple((string) " | ", 1)),
|
||||
make_test("should print 3.14 / 42 / \"hello world\" for a list of float, int and string",
|
||||
(string) "3.14 / 42 / \"hello world\"",
|
||||
make_tuple((string) " / ", 2)),
|
||||
make_test("should print \"hello\" - \"world\" for a list of strings",
|
||||
(string) "\"hello\" - \"world\"",
|
||||
make_tuple((string) " - ", 3)),
|
||||
}));
|
||||
}
|
||||
|
||||
TestResults test_PrettyPrintWithSeparatorWithAStringView() {
|
||||
auto pretty_print = [](const string_view& separator, int id) -> string {
|
||||
ostringstream os;
|
||||
switch (id) {
|
||||
case 1:
|
||||
PrettyPrintWithSeparator(os, separator, 1, 2, 3);
|
||||
break;
|
||||
case 2:
|
||||
PrettyPrintWithSeparator(os, separator, 3.14f, 42, "hello world");
|
||||
break;
|
||||
case 3:
|
||||
PrettyPrintWithSeparator(os, separator, "hello", "world");
|
||||
break;
|
||||
}
|
||||
return os.str();
|
||||
};
|
||||
return execute_suite(make_test_suite(
|
||||
"CPPUtils::PrettyPrintWithSeparator(std::ostream&, const TChar*, Args&&...)",
|
||||
pretty_print,
|
||||
{
|
||||
make_test(
|
||||
"should print 1 | 2 | 3 for a list of ints", (string) "1 | 2 | 3", make_tuple((string_view) " | ", 1)),
|
||||
make_test("should print 3.14 / 42 / \"hello world\" for a list of float, int and string",
|
||||
(string) "3.14 / 42 / \"hello world\"",
|
||||
make_tuple((string_view) " / ", 2)),
|
||||
make_test("should print \"hello\" - \"world\" for a list of strings",
|
||||
(string) "\"hello\" - \"world\"",
|
||||
make_tuple((string_view) " - ", 3)),
|
||||
}));
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
setlocale(LC_ALL, "");
|
||||
TestResults results;
|
||||
|
||||
results += test_EscapeForPrintingWithAConstCharPointer();
|
||||
results += test_EscapeForPrintingWithAString();
|
||||
results += test_EscapeForPrintingWithAStringView();
|
||||
|
||||
results += test_PrettyPrintWithAConstCharPointer();
|
||||
results += test_PrettyPrintWithAString();
|
||||
results += test_PrettyPrintWithAStringView();
|
||||
results += test_PrettyPrintWithATuple();
|
||||
results += test_PrettyPrintWithAnInitializerList();
|
||||
results += test_PrettyPrintWithDifferentContainerTypes();
|
||||
results += test_PrettyPrintWithSimpleTypes();
|
||||
results += test_PrettyPrintWithAPair();
|
||||
|
||||
results += test_PrettyPrintWithSeparatorWithAConstCharPointer();
|
||||
results += test_PrettyPrintWithSeparatorWithAString();
|
||||
results += test_PrettyPrintWithSeparatorWithAStringView();
|
||||
|
||||
return results.failed() + results.errors();
|
||||
}
|
||||
Reference in New Issue
Block a user