| // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "tools/gn/test_with_scope.h" | |
| #include "util/test/test.h" | |
| TEST(FunctionForeach, CollisionOnLoopVar) { | |
| TestWithScope setup; | |
| TestParseInput input( | |
| "a = 5\n" | |
| "i = 6\n" | |
| "foreach(i, [1, 2, 3]) {\n" // Use same loop var name previously defined. | |
| " print(\"$a $i\")\n" | |
| " a = a + 1\n" // Test for side effects inside loop. | |
| "}\n" | |
| "print(\"$a $i\")"); // Make sure that i goes back to original value. | |
| ASSERT_FALSE(input.has_error()); | |
| Err err; | |
| input.parsed()->Execute(setup.scope(), &err); | |
| ASSERT_FALSE(err.has_error()) << err.message(); | |
| EXPECT_EQ("5 1\n6 2\n7 3\n8 6\n", setup.print_output()); | |
| } | |
| TEST(FunctionForeach, UniqueLoopVar) { | |
| TestWithScope setup; | |
| TestParseInput input_good( | |
| "foreach(i, [1, 2, 3]) {\n" | |
| " print(i)\n" | |
| "}\n"); | |
| ASSERT_FALSE(input_good.has_error()); | |
| Err err; | |
| input_good.parsed()->Execute(setup.scope(), &err); | |
| ASSERT_FALSE(err.has_error()) << err.message(); | |
| EXPECT_EQ("1\n2\n3\n", setup.print_output()); | |
| setup.print_output().clear(); | |
| // Same thing but try to use the loop var after loop is done. It should be | |
| // undefined and throw an error. | |
| TestParseInput input_bad( | |
| "foreach(i, [1, 2, 3]) {\n" | |
| " print(i)\n" | |
| "}\n" | |
| "print(i)"); | |
| ASSERT_FALSE(input_bad.has_error()); // Should parse OK. | |
| input_bad.parsed()->Execute(setup.scope(), &err); | |
| ASSERT_TRUE(err.has_error()); // Shouldn't actually run. | |
| } | |
| // Checks that the identifier used as the list is marked as "used". | |
| TEST(FunctionForeach, MarksIdentAsUsed) { | |
| TestWithScope setup; | |
| TestParseInput input_good( | |
| "a = [1, 2]\n" | |
| "foreach(i, a) {\n" | |
| " print(i)\n" | |
| "}\n"); | |
| ASSERT_FALSE(input_good.has_error()); | |
| Err err; | |
| input_good.parsed()->Execute(setup.scope(), &err); | |
| ASSERT_FALSE(err.has_error()) << err.message(); | |
| EXPECT_EQ("1\n2\n", setup.print_output()); | |
| setup.print_output().clear(); | |
| // Check for unused vars. | |
| EXPECT_TRUE(setup.scope()->CheckForUnusedVars(&err)); | |
| EXPECT_FALSE(err.has_error()); | |
| } | |
| // Checks that the list can be modified during iteration without crashing. | |
| TEST(FunctionForeach, ListModification) { | |
| TestWithScope setup; | |
| TestParseInput input_grow( | |
| "a = [1, 2]\n" | |
| "foreach(i, a) {\n" | |
| " print(i)\n" | |
| " if (i <= 8) {\n" | |
| " a += [ i + 2 ]\n" | |
| " }\n" | |
| "}\n" | |
| "print(a)"); | |
| ASSERT_FALSE(input_grow.has_error()); | |
| Err err; | |
| input_grow.parsed()->Execute(setup.scope(), &err); | |
| ASSERT_FALSE(err.has_error()) << err.message(); | |
| // The result of the loop should have been unaffected by the mutations of | |
| // the list variable inside the loop, but the modifications made to it | |
| // should have been persisted. | |
| EXPECT_EQ("1\n2\n[1, 2, 3, 4]\n", setup.print_output()); | |
| setup.print_output().clear(); | |
| } |