Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.syntax; |
| 15 | |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 16 | import static com.google.common.truth.Truth.assertThat; |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 17 | |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 18 | import com.google.devtools.build.lib.actions.Artifact; |
| 19 | import com.google.devtools.build.lib.analysis.RuleConfiguredTarget; |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 20 | import com.google.devtools.build.lib.events.Event; |
John Field | 585d1a0 | 2015-12-16 16:03:52 +0000 | [diff] [blame] | 21 | import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; |
Francois-Rene Rideau | 4e99410 | 2015-09-17 22:41:28 +0000 | [diff] [blame] | 22 | import com.google.devtools.build.lib.syntax.SkylarkList.MutableList; |
| 23 | import com.google.devtools.build.lib.syntax.SkylarkList.Tuple; |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 24 | import com.google.devtools.build.lib.syntax.util.EvaluationTestCase; |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 25 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 26 | import org.junit.Test; |
| 27 | import org.junit.runner.RunWith; |
| 28 | import org.junit.runners.JUnit4; |
| 29 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 30 | /** |
| 31 | * Tests for the validation process of Skylark files. |
| 32 | */ |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 33 | @RunWith(JUnit4.class) |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 34 | public class ValidationTest extends EvaluationTestCase { |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 35 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 36 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 37 | public void testAssignmentNotValidLValue() { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 38 | checkError("can only assign to variables and tuples, not to ''a''", "'a' = 1"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 39 | } |
| 40 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 41 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 42 | public void testTopLevelForStatement() throws Exception { |
| 43 | checkError("'For' is not allowed as a top level statement", "for i in [1,2,3]: a = i\n"); |
| 44 | } |
| 45 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 46 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 47 | public void testReturnOutsideFunction() throws Exception { |
| 48 | checkError("Return statements must be inside a function", "return 2\n"); |
| 49 | } |
| 50 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 51 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 52 | public void testTwoFunctionsWithTheSameName() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 53 | checkError( |
| 54 | "Variable foo is read only", "def foo():", " return 1", "def foo(x, y):", " return 1"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 55 | } |
| 56 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 57 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 58 | public void testFunctionLocalVariable() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 59 | checkError( |
| 60 | "name 'a' is not defined", |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 61 | "def func2(b):", |
| 62 | " c = b", |
| 63 | " c = a", |
| 64 | "def func1():", |
| 65 | " a = 1", |
| 66 | " func2(2)"); |
| 67 | } |
| 68 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 69 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 70 | public void testFunctionLocalVariableDoesNotEffectGlobalValidationEnv() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 71 | checkError("name 'a' is not defined", "def func1():", " a = 1", "def func2(b):", " b = a"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 72 | } |
| 73 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 74 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 75 | public void testFunctionParameterDoesNotEffectGlobalValidationEnv() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 76 | checkError("name 'a' is not defined", "def func1(a):", " return a", "def func2():", " b = a"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 79 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 80 | public void testLocalValidationEnvironmentsAreSeparated() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 81 | parse("def func1():", " a = 1", "def func2():", " a = 'abc'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 82 | } |
| 83 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 84 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 85 | public void testBuiltinSymbolsAreReadOnly() throws Exception { |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 86 | checkError("Variable repr is read only", "repr = 1"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 87 | } |
| 88 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 89 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 90 | public void testSkylarkGlobalVariablesAreReadonly() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 91 | checkError("Variable a is read only", "a = 1", "a = 2"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 92 | } |
| 93 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 94 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 95 | public void testFunctionDefRecursion() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 96 | parse("def func():", " func()\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 97 | } |
| 98 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 99 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 100 | public void testMutualRecursion() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 101 | parse("def foo(i):", " bar(i)", "def bar(i):", " foo(i)", "foo(4)"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 102 | } |
| 103 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 104 | @Test |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 105 | public void testFunctionDefinedBelow() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 106 | parse("def bar(): a = foo() + 'a'", "def foo(): return 1\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 107 | } |
| 108 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 109 | @Test |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 110 | public void testFunctionDoesNotExist() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 111 | checkError("function 'foo' does not exist", "def bar(): a = foo() + 'a'"); |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 115 | public void testStructMembersAreImmutable() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 116 | checkError( |
| 117 | "can only assign to variables and tuples, not to 's.x'", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 118 | "s = struct(x = 'a')", |
| 119 | "s.x = 'b'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 120 | } |
| 121 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 122 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 123 | public void testStructDictMembersAreImmutable() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 124 | checkError( |
| 125 | "can only assign to variables and tuples, not to 's.x['b']'", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 126 | "s = struct(x = {'a' : 1})", |
| 127 | "s.x['b'] = 2\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 128 | } |
| 129 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 130 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 131 | public void testTupleLiteralWorksForDifferentTypes() throws Exception { |
| 132 | parse("('a', 1)"); |
| 133 | } |
| 134 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 135 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 136 | public void testDictLiteralDifferentValueTypeWorks() throws Exception { |
| 137 | parse("{'a': 1, 'b': 'c'}"); |
| 138 | } |
| 139 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 140 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 141 | public void testNoneAssignment() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 142 | parse("def func():", " a = None", " a = 2", " a = None\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 143 | } |
| 144 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 145 | @Test |
Laurent Le Brun | 65ec957 | 2015-03-16 10:45:07 +0000 | [diff] [blame] | 146 | public void testNoneIsAnyType() throws Exception { |
| 147 | parse("None + None"); |
| 148 | parse("2 == None"); |
| 149 | parse("None > 'a'"); |
| 150 | parse("[] in None"); |
| 151 | parse("5 * None"); |
| 152 | } |
| 153 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 154 | // Skylark built-in functions specific tests |
| 155 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 156 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 157 | public void testFuncReturningDictAssignmentAsLValue() throws Exception { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 158 | checkError( |
| 159 | "can only assign to variables and tuples, not to 'my_dict()['b']'", |
Florian Weikert | a6dae6b | 2015-08-04 20:17:23 +0000 | [diff] [blame] | 160 | "def my_dict():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 161 | " return {'a': 1}", |
| 162 | "def func():", |
Florian Weikert | a6dae6b | 2015-08-04 20:17:23 +0000 | [diff] [blame] | 163 | " my_dict()['b'] = 2", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 164 | " return d\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 165 | } |
| 166 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 167 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 168 | public void testEmptyLiteralGenericIsSetInLaterConcatWorks() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 169 | parse("def func():", " s = {}", " s['a'] = 'b'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 170 | } |
| 171 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 172 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 173 | public void testReadOnlyWorksForSimpleBranching() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 174 | parse("if 1:", " v = 'a'", "else:", " v = 'b'"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 175 | } |
| 176 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 177 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 178 | public void testReadOnlyWorksForNestedBranching() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 179 | parse( |
| 180 | "if 1:", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 181 | " if 0:", |
| 182 | " v = 'a'", |
| 183 | " else:", |
| 184 | " v = 'b'", |
| 185 | "else:", |
| 186 | " if 0:", |
| 187 | " v = 'c'", |
| 188 | " else:", |
| 189 | " v = 'd'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 190 | } |
| 191 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 192 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 193 | public void testReadOnlyWorksForDifferentLevelBranches() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 194 | checkError("Variable v is read only", "if 1:", " if 1:", " v = 'a'", " v = 'b'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 195 | } |
| 196 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 197 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 198 | public void testReadOnlyWorksWithinSimpleBranch() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 199 | checkError( |
| 200 | "Variable v is read only", "if 1:", " v = 'a'", "else:", " v = 'b'", " v = 'c'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 201 | } |
| 202 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 203 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 204 | public void testReadOnlyWorksWithinNestedBranch() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 205 | checkError( |
| 206 | "Variable v is read only", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 207 | "if 1:", |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 208 | " v = 'a'", |
| 209 | "else:", |
| 210 | " if 1:", |
| 211 | " v = 'b'", |
| 212 | " else:", |
| 213 | " v = 'c'", |
| 214 | " v = 'd'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 215 | } |
| 216 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 217 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 218 | public void testReadOnlyWorksAfterSimpleBranch() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 219 | checkError("Variable v is read only", "if 1:", " v = 'a'", "else:", " w = 'a'", "v = 'b'"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 220 | } |
| 221 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 222 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 223 | public void testReadOnlyWorksAfterNestedBranch() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 224 | checkError("Variable v is read only", "if 1:", " if 1:", " v = 'a'", "v = 'b'"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 225 | } |
| 226 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 227 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 228 | public void testReadOnlyWorksAfterNestedBranch2() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 229 | checkError( |
| 230 | "Variable v is read only", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 231 | "if 1:", |
| 232 | " v = 'a'", |
| 233 | "else:", |
| 234 | " if 0:", |
| 235 | " w = 1", |
| 236 | "v = 'b'\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 237 | } |
| 238 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 239 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 240 | public void testModulesReadOnlyInFuncDefBody() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 241 | parse("def func():", " cmd_helper = set()"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 242 | } |
| 243 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 244 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 245 | public void testBuiltinGlobalFunctionsReadOnlyInFuncDefBody() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 246 | parse("def func():", " rule = 'abc'"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 247 | } |
| 248 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 249 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 250 | public void testBuiltinGlobalFunctionsReadOnlyAsFuncDefArg() { |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 251 | parse("def func(rule):", " return rule"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 252 | } |
| 253 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 254 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 255 | public void testFunctionReturnsFunction() { |
| 256 | parse( |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 257 | "def rule(*, implementation): return None", |
| 258 | "def impl(ctx): return None", |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 259 | "", |
| 260 | "skylark_rule = rule(implementation = impl)", |
| 261 | "", |
| 262 | "def macro(name):", |
| 263 | " skylark_rule(name = name)"); |
| 264 | } |
| 265 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 266 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 267 | public void testTypeForBooleanLiterals() { |
| 268 | parse("len([1, 2]) == 0 and True"); |
| 269 | parse("len([1, 2]) == 0 and False"); |
| 270 | } |
| 271 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 272 | @Test |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 273 | public void testDollarErrorDoesNotLeak() throws Exception { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 274 | setFailFast(false); |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 275 | parseFile( |
| 276 | "def GenerateMapNames():", " a = 2", " b = [3, 4]", " if a not b:", " print(a)"); |
Ulf Adams | c708f96 | 2015-10-22 12:02:28 +0000 | [diff] [blame] | 277 | assertContainsError("syntax error at 'b': expected in"); |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 278 | // Parser uses "$error" symbol for error recovery. |
| 279 | // It should not be used in error messages. |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 280 | for (Event event : getEventCollector()) { |
Laurent Le Brun | a5cdb19e | 2015-04-01 17:19:57 +0000 | [diff] [blame] | 281 | assertThat(event.getMessage()).doesNotContain("$error$"); |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | @Test |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 286 | public void testParentWithSkylarkModule() throws Exception { |
Francois-Rene Rideau | ab049e0 | 2016-02-17 16:13:46 +0000 | [diff] [blame] | 287 | Class<?> emptyTupleClass = Tuple.empty().getClass(); |
Francois-Rene Rideau | 4e99410 | 2015-09-17 22:41:28 +0000 | [diff] [blame] | 288 | Class<?> tupleClass = Tuple.of(1, "a", "b").getClass(); |
| 289 | Class<?> mutableListClass = new MutableList(Tuple.of(1, 2, 3), env).getClass(); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 290 | |
Francois-Rene Rideau | 4e99410 | 2015-09-17 22:41:28 +0000 | [diff] [blame] | 291 | assertThat(mutableListClass).isEqualTo(MutableList.class); |
| 292 | assertThat(MutableList.class.isAnnotationPresent(SkylarkModule.class)).isTrue(); |
| 293 | assertThat(EvalUtils.getParentWithSkylarkModule(MutableList.class)) |
| 294 | .isEqualTo(MutableList.class); |
| 295 | assertThat(EvalUtils.getParentWithSkylarkModule(emptyTupleClass)).isEqualTo(Tuple.class); |
| 296 | assertThat(EvalUtils.getParentWithSkylarkModule(tupleClass)).isEqualTo(Tuple.class); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 297 | // TODO(bazel-team): make a tuple not a list anymore. |
Francois-Rene Rideau | 4e99410 | 2015-09-17 22:41:28 +0000 | [diff] [blame] | 298 | assertThat(EvalUtils.getParentWithSkylarkModule(tupleClass)).isEqualTo(Tuple.class); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 299 | |
| 300 | // TODO(bazel-team): fix that? |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 301 | assertThat(ClassObject.class.isAnnotationPresent(SkylarkModule.class)).isFalse(); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 302 | assertThat(ClassObject.SkylarkClassObject.class.isAnnotationPresent(SkylarkModule.class)) |
| 303 | .isTrue(); |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 304 | assertThat( |
| 305 | EvalUtils.getParentWithSkylarkModule(ClassObject.SkylarkClassObject.class) |
| 306 | == ClassObject.SkylarkClassObject.class) |
| 307 | .isTrue(); |
| 308 | assertThat(EvalUtils.getParentWithSkylarkModule(ClassObject.class)).isNull(); |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | @Test |
| 312 | public void testSkylarkTypeEquivalence() throws Exception { |
| 313 | // All subclasses of SkylarkList are made equivalent |
Francois-Rene Rideau | ab049e0 | 2016-02-17 16:13:46 +0000 | [diff] [blame] | 314 | Class<?> emptyTupleClass = Tuple.empty().getClass(); |
Francois-Rene Rideau | 4e99410 | 2015-09-17 22:41:28 +0000 | [diff] [blame] | 315 | Class<?> tupleClass = Tuple.of(1, "a", "b").getClass(); |
| 316 | Class<?> mutableListClass = new MutableList(Tuple.of(1, 2, 3), env).getClass(); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 317 | |
Francois-Rene Rideau | 4e99410 | 2015-09-17 22:41:28 +0000 | [diff] [blame] | 318 | assertThat(SkylarkType.of(mutableListClass)).isEqualTo(SkylarkType.LIST); |
| 319 | assertThat(SkylarkType.of(emptyTupleClass)).isEqualTo(SkylarkType.TUPLE); |
| 320 | assertThat(SkylarkType.of(tupleClass)).isEqualTo(SkylarkType.TUPLE); |
| 321 | assertThat(SkylarkType.TUPLE).isNotEqualTo(SkylarkType.LIST); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 322 | |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 323 | // Also for ClassObject |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 324 | assertThat(SkylarkType.of(ClassObject.SkylarkClassObject.class)).isEqualTo(SkylarkType.STRUCT); |
Francois-Rene Rideau | ab049e0 | 2016-02-17 16:13:46 +0000 | [diff] [blame] | 325 | try { |
| 326 | SkylarkType.of(ClassObject.class); |
| 327 | throw new Exception("foo"); |
| 328 | } catch (Exception e) { |
| 329 | assertThat(e.getMessage()).contains( |
| 330 | "interface com.google.devtools.build.lib.syntax.ClassObject " |
| 331 | + "is not allowed as a Skylark value"); |
| 332 | } |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 333 | |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 334 | // Also test for these bazel classes, to avoid some regression. |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 335 | // TODO(bazel-team): move to some other place to remove dependency of syntax tests on Artifact? |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 336 | assertThat(SkylarkType.of(Artifact.SpecialArtifact.class)) |
| 337 | .isEqualTo(SkylarkType.of(Artifact.class)); |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 338 | assertThat(SkylarkType.of(RuleConfiguredTarget.class)).isNotEqualTo(SkylarkType.STRUCT); |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 339 | } |
| 340 | |
| 341 | @Test |
| 342 | public void testSkylarkTypeInclusion() throws Exception { |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 343 | assertThat(SkylarkType.INT.includes(SkylarkType.BOTTOM)).isTrue(); |
| 344 | assertThat(SkylarkType.BOTTOM.includes(SkylarkType.INT)).isFalse(); |
| 345 | assertThat(SkylarkType.TOP.includes(SkylarkType.INT)).isTrue(); |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 346 | |
| 347 | SkylarkType combo1 = SkylarkType.Combination.of(SkylarkType.LIST, SkylarkType.INT); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 348 | assertThat(SkylarkType.LIST.includes(combo1)).isTrue(); |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 349 | |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 350 | SkylarkType union1 = |
Francois-Rene Rideau | ab049e0 | 2016-02-17 16:13:46 +0000 | [diff] [blame] | 351 | SkylarkType.Union.of(SkylarkType.DICT, SkylarkType.LIST, SkylarkType.STRUCT); |
| 352 | assertThat(union1.includes(SkylarkType.DICT)).isTrue(); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 353 | assertThat(union1.includes(SkylarkType.STRUCT)).isTrue(); |
| 354 | assertThat(union1.includes(combo1)).isTrue(); |
| 355 | assertThat(union1.includes(SkylarkType.STRING)).isFalse(); |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 356 | |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 357 | SkylarkType union2 = |
| 358 | SkylarkType.Union.of( |
Francois-Rene Rideau | ab049e0 | 2016-02-17 16:13:46 +0000 | [diff] [blame] | 359 | SkylarkType.LIST, SkylarkType.DICT, SkylarkType.STRING, SkylarkType.INT); |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 360 | SkylarkType inter1 = SkylarkType.intersection(union1, union2); |
Francois-Rene Rideau | ab049e0 | 2016-02-17 16:13:46 +0000 | [diff] [blame] | 361 | assertThat(inter1.includes(SkylarkType.DICT)).isTrue(); |
Francois-Rene Rideau | b6ab6f2 | 2015-03-10 16:05:12 +0000 | [diff] [blame] | 362 | assertThat(inter1.includes(SkylarkType.LIST)).isTrue(); |
| 363 | assertThat(inter1.includes(combo1)).isTrue(); |
| 364 | assertThat(inter1.includes(SkylarkType.INT)).isFalse(); |
Francois-Rene Rideau | 3e9bab3 | 2015-03-06 13:41:00 +0000 | [diff] [blame] | 365 | } |
| 366 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 367 | private void parse(String... lines) { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 368 | parseFile(lines); |
Ulf Adams | b089c8d | 2015-10-26 12:20:33 +0000 | [diff] [blame] | 369 | assertNoWarningsOrErrors(); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 370 | } |
| 371 | |
| 372 | private void checkError(String errorMsg, String... lines) { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 373 | setFailFast(false); |
| 374 | parseFile(lines); |
Ulf Adams | c708f96 | 2015-10-22 12:02:28 +0000 | [diff] [blame] | 375 | assertContainsError(errorMsg); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 376 | } |
| 377 | } |