1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gn/functions.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "gn/parse_tree.h"
11 #include "gn/test_with_scope.h"
12 #include "gn/value.h"
13 #include "util/test/test.h"
14
TEST(Functions,Assert)15 TEST(Functions, Assert) {
16 TestWithScope setup;
17
18 // Verify cases where the assertion passes.
19 std::vector<std::string> assert_pass_examples = {
20 R"gn(assert(true))gn",
21 R"gn(assert(true, "This message is ignored for passed assertions."))gn",
22 };
23 for (const auto& assert_pass_example : assert_pass_examples) {
24 TestParseInput input(assert_pass_example);
25 ASSERT_FALSE(input.has_error());
26 Err err;
27 input.parsed()->Execute(setup.scope(), &err);
28 ASSERT_FALSE(err.has_error()) << assert_pass_example;
29 }
30
31 // Verify case where the assertion fails, with no message.
32 {
33 TestParseInput input("assert(false)");
34 ASSERT_FALSE(input.has_error());
35 Err err;
36 input.parsed()->Execute(setup.scope(), &err);
37 ASSERT_TRUE(err.has_error());
38 ASSERT_EQ(err.message(), "Assertion failed.");
39 }
40
41 // Verify case where the assertion fails, with a message.
42 {
43 TestParseInput input("assert(false, \"What failed\")");
44 ASSERT_FALSE(input.has_error());
45 Err err;
46 input.parsed()->Execute(setup.scope(), &err);
47 ASSERT_TRUE(err.has_error());
48 ASSERT_EQ(err.message(), "Assertion failed.");
49 ASSERT_EQ(err.help_text(), "What failed");
50 }
51
52 // Verify usage errors are detected.
53 std::vector<std::string> bad_usage_examples = {
54 // Number of arguments.
55 R"gn(assert())gn",
56 R"gn(assert(1, 2, 3))gn",
57
58 // Argument types.
59 R"gn(assert(1))gn",
60 R"gn(assert("oops"))gn",
61 R"gn(assert(true, 1))gn",
62 R"gn(assert(true, []))gn",
63 };
64 for (const auto& bad_usage_example : bad_usage_examples) {
65 TestParseInput input(bad_usage_example);
66 ASSERT_FALSE(input.has_error());
67 Err err;
68 input.parsed()->Execute(setup.scope(), &err);
69 ASSERT_TRUE(err.has_error()) << bad_usage_example;
70 // We are checking for usage errors, not assertion failures.
71 ASSERT_NE(err.message(), "Assertion failed.") << bad_usage_example;
72 }
73 }
74
TEST(Functions,Defined)75 TEST(Functions, Defined) {
76 TestWithScope setup;
77
78 FunctionCallNode function_call;
79 Err err;
80
81 // Test an undefined identifier.
82 Token undefined_token(Location(), Token::IDENTIFIER, "undef");
83 ListNode args_list_identifier_undefined;
84 args_list_identifier_undefined.append_item(
85 std::make_unique<IdentifierNode>(undefined_token));
86 Value result = functions::RunDefined(setup.scope(), &function_call,
87 &args_list_identifier_undefined, &err);
88 ASSERT_EQ(Value::BOOLEAN, result.type());
89 EXPECT_FALSE(result.boolean_value());
90
91 // Define a value that's itself a scope value.
92 const char kDef[] = "def"; // Defined variable name.
93 setup.scope()->SetValue(
94 kDef, Value(nullptr, std::make_unique<Scope>(setup.scope())), nullptr);
95
96 // Test the defined identifier.
97 Token defined_token(Location(), Token::IDENTIFIER, kDef);
98 ListNode args_list_identifier_defined;
99 args_list_identifier_defined.append_item(
100 std::make_unique<IdentifierNode>(defined_token));
101 result = functions::RunDefined(setup.scope(), &function_call,
102 &args_list_identifier_defined, &err);
103 ASSERT_EQ(Value::BOOLEAN, result.type());
104 EXPECT_TRUE(result.boolean_value());
105
106 // Should also work by passing an accessor node so you can do
107 // "defined(def.foo)" to see if foo is defined on the def scope.
108 std::unique_ptr<AccessorNode> undef_accessor =
109 std::make_unique<AccessorNode>();
110 undef_accessor->set_base(defined_token);
111 undef_accessor->set_member(std::make_unique<IdentifierNode>(undefined_token));
112 ListNode args_list_accessor_defined;
113 args_list_accessor_defined.append_item(std::move(undef_accessor));
114 result = functions::RunDefined(setup.scope(), &function_call,
115 &args_list_accessor_defined, &err);
116 ASSERT_EQ(Value::BOOLEAN, result.type());
117 EXPECT_FALSE(result.boolean_value());
118
119 // Should also work by pasing an accessor node so you can do
120 // "defined(def["foo"])" to see if foo is defined on the def scope.
121 std::unique_ptr<AccessorNode> subscript_accessor =
122 std::make_unique<AccessorNode>();
123 subscript_accessor->set_base(defined_token);
124 subscript_accessor->set_subscript(
125 std::make_unique<LiteralNode>(Token(Location(), Token::STRING, "foo")));
126 ListNode args_list_subscript_accessor_defined;
127 args_list_subscript_accessor_defined.append_item(
128 std::move(subscript_accessor));
129 result = functions::RunDefined(setup.scope(), &function_call,
130 &args_list_subscript_accessor_defined, &err);
131 ASSERT_EQ(Value::BOOLEAN, result.type());
132 EXPECT_FALSE(result.boolean_value());
133 }
134
135 // Tests that an error is thrown when a {} is supplied to a function that
136 // doesn't take one.
TEST(Functions,FunctionsWithBlock)137 TEST(Functions, FunctionsWithBlock) {
138 TestWithScope setup;
139 Err err;
140
141 // No scope to print() is OK.
142 TestParseInput print_no_scope("print(6)");
143 EXPECT_FALSE(print_no_scope.has_error());
144 Value result = print_no_scope.parsed()->Execute(setup.scope(), &err);
145 EXPECT_FALSE(err.has_error());
146
147 // Passing a scope should pass parsing (it doesn't know about what kind of
148 // function it is) and then throw an error during execution.
149 TestParseInput print_with_scope("print(foo) {}");
150 EXPECT_FALSE(print_with_scope.has_error());
151 result = print_with_scope.parsed()->Execute(setup.scope(), &err);
152 EXPECT_TRUE(err.has_error());
153 err = Err();
154
155 // defined() is a special function so test it separately.
156 TestParseInput defined_no_scope("defined(foo)");
157 EXPECT_FALSE(defined_no_scope.has_error());
158 result = defined_no_scope.parsed()->Execute(setup.scope(), &err);
159 EXPECT_FALSE(err.has_error());
160
161 // A block to defined should fail.
162 TestParseInput defined_with_scope("defined(foo) {}");
163 EXPECT_FALSE(defined_with_scope.has_error());
164 result = defined_with_scope.parsed()->Execute(setup.scope(), &err);
165 EXPECT_TRUE(err.has_error());
166 }
167
TEST(Functions,SplitList)168 TEST(Functions, SplitList) {
169 TestWithScope setup;
170
171 TestParseInput input(
172 // Empty input with varying result items.
173 "out1 = split_list([], 1)\n"
174 "out2 = split_list([], 3)\n"
175 "print(\"empty = $out1 $out2\")\n"
176
177 // One item input.
178 "out3 = split_list([1], 1)\n"
179 "out4 = split_list([1], 2)\n"
180 "print(\"one = $out3 $out4\")\n"
181
182 // Multiple items.
183 "out5 = split_list([1, 2, 3, 4, 5, 6, 7, 8, 9], 2)\n"
184 "print(\"many = $out5\")\n"
185
186 // Rounding.
187 "out6 = split_list([1, 2, 3, 4, 5, 6], 4)\n"
188 "print(\"rounding = $out6\")\n");
189 ASSERT_FALSE(input.has_error());
190
191 Err err;
192 input.parsed()->Execute(setup.scope(), &err);
193 ASSERT_FALSE(err.has_error()) << err.message();
194
195 EXPECT_EQ(
196 "empty = [[]] [[], [], []]\n"
197 "one = [[1]] [[1], []]\n"
198 "many = [[1, 2, 3, 4, 5], [6, 7, 8, 9]]\n"
199 "rounding = [[1, 2], [3, 4], [5], [6]]\n",
200 setup.print_output());
201 }
202
TEST(Functions,StringJoin)203 TEST(Functions, StringJoin) {
204 TestWithScope setup;
205
206 // Verify outputs when string_join() is called correctly.
207 {
208 TestParseInput input(R"gn(
209 # No elements in the list and empty separator.
210 print("<" + string_join("", []) + ">")
211
212 # No elements in the list.
213 print("<" + string_join(" ", []) + ">")
214
215 # One element in the list.
216 print(string_join("|", ["a"]))
217
218 # Multiple elements in the list.
219 print(string_join(" ", ["a", "b", "c"]))
220
221 # Multi-character separator.
222 print(string_join("-.", ["a", "b", "c"]))
223
224 # Empty separator.
225 print(string_join("", ["x", "y", "z"]))
226
227 # Empty string list elements.
228 print(string_join("x", ["", "", ""]))
229
230 # Empty string list elements and separator
231 print(string_join("", ["", "", ""]))
232 )gn");
233 ASSERT_FALSE(input.has_error());
234
235 Err err;
236 input.parsed()->Execute(setup.scope(), &err);
237 ASSERT_FALSE(err.has_error()) << err.message();
238
239 EXPECT_EQ(
240 "<>\n"
241 "<>\n"
242 "a\n"
243 "a b c\n"
244 "a-.b-.c\n"
245 "xyz\n"
246 "xx\n"
247 "\n",
248 setup.print_output())
249 << setup.print_output();
250 }
251
252 // Verify usage errors are detected.
253 std::vector<std::string> bad_usage_examples = {
254 // Number of arguments.
255 R"gn(string_join())gn",
256 R"gn(string_join(["oops"]))gn",
257 R"gn(string_join("kk", [], "oops"))gn",
258
259 // Argument types.
260 R"gn(string_join(1, []))gn",
261 R"gn(string_join("kk", "oops"))gn",
262 R"gn(string_join(["oops"], []))gn",
263
264 // Non-string elements in list of strings.
265 R"gn(string_join("kk", [1]))gn",
266 R"gn(string_join("kk", ["hello", 1]))gn",
267 R"gn(string_join("kk", ["hello", []]))gn",
268 };
269 for (const auto& bad_usage_example : bad_usage_examples) {
270 TestParseInput input(bad_usage_example);
271 ASSERT_FALSE(input.has_error());
272
273 Err err;
274 input.parsed()->Execute(setup.scope(), &err);
275 ASSERT_TRUE(err.has_error()) << bad_usage_example;
276 }
277 }
278
TEST(Functions,StringReplace)279 TEST(Functions, StringReplace) {
280 TestWithScope setup;
281
282 TestParseInput input(
283 // Replace all occurrences of string.
284 "out1 = string_replace(\"abbcc\", \"b\", \"d\")\n"
285 "print(out1)\n"
286
287 // Replace only the first occurrence.
288 "out2 = string_replace(\"abbcc\", \"b\", \"d\", 1)\n"
289 "print(out2)\n"
290
291 // Duplicate string to be replaced.
292 "out3 = string_replace(\"abbcc\", \"b\", \"bb\")\n"
293 "print(out3)\n"
294
295 // Handle overlapping occurrences.
296 "out4 = string_replace(\"aaa\", \"aa\", \"b\")\n"
297 "print(out4)\n");
298 ASSERT_FALSE(input.has_error());
299
300 Err err;
301 input.parsed()->Execute(setup.scope(), &err);
302 ASSERT_FALSE(err.has_error()) << err.message();
303
304 EXPECT_EQ(
305 "addcc\n"
306 "adbcc\n"
307 "abbbbcc\n"
308 "ba\n",
309 setup.print_output());
310 }
311
TEST(Functions,StringSplit)312 TEST(Functions, StringSplit) {
313 TestWithScope setup;
314
315 // Verify outputs when string_join() is called correctly.
316 {
317 TestParseInput input(R"gn(
318 # Split on all whitespace: empty string.
319 print(string_split(""))
320
321 # Split on all whitespace: string is only whitespace
322 print(string_split(" "))
323
324 # Split on all whitespace: leading, trailing, runs; one element.
325 print(string_split("hello"))
326 print(string_split(" hello"))
327 print(string_split(" hello "))
328 print(string_split("hello "))
329
330 # Split on all whitespace: leading, trailing, runs; multiple elements.
331 print(string_split("a b")) # Pre-stripped
332 print(string_split(" a b")) # Leading whitespace
333 print(string_split(" a b ")) # Leading & trailing whitespace
334 print(string_split("a b ")) # Trailing whitespace
335 print(string_split("a b ")) # Whitespace run between words
336 print(string_split(" a b cc ddd")) # More & multi-character elements
337
338 # Split on string.
339 print(string_split("", "|")) # Empty string
340 print(string_split("|", "|")) # Only a separator
341 print(string_split("||", "|")) # Only separators
342 print(string_split("ab", "|")) # String is missing separator
343 print(string_split("a|b", "|")) # Two elements
344 print(string_split("|a|b", "|")) # Leading separator
345 print(string_split("a|b|", "|")) # Trailing separator
346 print(string_split("||x", "|")) # Leading consecutive separators
347 print(string_split("x||", "|")) # Trailing consecutive separators
348 print(string_split("a|bb|ccc", "|")) # Multiple elements
349 print(string_split(".x.x.x.", ".x.")) # Self-overlapping separators 1
350 print(string_split("x.x.x.", ".x.")) # Self-overlapping separators 2
351 )gn");
352 ASSERT_FALSE(input.has_error());
353
354 Err err;
355 input.parsed()->Execute(setup.scope(), &err);
356 ASSERT_FALSE(err.has_error()) << err.message();
357
358 EXPECT_EQ(
359 // Split on all whitespace: empty string.
360 "[]\n"
361
362 // Split on all whitespace: string is only whitespace.
363 "[]\n"
364
365 // Split on all whitespace: leading, trailing, runs; one element.
366 "[\"hello\"]\n"
367 "[\"hello\"]\n"
368 "[\"hello\"]\n"
369 "[\"hello\"]\n"
370
371 // Split on all whitespace: leading, trailing, runs; multiple elements.
372 "[\"a\", \"b\"]\n"
373 "[\"a\", \"b\"]\n"
374 "[\"a\", \"b\"]\n"
375 "[\"a\", \"b\"]\n"
376 "[\"a\", \"b\"]\n"
377 "[\"a\", \"b\", \"cc\", \"ddd\"]\n"
378
379 // Split on string.
380 "[\"\"]\n" // Empty string (like Python)
381 "[\"\", \"\"]\n" // Only a separator
382 "[\"\", \"\", \"\"]\n" // Only separators
383 "[\"ab\"]\n" // String is missing separator
384 "[\"a\", \"b\"]\n" // Two elements
385 "[\"\", \"a\", \"b\"]\n" // Leading
386 "[\"a\", \"b\", \"\"]\n" // Trailing
387 "[\"\", \"\", \"x\"]\n" // Leading consecutive separators
388 "[\"x\", \"\", \"\"]\n" // Trailing consecutive separators
389 "[\"a\", \"bb\", \"ccc\"]\n" // Multiple elements
390 "[\"\", \"x\", \"\"]\n" // Self-overlapping separators 1
391 "[\"x\", \"x.\"]\n" // Self-overlapping separators 2
392 ,
393 setup.print_output())
394 << setup.print_output();
395 }
396
397 // Verify usage errors are detected.
398 std::vector<std::string> bad_usage_examples = {
399 // Number of arguments.
400 R"gn(string_split())gn",
401 R"gn(string_split("a", "b", "c"))gn",
402
403 // Argument types.
404 R"gn(string_split(1))gn",
405 R"gn(string_split(["oops"]))gn",
406 R"gn(string_split("kk", 1))gn",
407 R"gn(string_split("kk", ["oops"]))gn",
408
409 // Empty separator argument.
410 R"gn(string_split("kk", ""))gn",
411 };
412 for (const auto& bad_usage_example : bad_usage_examples) {
413 TestParseInput input(bad_usage_example);
414 ASSERT_FALSE(input.has_error());
415 Err err;
416 input.parsed()->Execute(setup.scope(), &err);
417 ASSERT_TRUE(err.has_error()) << bad_usage_example;
418 }
419 }
420
TEST(Functions,DeclareArgs)421 TEST(Functions, DeclareArgs) {
422 TestWithScope setup;
423 Err err;
424
425 // It is not legal to read the value of an argument declared in a
426 // declare_args() from inside the call, but outside the call and in
427 // a separate call should work.
428
429 TestParseInput reading_from_same_call(R"(
430 declare_args() {
431 foo = true
432 bar = foo
433 })");
434 reading_from_same_call.parsed()->Execute(setup.scope(), &err);
435 ASSERT_TRUE(err.has_error());
436
437 TestParseInput reading_from_outside_call(R"(
438 declare_args() {
439 foo = true
440 }
441
442 bar = foo
443 assert(bar)
444 )");
445 err = Err();
446 reading_from_outside_call.parsed()->Execute(setup.scope(), &err);
447 ASSERT_FALSE(err.has_error());
448
449 TestParseInput reading_from_different_call(R"(
450 declare_args() {
451 foo = true
452 }
453
454 declare_args() {
455 bar = foo
456 }
457
458 assert(bar)
459 )");
460 err = Err();
461 TestWithScope setup2;
462 reading_from_different_call.parsed()->Execute(setup2.scope(), &err);
463 ASSERT_FALSE(err.has_error());
464 }
465
TEST(Functions,NotNeeded)466 TEST(Functions, NotNeeded) {
467 TestWithScope setup;
468
469 TestParseInput input("not_needed({ a = 1 }, \"*\")");
470 ASSERT_FALSE(input.has_error());
471
472 Err err;
473 input.parsed()->Execute(setup.scope(), &err);
474 ASSERT_FALSE(err.has_error())
475 << err.message() << err.location().Describe(true);
476 }
477
TEST(Template,PrintStackTraceWithOneTemplate)478 TEST(Template, PrintStackTraceWithOneTemplate) {
479 TestWithScope setup;
480 TestParseInput input(
481 "template(\"foo\") {\n"
482 " print(target_name)\n"
483 " print(invoker.foo_value)\n"
484 " print_stack_trace()\n"
485 "}\n"
486 "foo(\"lala\") {\n"
487 " foo_value = 42\n"
488 "}");
489 ASSERT_FALSE(input.has_error());
490
491 Err err;
492 input.parsed()->Execute(setup.scope(), &err);
493 ASSERT_FALSE(err.has_error()) << err.message();
494
495 EXPECT_EQ(
496 "lala\n"
497 "42\n"
498 "print_stack_trace() initiated at: //test:4 using: "
499 "//toolchain:default\n"
500 " foo(\"lala\") //test:6\n"
501 " print_stack_trace() //test:4\n",
502 setup.print_output());
503 }
504
TEST(Template,PrintStackTraceWithNoTemplates)505 TEST(Template, PrintStackTraceWithNoTemplates) {
506 TestWithScope setup;
507 TestParseInput input("print_stack_trace()\n");
508 ASSERT_FALSE(input.has_error());
509
510 Err err;
511 input.parsed()->Execute(setup.scope(), &err);
512 ASSERT_FALSE(err.has_error()) << err.message() << "\n\n" << err.help_text();
513
514 EXPECT_EQ(
515 "print_stack_trace() initiated at: //test:1 using: "
516 "//toolchain:default\n"
517 " print_stack_trace() //test:1\n",
518 setup.print_output());
519 }
520
TEST(Template,PrintStackTraceWithNestedTemplates)521 TEST(Template, PrintStackTraceWithNestedTemplates) {
522 TestWithScope setup;
523 TestParseInput input(
524 "template(\"foo\") {\n"
525 " print(target_name)\n"
526 " print(invoker.foo_value)\n"
527 " print_stack_trace()\n"
528 "}\n"
529 "template(\"baz\") {\n"
530 " foo(\"${target_name}.foo\") {\n"
531 " foo_value = invoker.bar\n"
532 " }\n"
533 "}\n"
534 "baz(\"lala\") {\n"
535 " bar = 42\n"
536 "}");
537 ASSERT_FALSE(input.has_error());
538
539 Err err;
540 input.parsed()->Execute(setup.scope(), &err);
541 ASSERT_FALSE(err.has_error()) << err.message() << "\n\n" << err.help_text();
542
543 EXPECT_EQ(
544 "lala.foo\n"
545 "42\n"
546 "print_stack_trace() initiated at: //test:4 using: "
547 "//toolchain:default\n"
548 " baz(\"lala\") //test:11\n"
549 " foo(\"lala.foo\") //test:7\n"
550 " print_stack_trace() //test:4\n",
551 setup.print_output());
552 }
553
TEST(Template,PrintStackTraceWithNonTemplateScopes)554 TEST(Template, PrintStackTraceWithNonTemplateScopes) {
555 TestWithScope setup;
556 TestParseInput input(
557 "template(\"foo\") {\n"
558 " print(target_name)\n"
559 " if (defined(invoker.foo_value)) {\n"
560 " print(invoker.foo_value)\n"
561 " print_stack_trace()\n"
562 " }\n"
563 "}\n"
564 "template(\"baz\") {\n"
565 " foo(\"${target_name}.foo\") {\n"
566 " foo_value = invoker.bar\n"
567 " }\n"
568 "}\n"
569 "baz(\"lala\") {\n"
570 " bar = 42\n"
571 "}");
572 ASSERT_FALSE(input.has_error());
573
574 Err err;
575 input.parsed()->Execute(setup.scope(), &err);
576 ASSERT_FALSE(err.has_error()) << err.message() << "\n\n" << err.help_text();
577
578 EXPECT_EQ(
579 "lala.foo\n"
580 "42\n"
581 "print_stack_trace() initiated at: //test:5 using: "
582 "//toolchain:default\n"
583 " baz(\"lala\") //test:13\n"
584 " foo(\"lala.foo\") //test:9\n"
585 " print_stack_trace() //test:5\n",
586 setup.print_output());
587 }
588
TEST(Template,PrintStackTraceWithNonTemplateScopesBetweenTemplateInvocations)589 TEST(Template, PrintStackTraceWithNonTemplateScopesBetweenTemplateInvocations) {
590 TestWithScope setup;
591 TestParseInput input(
592 "template(\"foo\") {\n"
593 " print(target_name)\n"
594 " if (defined(invoker.foo_value)) {\n"
595 " print(invoker.foo_value)\n"
596 " print_stack_trace()\n"
597 " }\n"
598 "}\n"
599 "template(\"baz\") {\n"
600 " if (invoker.bar == 42) {\n"
601 " foo(\"${target_name}.foo\") {\n"
602 " foo_value = invoker.bar\n"
603 " }\n"
604 " }\n"
605 "}\n"
606 "baz(\"lala\") {\n"
607 " bar = 42\n"
608 "}");
609 ASSERT_FALSE(input.has_error());
610 Err err;
611 input.parsed()->Execute(setup.scope(), &err);
612 ASSERT_FALSE(err.has_error()) << err.message() << "\n\n" << err.help_text();
613
614 EXPECT_EQ(
615 "lala.foo\n"
616 "42\n"
617 "print_stack_trace() initiated at: //test:5 using: "
618 "//toolchain:default\n"
619 " baz(\"lala\") //test:15\n"
620 " foo(\"lala.foo\") //test:10\n"
621 " print_stack_trace() //test:5\n",
622 setup.print_output());
623 }
624
TEST(Template,PrintStackTraceWithTemplateDefinedWithinATemplate)625 TEST(Template, PrintStackTraceWithTemplateDefinedWithinATemplate) {
626 TestWithScope setup;
627 TestParseInput input(
628 "template(\"foo\") {\n"
629 " print(target_name)\n"
630 " if (defined(invoker.foo_value)) {\n"
631 " template(\"foo_internal\") {"
632 " print(target_name)\n"
633 " print(invoker.foo_internal_value)\n"
634 " print_stack_trace()\n"
635 " }\n"
636 " foo_internal(target_name+\".internal\") {"
637 " foo_internal_value = invoker.foo_value\n"
638 " }\n"
639 " }\n"
640 "}\n"
641 "template(\"baz\") {\n"
642 " if (invoker.bar == 42) {\n"
643 " foo(\"${target_name}.foo\") {\n"
644 " foo_value = invoker.bar\n"
645 " }\n"
646 " }\n"
647 "}\n"
648 "baz(\"lala\") {\n"
649 " bar = 42\n"
650 "}");
651 ASSERT_FALSE(input.has_error());
652 Err err;
653 input.parsed()->Execute(setup.scope(), &err);
654 ASSERT_FALSE(err.has_error()) << err.message() << "\n\n" << err.help_text();
655
656 EXPECT_EQ(
657 "lala.foo\n"
658 "lala.foo.internal\n"
659 "42\n"
660 "print_stack_trace() initiated at: //test:6 using: "
661 "//toolchain:default\n"
662 " baz(\"lala\") //test:19\n"
663 " foo(\"lala.foo\") //test:14\n"
664 " foo_internal(\"lala.foo.internal\") //test:8\n"
665 " print_stack_trace() //test:6\n",
666 setup.print_output());
667 }
668