blob: c44e5c918bcd83cce2e0b421d193144c325e76e6 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Ulf Adams89f012d2015-02-26 13:39:28 +00002//
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.
14package com.google.devtools.build.lib.syntax;
15
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +000016import static com.google.common.truth.Truth.assertThat;
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +000017
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +000018import com.google.devtools.build.lib.actions.Artifact;
19import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
Laurent Le Bruna5cdb19e2015-04-01 17:19:57 +000020import com.google.devtools.build.lib.events.Event;
John Field585d1a02015-12-16 16:03:52 +000021import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
Francois-Rene Rideau4e994102015-09-17 22:41:28 +000022import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
23import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000024import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
Ulf Adams89f012d2015-02-26 13:39:28 +000025
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000026import org.junit.Test;
27import org.junit.runner.RunWith;
28import org.junit.runners.JUnit4;
29
Ulf Adams89f012d2015-02-26 13:39:28 +000030/**
31 * Tests for the validation process of Skylark files.
32 */
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000033@RunWith(JUnit4.class)
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000034public class ValidationTest extends EvaluationTestCase {
Ulf Adams89f012d2015-02-26 13:39:28 +000035
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000036 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000037 public void testAssignmentNotValidLValue() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +000038 checkError("can only assign to variables and tuples, not to ''a''", "'a' = 1");
Ulf Adams89f012d2015-02-26 13:39:28 +000039 }
40
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000041 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000042 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 Nienhuysccf19ea2015-02-27 15:53:24 +000046 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000047 public void testReturnOutsideFunction() throws Exception {
48 checkError("Return statements must be inside a function", "return 2\n");
49 }
50
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000051 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000052 public void testTwoFunctionsWithTheSameName() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000053 checkError(
54 "Variable foo is read only", "def foo():", " return 1", "def foo(x, y):", " return 1");
Ulf Adams89f012d2015-02-26 13:39:28 +000055 }
56
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000057 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000058 public void testFunctionLocalVariable() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000059 checkError(
60 "name 'a' is not defined",
Ulf Adams89f012d2015-02-26 13:39:28 +000061 "def func2(b):",
62 " c = b",
63 " c = a",
64 "def func1():",
65 " a = 1",
66 " func2(2)");
67 }
68
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000069 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000070 public void testFunctionLocalVariableDoesNotEffectGlobalValidationEnv() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000071 checkError("name 'a' is not defined", "def func1():", " a = 1", "def func2(b):", " b = a");
Ulf Adams89f012d2015-02-26 13:39:28 +000072 }
73
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000074 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000075 public void testFunctionParameterDoesNotEffectGlobalValidationEnv() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000076 checkError("name 'a' is not defined", "def func1(a):", " return a", "def func2():", " b = a");
Ulf Adams89f012d2015-02-26 13:39:28 +000077 }
78
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000079 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000080 public void testLocalValidationEnvironmentsAreSeparated() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000081 parse("def func1():", " a = 1", "def func2():", " a = 'abc'\n");
Ulf Adams89f012d2015-02-26 13:39:28 +000082 }
83
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000084 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000085 public void testBuiltinSymbolsAreReadOnly() throws Exception {
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +000086 checkError("Variable repr is read only", "repr = 1");
Ulf Adams89f012d2015-02-26 13:39:28 +000087 }
88
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000089 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000090 public void testSkylarkGlobalVariablesAreReadonly() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000091 checkError("Variable a is read only", "a = 1", "a = 2");
Ulf Adams89f012d2015-02-26 13:39:28 +000092 }
93
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000094 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000095 public void testFunctionDefRecursion() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000096 parse("def func():", " func()\n");
Ulf Adams89f012d2015-02-26 13:39:28 +000097 }
98
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000099 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000100 public void testMutualRecursion() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000101 parse("def foo(i):", " bar(i)", "def bar(i):", " foo(i)", "foo(4)");
Ulf Adams89f012d2015-02-26 13:39:28 +0000102 }
103
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000104 @Test
Laurent Le Brun68743162015-05-13 13:18:09 +0000105 public void testFunctionDefinedBelow() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000106 parse("def bar(): a = foo() + 'a'", "def foo(): return 1\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000107 }
108
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000109 @Test
Laurent Le Brun68743162015-05-13 13:18:09 +0000110 public void testFunctionDoesNotExist() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000111 checkError("function 'foo' does not exist", "def bar(): a = foo() + 'a'");
Laurent Le Brun68743162015-05-13 13:18:09 +0000112 }
113
114 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000115 public void testStructMembersAreImmutable() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000116 checkError(
117 "can only assign to variables and tuples, not to 's.x'",
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000118 "s = struct(x = 'a')",
119 "s.x = 'b'\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000120 }
121
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000122 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000123 public void testStructDictMembersAreImmutable() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000124 checkError(
125 "can only assign to variables and tuples, not to 's.x['b']'",
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000126 "s = struct(x = {'a' : 1})",
127 "s.x['b'] = 2\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000128 }
129
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000130 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000131 public void testTupleLiteralWorksForDifferentTypes() throws Exception {
132 parse("('a', 1)");
133 }
134
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000135 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000136 public void testDictLiteralDifferentValueTypeWorks() throws Exception {
137 parse("{'a': 1, 'b': 'c'}");
138 }
139
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000140 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000141 public void testNoneAssignment() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000142 parse("def func():", " a = None", " a = 2", " a = None\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000143 }
144
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000145 @Test
Laurent Le Brun65ec9572015-03-16 10:45:07 +0000146 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 Adams89f012d2015-02-26 13:39:28 +0000154 // Skylark built-in functions specific tests
155
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000156 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000157 public void testFuncReturningDictAssignmentAsLValue() throws Exception {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000158 checkError(
159 "can only assign to variables and tuples, not to 'my_dict()['b']'",
Florian Weikerta6dae6b2015-08-04 20:17:23 +0000160 "def my_dict():",
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000161 " return {'a': 1}",
162 "def func():",
Florian Weikerta6dae6b2015-08-04 20:17:23 +0000163 " my_dict()['b'] = 2",
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000164 " return d\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000165 }
166
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000167 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000168 public void testEmptyLiteralGenericIsSetInLaterConcatWorks() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000169 parse("def func():", " s = {}", " s['a'] = 'b'\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000170 }
171
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000172 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000173 public void testReadOnlyWorksForSimpleBranching() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000174 parse("if 1:", " v = 'a'", "else:", " v = 'b'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000175 }
176
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000177 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000178 public void testReadOnlyWorksForNestedBranching() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000179 parse(
180 "if 1:",
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000181 " 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 Adams89f012d2015-02-26 13:39:28 +0000190 }
191
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000192 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000193 public void testReadOnlyWorksForDifferentLevelBranches() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000194 checkError("Variable v is read only", "if 1:", " if 1:", " v = 'a'", " v = 'b'\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000195 }
196
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000197 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000198 public void testReadOnlyWorksWithinSimpleBranch() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000199 checkError(
200 "Variable v is read only", "if 1:", " v = 'a'", "else:", " v = 'b'", " v = 'c'\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000201 }
202
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000203 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000204 public void testReadOnlyWorksWithinNestedBranch() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000205 checkError(
206 "Variable v is read only",
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000207 "if 1:",
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000208 " v = 'a'",
209 "else:",
210 " if 1:",
211 " v = 'b'",
212 " else:",
213 " v = 'c'",
214 " v = 'd'\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000215 }
216
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000217 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000218 public void testReadOnlyWorksAfterSimpleBranch() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000219 checkError("Variable v is read only", "if 1:", " v = 'a'", "else:", " w = 'a'", "v = 'b'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000220 }
221
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000222 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000223 public void testReadOnlyWorksAfterNestedBranch() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000224 checkError("Variable v is read only", "if 1:", " if 1:", " v = 'a'", "v = 'b'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000225 }
226
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000227 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000228 public void testReadOnlyWorksAfterNestedBranch2() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000229 checkError(
230 "Variable v is read only",
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000231 "if 1:",
232 " v = 'a'",
233 "else:",
234 " if 0:",
235 " w = 1",
236 "v = 'b'\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000237 }
238
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000239 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000240 public void testModulesReadOnlyInFuncDefBody() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000241 parse("def func():", " cmd_helper = set()");
Ulf Adams89f012d2015-02-26 13:39:28 +0000242 }
243
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000244 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000245 public void testBuiltinGlobalFunctionsReadOnlyInFuncDefBody() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000246 parse("def func():", " rule = 'abc'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000247 }
248
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000249 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000250 public void testBuiltinGlobalFunctionsReadOnlyAsFuncDefArg() {
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000251 parse("def func(rule):", " return rule");
Ulf Adams89f012d2015-02-26 13:39:28 +0000252 }
253
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000254 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000255 public void testFunctionReturnsFunction() {
256 parse(
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +0000257 "def rule(*, implementation): return None",
258 "def impl(ctx): return None",
Ulf Adams89f012d2015-02-26 13:39:28 +0000259 "",
260 "skylark_rule = rule(implementation = impl)",
261 "",
262 "def macro(name):",
263 " skylark_rule(name = name)");
264 }
265
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000266 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000267 public void testTypeForBooleanLiterals() {
268 parse("len([1, 2]) == 0 and True");
269 parse("len([1, 2]) == 0 and False");
270 }
271
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000272 @Test
Laurent Le Bruna5cdb19e2015-04-01 17:19:57 +0000273 public void testDollarErrorDoesNotLeak() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000274 setFailFast(false);
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000275 parseFile(
276 "def GenerateMapNames():", " a = 2", " b = [3, 4]", " if a not b:", " print(a)");
Ulf Adamsc708f962015-10-22 12:02:28 +0000277 assertContainsError("syntax error at 'b': expected in");
Laurent Le Bruna5cdb19e2015-04-01 17:19:57 +0000278 // Parser uses "$error" symbol for error recovery.
279 // It should not be used in error messages.
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000280 for (Event event : getEventCollector()) {
Laurent Le Bruna5cdb19e2015-04-01 17:19:57 +0000281 assertThat(event.getMessage()).doesNotContain("$error$");
282 }
283 }
284
285 @Test
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000286 public void testParentWithSkylarkModule() throws Exception {
Francois-Rene Rideauab049e02016-02-17 16:13:46 +0000287 Class<?> emptyTupleClass = Tuple.empty().getClass();
Francois-Rene Rideau4e994102015-09-17 22:41:28 +0000288 Class<?> tupleClass = Tuple.of(1, "a", "b").getClass();
289 Class<?> mutableListClass = new MutableList(Tuple.of(1, 2, 3), env).getClass();
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000290
Francois-Rene Rideau4e994102015-09-17 22:41:28 +0000291 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 Rideaub6ab6f22015-03-10 16:05:12 +0000297 // TODO(bazel-team): make a tuple not a list anymore.
Francois-Rene Rideau4e994102015-09-17 22:41:28 +0000298 assertThat(EvalUtils.getParentWithSkylarkModule(tupleClass)).isEqualTo(Tuple.class);
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000299
300 // TODO(bazel-team): fix that?
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000301 assertThat(ClassObject.class.isAnnotationPresent(SkylarkModule.class)).isFalse();
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000302 assertThat(ClassObject.SkylarkClassObject.class.isAnnotationPresent(SkylarkModule.class))
303 .isTrue();
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000304 assertThat(
305 EvalUtils.getParentWithSkylarkModule(ClassObject.SkylarkClassObject.class)
306 == ClassObject.SkylarkClassObject.class)
307 .isTrue();
308 assertThat(EvalUtils.getParentWithSkylarkModule(ClassObject.class)).isNull();
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000309 }
310
311 @Test
312 public void testSkylarkTypeEquivalence() throws Exception {
313 // All subclasses of SkylarkList are made equivalent
Francois-Rene Rideauab049e02016-02-17 16:13:46 +0000314 Class<?> emptyTupleClass = Tuple.empty().getClass();
Francois-Rene Rideau4e994102015-09-17 22:41:28 +0000315 Class<?> tupleClass = Tuple.of(1, "a", "b").getClass();
316 Class<?> mutableListClass = new MutableList(Tuple.of(1, 2, 3), env).getClass();
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000317
Francois-Rene Rideau4e994102015-09-17 22:41:28 +0000318 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 Rideaub6ab6f22015-03-10 16:05:12 +0000322
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000323 // Also for ClassObject
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000324 assertThat(SkylarkType.of(ClassObject.SkylarkClassObject.class)).isEqualTo(SkylarkType.STRUCT);
Francois-Rene Rideauab049e02016-02-17 16:13:46 +0000325 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 Rideau3e9bab32015-03-06 13:41:00 +0000333
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000334 // Also test for these bazel classes, to avoid some regression.
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000335 // TODO(bazel-team): move to some other place to remove dependency of syntax tests on Artifact?
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000336 assertThat(SkylarkType.of(Artifact.SpecialArtifact.class))
337 .isEqualTo(SkylarkType.of(Artifact.class));
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000338 assertThat(SkylarkType.of(RuleConfiguredTarget.class)).isNotEqualTo(SkylarkType.STRUCT);
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000339 }
340
341 @Test
342 public void testSkylarkTypeInclusion() throws Exception {
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000343 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 Rideau3e9bab32015-03-06 13:41:00 +0000346
347 SkylarkType combo1 = SkylarkType.Combination.of(SkylarkType.LIST, SkylarkType.INT);
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000348 assertThat(SkylarkType.LIST.includes(combo1)).isTrue();
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000349
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000350 SkylarkType union1 =
Francois-Rene Rideauab049e02016-02-17 16:13:46 +0000351 SkylarkType.Union.of(SkylarkType.DICT, SkylarkType.LIST, SkylarkType.STRUCT);
352 assertThat(union1.includes(SkylarkType.DICT)).isTrue();
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000353 assertThat(union1.includes(SkylarkType.STRUCT)).isTrue();
354 assertThat(union1.includes(combo1)).isTrue();
355 assertThat(union1.includes(SkylarkType.STRING)).isFalse();
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000356
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000357 SkylarkType union2 =
358 SkylarkType.Union.of(
Francois-Rene Rideauab049e02016-02-17 16:13:46 +0000359 SkylarkType.LIST, SkylarkType.DICT, SkylarkType.STRING, SkylarkType.INT);
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000360 SkylarkType inter1 = SkylarkType.intersection(union1, union2);
Francois-Rene Rideauab049e02016-02-17 16:13:46 +0000361 assertThat(inter1.includes(SkylarkType.DICT)).isTrue();
Francois-Rene Rideaub6ab6f22015-03-10 16:05:12 +0000362 assertThat(inter1.includes(SkylarkType.LIST)).isTrue();
363 assertThat(inter1.includes(combo1)).isTrue();
364 assertThat(inter1.includes(SkylarkType.INT)).isFalse();
Francois-Rene Rideau3e9bab32015-03-06 13:41:00 +0000365 }
366
Ulf Adams89f012d2015-02-26 13:39:28 +0000367 private void parse(String... lines) {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000368 parseFile(lines);
Ulf Adamsb089c8d2015-10-26 12:20:33 +0000369 assertNoWarningsOrErrors();
Ulf Adams89f012d2015-02-26 13:39:28 +0000370 }
371
372 private void checkError(String errorMsg, String... lines) {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000373 setFailFast(false);
374 parseFile(lines);
Ulf Adamsc708f962015-10-22 12:02:28 +0000375 assertContainsError(errorMsg);
Ulf Adams89f012d2015-02-26 13:39:28 +0000376 }
377}