xref: /llvm-project/lldb/unittests/DataFormatter/StringPrinterTests.cpp (revision cfc9f3695fafddfa6f537d6dac702afab00c3cce)
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>
format(StringRef input,StringPrinter::EscapeStyle escape_style)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).
TEST(StringPrinterTests,CxxASCII)49 TEST(StringPrinterTests, CxxASCII) {
50   auto fmt = [](StringRef str) {
51     return format<StringPrinter::StringElementType::ASCII>(
52         str, 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++.
TEST(StringPrinterTests,CxxUTF8)83 TEST(StringPrinterTests, CxxUTF8) {
84   auto fmt = [](StringRef str) {
85     return format<StringPrinter::StringElementType::UTF8>(
86         str, 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.
TEST(StringPrinterTests,SwiftUTF8)117 TEST(StringPrinterTests, SwiftUTF8) {
118   auto fmt = [](StringRef str) {
119     return format<StringPrinter::StringElementType::UTF8>(
120         str, 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