1 | //===----------------------------------------------------------------------===// |
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 | // REQUIRES: host-has-gdb-with-python |
10 | // REQUIRES: locale.en_US.UTF-8 |
11 | // UNSUPPORTED: no-localization |
12 | // UNSUPPORTED: c++03 |
13 | |
14 | // TODO: Investigate these failures which break the CI. |
15 | // UNSUPPORTED: clang-17, clang-18, clang-19 |
16 | |
17 | // TODO: Investigate this failure on GCC 13 (in Ubuntu Jammy) |
18 | // UNSUPPORTED: gcc-13 |
19 | |
20 | // The Android libc++ tests are run on a non-Android host, connected to an |
21 | // Android device over adb. gdb needs special support to make this work (e.g. |
22 | // gdbclient.py, ndk-gdb.py, gdbserver), and the Android organization doesn't |
23 | // support gdb anymore, favoring lldb instead. |
24 | // UNSUPPORTED: android |
25 | |
26 | // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags} |
27 | // Ensure locale-independence for unicode tests. |
28 | // RUN: env LANG=en_US.UTF-8 %{gdb} -nx -batch -iex "set autoload off" -ex "source %S/../../../utils/gdb/libcxx/printers.py" -ex "python register_libcxx_printer_loader()" -ex "source %S/gdb_pretty_printer_test.py" %t.exe |
29 | |
30 | #include <bitset> |
31 | #include <deque> |
32 | #include <list> |
33 | #include <map> |
34 | #include <memory> |
35 | #include <queue> |
36 | #include <set> |
37 | #include <sstream> |
38 | #include <stack> |
39 | #include <string> |
40 | #include <tuple> |
41 | #include <unordered_map> |
42 | #include <unordered_set> |
43 | |
44 | #include "test_macros.h" |
45 | |
46 | // To write a pretty-printer test: |
47 | // |
48 | // 1. Declare a variable of the type you want to test |
49 | // |
50 | // 2. Set its value to something which will test the pretty printer in an |
51 | // interesting way. |
52 | // |
53 | // 3. Call ComparePrettyPrintToChars with that variable, and a "const char*" |
54 | // value to compare to the printer's output. |
55 | // |
56 | // Or |
57 | // |
58 | // Call ComparePrettyPrintToRegex with that variable, and a "const char*" |
59 | // *python* regular expression to match against the printer's output. |
60 | // The set of special characters in a Python regular expression overlaps |
61 | // with a lot of things the pretty printers print--brackets, for |
62 | // example--so take care to escape appropriately. |
63 | // |
64 | // Alternatively, construct a string that gdb can parse as an expression, |
65 | // so that printing the value of the expression will test the pretty printer |
66 | // in an interesting way. Then, call CompareExpressionPrettyPrintToChars or |
67 | // CompareExpressionPrettyPrintToRegex to compare the printer's output. |
68 | |
69 | // Avoids setting a breakpoint in every-single instantiation of |
70 | // ComparePrettyPrintTo*. Also, make sure neither it, nor the |
71 | // variables we need present in the Compare functions are optimized |
72 | // away. |
73 | #ifdef TEST_COMPILER_GCC |
74 | #define OPT_NONE __attribute__((noinline)) |
75 | #else |
76 | #define OPT_NONE __attribute__((optnone)) |
77 | #endif |
78 | void StopForDebugger(void *, void *) OPT_NONE; |
79 | void StopForDebugger(void *, void *) {} |
80 | |
81 | |
82 | // Prevents the compiler optimizing away the parameter in the caller function. |
83 | template <typename Type> |
84 | void MarkAsLive(Type &&) OPT_NONE; |
85 | template <typename Type> |
86 | void MarkAsLive(Type &&) {} |
87 | |
88 | // In all of the Compare(Expression)PrettyPrintTo(Regex/Chars) functions below, |
89 | // the python script sets a breakpoint just before the call to StopForDebugger, |
90 | // compares the result to the expectation. |
91 | // |
92 | // The expectation is a literal string to be matched exactly in |
93 | // *PrettyPrintToChars functions, and is a python regular expression in |
94 | // *PrettyPrintToRegex functions. |
95 | // |
96 | // In ComparePrettyPrint* functions, the value is a variable of any type. In |
97 | // CompareExpressionPrettyPrint functions, the value is a string expression that |
98 | // gdb will parse and print the result. |
99 | // |
100 | // The python script will print either "PASS", or a detailed failure explanation |
101 | // along with the line that has invoke the function. The testing will continue |
102 | // in either case. |
103 | |
104 | template <typename TypeToPrint> void ComparePrettyPrintToChars( |
105 | TypeToPrint value, |
106 | const char *expectation) { |
107 | MarkAsLive(value); |
108 | StopForDebugger(&value, &expectation); |
109 | } |
110 | |
111 | template <typename TypeToPrint> void ComparePrettyPrintToRegex( |
112 | TypeToPrint value, |
113 | const char *expectation) { |
114 | MarkAsLive(value); |
115 | StopForDebugger(&value, &expectation); |
116 | } |
117 | |
118 | void CompareExpressionPrettyPrintToChars( |
119 | std::string value, |
120 | const char *expectation) { |
121 | MarkAsLive(value); |
122 | StopForDebugger(&value, &expectation); |
123 | } |
124 | |
125 | void CompareExpressionPrettyPrintToRegex( |
126 | std::string value, |
127 | const char *expectation) { |
128 | MarkAsLive(value); |
129 | StopForDebugger(&value, &expectation); |
130 | } |
131 | |
132 | namespace example { |
133 | struct example_struct { |
134 | int a = 0; |
135 | int arr[1000]; |
136 | }; |
137 | } |
138 | |
139 | // If enabled, the self test will "fail"--because we want to be sure it properly |
140 | // diagnoses tests that *should* fail. Evaluate the output by hand. |
141 | void framework_self_test() { |
142 | #ifdef FRAMEWORK_SELF_TEST |
143 | // Use the most simple data structure we can. |
144 | const char a = 'a'; |
145 | |
146 | // Tests that should pass |
147 | ComparePrettyPrintToChars(a, "97 'a'" ); |
148 | ComparePrettyPrintToRegex(a, ".*" ); |
149 | |
150 | // Tests that should fail. |
151 | ComparePrettyPrintToChars(a, "b" ); |
152 | ComparePrettyPrintToRegex(a, "b" ); |
153 | #endif |
154 | } |
155 | |
156 | // A simple pass-through allocator to check that we handle CompressedPair |
157 | // correctly. |
158 | template <typename T> class UncompressibleAllocator : public std::allocator<T> { |
159 | public: |
160 | char X; |
161 | }; |
162 | |
163 | void string_test() { |
164 | std::string short_string("kdjflskdjf" ); |
165 | // The display_hint "string" adds quotes the printed result. |
166 | ComparePrettyPrintToChars(value: short_string, expectation: "\"kdjflskdjf\"" ); |
167 | |
168 | std::basic_string<char, std::char_traits<char>, UncompressibleAllocator<char>> |
169 | long_string("mehmet bizim dostumuz agzi kirik testimiz" ); |
170 | ComparePrettyPrintToChars(value: long_string, |
171 | expectation: "\"mehmet bizim dostumuz agzi kirik testimiz\"" ); |
172 | } |
173 | |
174 | namespace a_namespace { |
175 | // To test name-lookup in the presence of using inside a namespace. Inside this |
176 | // namespace, unqualified string_view variables will appear in the debug info as |
177 | // "a_namespace::string_view, rather than "std::string_view". |
178 | // |
179 | // There is nothing special here about string_view; it's just the data structure |
180 | // where lookup with using inside a namespace wasn't always working. |
181 | |
182 | using string_view = std::string_view; |
183 | |
184 | void string_view_test() { |
185 | std::string_view i_am_empty; |
186 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "\"\"" ); |
187 | |
188 | std::string source_string("to be or not to be" ); |
189 | std::string_view to_be(source_string); |
190 | ComparePrettyPrintToChars(value: to_be, expectation: "\"to be or not to be\"" ); |
191 | |
192 | const char char_arr[] = "what a wonderful world" ; |
193 | std::string_view wonderful(&char_arr[7], 9); |
194 | ComparePrettyPrintToChars(value: wonderful, expectation: "\"wonderful\"" ); |
195 | |
196 | const char char_arr1[] = "namespace_stringview" ; |
197 | string_view namespace_stringview(&char_arr1[10], 10); |
198 | ComparePrettyPrintToChars(value: namespace_stringview, expectation: "\"stringview\"" ); |
199 | } |
200 | } |
201 | |
202 | void u16string_test() { |
203 | std::u16string test0 = u"Hello World" ; |
204 | ComparePrettyPrintToChars(value: test0, expectation: "u\"Hello World\"" ); |
205 | std::u16string test1 = u"\U00010196\u20AC\u00A3\u0024" ; |
206 | ComparePrettyPrintToChars(value: test1, expectation: "u\"\U00010196\u20AC\u00A3\u0024\"" ); |
207 | std::u16string test2 = u"\u0024\u0025\u0026\u0027" ; |
208 | ComparePrettyPrintToChars(value: test2, expectation: "u\"\u0024\u0025\u0026\u0027\"" ); |
209 | std::u16string test3 = u"mehmet bizim dostumuz agzi kirik testimiz" ; |
210 | ComparePrettyPrintToChars(value: test3, |
211 | expectation: ("u\"mehmet bizim dostumuz agzi kirik testimiz\"" )); |
212 | } |
213 | |
214 | void u32string_test() { |
215 | std::u32string test0 = U"Hello World" ; |
216 | ComparePrettyPrintToChars(value: test0, expectation: "U\"Hello World\"" ); |
217 | std::u32string test1 = |
218 | U"\U0001d552\U0001d553\U0001d554\U0001d555\U0001d556\U0001d557" ; |
219 | ComparePrettyPrintToChars( |
220 | value: test1, |
221 | expectation: ("U\"\U0001d552\U0001d553\U0001d554\U0001d555\U0001d556\U0001d557\"" )); |
222 | std::u32string test2 = U"\U00004f60\U0000597d" ; |
223 | ComparePrettyPrintToChars(value: test2, expectation: ("U\"\U00004f60\U0000597d\"" )); |
224 | std::u32string test3 = U"mehmet bizim dostumuz agzi kirik testimiz" ; |
225 | ComparePrettyPrintToChars(value: test3, expectation: ("U\"mehmet bizim dostumuz agzi kirik testimiz\"" )); |
226 | } |
227 | |
228 | void tuple_test() { |
229 | std::tuple<int, int, int> test0(2, 3, 4); |
230 | ComparePrettyPrintToChars( |
231 | value: test0, |
232 | expectation: "std::tuple containing = {[1] = 2, [2] = 3, [3] = 4}" ); |
233 | |
234 | std::tuple<> test1; |
235 | ComparePrettyPrintToChars( |
236 | value: test1, |
237 | expectation: "empty std::tuple" ); |
238 | } |
239 | |
240 | void unique_ptr_test() { |
241 | std::unique_ptr<std::string> matilda(new std::string("Matilda" )); |
242 | ComparePrettyPrintToRegex( |
243 | value: std::move(matilda), |
244 | expectation: R"(std::unique_ptr<std::string> containing = {__ptr_ = 0x[a-f0-9]+})" ); |
245 | std::unique_ptr<int> forty_two(new int(42)); |
246 | ComparePrettyPrintToRegex(value: std::move(forty_two), |
247 | expectation: R"(std::unique_ptr<int> containing = {__ptr_ = 0x[a-f0-9]+})" ); |
248 | |
249 | std::unique_ptr<int> this_is_null; |
250 | ComparePrettyPrintToChars(value: std::move(this_is_null), |
251 | expectation: R"(std::unique_ptr is nullptr)" ); |
252 | } |
253 | |
254 | void bitset_test() { |
255 | std::bitset<258> i_am_empty(0); |
256 | ComparePrettyPrintToRegex(value: i_am_empty, expectation: "std::bitset<258(u|ul)?>" ); |
257 | |
258 | std::bitset<0> very_empty; |
259 | ComparePrettyPrintToRegex(value: very_empty, expectation: "std::bitset<0(u|ul)?>" ); |
260 | |
261 | std::bitset<15> b_000001111111100(1020); |
262 | ComparePrettyPrintToRegex(value: b_000001111111100, |
263 | expectation: R"(std::bitset<15(u|ul)?> = {\[2\] = 1, \[3\] = 1, \[4\] = 1, \[5\] = 1, \[6\] = 1, )" |
264 | R"(\[7\] = 1, \[8\] = 1, \[9\] = 1})" ); |
265 | |
266 | std::bitset<258> b_0_129_132(0); |
267 | b_0_129_132[0] = true; |
268 | b_0_129_132[129] = true; |
269 | b_0_129_132[132] = true; |
270 | ComparePrettyPrintToRegex(value: b_0_129_132, |
271 | expectation: R"(std::bitset<258(u|ul)?> = {\[0\] = 1, \[129\] = 1, \[132\] = 1})" ); |
272 | } |
273 | |
274 | void list_test() { |
275 | std::list<int> i_am_empty{}; |
276 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::list is empty" ); |
277 | |
278 | std::list<int> one_two_three {1, 2, 3}; |
279 | ComparePrettyPrintToChars(value: one_two_three, |
280 | expectation: "std::list with 3 elements = {1, 2, 3}" ); |
281 | |
282 | std::list<std::string> colors {"red" , "blue" , "green" }; |
283 | ComparePrettyPrintToChars(value: colors, |
284 | expectation: R"(std::list with 3 elements = {"red", "blue", "green"})" ); |
285 | } |
286 | |
287 | void deque_test() { |
288 | std::deque<int> i_am_empty{}; |
289 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::deque is empty" ); |
290 | |
291 | std::deque<int> one_two_three {1, 2, 3}; |
292 | ComparePrettyPrintToChars(value: one_two_three, |
293 | expectation: "std::deque with 3 elements = {1, 2, 3}" ); |
294 | |
295 | std::deque<example::example_struct> bfg; |
296 | for (int i = 0; i < 10; ++i) { |
297 | example::example_struct current; |
298 | current.a = i; |
299 | bfg.push_back(x: current); |
300 | } |
301 | for (int i = 0; i < 3; ++i) { |
302 | bfg.pop_front(); |
303 | } |
304 | for (int i = 0; i < 3; ++i) { |
305 | bfg.pop_back(); |
306 | } |
307 | ComparePrettyPrintToRegex(value: bfg, |
308 | expectation: "std::deque with 4 elements = {" |
309 | "{a = 3, arr = {[^}]+}}, " |
310 | "{a = 4, arr = {[^}]+}}, " |
311 | "{a = 5, arr = {[^}]+}}, " |
312 | "{a = 6, arr = {[^}]+}}}" ); |
313 | } |
314 | |
315 | void map_test() { |
316 | std::map<int, int> i_am_empty{}; |
317 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::map is empty" ); |
318 | |
319 | std::map<int, std::string> one_two_three; |
320 | one_two_three.insert(x: {1, "one" }); |
321 | one_two_three.insert(x: {2, "two" }); |
322 | one_two_three.insert(x: {3, "three" }); |
323 | ComparePrettyPrintToChars(value: one_two_three, |
324 | expectation: "std::map with 3 elements = " |
325 | R"({[1] = "one", [2] = "two", [3] = "three"})" ); |
326 | |
327 | std::map<int, example::example_struct> bfg; |
328 | for (int i = 0; i < 4; ++i) { |
329 | example::example_struct current; |
330 | current.a = 17 * i; |
331 | bfg.insert(x: {i, current}); |
332 | } |
333 | ComparePrettyPrintToRegex(value: bfg, |
334 | expectation: R"(std::map with 4 elements = {)" |
335 | R"(\[0\] = {a = 0, arr = {[^}]+}}, )" |
336 | R"(\[1\] = {a = 17, arr = {[^}]+}}, )" |
337 | R"(\[2\] = {a = 34, arr = {[^}]+}}, )" |
338 | R"(\[3\] = {a = 51, arr = {[^}]+}}})" ); |
339 | } |
340 | |
341 | void multimap_test() { |
342 | std::multimap<int, int> i_am_empty{}; |
343 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::multimap is empty" ); |
344 | |
345 | std::multimap<int, std::string> one_two_three; |
346 | one_two_three.insert(x: {1, "one" }); |
347 | one_two_three.insert(x: {3, "three" }); |
348 | one_two_three.insert(x: {1, "ein" }); |
349 | one_two_three.insert(x: {2, "two" }); |
350 | one_two_three.insert(x: {2, "zwei" }); |
351 | one_two_three.insert(x: {1, "bir" }); |
352 | |
353 | ComparePrettyPrintToChars(value: one_two_three, |
354 | expectation: "std::multimap with 6 elements = " |
355 | R"({[1] = "one", [1] = "ein", [1] = "bir", )" |
356 | R"([2] = "two", [2] = "zwei", [3] = "three"})" ); |
357 | } |
358 | |
359 | void queue_test() { |
360 | std::queue<int> i_am_empty; |
361 | ComparePrettyPrintToChars(value: i_am_empty, |
362 | expectation: "std::queue wrapping = {std::deque is empty}" ); |
363 | |
364 | std::queue<int> one_two_three(std::deque<int>{1, 2, 3}); |
365 | ComparePrettyPrintToChars(value: one_two_three, |
366 | expectation: "std::queue wrapping = {" |
367 | "std::deque with 3 elements = {1, 2, 3}}" ); |
368 | } |
369 | |
370 | void priority_queue_test() { |
371 | std::priority_queue<int> i_am_empty; |
372 | ComparePrettyPrintToChars(value: i_am_empty, |
373 | expectation: "std::priority_queue wrapping = {std::vector of length 0, capacity 0}" ); |
374 | |
375 | std::priority_queue<int> one_two_three; |
376 | one_two_three.push(x: 11111); |
377 | one_two_three.push(x: 22222); |
378 | one_two_three.push(x: 33333); |
379 | |
380 | ComparePrettyPrintToRegex(value: one_two_three, |
381 | expectation: R"(std::priority_queue wrapping = )" |
382 | R"({std::vector of length 3, capacity 3 = {33333)" ); |
383 | |
384 | ComparePrettyPrintToRegex(value: one_two_three, expectation: ".*11111.*" ); |
385 | ComparePrettyPrintToRegex(value: one_two_three, expectation: ".*22222.*" ); |
386 | } |
387 | |
388 | void set_test() { |
389 | std::set<int> i_am_empty; |
390 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::set is empty" ); |
391 | |
392 | std::set<int> one_two_three {3, 1, 2}; |
393 | ComparePrettyPrintToChars(value: one_two_three, |
394 | expectation: "std::set with 3 elements = {1, 2, 3}" ); |
395 | |
396 | std::set<std::pair<int, int>> prime_pairs { |
397 | std::make_pair(x: 3, y: 5), std::make_pair(x: 5, y: 7), std::make_pair(x: 3, y: 5)}; |
398 | |
399 | ComparePrettyPrintToChars(value: prime_pairs, |
400 | expectation: "std::set with 2 elements = {" |
401 | "{first = 3, second = 5}, {first = 5, second = 7}}" ); |
402 | |
403 | using using_set = std::set<int>; |
404 | using_set other{1, 2, 3}; |
405 | ComparePrettyPrintToChars(value: other, expectation: "std::set with 3 elements = {1, 2, 3}" ); |
406 | } |
407 | |
408 | void stack_test() { |
409 | std::stack<int> test0; |
410 | ComparePrettyPrintToChars(value: test0, |
411 | expectation: "std::stack wrapping = {std::deque is empty}" ); |
412 | test0.push(x: 5); |
413 | test0.push(x: 6); |
414 | ComparePrettyPrintToChars( |
415 | value: test0, expectation: "std::stack wrapping = {std::deque with 2 elements = {5, 6}}" ); |
416 | std::stack<bool> test1; |
417 | test1.push(x: true); |
418 | test1.push(x: false); |
419 | ComparePrettyPrintToChars( |
420 | value: test1, |
421 | expectation: "std::stack wrapping = {std::deque with 2 elements = {true, false}}" ); |
422 | |
423 | std::stack<std::string> test2; |
424 | test2.push(x: "Hello" ); |
425 | test2.push(x: "World" ); |
426 | ComparePrettyPrintToChars(value: test2, |
427 | expectation: "std::stack wrapping = {std::deque with 2 elements " |
428 | "= {\"Hello\", \"World\"}}" ); |
429 | } |
430 | |
431 | void multiset_test() { |
432 | std::multiset<int> i_am_empty; |
433 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::multiset is empty" ); |
434 | |
435 | std::multiset<std::string> one_two_three {"1:one" , "2:two" , "3:three" , "1:one" }; |
436 | ComparePrettyPrintToChars(value: one_two_three, |
437 | expectation: "std::multiset with 4 elements = {" |
438 | R"("1:one", "1:one", "2:two", "3:three"})" ); |
439 | } |
440 | |
441 | void vector_test() { |
442 | std::vector<bool> test0 = {true, false}; |
443 | ComparePrettyPrintToRegex(value: test0, |
444 | expectation: "std::vector<bool> of " |
445 | "length 2, capacity (32|64) = {1, 0}" ); |
446 | for (int i = 0; i < 31; ++i) { |
447 | test0.push_back(x: true); |
448 | test0.push_back(x: false); |
449 | } |
450 | ComparePrettyPrintToRegex( |
451 | value: test0, |
452 | expectation: "std::vector<bool> of length 64, " |
453 | "capacity 64 = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, " |
454 | "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, " |
455 | "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}" ); |
456 | test0.push_back(x: true); |
457 | ComparePrettyPrintToRegex( |
458 | value: test0, |
459 | expectation: "std::vector<bool> of length 65, " |
460 | "capacity (96|128) = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, " |
461 | "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, " |
462 | "0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}" ); |
463 | |
464 | std::vector<int> test1; |
465 | ComparePrettyPrintToChars(value: test1, expectation: "std::vector of length 0, capacity 0" ); |
466 | |
467 | std::vector<int> test2 = {5, 6, 7}; |
468 | ComparePrettyPrintToChars(value: test2, |
469 | expectation: "std::vector of length " |
470 | "3, capacity 3 = {5, 6, 7}" ); |
471 | |
472 | std::vector<int, UncompressibleAllocator<int>> test3({7, 8}); |
473 | ComparePrettyPrintToChars(value: std::move(test3), |
474 | expectation: "std::vector of length " |
475 | "2, capacity 2 = {7, 8}" ); |
476 | } |
477 | |
478 | void set_iterator_test() { |
479 | std::set<int> one_two_three {1111, 2222, 3333}; |
480 | auto it = one_two_three.find(x: 2222); |
481 | MarkAsLive(it); |
482 | CompareExpressionPrettyPrintToRegex(value: "it" , |
483 | expectation: R"(std::__tree_const_iterator = {\[0x[a-f0-9]+\] = 2222})" ); |
484 | |
485 | auto not_found = one_two_three.find(x: 1234); |
486 | MarkAsLive(not_found); |
487 | // Because the end_node is not easily detected, just be sure it doesn't crash. |
488 | CompareExpressionPrettyPrintToRegex(value: "not_found" , |
489 | expectation: R"(std::__tree_const_iterator ( = {\[0x[a-f0-9]+\] = .*}|<error reading variable:.*>))" ); |
490 | } |
491 | |
492 | void map_iterator_test() { |
493 | std::map<int, std::string> one_two_three; |
494 | one_two_three.insert(x: {1, "one" }); |
495 | one_two_three.insert(x: {2, "two" }); |
496 | one_two_three.insert(x: {3, "three" }); |
497 | auto it = one_two_three.begin(); |
498 | MarkAsLive(it); |
499 | CompareExpressionPrettyPrintToRegex(value: "it" , |
500 | expectation: R"(std::__map_iterator = )" |
501 | R"({\[0x[a-f0-9]+\] = {first = 1, second = "one"}})" ); |
502 | |
503 | auto not_found = one_two_three.find(x: 7); |
504 | MarkAsLive(not_found); |
505 | // Because the end_node is not easily detected, just be sure it doesn't crash. |
506 | CompareExpressionPrettyPrintToRegex( |
507 | value: "not_found" , expectation: R"(std::__map_iterator ( = {\[0x[a-f0-9]+\] = .*}|<error reading variable:.*>))" ); |
508 | } |
509 | |
510 | void unordered_set_test() { |
511 | std::unordered_set<int> i_am_empty; |
512 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::unordered_set is empty" ); |
513 | |
514 | std::unordered_set<int> numbers {12345, 67890, 222333, 12345}; |
515 | numbers.erase(position: numbers.find(x: 222333)); |
516 | ComparePrettyPrintToRegex(value: numbers, expectation: "std::unordered_set with 2 elements = " ); |
517 | ComparePrettyPrintToRegex(value: numbers, expectation: ".*12345.*" ); |
518 | ComparePrettyPrintToRegex(value: numbers, expectation: ".*67890.*" ); |
519 | |
520 | std::unordered_set<std::string> colors {"red" , "blue" , "green" }; |
521 | ComparePrettyPrintToRegex(value: colors, expectation: "std::unordered_set with 3 elements = " ); |
522 | ComparePrettyPrintToRegex(value: colors, expectation: R"(.*"red".*)" ); |
523 | ComparePrettyPrintToRegex(value: colors, expectation: R"(.*"blue".*)" ); |
524 | ComparePrettyPrintToRegex(value: colors, expectation: R"(.*"green".*)" ); |
525 | } |
526 | |
527 | void unordered_multiset_test() { |
528 | std::unordered_multiset<int> i_am_empty; |
529 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::unordered_multiset is empty" ); |
530 | |
531 | std::unordered_multiset<int> numbers {12345, 67890, 222333, 12345}; |
532 | ComparePrettyPrintToRegex(value: numbers, |
533 | expectation: "std::unordered_multiset with 4 elements = " ); |
534 | ComparePrettyPrintToRegex(value: numbers, expectation: ".*12345.*12345.*" ); |
535 | ComparePrettyPrintToRegex(value: numbers, expectation: ".*67890.*" ); |
536 | ComparePrettyPrintToRegex(value: numbers, expectation: ".*222333.*" ); |
537 | |
538 | std::unordered_multiset<std::string> colors {"red" , "blue" , "green" , "red" }; |
539 | ComparePrettyPrintToRegex(value: colors, |
540 | expectation: "std::unordered_multiset with 4 elements = " ); |
541 | ComparePrettyPrintToRegex(value: colors, expectation: R"(.*"red".*"red".*)" ); |
542 | ComparePrettyPrintToRegex(value: colors, expectation: R"(.*"blue".*)" ); |
543 | ComparePrettyPrintToRegex(value: colors, expectation: R"(.*"green".*)" ); |
544 | } |
545 | |
546 | void unordered_map_test() { |
547 | std::unordered_map<int, int> i_am_empty; |
548 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::unordered_map is empty" ); |
549 | |
550 | std::unordered_map<int, std::string> one_two_three; |
551 | one_two_three.insert(x: {1, "one" }); |
552 | one_two_three.insert(x: {2, "two" }); |
553 | one_two_three.insert(x: {3, "three" }); |
554 | ComparePrettyPrintToRegex(value: one_two_three, |
555 | expectation: "std::unordered_map with 3 elements = " ); |
556 | ComparePrettyPrintToRegex(value: one_two_three, expectation: R"(.*\[1\] = "one".*)" ); |
557 | ComparePrettyPrintToRegex(value: one_two_three, expectation: R"(.*\[2\] = "two".*)" ); |
558 | ComparePrettyPrintToRegex(value: one_two_three, expectation: R"(.*\[3\] = "three".*)" ); |
559 | } |
560 | |
561 | void unordered_multimap_test() { |
562 | std::unordered_multimap<int, int> i_am_empty; |
563 | ComparePrettyPrintToChars(value: i_am_empty, expectation: "std::unordered_multimap is empty" ); |
564 | |
565 | std::unordered_multimap<int, std::string> one_two_three; |
566 | one_two_three.insert(x: {1, "one" }); |
567 | one_two_three.insert(x: {2, "two" }); |
568 | one_two_three.insert(x: {3, "three" }); |
569 | one_two_three.insert(x: {2, "two" }); |
570 | ComparePrettyPrintToRegex(value: one_two_three, |
571 | expectation: "std::unordered_multimap with 4 elements = " ); |
572 | ComparePrettyPrintToRegex(value: one_two_three, expectation: R"(.*\[1\] = "one".*)" ); |
573 | ComparePrettyPrintToRegex(value: one_two_three, expectation: R"(.*\[2\] = "two".*\[2\] = "two")" ); |
574 | ComparePrettyPrintToRegex(value: one_two_three, expectation: R"(.*\[3\] = "three".*)" ); |
575 | } |
576 | |
577 | void unordered_map_iterator_test() { |
578 | std::unordered_map<int, int> ones_to_eights; |
579 | ones_to_eights.insert(x: {1, 8}); |
580 | ones_to_eights.insert(x: {11, 88}); |
581 | ones_to_eights.insert(x: {111, 888}); |
582 | |
583 | auto ones_to_eights_begin = ones_to_eights.begin(); |
584 | MarkAsLive(ones_to_eights_begin); |
585 | CompareExpressionPrettyPrintToRegex(value: "ones_to_eights_begin" , |
586 | expectation: R"(std::__hash_map_iterator = {\[1+\] = 8+})" ); |
587 | |
588 | auto not_found = ones_to_eights.find(x: 5); |
589 | MarkAsLive(not_found); |
590 | CompareExpressionPrettyPrintToRegex(value: "not_found" , |
591 | expectation: R"(std::__hash_map_iterator = end\(\))" ); |
592 | } |
593 | |
594 | void unordered_set_iterator_test() { |
595 | std::unordered_set<int> ones; |
596 | ones.insert(x: 111); |
597 | ones.insert(x: 1111); |
598 | ones.insert(x: 11111); |
599 | |
600 | auto ones_begin = ones.begin(); |
601 | MarkAsLive(ones_begin); |
602 | CompareExpressionPrettyPrintToRegex(value: "ones_begin" , |
603 | expectation: R"(std::__hash_const_iterator = {1+})" ); |
604 | |
605 | auto not_found = ones.find(x: 5); |
606 | MarkAsLive(not_found); |
607 | CompareExpressionPrettyPrintToRegex(value: "not_found" , |
608 | expectation: R"(std::__hash_const_iterator = end\(\))" ); |
609 | } |
610 | |
611 | // Check that libc++ pretty printers do not handle pointers. |
612 | void pointer_negative_test() { |
613 | int abc = 123; |
614 | int *int_ptr = &abc; |
615 | // Check that the result is equivalent to "p/r int_ptr" command. |
616 | ComparePrettyPrintToRegex(value: int_ptr, expectation: R"(\(int \*\) 0x[a-f0-9]+)" ); |
617 | } |
618 | |
619 | void shared_ptr_test() { |
620 | // Shared ptr tests while using test framework call another function |
621 | // due to which there is one more count for the pointer. Hence, all the |
622 | // following tests are testing with expected count plus 1. |
623 | std::shared_ptr<const int> test0 = std::make_shared<const int>(args: 5); |
624 | // The python regular expression matcher treats newlines as significant, so |
625 | // these regular expressions should be on one line. |
626 | ComparePrettyPrintToRegex( |
627 | value: test0, |
628 | expectation: R"(std::shared_ptr<int> count [2\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})" ); |
629 | |
630 | std::shared_ptr<const int> test1(test0); |
631 | ComparePrettyPrintToRegex( |
632 | value: test1, |
633 | expectation: R"(std::shared_ptr<int> count [3\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})" ); |
634 | |
635 | { |
636 | std::weak_ptr<const int> test2 = test1; |
637 | ComparePrettyPrintToRegex( |
638 | value: test0, |
639 | expectation: R"(std::shared_ptr<int> count [3\?], weak [1\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})" ); |
640 | } |
641 | |
642 | ComparePrettyPrintToRegex( |
643 | value: test0, |
644 | expectation: R"(std::shared_ptr<int> count [3\?], weak [0\?]( \(libc\+\+ missing debug info\))? containing = {__ptr_ = 0x[a-f0-9]+})" ); |
645 | |
646 | std::shared_ptr<const int> test3; |
647 | ComparePrettyPrintToChars(value: test3, expectation: "std::shared_ptr is nullptr" ); |
648 | } |
649 | |
650 | void streampos_test() { |
651 | std::streampos test0 = 67; |
652 | ComparePrettyPrintToRegex(value: test0, expectation: "^std::fpos with stream offset:67( with state: {count:0 value:0})?$" ); |
653 | std::istringstream input("testing the input stream here" ); |
654 | std::streampos test1 = input.tellg(); |
655 | ComparePrettyPrintToRegex(value: test1, expectation: "^std::fpos with stream offset:0( with state: {count:0 value:0})?$" ); |
656 | std::unique_ptr<char[]> buffer(new char[5]); |
657 | input.read(s: buffer.get(), n: 5); |
658 | test1 = input.tellg(); |
659 | ComparePrettyPrintToRegex(value: test1, expectation: "^std::fpos with stream offset:5( with state: {count:0 value:0})?$" ); |
660 | } |
661 | |
662 | int main(int, char**) { |
663 | framework_self_test(); |
664 | |
665 | string_test(); |
666 | a_namespace::string_view_test(); |
667 | |
668 | //u16string_test(); |
669 | u32string_test(); |
670 | tuple_test(); |
671 | unique_ptr_test(); |
672 | shared_ptr_test(); |
673 | bitset_test(); |
674 | list_test(); |
675 | deque_test(); |
676 | map_test(); |
677 | multimap_test(); |
678 | queue_test(); |
679 | priority_queue_test(); |
680 | stack_test(); |
681 | set_test(); |
682 | multiset_test(); |
683 | vector_test(); |
684 | set_iterator_test(); |
685 | map_iterator_test(); |
686 | unordered_set_test(); |
687 | unordered_multiset_test(); |
688 | unordered_map_test(); |
689 | unordered_multimap_test(); |
690 | unordered_map_iterator_test(); |
691 | unordered_set_iterator_test(); |
692 | pointer_negative_test(); |
693 | streampos_test(); |
694 | return 0; |
695 | } |
696 | |