1 | //===-- StringPrinterTests.cpp --------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/DataFormatters/StringPrinter.h" |
10 | #include "lldb/Utility/DataExtractor.h" |
11 | #include "lldb/Utility/Endian.h" |
12 | #include "lldb/Utility/StreamString.h" |
13 | #include "llvm/ADT/StringRef.h" |
14 | #include "llvm/Support/raw_ostream.h" |
15 | #include "gtest/gtest.h" |
16 | #include <optional> |
17 | #include <string> |
18 | |
19 | using namespace lldb; |
20 | using namespace lldb_private; |
21 | using lldb_private::formatters::StringPrinter; |
22 | using llvm::StringRef; |
23 | |
24 | #define QUOTE(x) std::string("\"" x "\"") |
25 | |
26 | /// Format \p input according to the specified string encoding and special char |
27 | /// escape style. |
28 | template <StringPrinter::StringElementType elem_ty> |
29 | static std::optional<std::string> |
30 | format(StringRef input, StringPrinter::EscapeStyle escape_style) { |
31 | StreamString out; |
32 | StringPrinter::ReadBufferAndDumpToStreamOptions opts; |
33 | opts.SetStream(&out); |
34 | opts.SetSourceSize(input.size()); |
35 | opts.SetNeedsZeroTermination(true); |
36 | opts.SetEscapeNonPrintables(true); |
37 | opts.SetIgnoreMaxLength(false); |
38 | opts.SetEscapeStyle(escape_style); |
39 | opts.SetData(DataExtractor(input.data(), input.size(), |
40 | endian::InlHostByteOrder(), sizeof(void *))); |
41 | const bool success = StringPrinter::ReadBufferAndDumpToStream<elem_ty>(opts); |
42 | if (!success) |
43 | return std::nullopt; |
44 | return out.GetString().str(); |
45 | } |
46 | |
47 | // Test ASCII formatting for C++. This behaves exactly like UTF8 formatting for |
48 | // C++, although that's questionable (see FIXME in StringPrinter.cpp). |
49 | TEST(StringPrinterTests, CxxASCII) { |
50 | auto fmt = [](StringRef str) { |
51 | return format<StringPrinter::StringElementType::ASCII>( |
52 | input: str, escape_style: StringPrinter::EscapeStyle::CXX); |
53 | }; |
54 | |
55 | // Special escapes. |
56 | EXPECT_EQ(fmt({"\0" , 1}), QUOTE("" )); |
57 | EXPECT_EQ(fmt("\a" ), QUOTE(R"(\a)" )); |
58 | EXPECT_EQ(fmt("\b" ), QUOTE(R"(\b)" )); |
59 | EXPECT_EQ(fmt("\f" ), QUOTE(R"(\f)" )); |
60 | EXPECT_EQ(fmt("\n" ), QUOTE(R"(\n)" )); |
61 | EXPECT_EQ(fmt("\r" ), QUOTE(R"(\r)" )); |
62 | EXPECT_EQ(fmt("\t" ), QUOTE(R"(\t)" )); |
63 | EXPECT_EQ(fmt("\v" ), QUOTE(R"(\v)" )); |
64 | EXPECT_EQ(fmt("\"" ), QUOTE(R"(\")" )); |
65 | EXPECT_EQ(fmt("\'" ), QUOTE(R"(')" )); |
66 | EXPECT_EQ(fmt("\\" ), QUOTE(R"(\\)" )); |
67 | |
68 | // Printable characters. |
69 | EXPECT_EQ(fmt("'" ), QUOTE("'" )); |
70 | EXPECT_EQ(fmt("a" ), QUOTE("a" )); |
71 | EXPECT_EQ(fmt("Z" ), QUOTE("Z" )); |
72 | EXPECT_EQ(fmt("🥑" ), QUOTE("🥑" )); |
73 | |
74 | // Octal (\nnn), hex (\xnn), extended octal (\unnnn or \Unnnnnnnn). |
75 | EXPECT_EQ(fmt("\uD55C" ), QUOTE("\uD55C" )); |
76 | EXPECT_EQ(fmt("\U00010348" ), QUOTE("\U00010348" )); |
77 | |
78 | EXPECT_EQ(fmt("\376" ), QUOTE(R"(\xfe)" )); // \376 is 254 in decimal. |
79 | EXPECT_EQ(fmt("\xfe" ), QUOTE(R"(\xfe)" )); // \xfe is 254 in decimal. |
80 | } |
81 | |
82 | // Test UTF8 formatting for C++. |
83 | TEST(StringPrinterTests, CxxUTF8) { |
84 | auto fmt = [](StringRef str) { |
85 | return format<StringPrinter::StringElementType::UTF8>( |
86 | input: str, escape_style: StringPrinter::EscapeStyle::CXX); |
87 | }; |
88 | |
89 | // Special escapes. |
90 | EXPECT_EQ(fmt({"\0" , 1}), QUOTE("" )); |
91 | EXPECT_EQ(fmt("\a" ), QUOTE(R"(\a)" )); |
92 | EXPECT_EQ(fmt("\b" ), QUOTE(R"(\b)" )); |
93 | EXPECT_EQ(fmt("\f" ), QUOTE(R"(\f)" )); |
94 | EXPECT_EQ(fmt("\n" ), QUOTE(R"(\n)" )); |
95 | EXPECT_EQ(fmt("\r" ), QUOTE(R"(\r)" )); |
96 | EXPECT_EQ(fmt("\t" ), QUOTE(R"(\t)" )); |
97 | EXPECT_EQ(fmt("\v" ), QUOTE(R"(\v)" )); |
98 | EXPECT_EQ(fmt("\"" ), QUOTE(R"(\")" )); |
99 | EXPECT_EQ(fmt("\'" ), QUOTE(R"(')" )); |
100 | EXPECT_EQ(fmt("\\" ), QUOTE(R"(\\)" )); |
101 | |
102 | // Printable characters. |
103 | EXPECT_EQ(fmt("'" ), QUOTE("'" )); |
104 | EXPECT_EQ(fmt("a" ), QUOTE("a" )); |
105 | EXPECT_EQ(fmt("Z" ), QUOTE("Z" )); |
106 | EXPECT_EQ(fmt("🥑" ), QUOTE("🥑" )); |
107 | |
108 | // Octal (\nnn), hex (\xnn), extended octal (\unnnn or \Unnnnnnnn). |
109 | EXPECT_EQ(fmt("\uD55C" ), QUOTE("\uD55C" )); |
110 | EXPECT_EQ(fmt("\U00010348" ), QUOTE("\U00010348" )); |
111 | |
112 | EXPECT_EQ(fmt("\376" ), QUOTE(R"(\xfe)" )); // \376 is 254 in decimal. |
113 | EXPECT_EQ(fmt("\xfe" ), QUOTE(R"(\xfe)" )); // \xfe is 254 in decimal. |
114 | } |
115 | |
116 | // Test UTF8 formatting for Swift. |
117 | TEST(StringPrinterTests, SwiftUTF8) { |
118 | auto fmt = [](StringRef str) { |
119 | return format<StringPrinter::StringElementType::UTF8>( |
120 | input: str, escape_style: StringPrinter::EscapeStyle::Swift); |
121 | }; |
122 | |
123 | // Special escapes. |
124 | EXPECT_EQ(fmt({"\0" , 1}), QUOTE("" )); |
125 | EXPECT_EQ(fmt("\a" ), QUOTE(R"(\a)" )); |
126 | EXPECT_EQ(fmt("\b" ), QUOTE(R"(\u{8})" )); |
127 | EXPECT_EQ(fmt("\f" ), QUOTE(R"(\u{c})" )); |
128 | EXPECT_EQ(fmt("\n" ), QUOTE(R"(\n)" )); |
129 | EXPECT_EQ(fmt("\r" ), QUOTE(R"(\r)" )); |
130 | EXPECT_EQ(fmt("\t" ), QUOTE(R"(\t)" )); |
131 | EXPECT_EQ(fmt("\v" ), QUOTE(R"(\u{b})" )); |
132 | EXPECT_EQ(fmt("\"" ), QUOTE(R"(\")" )); |
133 | EXPECT_EQ(fmt("\'" ), QUOTE(R"(\')" )); |
134 | EXPECT_EQ(fmt("\\" ), QUOTE(R"(\\)" )); |
135 | |
136 | // Printable characters. |
137 | EXPECT_EQ(fmt("'" ), QUOTE(R"(\')" )); |
138 | EXPECT_EQ(fmt("a" ), QUOTE("a" )); |
139 | EXPECT_EQ(fmt("Z" ), QUOTE("Z" )); |
140 | EXPECT_EQ(fmt("🥑" ), QUOTE("🥑" )); |
141 | |
142 | // Octal (\nnn), hex (\xnn), extended octal (\unnnn or \Unnnnnnnn). |
143 | EXPECT_EQ(fmt("\uD55C" ), QUOTE("\uD55C" )); |
144 | EXPECT_EQ(fmt("\U00010348" ), QUOTE("\U00010348" )); |
145 | |
146 | EXPECT_EQ(fmt("\376" ), QUOTE(R"(\u{fe})" )); // \376 is 254 in decimal. |
147 | EXPECT_EQ(fmt("\xfe" ), QUOTE(R"(\u{fe})" )); // \xfe is 254 in decimal. |
148 | } |
149 | |