summaryrefslogtreecommitdiffstats
path: root/libcxx/test
diff options
context:
space:
mode:
authorSterling Augustine <saugustine@google.com>2019-08-30 23:43:34 +0000
committerSterling Augustine <saugustine@google.com>2019-08-30 23:43:34 +0000
commitd21a3e41a4cfd52e3c5c9341f0b5ce8a173198bf (patch)
treece63cf6f54b2de0e481e2db752ac72073a209cd1 /libcxx/test
parent802aab5de87c5908a6915fca837843db3f8279bb (diff)
downloadbcm5719-llvm-d21a3e41a4cfd52e3c5c9341f0b5ce8a173198bf.tar.gz
bcm5719-llvm-d21a3e41a4cfd52e3c5c9341f0b5ce8a173198bf.zip
Add gdb pretty printers for a wide variety of libc++ data structures.
Summary: Also add a test suite. Reviewers: EricWF Subscribers: christof, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65609 Run a pep8 formatter. Run pep8 formatter. Convert to PEP8, address other comments from code review. llvm-svn: 370551
Diffstat (limited to 'libcxx/test')
-rw-r--r--libcxx/test/pretty_printers/gdb_pretty_printer_test.py112
-rw-r--r--libcxx/test/pretty_printers/gdb_pretty_printer_test.sh.cpp631
2 files changed, 743 insertions, 0 deletions
diff --git a/libcxx/test/pretty_printers/gdb_pretty_printer_test.py b/libcxx/test/pretty_printers/gdb_pretty_printer_test.py
new file mode 100644
index 00000000000..5e425688734
--- /dev/null
+++ b/libcxx/test/pretty_printers/gdb_pretty_printer_test.py
@@ -0,0 +1,112 @@
+#===----------------------------------------------------------------------===##
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+#===----------------------------------------------------------------------===##
+"""Commands used to automate testing gdb pretty printers.
+
+This script is part of a larger framework to test gdb pretty printers. It
+runs the program, detects test cases, checks them, and prints results.
+
+See gdb_pretty_printer_test.sh.cpp on how to write a test case.
+
+"""
+
+from __future__ import print_function
+import re
+import gdb
+
+test_failures = 0
+
+
+class CheckResult(gdb.Command):
+
+ def __init__(self):
+ super(CheckResult, self).__init__(
+ "print_and_compare", gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ try:
+ # Stack frame is:
+ # 0. StopForDebugger
+ # 1. ComparePrettyPrintToChars or ComparePrettyPrintToRegex
+ # 2. TestCase
+ compare_frame = gdb.newest_frame().older()
+ testcase_frame = compare_frame.older()
+ test_loc = testcase_frame.find_sal()
+ # Use interactive commands in the correct context to get the pretty
+ # printed version
+
+ value_str = self._get_value_string(compare_frame, testcase_frame)
+
+ # Ignore the convenience variable name and newline
+ value = value_str[value_str.find("= ") + 2:-1]
+ gdb.newest_frame().select()
+
+ expectation_val = compare_frame.read_var("expectation")
+ if "PrettyPrintToRegex" in compare_frame.name():
+ check_literal = expectation_val.string()
+ test_fails = not re.match(check_literal, value)
+ else:
+ check_literal_string = expectation_val.string(encoding="utf-8")
+ check_literal = check_literal_string.encode("utf-8")
+ test_fails = value != check_literal
+
+ if test_fails:
+ global test_failures
+ print("FAIL: " + test_loc.symtab.filename +
+ ":" + str(test_loc.line))
+ print("GDB printed:")
+ print(" " + value)
+ print("Value should match:")
+ print(" " + check_literal)
+ test_failures += 1
+ else:
+ print("PASS: " + test_loc.symtab.filename +
+ ":" + str(test_loc.line))
+
+ except RuntimeError as e:
+ # At this point, lots of different things could be wrong, so don't try to
+ # recover or figure it out. Don't exit either, because then it's
+ # impossible debug the framework itself.
+ print("FAIL: Something is wrong in the test framework.")
+ print(str(e))
+ test_failures += 1
+
+ def _get_value_string(self, compare_frame, testcase_frame):
+ compare_frame.select()
+ if "ComparePrettyPrint" in compare_frame.name():
+ return gdb.execute("p value", to_string=True)
+ value_str = str(compare_frame.read_var("value"))
+ clean_expression_str = value_str.strip("'\"")
+ testcase_frame.select()
+ return gdb.execute("p " + clean_expression_str, to_string=True)
+
+
+def exit_handler(event=None):
+ global test_failures
+ if test_failures:
+ print("FAILED %d cases" % test_failures)
+ exit(test_failures)
+
+
+# Start code executed at load time
+
+# Disable terminal paging
+gdb.execute("set height 0")
+gdb.execute("set python print-stack full")
+test_failures = 0
+CheckResult()
+test_bp = gdb.Breakpoint("StopForDebugger")
+test_bp.enabled = True
+test_bp.silent = True
+test_bp.commands = "print_and_compare\ncontinue"
+# "run" won't return if the program exits; ensure the script regains control.
+gdb.events.exited.connect(exit_handler)
+gdb.execute("run")
+# If the program didn't exit, something went wrong, but we don't
+# know what. Fail on exit.
+test_failures += 1
+exit_handler(None)
diff --git a/libcxx/test/pretty_printers/gdb_pretty_printer_test.sh.cpp b/libcxx/test/pretty_printers/gdb_pretty_printer_test.sh.cpp
new file mode 100644
index 00000000000..27c747bb76f
--- /dev/null
+++ b/libcxx/test/pretty_printers/gdb_pretty_printer_test.sh.cpp
@@ -0,0 +1,631 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: system-windows
+
+// RUN: %cxx %flags %s -o %t.exe %compile_flags -g %link_flags
+// Ensure locale-independence for unicode tests.
+// RUN: LC_CTYPE="en_US.UTF-8" gdb -batch -nx -iex "set autoload off" -ex "source %libcxx_src_root/utils/gdb/libcxx/printers.py" -ex "python register_libcxx_printer_loader()" -ex "source %libcxx_src_root/test/pretty_printers/gdb_pretty_printer_test.py" %t.exe
+
+#include <bitset>
+#include <deque>
+#include <list>
+#include <map>
+#include <memory>
+#include <queue>
+#include <set>
+#include <sstream>
+#include <stack>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+#include <unordered_set>
+
+// To write a pretty-printer test:
+//
+// 1. Declare a variable of the type you want to test
+//
+// 2. Set its value to something which will test the pretty printer in an
+// interesting way.
+//
+// 3. Call ComparePrettyPrintToChars with that variable, and a "const char*"
+// value to compare to the printer's output.
+//
+// Or
+//
+// Call ComparePrettyPrintToChars with that variable, and a "const char*"
+// *python* regular expression to match against the printer's output.
+// The set of special characters in a Python regular expression overlaps
+// with a lot of things the pretty printers print--brackets, for
+// example--so take care to escape appropriately.
+//
+// Alternatively, construct a string that gdb can parse as an expression,
+// so that printing the value of the expression will test the pretty printer
+// in an interesting way. Then, call CompareExpressionPrettyPrintToChars or
+// CompareExpressionPrettyPrintToRegex to compare the printer's output.
+
+// Avoids setting a breakpoint in every-single instantiation of
+// ComparePrettyPrintTo*. Also, make sure neither it, nor the
+// variables we need present in the Compare functions are optimized
+// away.
+void StopForDebugger(void *value, void *check) __attribute__((optnone)) { }
+
+// Prevents the compiler optimizing away the parameter in the caller function.
+template <typename Type>
+void MarkAsLive(Type &&t) __attribute__((optnone)) { }
+
+// In all of the Compare(Expression)PrettyPrintTo(Regex/Chars) functions below,
+// the python script sets a breakpoint just before the call to StopForDebugger,
+// compares the result to the expectation.
+//
+// The expectation is a literal string to be matched exactly in
+// *PrettyPrintToChars functions, and is a python regular expression in
+// *PrettyPrintToRegex functions.
+//
+// In ComparePrettyPrint* functions, the value is a variable of any type. In
+// CompareExpressionPrettyPrint functions, the value is a string expression that
+// gdb will parse and print the result.
+//
+// The python script will print either "PASS", or a detailed failure explanation
+// along with the line that has invoke the function. The testing will continue
+// in either case.
+
+template <typename TypeToPrint> void ComparePrettyPrintToChars(
+ TypeToPrint value,
+ const char *expectation) {
+ StopForDebugger(&value, &expectation);
+}
+
+template <typename TypeToPrint> void ComparePrettyPrintToRegex(
+ TypeToPrint value,
+ const char *expectation) {
+ StopForDebugger(&value, &expectation);
+}
+
+void CompareExpressionPrettyPrintToChars(
+ std::string value,
+ const char *expectation) {
+ StopForDebugger(&value, &expectation);
+}
+
+void CompareExpressionPrettyPrintToRegex(
+ std::string value,
+ const char *expectation) {
+ StopForDebugger(&value, &expectation);
+}
+
+namespace example {
+ struct example_struct {
+ int a = 0;
+ int arr[1000];
+ };
+}
+
+// If enabled, the self test will "fail"--because we want to be sure it properly
+// diagnoses tests that *should* fail. Evaluate the output by hand.
+void framework_self_test() {
+#ifdef FRAMEWORK_SELF_TEST
+ // Use the most simple data structure we can.
+ const char a = 'a';
+
+ // Tests that should pass
+ ComparePrettyPrintToChars(a, "97 'a'");
+ ComparePrettyPrintToRegex(a, ".*");
+
+ // Tests that should fail.
+ ComparePrettyPrintToChars(a, "b");
+ ComparePrettyPrintToRegex(a, "b");
+#endif
+}
+
+// A simple pass-through allocator to check that we handle CompressedPair
+// correctly.
+template <typename T> class UncompressibleAllocator : public std::allocator<T> {
+ public:
+ char X;
+};
+
+void string_test() {
+ std::string short_string("kdjflskdjf");
+ // The display_hint "string" adds quotes the printed result.
+ ComparePrettyPrintToChars(short_string, "\"kdjflskdjf\"");
+
+ std::basic_string<char, std::char_traits<char>, UncompressibleAllocator<char>>
+ long_string("mehmet bizim dostumuz agzi kirik testimiz");
+ ComparePrettyPrintToChars(long_string,
+ "\"mehmet bizim dostumuz agzi kirik testimiz\"");
+}
+
+void u16string_test() {
+ std::u16string test0 = u"Hello World";
+ ComparePrettyPrintToChars(test0, "u\"Hello World\"");
+ std::u16string test1 = u"\U00010196\u20AC\u00A3\u0024";
+ ComparePrettyPrintToChars(test1, "u\"\U00010196\u20AC\u00A3\u0024\"");
+ std::u16string test2 = u"\u0024\u0025\u0026\u0027";
+ ComparePrettyPrintToChars(test2, "u\"\u0024\u0025\u0026\u0027\"");
+ std::u16string test3 = u"mehmet bizim dostumuz agzi kirik testimiz";
+ ComparePrettyPrintToChars(test3,
+ ("u\"mehmet bizim dostumuz agzi kirik testimiz\""));
+}
+
+void u32string_test() {
+ std::u32string test0 = U"Hello World";
+ ComparePrettyPrintToChars(test0, "U\"Hello World\"");
+ std::u32string test1 =
+ U"\U0001d552\U0001d553\U0001d554\U0001d555\U0001d556\U0001d557";
+ ComparePrettyPrintToChars(
+ test1,
+ ("U\"\U0001d552\U0001d553\U0001d554\U0001d555\U0001d556\U0001d557\""));
+ std::u32string test2 = U"\U00004f60\U0000597d";
+ ComparePrettyPrintToChars(test2, ("U\"\U00004f60\U0000597d\""));
+ std::u32string test3 = U"mehmet bizim dostumuz agzi kirik testimiz";
+ ComparePrettyPrintToChars(test3, ("U\"mehmet bizim dostumuz agzi kirik testimiz\""));
+}
+
+void tuple_test() {
+ std::tuple<int, int, int> test0(2, 3, 4);
+ ComparePrettyPrintToChars(
+ test0,
+ "std::tuple containing = {[1] = 2, [2] = 3, [3] = 4}");
+
+ std::tuple<> test1;
+ ComparePrettyPrintToChars(
+ test1,
+ "empty std::tuple");
+}
+
+void unique_ptr_test() {
+ std::unique_ptr<std::string> matilda(new std::string("Matilda"));
+ ComparePrettyPrintToRegex(
+ std::move(matilda),
+ R"(std::unique_ptr<std::string> containing = {__ptr_ = 0x[a-f0-9]+})");
+ std::unique_ptr<int> forty_two(new int(42));
+ ComparePrettyPrintToRegex(std::move(forty_two),
+ R"(std::unique_ptr<int> containing = {__ptr_ = 0x[a-f0-9]+})");
+
+ std::unique_ptr<int> this_is_null;
+ ComparePrettyPrintToChars(std::move(this_is_null),
+ R"(std::unique_ptr is nullptr)");
+}
+
+void bitset_test() {
+ std::bitset<258> i_am_empty(0);
+ ComparePrettyPrintToChars(i_am_empty, "std::bitset<258>");
+
+ std::bitset<0> very_empty;
+ ComparePrettyPrintToChars(very_empty, "std::bitset<0>");
+
+ std::bitset<15> b_000001111111100(1020);
+ ComparePrettyPrintToChars(b_000001111111100,
+ "std::bitset<15> = {[2] = 1, [3] = 1, [4] = 1, [5] = 1, [6] = 1, "
+ "[7] = 1, [8] = 1, [9] = 1}");
+
+ std::bitset<258> b_0_129_132(0);
+ b_0_129_132[0] = true;
+ b_0_129_132[129] = true;
+ b_0_129_132[132] = true;
+ ComparePrettyPrintToChars(b_0_129_132,
+ "std::bitset<258> = {[0] = 1, [129] = 1, [132] = 1}");
+}
+
+void list_test() {
+ std::list<int> i_am_empty{};
+ ComparePrettyPrintToChars(i_am_empty, "std::list is empty");
+
+ std::list<int> one_two_three {1, 2, 3};
+ ComparePrettyPrintToChars(one_two_three,
+ "std::list with 3 elements = {1, 2, 3}");
+
+ std::list<std::string> colors {"red", "blue", "green"};
+ ComparePrettyPrintToChars(colors,
+ R"(std::list with 3 elements = {"red", "blue", "green"})");
+}
+
+void deque_test() {
+ std::deque<int> i_am_empty{};
+ ComparePrettyPrintToChars(i_am_empty, "std::deque is empty");
+
+ std::deque<int> one_two_three {1, 2, 3};
+ ComparePrettyPrintToChars(one_two_three,
+ "std::deque with 3 elements = {1, 2, 3}");
+
+ std::deque<example::example_struct> bfg;
+ for (int i = 0; i < 10; ++i) {
+ example::example_struct current;
+ current.a = i;
+ bfg.push_back(current);
+ }
+ for (int i = 0; i < 3; ++i) {
+ bfg.pop_front();
+ }
+ for (int i = 0; i < 3; ++i) {
+ bfg.pop_back();
+ }
+ ComparePrettyPrintToRegex(bfg,
+ "std::deque with 4 elements = {"
+ "{a = 3, arr = {[^}]+}}, "
+ "{a = 4, arr = {[^}]+}}, "
+ "{a = 5, arr = {[^}]+}}, "
+ "{a = 6, arr = {[^}]+}}}");
+}
+
+void map_test() {
+ std::map<int, int> i_am_empty{};
+ ComparePrettyPrintToChars(i_am_empty, "std::map is empty");
+
+ std::map<int, std::string> one_two_three;
+ one_two_three.insert({1, "one"});
+ one_two_three.insert({2, "two"});
+ one_two_three.insert({3, "three"});
+ ComparePrettyPrintToChars(one_two_three,
+ "std::map with 3 elements = "
+ R"({[1] = "one", [2] = "two", [3] = "three"})");
+
+ std::map<int, example::example_struct> bfg;
+ for (int i = 0; i < 4; ++i) {
+ example::example_struct current;
+ current.a = 17 * i;
+ bfg.insert({i, current});
+ }
+ ComparePrettyPrintToRegex(bfg,
+ R"(std::map with 4 elements = {)"
+ R"(\[0\] = {a = 0, arr = {[^}]+}}, )"
+ R"(\[1\] = {a = 17, arr = {[^}]+}}, )"
+ R"(\[2\] = {a = 34, arr = {[^}]+}}, )"
+ R"(\[3\] = {a = 51, arr = {[^}]+}}})");
+}
+
+void multimap_test() {
+ std::multimap<int, int> i_am_empty{};
+ ComparePrettyPrintToChars(i_am_empty, "std::multimap is empty");
+
+ std::multimap<int, std::string> one_two_three;
+ one_two_three.insert({1, "one"});
+ one_two_three.insert({3, "three"});
+ one_two_three.insert({1, "ein"});
+ one_two_three.insert({2, "two"});
+ one_two_three.insert({2, "zwei"});
+ one_two_three.insert({1, "bir"});
+
+ ComparePrettyPrintToChars(one_two_three,
+ "std::multimap with 6 elements = "
+ R"({[1] = "one", [1] = "ein", [1] = "bir", )"
+ R"([2] = "two", [2] = "zwei", [3] = "three"})");
+}
+
+void queue_test() {
+ std::queue<int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty,
+ "std::queue wrapping = {std::deque is empty}");
+
+ std::queue<int> one_two_three(std::deque<int>{1, 2, 3});
+ ComparePrettyPrintToChars(one_two_three,
+ "std::queue wrapping = {"
+ "std::deque with 3 elements = {1, 2, 3}}");
+}
+
+void priority_queue_test() {
+ std::priority_queue<int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty,
+ "std::priority_queue wrapping = {std::vector of length 0, capacity 0}");
+
+ std::priority_queue<int> one_two_three;
+ one_two_three.push(11111);
+ one_two_three.push(22222);
+ one_two_three.push(33333);
+
+ ComparePrettyPrintToRegex(one_two_three,
+ R"(std::priority_queue wrapping = )"
+ R"({std::vector of length 3, capacity 3 = {33333)");
+
+ ComparePrettyPrintToRegex(one_two_three, ".*11111.*");
+ ComparePrettyPrintToRegex(one_two_three, ".*22222.*");
+}
+
+void set_test() {
+ std::set<int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty, "std::set is empty");
+
+ std::set<int> one_two_three {3, 1, 2};
+ ComparePrettyPrintToChars(one_two_three,
+ "std::set with 3 elements = {1, 2, 3}");
+
+ std::set<std::pair<int, int>> prime_pairs {
+ std::make_pair(3, 5), std::make_pair(5, 7), std::make_pair(3, 5)};
+
+ ComparePrettyPrintToChars(prime_pairs,
+ "std::set with 2 elements = {"
+ "{first = 3, second = 5}, {first = 5, second = 7}}");
+}
+
+void stack_test() {
+ std::stack<int> test0;
+ ComparePrettyPrintToChars(test0,
+ "std::stack wrapping = {std::deque is empty}");
+ test0.push(5);
+ test0.push(6);
+ ComparePrettyPrintToChars(
+ test0, "std::stack wrapping = {std::deque with 2 elements = {5, 6}}");
+ std::stack<bool> test1;
+ test1.push(true);
+ test1.push(false);
+ ComparePrettyPrintToChars(
+ test1,
+ "std::stack wrapping = {std::deque with 2 elements = {true, false}}");
+
+ std::stack<std::string> test2;
+ test2.push("Hello");
+ test2.push("World");
+ ComparePrettyPrintToChars(test2,
+ "std::stack wrapping = {std::deque with 2 elements "
+ "= {\"Hello\", \"World\"}}");
+}
+
+void multiset_test() {
+ std::multiset<int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty, "std::multiset is empty");
+
+ std::multiset<std::string> one_two_three {"1:one", "2:two", "3:three", "1:one"};
+ ComparePrettyPrintToChars(one_two_three,
+ "std::multiset with 4 elements = {"
+ R"("1:one", "1:one", "2:two", "3:three"})");
+}
+
+void vector_test() {
+ std::vector<bool> test0 = {true, false};
+ ComparePrettyPrintToChars(test0,
+ "std::vector<bool> of "
+ "length 2, capacity 64 = {1, 0}");
+ for (int i = 0; i < 31; ++i) {
+ test0.push_back(true);
+ test0.push_back(false);
+ }
+ ComparePrettyPrintToRegex(
+ test0,
+ "std::vector<bool> of length 64, "
+ "capacity 64 = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, "
+ "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, "
+ "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}");
+ test0.push_back(true);
+ ComparePrettyPrintToRegex(
+ test0,
+ "std::vector<bool> of length 65, "
+ "capacity 128 = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, "
+ "1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, "
+ "1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}");
+
+ std::vector<int> test1;
+ ComparePrettyPrintToChars(test1, "std::vector of length 0, capacity 0");
+
+ std::vector<int> test2 = {5, 6, 7};
+ ComparePrettyPrintToChars(test2,
+ "std::vector of length "
+ "3, capacity 3 = {5, 6, 7}");
+
+ std::vector<int, UncompressibleAllocator<int>> test3({7, 8});
+ ComparePrettyPrintToChars(std::move(test3),
+ "std::vector of length "
+ "2, capacity 2 = {7, 8}");
+}
+
+void set_iterator_test() {
+ std::set<int> one_two_three {1111, 2222, 3333};
+ auto it = one_two_three.find(2222);
+ MarkAsLive(it);
+ CompareExpressionPrettyPrintToRegex("it",
+ R"(std::__tree_const_iterator = {\[0x[a-f0-9]+\] = 2222})");
+
+ auto not_found = one_two_three.find(1234);
+ MarkAsLive(not_found);
+ // Because the end_node is not easily detected, just be sure it doesn't crash.
+ CompareExpressionPrettyPrintToRegex("not_found",
+ R"(std::__tree_const_iterator = {\[0x[a-f0-9]+\] = .*})");
+}
+
+void map_iterator_test() {
+ std::map<int, std::string> one_two_three;
+ one_two_three.insert({1, "one"});
+ one_two_three.insert({2, "two"});
+ one_two_three.insert({3, "three"});
+ auto it = one_two_three.begin();
+ MarkAsLive(it);
+ CompareExpressionPrettyPrintToRegex("it",
+ R"(std::__map_iterator = )"
+ R"({\[0x[a-f0-9]+\] = {first = 1, second = "one"}})");
+
+ auto not_found = one_two_three.find(7);
+ MarkAsLive(not_found);
+ CompareExpressionPrettyPrintToRegex("not_found",
+ R"(std::__map_iterator = {\[0x[a-f0-9]+\] = end\(\)})");
+}
+
+void unordered_set_test() {
+ std::unordered_set<int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty, "std::unordered_set is empty");
+
+ std::unordered_set<int> numbers {12345, 67890, 222333, 12345};
+ numbers.erase(numbers.find(222333));
+ ComparePrettyPrintToRegex(numbers, "std::unordered_set with 2 elements = ");
+ ComparePrettyPrintToRegex(numbers, ".*12345.*");
+ ComparePrettyPrintToRegex(numbers, ".*67890.*");
+
+ std::unordered_set<std::string> colors {"red", "blue", "green"};
+ ComparePrettyPrintToRegex(colors, "std::unordered_set with 3 elements = ");
+ ComparePrettyPrintToRegex(colors, R"(.*"red".*)");
+ ComparePrettyPrintToRegex(colors, R"(.*"blue".*)");
+ ComparePrettyPrintToRegex(colors, R"(.*"green".*)");
+}
+
+void unordered_multiset_test() {
+ std::unordered_multiset<int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty, "std::unordered_multiset is empty");
+
+ std::unordered_multiset<int> numbers {12345, 67890, 222333, 12345};
+ ComparePrettyPrintToRegex(numbers,
+ "std::unordered_multiset with 4 elements = ");
+ ComparePrettyPrintToRegex(numbers, ".*12345.*12345.*");
+ ComparePrettyPrintToRegex(numbers, ".*67890.*");
+ ComparePrettyPrintToRegex(numbers, ".*222333.*");
+
+ std::unordered_multiset<std::string> colors {"red", "blue", "green", "red"};
+ ComparePrettyPrintToRegex(colors,
+ "std::unordered_multiset with 4 elements = ");
+ ComparePrettyPrintToRegex(colors, R"(.*"red".*"red".*)");
+ ComparePrettyPrintToRegex(colors, R"(.*"blue".*)");
+ ComparePrettyPrintToRegex(colors, R"(.*"green".*)");
+}
+
+void unordered_map_test() {
+ std::unordered_map<int, int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty, "std::unordered_map is empty");
+
+ std::unordered_map<int, std::string> one_two_three;
+ one_two_three.insert({1, "one"});
+ one_two_three.insert({2, "two"});
+ one_two_three.insert({3, "three"});
+ ComparePrettyPrintToRegex(one_two_three,
+ "std::unordered_map with 3 elements = ");
+ ComparePrettyPrintToRegex(one_two_three, R"(.*\[1\] = "one".*)");
+ ComparePrettyPrintToRegex(one_two_three, R"(.*\[2\] = "two".*)");
+ ComparePrettyPrintToRegex(one_two_three, R"(.*\[3\] = "three".*)");
+}
+
+void unordered_multimap_test() {
+ std::unordered_multimap<int, int> i_am_empty;
+ ComparePrettyPrintToChars(i_am_empty, "std::unordered_multimap is empty");
+
+ std::unordered_multimap<int, std::string> one_two_three;
+ one_two_three.insert({1, "one"});
+ one_two_three.insert({2, "two"});
+ one_two_three.insert({3, "three"});
+ one_two_three.insert({2, "two"});
+ ComparePrettyPrintToRegex(one_two_three,
+ "std::unordered_multimap with 4 elements = ");
+ ComparePrettyPrintToRegex(one_two_three, R"(.*\[1\] = "one".*)");
+ ComparePrettyPrintToRegex(one_two_three, R"(.*\[2\] = "two".*\[2\] = "two")");
+ ComparePrettyPrintToRegex(one_two_three, R"(.*\[3\] = "three".*)");
+}
+
+void unordered_map_iterator_test() {
+ std::unordered_map<int, int> ones_to_eights;
+ ones_to_eights.insert({1, 8});
+ ones_to_eights.insert({11, 88});
+ ones_to_eights.insert({111, 888});
+
+ auto ones_to_eights_begin = ones_to_eights.begin();
+ MarkAsLive(ones_to_eights_begin);
+ CompareExpressionPrettyPrintToRegex("ones_to_eights_begin",
+ R"(std::__hash_map_iterator = {\[1+\] = 8+})");
+
+ auto not_found = ones_to_eights.find(5);
+ MarkAsLive(not_found);
+ CompareExpressionPrettyPrintToRegex("not_found",
+ R"(std::__hash_map_iterator = end\(\))");
+}
+
+void unordered_set_iterator_test() {
+ std::unordered_set<int> ones;
+ ones.insert(111);
+ ones.insert(1111);
+ ones.insert(11111);
+
+ auto ones_begin = ones.begin();
+ MarkAsLive(ones_begin);
+ CompareExpressionPrettyPrintToRegex("ones_begin",
+ R"(std::__hash_const_iterator = {1+})");
+
+ auto not_found = ones.find(5);
+ MarkAsLive(not_found);
+ CompareExpressionPrettyPrintToRegex("not_found",
+ R"(std::__hash_const_iterator = end\(\))");
+}
+
+// Check that libc++ pretty printers do not handle pointers.
+void pointer_negative_test() {
+ int abc = 123;
+ int *int_ptr = &abc;
+ // Check that the result is equivalent to "p/r int_ptr" command.
+ ComparePrettyPrintToRegex(int_ptr, R"(\(int \*\) 0x[a-f0-9]+)");
+}
+
+void shared_ptr_test() {
+ // Shared ptr tests while using test framework call another function
+ // due to which there is one more count for the pointer. Hence, all the
+ // following tests are testing with expected count plus 1.
+ std::shared_ptr<const int> test0 = std::make_shared<const int>(5);
+ ComparePrettyPrintToRegex(
+ test0,
+ R"(std::shared_ptr<int> count 2, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})");
+
+ std::shared_ptr<const int> test1(test0);
+ ComparePrettyPrintToRegex(
+ test1,
+ R"(std::shared_ptr<int> count 3, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})");
+
+ {
+ std::weak_ptr<const int> test2 = test1;
+ ComparePrettyPrintToRegex(
+ test0,
+ R"(std::shared_ptr<int> count 3, weak 1 containing = {__ptr_ = 0x[a-f0-9]+})");
+ }
+
+ ComparePrettyPrintToRegex(
+ test0,
+ R"(std::shared_ptr<int> count 3, weak 0 containing = {__ptr_ = 0x[a-f0-9]+})");
+
+ std::shared_ptr<const int> test3;
+ ComparePrettyPrintToChars(test3, "std::shared_ptr is nullptr");
+}
+
+void streampos_test() {
+ std::streampos test0 = 67;
+ ComparePrettyPrintToChars(
+ test0, "std::fpos with stream offset:67 with state: {count:0 value:0}");
+ std::istringstream input("testing the input stream here");
+ std::streampos test1 = input.tellg();
+ ComparePrettyPrintToChars(
+ test1, "std::fpos with stream offset:0 with state: {count:0 value:0}");
+ std::unique_ptr<char[]> buffer(new char[5]);
+ input.read(buffer.get(), 5);
+ test1 = input.tellg();
+ ComparePrettyPrintToChars(
+ test1, "std::fpos with stream offset:5 with state: {count:0 value:0}");
+}
+
+int main(int argc, char* argv[]) {
+ framework_self_test();
+
+ string_test();
+
+ u32string_test();
+ tuple_test();
+ unique_ptr_test();
+ shared_ptr_test();
+ bitset_test();
+ list_test();
+ deque_test();
+ map_test();
+ multimap_test();
+ queue_test();
+ priority_queue_test();
+ stack_test();
+ set_test();
+ multiset_test();
+ vector_test();
+ set_iterator_test();
+ map_iterator_test();
+ unordered_set_test();
+ unordered_multiset_test();
+ unordered_map_test();
+ unordered_multimap_test();
+ unordered_map_iterator_test();
+ unordered_set_iterator_test();
+ pointer_negative_test();
+ streampos_test();
+ return 0;
+}
OpenPOWER on IntegriCloud