Printing support enables the production of more useful error messages in unit testing e.g. when using matchers such as `UnorderedElementsAre()` to inspect the contents of a `StringMap`.
Reviewed By: gribozavr2, sgatev, ymandel
Differential Revision: https://reviews.llvm.org/D132747
--- /dev/null
+//===- llvm/Testing/ADT/StringMap.h ---------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TESTING_ADT_STRINGMAP_H_
+#define LLVM_TESTING_ADT_STRINGMAP_H_
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Testing/ADT/StringMapEntry.h"
+#include <ostream>
+#include <sstream>
+
+namespace llvm {
+
+/// Support for printing to std::ostream, for use with e.g. producing more
+/// useful error messages with Google Test.
+template <typename T>
+std::ostream &operator<<(std::ostream &OS, const StringMap<T> &M) {
+ if (M.empty()) {
+ return OS << "{ }";
+ }
+
+ std::vector<std::string> Lines;
+ for (const auto &E : M) {
+ std::ostringstream SS;
+ SS << E << ",";
+ Lines.push_back(SS.str());
+ }
+ llvm::sort(Lines);
+ Lines.insert(Lines.begin(), "{");
+ Lines.insert(Lines.end(), "}");
+
+ return OS << llvm::formatv("{0:$[\n]}",
+ make_range(Lines.begin(), Lines.end()))
+ .str();
+}
+
+} // namespace llvm
+
+#endif
--- /dev/null
+//===- llvm/Testing/ADT/StringMapEntry.h ----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TESTING_ADT_STRINGMAPENTRY_H_
+#define LLVM_TESTING_ADT_STRINGMAPENTRY_H_
+
+#include "llvm/ADT/StringMapEntry.h"
+#include <ostream>
+#include <type_traits>
+
+namespace llvm {
+namespace detail {
+
+template <typename T, typename = std::void_t<>>
+struct CanOutputToOStream : std::false_type {};
+
+template <typename T>
+struct CanOutputToOStream<T, std::void_t<decltype(std::declval<std::ostream &>()
+ << std::declval<T>())>>
+ : std::true_type {};
+
+} // namespace detail
+
+/// Support for printing to std::ostream, for use with e.g. producing more
+/// useful error messages with Google Test.
+template <typename T>
+std::ostream &operator<<(std::ostream &OS, const StringMapEntry<T> &E) {
+ OS << "{\"" << E.getKey().data() << "\": ";
+ if constexpr (detail::CanOutputToOStream<decltype(E.getValue())>::value) {
+ OS << E.getValue();
+ } else {
+ OS << "non-printable value";
+ }
+ return OS << "}";
+}
+
+} // namespace llvm
+
+#endif
--- /dev/null
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_llvm_unittest(TestingADTTests
+ StringMapTest.cpp
+ )
--- /dev/null
+//===- StringMapTest.cpp --------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Testing/ADT/StringMap.h"
+#include "llvm/ADT/StringMap.h"
+
+#include "gtest/gtest.h"
+#include <sstream>
+
+namespace llvm {
+namespace {
+
+TEST(StringMapTest, StringMapStream) {
+ std::ostringstream OS;
+ StringMap<int> Map;
+ Map["A"] = 42;
+ Map["Z"] = 35;
+ Map["B"] = 7;
+ OS << Map;
+
+ EXPECT_EQ(OS.str(), R"({
+{"A": 42},
+{"B": 7},
+{"Z": 35},
+})");
+}
+
+TEST(StringMapTest, NestedStringMapStream) {
+ std::ostringstream OS;
+ StringMap<StringMap<int>> Map;
+ Map["Z"];
+ Map["A"]["Apple"] = 5;
+ Map["B"]["Bee"] = 3;
+ Map["A"]["Axe"] = 3;
+ OS << Map;
+
+ EXPECT_EQ(OS.str(), R"({
+{"A": {
+{"Apple": 5},
+{"Axe": 3},
+}},
+{"B": {
+{"Bee": 3},
+}},
+{"Z": { }},
+})");
+}
+
+} // namespace
+} // namespace llvm
+add_subdirectory(ADT)
add_subdirectory(Support)
)
cc_library(
+ name = "TestingADT",
+ testonly = True,
+ hdrs = glob([
+ "include/llvm/Testing/ADT/*.h",
+ ]),
+ copts = llvm_copts,
+ deps = [":Support"],
+)
+
+cc_library(
name = "TestingSupport",
testonly = True,
srcs = glob([
)
cc_test(
+ name = "testing_adt_tests",
+ size = "small",
+ srcs = glob(
+ [
+ "Testing/ADT/*.cpp",
+ ],
+ allow_empty = False,
+ ),
+ deps = [
+ "//llvm:Support",
+ "//llvm:TestingADT",
+ "//llvm:gtest",
+ "//llvm:gtest_main",
+ ],
+)
+
+cc_test(
name = "transforms_tests",
size = "small",
srcs = glob(