blob: d487eff0d27fb315efd0f439c66be9f1113b6172 [file] [log] [blame]
Laurent Le Brunad849742015-10-15 11:36:01 +00001// Copyright 2006 The Bazel Authors. All Rights Reserved.
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +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.
14
15package com.google.devtools.build.lib.syntax;
16
17import static com.google.common.truth.Truth.assertThat;
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000018
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000019import com.google.common.collect.Iterables;
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000020import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000021import org.junit.Before;
22import org.junit.Test;
23import org.junit.runner.RunWith;
24import org.junit.runners.JUnit4;
25
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000026/**
27 * Tests for MethodLibrary.
28 */
29@RunWith(JUnit4.class)
30public class MethodLibraryTest extends EvaluationTestCase {
31
Yun Pengfc610052016-06-20 11:44:06 +000032 private static final String LINE_SEPARATOR = System.lineSeparator();
33
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000034 @Before
Florian Weikertb4c59042015-12-01 10:47:18 +000035 public final void setFailFast() throws Exception {
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000036 setFailFast(true);
37 }
38
39 @Test
Florian Weikert90a15962015-09-11 13:43:10 +000040 public void testStackTraceLocation() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +000041 new SkylarkTest()
42 .testIfErrorContains(
Yun Penge7e55bb2016-09-09 09:11:42 +000043 "Traceback (most recent call last):"
Yun Pengfc610052016-06-20 11:44:06 +000044 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +000045 + "\tFile \"\", line 8"
Yun Pengfc610052016-06-20 11:44:06 +000046 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +000047 + "\t\tfoo()"
48 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +000049 + "\tFile \"\", line 2, in foo"
Yun Penge7e55bb2016-09-09 09:11:42 +000050 + LINE_SEPARATOR
51 + "\t\tbar(1)"
52 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +000053 + "\tFile \"\", line 7, in bar"
Yun Pengfc610052016-06-20 11:44:06 +000054 + LINE_SEPARATOR
Michajlo Matijkiw8c539ea2017-02-22 23:02:46 +000055 + "\t\t\"test\".index(x)",
Yun Pengfc610052016-06-20 11:44:06 +000056 "def foo():",
57 " bar(1)",
58 "def bar(x):",
59 " if x == 1:",
60 " a = x",
61 " b = 2",
62 " 'test'.index(x)",
63 "foo()");
Florian Weikert90a15962015-09-11 13:43:10 +000064 }
65
66 @Test
67 public void testStackTraceWithIf() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +000068 new SkylarkTest()
69 .testIfErrorContains(
Carmi Grushko46bf88c2017-02-20 22:37:15 +000070 "File \"\", line 5"
Yun Pengfc610052016-06-20 11:44:06 +000071 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +000072 + "\t\tfoo()"
73 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +000074 + "\tFile \"\", line 3, in foo"
Yun Pengfc610052016-06-20 11:44:06 +000075 + LINE_SEPARATOR
76 + "\t\ts[0]",
77 "def foo():",
Vladimir Moskvad200daf2016-12-23 16:35:37 +000078 " s = depset()",
Yun Pengfc610052016-06-20 11:44:06 +000079 " if s[0] == 1:",
80 " x = 1",
81 "foo()");
Florian Weikert90a15962015-09-11 13:43:10 +000082 }
83
84 @Test
vladmosaa12ec32017-09-25 21:11:31 +020085 public void testStackTraceWithAugmentedAssignment() throws Exception {
86 new SkylarkTest()
87 .testIfErrorContains(
88 "File \"\", line 4"
89 + LINE_SEPARATOR
90 + "\t\tfoo()"
91 + LINE_SEPARATOR
92 + "\tFile \"\", line 3, in foo"
93 + LINE_SEPARATOR
94 + "\t\ts += \"2\""
95 + LINE_SEPARATOR
96 + "unsupported operand type(s) for +: 'int' and 'string'",
97 "def foo():",
98 " s = 1",
99 " s += '2'",
100 "foo()");
101 }
102
103 @Test
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000104 public void testStackTraceSkipBuiltInOnly() throws Exception {
105 // The error message should not include the stack trace when there is
106 // only one built-in function.
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000107 new BothModesTest()
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000108 .testIfExactError(
cparsons0fcad772018-04-11 14:24:00 -0700109 "expected value of type 'string' for parameter 'sub', "
110 + "in method call index(int) of 'string'",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000111 "'test'.index(1)");
112 }
113
114 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000115 public void testStackTrace() throws Exception {
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000116 // Unlike SkylarintegrationTests#testStackTraceErrorInFunction(), this test
117 // has neither a BUILD nor a bzl file.
118 new SkylarkTest()
119 .testIfExactError(
Yun Penge7e55bb2016-09-09 09:11:42 +0000120 "Traceback (most recent call last):"
121 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000122 + "\tFile \"\", line 6"
Yun Pengfc610052016-06-20 11:44:06 +0000123 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000124 + "\t\tfoo()"
125 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000126 + "\tFile \"\", line 2, in foo"
Yun Pengfc610052016-06-20 11:44:06 +0000127 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000128 + "\t\tbar(1)"
129 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000130 + "\tFile \"\", line 5, in bar"
Yun Pengfc610052016-06-20 11:44:06 +0000131 + LINE_SEPARATOR
Michajlo Matijkiw8c539ea2017-02-22 23:02:46 +0000132 + "\t\t\"test\".index(x)"
Yun Penge7e55bb2016-09-09 09:11:42 +0000133 + LINE_SEPARATOR
cparsons0fcad772018-04-11 14:24:00 -0700134 + "expected value of type 'string' for parameter 'sub', "
135 + "in method call index(int) of 'string'",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000136 "def foo():",
Florian Weikert90a15962015-09-11 13:43:10 +0000137 " bar(1)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000138 "def bar(x):",
Florian Weikert90a15962015-09-11 13:43:10 +0000139 " if 1 == 1:",
140 " 'test'.index(x)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000141 "foo()");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000142 }
143
144 @Test
145 public void testBuiltinFunctionErrorMessage() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000146 new BothModesTest()
laurentlb9e540882017-07-07 06:58:45 -0400147 .testIfErrorContains("substring \"z\" not found in \"abc\"", "'abc'.index('z')")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000148 .testIfErrorContains(
cparsons0fcad772018-04-11 14:24:00 -0700149 "expected value of type 'string' for parameter 'sub', "
150 + "in method call startswith(int) of 'string'",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000151 "'test'.startswith(1)")
152 .testIfErrorContains(
Florian Weikert1c07e322015-09-25 11:59:40 +0000153 "expected value of type 'list(object)' for parameter args in dict(), "
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000154 + "but got \"a\" (string)",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000155 "dict('a')");
156 }
157
158 @Test
159 public void testHasAttr() throws Exception {
160 new SkylarkTest()
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000161 .testStatement("hasattr(depset(), 'union')", Boolean.TRUE)
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000162 .testStatement("hasattr('test', 'count')", Boolean.TRUE)
163 .testStatement("hasattr(dict(a = 1, b = 2), 'items')", Boolean.TRUE)
164 .testStatement("hasattr({}, 'items')", Boolean.TRUE);
165 }
166
167 @Test
Florian Weikerte5e3e912016-03-08 03:08:26 +0000168 public void testGetAttrMissingField() throws Exception {
169 new SkylarkTest()
170 .testIfExactError(
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000171 "object of type 'string' has no attribute \"not_there\"",
Florian Weikerte5e3e912016-03-08 03:08:26 +0000172 "getattr('a string', 'not_there')")
Jon Brandveinad81cff2016-07-26 13:04:10 +0000173 .testStatement("getattr('a string', 'not_there', 'use this')", "use this")
174 .testStatement("getattr('a string', 'not there', None)", Runtime.NONE);
Florian Weikerte5e3e912016-03-08 03:08:26 +0000175 }
176
177 @Test
178 public void testGetAttrWithMethods() throws Exception {
179 String msg =
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000180 "object of type 'string' has no attribute \"count\", however, "
Florian Weikerte5e3e912016-03-08 03:08:26 +0000181 + "a method of that name exists";
182 new SkylarkTest()
183 .testIfExactError(msg, "getattr('a string', 'count')")
Jon Brandvein29bb6622016-10-27 13:55:43 +0000184 .testStatement("getattr('a string', 'count', 'default')", "default");
Florian Weikerte5e3e912016-03-08 03:08:26 +0000185 }
186
187 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000188 public void testDir() throws Exception {
Laurent Le Brunb525bee2016-03-07 17:14:10 +0000189 new SkylarkTest()
190 .testStatement(
191 "str(dir({}))",
Vladimir Moskva8d610c62016-09-15 14:36:41 +0000192 "[\"clear\", \"get\", \"items\", \"keys\","
Laurent Le Brunb525bee2016-03-07 17:14:10 +0000193 + " \"pop\", \"popitem\", \"setdefault\", \"update\", \"values\"]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000194 }
195
196 @Test
197 public void testBoolean() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000198 new BothModesTest().testStatement("False", Boolean.FALSE).testStatement("True", Boolean.TRUE);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000199 }
200
201 @Test
202 public void testBooleanUnsupportedOperationFails() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000203 new BothModesTest()
204 .testIfErrorContains("unsupported operand type(s) for +: 'bool' and 'bool'", "True + True");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000205 }
206
207 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000208 public void testListSort() throws Exception {
209 new BothModesTest()
210 .testEval("sorted([0,1,2,3])", "[0, 1, 2, 3]")
211 .testEval("sorted([])", "[]")
212 .testEval("sorted([3, 2, 1, 0])", "[0, 1, 2, 3]")
213 .testEval("sorted([[1], [], [2], [1, 2]])", "[[], [1], [1, 2], [2]]")
214 .testEval("sorted([True, False, True])", "[False, True, True]")
215 .testEval("sorted(['a','x','b','z'])", "[\"a\", \"b\", \"x\", \"z\"]")
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000216 .testEval("sorted({1: True, 5: True, 4: False})", "[1, 4, 5]")
Vladimir Moskva7f0cd622017-02-16 13:48:37 +0000217 .testEval("sorted(depset([1, 5, 4]))", "[1, 4, 5]")
218 .testIfExactError("Cannot compare function with function", "sorted([sorted, sorted])");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000219 }
220
221 @Test
Florian Weikert1c07e322015-09-25 11:59:40 +0000222 public void testDictionaryCopy() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000223 new BothModesTest()
Florian Weikert1c07e322015-09-25 11:59:40 +0000224 .setUp("x = {1 : 2}", "y = dict(x)")
225 .testEval("x[1] == 2 and y[1] == 2", "True");
226 }
227
228 @Test
229 public void testDictionaryCopyKeyCollision() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000230 new BothModesTest()
Florian Weikert1c07e322015-09-25 11:59:40 +0000231 .setUp("x = {'test' : 2}", "y = dict(x, test = 3)")
232 .testEval("y['test']", "3");
233 }
234
235 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000236 public void testDictionaryKeyNotFound() throws Exception {
237 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000238 .testIfErrorContains("key \"0\" not found in dictionary", "{}['0']")
239 .testIfErrorContains("key 0 not found in dictionary", "{'0': 1, 2: 3, 4: 5}[0]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000240 }
241
242 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000243 public void testDictionaryAccess() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000244 new BothModesTest()
245 .testEval("{1: ['foo']}[1]", "['foo']")
246 .testStatement("{'4': 8}['4']", 8)
247 .testStatement("{'a': 'aa', 'b': 'bb', 'c': 'cc'}['b']", "bb");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000248 }
249
250 @Test
251 public void testDictionaryVariableAccess() throws Exception {
252 new BothModesTest().setUp("d = {'a' : 1}", "a = d['a']\n").testLookup("a", 1);
253 }
254
255 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000256 public void testDictionaryCreation() throws Exception {
257 String expected = "{'a': 1, 'b': 2, 'c': 3}";
258
259 new BothModesTest()
260 .testEval("dict([('a', 1), ('b', 2), ('c', 3)])", expected)
261 .testEval("dict(a = 1, b = 2, c = 3)", expected)
262 .testEval("dict([('a', 1)], b = 2, c = 3)", expected);
263 }
264
265 @Test
266 public void testDictionaryCreationInnerLists() throws Exception {
267 new BothModesTest().testEval("dict([[1, 2], [3, 4]], a = 5)", "{1: 2, 3: 4, 'a': 5}");
268 }
269
270 @Test
271 public void testDictionaryCreationEmpty() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000272 new BothModesTest().testEval("dict()", "{}").testEval("dict([])", "{}");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000273 }
274
275 @Test
276 public void testDictionaryCreationDifferentKeyTypes() throws Exception {
277 String expected = "{'a': 1, 2: 3}";
278
279 new BothModesTest()
280 .testEval("dict([('a', 1), (2, 3)])", expected)
281 .testEval("dict([(2, 3)], a = 1)", expected);
282 }
283
284 @Test
285 public void testDictionaryCreationKeyCollision() throws Exception {
286 String expected = "{'a': 1, 'b': 2, 'c': 3}";
287
288 new BothModesTest()
289 .testEval("dict([('a', 42), ('b', 2), ('a', 1), ('c', 3)])", expected)
290 .testEval("dict([('a', 42)], a = 1, b = 2, c = 3)", expected);
Yun Pengfc610052016-06-20 11:44:06 +0000291 new SkylarkTest().testEval("dict([('a', 42)], **{'a': 1, 'b': 2, 'c': 3})", expected);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000292 }
293
294 @Test
295 public void testDictionaryCreationInvalidPositional() throws Exception {
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000296 new BothModesTest()
297 .testIfErrorContains(
Florian Weikert1c07e322015-09-25 11:59:40 +0000298 "expected value of type 'list(object)' for parameter args in dict(), "
Yun Pengfc610052016-06-20 11:44:06 +0000299 + "but got \"a\" (string)",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000300 "dict('a')")
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000301 .testIfErrorContains("cannot convert item #0 to a sequence", "dict(['a'])")
302 .testIfErrorContains("cannot convert item #0 to a sequence", "dict([('a')])")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000303 .testIfErrorContains("too many (3) positional arguments", "dict((3,4), (3,2), (1,2))")
304 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000305 "item #0 has length 3, but exactly two elements are required",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000306 "dict([('a', 'b', 'c')])");
307 }
308
309 @Test
310 public void testDictionaryValues() throws Exception {
311 new BothModesTest()
312 .testEval("{1: 'foo'}.values()", "['foo']")
313 .testEval("{}.values()", "[]")
Vladimir Moskva76e31d12016-12-05 16:28:37 +0000314 .testEval("{True: 3, False: 5}.values()", "[3, 5]")
315 .testEval("{'a': 5, 'c': 2, 'b': 4, 'd': 3}.values()", "[5, 2, 4, 3]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000316 // sorted by keys
317 }
318
319 @Test
320 public void testDictionaryKeys() throws Exception {
321 new BothModesTest()
322 .testEval("{1: 'foo'}.keys()", "[1]")
323 .testEval("{}.keys()", "[]")
Vladimir Moskva76e31d12016-12-05 16:28:37 +0000324 .testEval("{True: 3, False: 5}.keys()", "[True, False]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000325 .testEval(
Vladimir Moskva76e31d12016-12-05 16:28:37 +0000326 "{1:'a', 2:'b', 6:'c', 0:'d', 5:'e', 4:'f', 3:'g'}.keys()", "[1, 2, 6, 0, 5, 4, 3]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000327 }
328
329 @Test
330 public void testDictionaryGet() throws Exception {
331 new BuildTest()
332 .testStatement("{1: 'foo'}.get(1)", "foo")
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +0000333 .testStatement("{1: 'foo'}.get(2)", Runtime.NONE)
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000334 .testStatement("{1: 'foo'}.get(2, 'a')", "a")
335 .testStatement("{1: 'foo'}.get(2, default='a')", "a")
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +0000336 .testStatement("{1: 'foo'}.get(2, default=None)", Runtime.NONE);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000337 }
338
339 @Test
340 public void testDictionaryItems() throws Exception {
341 new BothModesTest()
342 .testEval("{'a': 'foo'}.items()", "[('a', 'foo')]")
343 .testEval("{}.items()", "[]")
344 .testEval("{1: 3, 2: 5}.items()", "[(1, 3), (2, 5)]")
Vladimir Moskva76e31d12016-12-05 16:28:37 +0000345 .testEval("{'a': 5, 'c': 2, 'b': 4}.items()", "[('a', 5), ('c', 2), ('b', 4)]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000346 }
347
348 @Test
Francois-Rene Rideau432d7152016-02-18 16:33:03 +0000349 public void testDictionaryClear() throws Exception {
350 new SkylarkTest()
351 .testEval(
352 "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n"
laurentlb85151182017-08-16 20:24:04 +0200353 + "len(d) == 3 or fail('clear 1')\n"
354 + "d.clear() == None or fail('clear 2')\n"
Yun Pengfc610052016-06-20 11:44:06 +0000355 + "d",
Francois-Rene Rideau432d7152016-02-18 16:33:03 +0000356 "{}");
357 }
358
359 @Test
360 public void testDictionaryPop() throws Exception {
361 new SkylarkTest()
362 .testIfErrorContains(
363 "KeyError: 1",
364 "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n"
laurentlb85151182017-08-16 20:24:04 +0200365 + "len(d) == 3 or fail('pop 1')\n"
366 + "d.pop(2) == 'bar' or fail('pop 2')\n"
367 + "d.pop(3, 'quux') == 'baz' or fail('pop 3a')\n"
368 + "d.pop(3, 'quux') == 'quux' or fail('pop 3b')\n"
369 + "d.pop(1) == 'foo' or fail('pop 1')\n"
370 + "d == {} or fail('pop 0')\n"
Yun Pengfc610052016-06-20 11:44:06 +0000371 + "d.pop(1)");
Francois-Rene Rideau432d7152016-02-18 16:33:03 +0000372 }
373
374 @Test
375 public void testDictionaryPopItem() throws Exception {
376 new SkylarkTest()
377 .testIfErrorContains(
378 "popitem(): dictionary is empty",
379 "d = {2: 'bar', 3: 'baz', 1: 'foo'}\n"
laurentlb85151182017-08-16 20:24:04 +0200380 + "len(d) == 3 or fail('popitem 0')\n"
381 + "d.popitem() == (2, 'bar') or fail('popitem 2')\n"
382 + "d.popitem() == (3, 'baz') or fail('popitem 3')\n"
383 + "d.popitem() == (1, 'foo') or fail('popitem 1')\n"
384 + "d == {} or fail('popitem 4')\n"
Yun Pengfc610052016-06-20 11:44:06 +0000385 + "d.popitem()");
Francois-Rene Rideau432d7152016-02-18 16:33:03 +0000386 }
387
388 @Test
Laurent Le Brunb525bee2016-03-07 17:14:10 +0000389 public void testDictionaryUpdate() throws Exception {
390 new BothModesTest()
391 .setUp("foo = {'a': 2}")
392 .testEval("foo.update({'b': 4}); foo", "{'a': 2, 'b': 4}");
393 new BothModesTest()
394 .setUp("foo = {'a': 2}")
395 .testEval("foo.update({'a': 3, 'b': 4}); foo", "{'a': 3, 'b': 4}");
396 }
397
398 @Test
Francois-Rene Rideau432d7152016-02-18 16:33:03 +0000399 public void testDictionarySetDefault() throws Exception {
400 new SkylarkTest()
401 .testEval(
402 "d = {2: 'bar', 1: 'foo'}\n"
laurentlb85151182017-08-16 20:24:04 +0200403 + "len(d) == 2 or fail('setdefault 0')\n"
404 + "d.setdefault(1, 'a') == 'foo' or fail('setdefault 1')\n"
405 + "d.setdefault(2) == 'bar' or fail('setdefault 2')\n"
406 + "d.setdefault(3) == None or fail('setdefault 3')\n"
407 + "d.setdefault(4, 'b') == 'b' or fail('setdefault 4')\n"
Yun Pengfc610052016-06-20 11:44:06 +0000408 + "d",
Francois-Rene Rideau432d7152016-02-18 16:33:03 +0000409 "{1: 'foo', 2: 'bar', 3: None, 4: 'b'}");
410 }
411
412 @Test
Laurent Le Brun3ef1eea2015-11-09 14:35:54 +0000413 public void testListIndexMethod() throws Exception {
414 new BothModesTest()
415 .testStatement("['a', 'b', 'c'].index('a')", 0)
416 .testStatement("['a', 'b', 'c'].index('b')", 1)
417 .testStatement("['a', 'b', 'c'].index('c')", 2)
418 .testStatement("[2, 4, 6].index(4)", 1)
419 .testStatement("[2, 4, 6].index(4)", 1)
420 .testStatement("[0, 1, [1]].index([1])", 2)
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000421 .testIfErrorContains("item \"a\" not found in list", "[1, 2].index('a')")
422 .testIfErrorContains("item 0 not found in list", "[].index(0)");
Laurent Le Brun3ef1eea2015-11-09 14:35:54 +0000423 }
424
425 @Test
Jon Brandvein9c4629d2016-07-20 20:16:33 +0000426 public void testHash() throws Exception {
Jon Brandvein3bdb4c32016-07-21 16:41:01 +0000427 // We specify the same string hashing algorithm as String.hashCode().
Jon Brandvein9c4629d2016-07-20 20:16:33 +0000428 new SkylarkTest()
429 .testStatement("hash('skylark')", "skylark".hashCode())
430 .testStatement("hash('google')", "google".hashCode())
431 .testIfErrorContains(
laurentlb9e540882017-07-07 06:58:45 -0400432 "argument 'value' has type 'NoneType', but should be 'string'\n"
433 + "in call to builtin function hash(value)",
Jon Brandvein9c4629d2016-07-20 20:16:33 +0000434 "hash(None)");
435 }
436
437 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000438 public void testRange() throws Exception {
439 new BothModesTest()
440 .testStatement("str(range(5))", "[0, 1, 2, 3, 4]")
441 .testStatement("str(range(0))", "[]")
442 .testStatement("str(range(1))", "[0]")
443 .testStatement("str(range(-2))", "[]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000444 .testStatement("str(range(-3, 2))", "[-3, -2, -1, 0, 1]")
445 .testStatement("str(range(3, 2))", "[]")
446 .testStatement("str(range(3, 3))", "[]")
447 .testStatement("str(range(3, 4))", "[3]")
448 .testStatement("str(range(3, 5))", "[3, 4]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000449 .testStatement("str(range(-3, 5, 2))", "[-3, -1, 1, 3]")
450 .testStatement("str(range(-3, 6, 2))", "[-3, -1, 1, 3, 5]")
451 .testStatement("str(range(5, 0, -1))", "[5, 4, 3, 2, 1]")
452 .testStatement("str(range(5, 0, -10))", "[5]")
453 .testStatement("str(range(0, -3, -2))", "[0, -2]")
454 .testIfErrorContains("step cannot be 0", "range(2, 3, 0)");
455 }
456
457 @Test
458 public void testEnumerate() throws Exception {
459 new BothModesTest()
460 .testStatement("str(enumerate([]))", "[]")
461 .testStatement("str(enumerate([5]))", "[(0, 5)]")
462 .testStatement("str(enumerate([5, 3]))", "[(0, 5), (1, 3)]")
463 .testStatement("str(enumerate(['a', 'b', 'c']))", "[(0, \"a\"), (1, \"b\"), (2, \"c\")]")
464 .testStatement("str(enumerate(['a']) + [(1, 'b')])", "[(0, \"a\"), (1, \"b\")]");
465 }
466
467 @Test
468 public void testEnumerateBadArg() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000469 new BothModesTest()
470 .testIfErrorContains(
laurentlb9e540882017-07-07 06:58:45 -0400471 "argument 'list' has type 'string', but should be 'sequence'\n"
472 + "in call to builtin function enumerate(list)",
Yun Pengfc610052016-06-20 11:44:06 +0000473 "enumerate('a')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000474 }
475
476 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000477 public void testReassignmentOfPrimitivesNotForbiddenByCoreLanguage() throws Exception {
478 new BuildTest()
479 .setUp("cc_binary = (['hello.cc'])")
480 .testIfErrorContains(
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +0000481 "'list' object is not callable",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000482 "cc_binary(name = 'hello', srcs=['hello.cc'], malloc = '//base:system_malloc')");
483 }
484
485 @Test
486 public void testLenOnString() throws Exception {
487 new BothModesTest().testStatement("len('abc')", 3);
488 }
489
490 @Test
491 public void testLenOnList() throws Exception {
492 new BothModesTest().testStatement("len([1,2,3])", 3);
493 }
494
495 @Test
496 public void testLenOnDict() throws Exception {
497 new BothModesTest().testStatement("len({'a' : 1, 'b' : 2})", 2);
498 }
499
500 @Test
501 public void testLenOnBadType() throws Exception {
502 new BothModesTest().testIfErrorContains("int is not iterable", "len(1)");
503 }
504
505 @Test
506 public void testIndexOnFunction() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000507 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000508 .testIfErrorContains("type 'function' has no operator [](int)", "len[1]")
laurentlb9b96c0b2018-02-12 02:53:19 -0800509 .testIfErrorContains("type 'function' has no operator [:](int, int, NoneType)", "len[1:4]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000510 }
511
512 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000513 public void testBool() throws Exception {
514 new BothModesTest()
515 .testStatement("bool(1)", Boolean.TRUE)
516 .testStatement("bool(0)", Boolean.FALSE)
517 .testStatement("bool([1, 2])", Boolean.TRUE)
518 .testStatement("bool([])", Boolean.FALSE)
519 .testStatement("bool(None)", Boolean.FALSE);
520 }
521
522 @Test
523 public void testStr() throws Exception {
vladmoscd6d8ae2017-10-12 15:35:17 +0200524 new BothModesTest()
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000525 .testStatement("str(1)", "1")
526 .testStatement("str(-2)", "-2")
527 .testStatement("str([1, 2])", "[1, 2]")
528 .testStatement("str(True)", "True")
529 .testStatement("str(False)", "False")
530 .testStatement("str(None)", "None")
vladmosaf624112017-08-25 16:41:47 +0200531 .testStatement("str(str)", "<built-in function str>");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000532 }
533
534 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000535 public void testStrFunction() throws Exception {
536 new SkylarkTest().testStatement("def foo(x): return x\nstr(foo)", "<function foo>");
537 }
538
539 @Test
540 public void testType() throws Exception {
541 new SkylarkTest()
542 .testStatement("type(1)", "int")
543 .testStatement("type('a')", "string")
544 .testStatement("type([1, 2])", "list")
545 .testStatement("type((1, 2))", "tuple")
546 .testStatement("type(True)", "bool")
547 .testStatement("type(None)", "NoneType")
548 .testStatement("type(str)", "function");
549 }
550
Jon Brandvein5b792dc2017-01-12 20:22:07 +0000551 // TODO(bazel-team): Move this into a new BazelLibraryTest.java file, or at least out of
552 // MethodLibraryTest.java.
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000553 @Test
554 public void testSelectFunction() throws Exception {
555 enableSkylarkMode();
556 eval("a = select({'a': 1})");
557 SelectorList result = (SelectorList) lookup("a");
558 assertThat(((SelectorValue) Iterables.getOnlyElement(result.getElements())).getDictionary())
lberkiaea56b32017-05-30 12:35:33 +0200559 .containsExactly("a", 1);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000560 }
561
562 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000563 public void testZipFunction() throws Exception {
564 new BothModesTest()
565 .testStatement("str(zip())", "[]")
566 .testStatement("str(zip([1, 2]))", "[(1,), (2,)]")
567 .testStatement("str(zip([1, 2], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]")
568 .testStatement("str(zip([1, 2, 3], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]")
569 .testStatement("str(zip([1], [2], [3]))", "[(1, 2, 3)]")
570 .testStatement("str(zip([1], {2: 'a'}))", "[(1, 2)]")
571 .testStatement("str(zip([1], []))", "[]")
572 .testIfErrorContains("type 'int' is not iterable", "zip(123)")
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000573 .testIfErrorContains("type 'int' is not iterable", "zip([1], 1)")
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000574 .testStatement("str(zip([1], depset([2])))", "[(1, 2)]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000575 }
Googler8e8fa052015-09-03 18:36:33 +0000576
Jon Brandvein36ecf162017-01-02 18:43:42 +0000577 /**
578 * Assert that lstrip(), rstrip(), and strip() produce the expected result for a given input
579 * string and chars argument. If chars is null no argument is passed.
580 */
581 private void checkStrip(
582 String input, Object chars,
583 String expLeft, String expRight, String expBoth) throws Exception {
584 if (chars == null) {
585 new BothModesTest()
586 .update("s", input)
587 .testStatement("s.lstrip()", expLeft)
588 .testStatement("s.rstrip()", expRight)
589 .testStatement("s.strip()", expBoth);
590 } else {
591 new BothModesTest()
592 .update("s", input)
593 .update("chars", chars)
594 .testStatement("s.lstrip(chars)", expLeft)
595 .testStatement("s.rstrip(chars)", expRight)
596 .testStatement("s.strip(chars)", expBoth);
597 }
Laurent Le Brunad849742015-10-15 11:36:01 +0000598 }
599
600 @Test
601 public void testStrip() throws Exception {
Jon Brandvein36ecf162017-01-02 18:43:42 +0000602 // Strip nothing.
603 checkStrip("a b c", "", "a b c", "a b c", "a b c");
604 checkStrip(" a b c ", "", " a b c ", " a b c ", " a b c ");
605 // Normal case, found and not found.
606 checkStrip("abcba", "ba", "cba", "abc", "c");
607 checkStrip("abc", "xyz", "abc", "abc", "abc");
608 // Default whitespace.
609 checkStrip(" a b c ", null, "a b c ", " a b c", "a b c");
610 checkStrip(" a b c ", Runtime.NONE, "a b c ", " a b c", "a b c");
611 // Default whitespace with full range of Latin-1 whitespace chars.
612 String whitespace = "\u0009\n\u000B\u000C\r\u001C\u001D\u001E\u001F\u0020\u0085\u00A0";
613 checkStrip(
614 whitespace + "a" + whitespace, null,
615 "a" + whitespace, whitespace + "a", "a");
616 checkStrip(
617 whitespace + "a" + whitespace, Runtime.NONE,
618 "a" + whitespace, whitespace + "a", "a");
619 // Empty cases.
620 checkStrip("", "", "", "", "");
621 checkStrip("abc", "abc", "", "", "");
622 checkStrip("", "xyz", "", "", "");
623 checkStrip("", null, "", "", "");
Laurent Le Brunad849742015-10-15 11:36:01 +0000624 }
Laurent Le Brunfe206a42016-05-23 17:03:49 +0000625
626 @Test
627 public void testFail() throws Exception {
628 new SkylarkTest()
629 .testIfErrorContains("abc", "fail('abc')")
630 .testIfErrorContains("18", "fail(18)");
631 }
Googlerde689132016-12-12 18:15:52 +0000632
633 @Test
634 public void testTupleCoercion() throws Exception {
635 new BothModesTest()
636 .testStatement("tuple([1, 2]) == (1, 2)", true)
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000637 .testStatement("tuple(depset([1, 2])) == (1, 2)", true)
Googlerde689132016-12-12 18:15:52 +0000638 // Depends on current implementation of dict
639 .testStatement("tuple({1: 'foo', 2: 'bar'}) == (1, 2)", true);
640 }
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000641}