blob: ea81adb35d52c919c890e965a8230f1aa82feeaf [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;
18import static org.junit.Assert.assertEquals;
19
20import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableMap;
22import com.google.common.collect.Iterables;
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +000023import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000024import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000025import org.junit.Before;
26import org.junit.Test;
27import org.junit.runner.RunWith;
28import org.junit.runners.JUnit4;
29
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000030/**
31 * Tests for MethodLibrary.
32 */
33@RunWith(JUnit4.class)
34public class MethodLibraryTest extends EvaluationTestCase {
35
Yun Pengfc610052016-06-20 11:44:06 +000036 private static final String LINE_SEPARATOR = System.lineSeparator();
37
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000038 @Before
Florian Weikertb4c59042015-12-01 10:47:18 +000039 public final void setFailFast() throws Exception {
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000040 setFailFast(true);
41 }
42
43 @Test
Florian Weikert5e8752b2015-12-11 21:54:43 +000044 public void testMinWithInvalidArgs() throws Exception {
45 new SkylarkTest()
46 .testIfExactError("type 'int' is not iterable", "min(1)")
47 .testIfExactError("Expected at least one argument", "min([])");
48 }
49
50 @Test
51 public void testMinWithString() throws Exception {
52 new SkylarkTest()
53 .testStatement("min('abcdefxyz')", "a")
54 .testStatement("min('test', 'xyz')", "test");
55 }
56
57 @Test
58 public void testMinWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000059 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +000060 .testEval("min([4, 5], [1])", "[1]")
61 .testEval("min([1, 2], [3])", "[1, 2]")
62 .testEval("min([1, 5], [1, 6], [2, 4], [0, 6])", "[0, 6]")
63 .testStatement("min([-1])", -1)
64 .testStatement("min([5, 2, 3])", 2);
65 }
66
67 @Test
68 public void testMinWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000069 new BothModesTest().testStatement("min({1: 2, -1 : 3})", -1).testStatement("min({2: None})", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +000070 }
71
72 @Test
73 public void testMinWithSet() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000074 new BothModesTest().testStatement("min(set([-1]))", -1).testStatement("min(set([5, 2, 3]))", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +000075 }
76
77 @Test
78 public void testMinWithPositionalArguments() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000079 new BothModesTest().testStatement("min(-1, 2)", -1).testStatement("min(5, 2, 3)", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +000080 }
81
82 @Test
83 public void testMinWithSameValues() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000084 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +000085 .testStatement("min(1, 1, 1, 1, 1, 1)", 1)
86 .testStatement("min([1, 1, 1, 1, 1, 1])", 1);
87 }
88
89 @Test
90 public void testMinWithDifferentTypes() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000091 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +000092 .testStatement("min(1, '2', True)", true)
93 .testStatement("min([1, '2', True])", true)
94 .testStatement("min(None, 1, 'test')", Runtime.NONE);
95 }
96
97 @Test
98 public void testMaxWithInvalidArgs() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000099 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +0000100 .testIfExactError("type 'int' is not iterable", "max(1)")
101 .testIfExactError("Expected at least one argument", "max([])");
102 }
103
104 @Test
105 public void testMaxWithString() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000106 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +0000107 .testStatement("max('abcdefxyz')", "z")
108 .testStatement("max('test', 'xyz')", "xyz");
109 }
110
111 @Test
112 public void testMaxWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000113 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +0000114 .testEval("max([1, 2], [5])", "[5]")
115 .testStatement("max([-1])", -1)
116 .testStatement("max([5, 2, 3])", 5);
117 }
118
119 @Test
120 public void testMaxWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000121 new BothModesTest().testStatement("max({1: 2, -1 : 3})", 1).testStatement("max({2: None})", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +0000122 }
123
124 @Test
125 public void testMaxWithSet() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000126 new BothModesTest().testStatement("max(set([-1]))", -1).testStatement("max(set([5, 2, 3]))", 5);
Florian Weikert5e8752b2015-12-11 21:54:43 +0000127 }
128
129 @Test
130 public void testMaxWithPositionalArguments() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000131 new BothModesTest().testStatement("max(-1, 2)", 2).testStatement("max(5, 2, 3)", 5);
Florian Weikert5e8752b2015-12-11 21:54:43 +0000132 }
133
134 @Test
135 public void testMaxWithSameValues() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000136 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +0000137 .testStatement("max(1, 1, 1, 1, 1, 1)", 1)
138 .testStatement("max([1, 1, 1, 1, 1, 1])", 1);
139 }
140
141 @Test
142 public void testMaxWithDifferentTypes() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000143 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +0000144 .testStatement("max(1, '2', True)", "2")
145 .testStatement("max([1, '2', True])", "2")
146 .testStatement("max(None, 1, 'test')", "test");
147 }
148
149 @Test
Florian Weikertcb8f2782015-12-10 23:30:23 +0000150 public void testSplitLines_EmptyLine() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000151 new BothModesTest().testEval("''.splitlines()", "[]").testEval("'\\n'.splitlines()", "['']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000152 }
153
154 @Test
155 public void testSplitLines_StartsWithLineBreak() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000156 new BothModesTest().testEval("'\\ntest'.splitlines()", "['', 'test']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000157 }
158
159 @Test
160 public void testSplitLines_EndsWithLineBreak() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000161 new BothModesTest().testEval("'test\\n'.splitlines()", "['test']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000162 }
163
164 @Test
165 public void testSplitLines_DifferentLineBreaks() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000166 new BothModesTest()
167 .testEval("'this\\nis\\na\\ntest'.splitlines()", "['this', 'is', 'a', 'test']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000168 }
169
170 @Test
171 public void testSplitLines_OnlyLineBreaks() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000172 new BothModesTest()
Florian Weikertcb8f2782015-12-10 23:30:23 +0000173 .testEval("'\\n\\n\\n'.splitlines()", "['', '', '']")
174 .testEval("'\\r\\r\\r'.splitlines()", "['', '', '']")
175 .testEval("'\\n\\r\\n\\r'.splitlines()", "['', '', '']")
176 .testEval("'\\r\\n\\r\\n\\r\\n'.splitlines()", "['', '', '']");
177 }
178
179 @Test
180 public void testSplitLines_EscapedSequences() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000181 new BothModesTest().testEval("'\\n\\\\n\\\\\\n'.splitlines()", "['', '\\\\n\\\\']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000182 }
183
184 @Test
185 public void testSplitLines_KeepEnds() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000186 new BothModesTest()
Florian Weikertcb8f2782015-12-10 23:30:23 +0000187 .testEval("''.splitlines(True)", "[]")
188 .testEval("'\\n'.splitlines(True)", "['\\n']")
189 .testEval(
190 "'this\\nis\\r\\na\\rtest'.splitlines(True)", "['this\\n', 'is\\r\\n', 'a\\r', 'test']")
191 .testEval("'\\ntest'.splitlines(True)", "['\\n', 'test']")
192 .testEval("'test\\n'.splitlines(True)", "['test\\n']")
193 .testEval("'\\n\\\\n\\\\\\n'.splitlines(True)", "['\\n', '\\\\n\\\\\\n']");
194 }
195
196 @Test
Florian Weikert532d3ba2015-12-17 10:36:45 +0000197 public void testStringIsAlnum() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000198 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000199 .testStatement("''.isalnum()", false)
200 .testStatement("'a0 33'.isalnum()", false)
201 .testStatement("'1'.isalnum()", true)
202 .testStatement("'a033'.isalnum()", true);
203 }
204
205 @Test
206 public void testStringIsDigit() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000207 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000208 .testStatement("''.isdigit()", false)
209 .testStatement("' '.isdigit()", false)
210 .testStatement("'a'.isdigit()", false)
211 .testStatement("'0234325.33'.isdigit()", false)
212 .testStatement("'1'.isdigit()", true)
213 .testStatement("'033'.isdigit()", true);
214 }
215
216 @Test
217 public void testStringIsSpace() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000218 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000219 .testStatement("''.isspace()", false)
220 .testStatement("'a'.isspace()", false)
221 .testStatement("'1'.isspace()", false)
222 .testStatement("'\\ta\\n'.isspace()", false)
223 .testStatement("' '.isspace()", true)
224 .testStatement("'\\t\\n'.isspace()", true);
225 }
226
227 @Test
228 public void testStringIsLower() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000229 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000230 .testStatement("''.islower()", false)
231 .testStatement("' '.islower()", false)
232 .testStatement("'1'.islower()", false)
233 .testStatement("'Almost'.islower()", false)
234 .testStatement("'abc'.islower()", true)
235 .testStatement("' \\nabc'.islower()", true)
236 .testStatement("'abc def\\n'.islower()", true)
237 .testStatement("'\\ta\\n'.islower()", true);
238 }
239
240 @Test
241 public void testStringIsUpper() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000242 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000243 .testStatement("''.isupper()", false)
244 .testStatement("' '.isupper()", false)
245 .testStatement("'1'.isupper()", false)
246 .testStatement("'aLMOST'.isupper()", false)
247 .testStatement("'ABC'.isupper()", true)
248 .testStatement("' \\nABC'.isupper()", true)
249 .testStatement("'ABC DEF\\n'.isupper()", true)
250 .testStatement("'\\tA\\n'.isupper()", true);
251 }
252
253 @Test
254 public void testStringIsTitle() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000255 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000256 .testStatement("''.istitle()", false)
257 .testStatement("' '.istitle()", false)
258 .testStatement("'134'.istitle()", false)
259 .testStatement("'almost Correct'.istitle()", false)
260 .testStatement("'1nope Nope Nope'.istitle()", false)
261 .testStatement("'NO Way'.istitle()", false)
262 .testStatement("'T'.istitle()", true)
263 .testStatement("'Correct'.istitle()", true)
264 .testStatement("'Very Correct! Yes\\nIndeed1X'.istitle()", true)
265 .testStatement("'1234Ab Ab'.istitle()", true)
266 .testStatement("'\\tA\\n'.istitle()", true);
267 }
268
269 @Test
Florian Weikert233a46e2015-12-16 12:38:38 +0000270 public void testAllWithEmptyValue() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000271 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000272 .testStatement("all('')", true)
273 .testStatement("all([])", true)
274 .testIfExactError("type 'NoneType' is not iterable", "any(None)");
275 }
276
277 @Test
278 public void testAllWithPrimitiveType() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000279 new BothModesTest().testStatement("all('test')", true).testIfErrorContains("", "all(1)");
Florian Weikert233a46e2015-12-16 12:38:38 +0000280 }
281
282 @Test
283 public void testAllWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000284 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000285 .testStatement("all([False])", false)
286 .testStatement("all([True, False])", false)
287 .testStatement("all([False, False])", false)
288 .testStatement("all([False, True])", false)
289 .testStatement("all(['', True])", false)
290 .testStatement("all([0, True])", false)
291 .testStatement("all([[], True])", false)
292 .testStatement("all([True, 't', 1])", true);
293 }
294
295 @Test
296 public void testAllWithSet() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000297 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000298 .testStatement("all(set([0]))", false)
299 .testStatement("all(set([1, 0]))", false)
300 .testStatement("all(set([1]))", true);
301 }
302
303 @Test
304 public void testAllWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000305 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000306 .testStatement("all({1 : None})", true)
307 .testStatement("all({None : 1})", false);
308 }
309
310 @Test
311 public void testAnyWithEmptyValue() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000312 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000313 .testStatement("any('')", false)
314 .testStatement("any([])", false)
315 .testIfExactError("type 'NoneType' is not iterable", "any(None)");
316 }
317
318 @Test
319 public void testAnyWithPrimitiveType() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000320 new BothModesTest().testStatement("any('test')", true).testIfErrorContains("", "any(1)");
Florian Weikert233a46e2015-12-16 12:38:38 +0000321 }
322
323 @Test
324 public void testAnyWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000325 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000326 .testStatement("any([False])", false)
327 .testStatement("any([0])", false)
328 .testStatement("any([''])", false)
329 .testStatement("any([[]])", false)
330 .testStatement("any([True, False])", true)
331 .testStatement("any([False, False])", false)
332 .testStatement("any([False, '', 0])", false)
333 .testStatement("any([False, '', 42])", true);
334 }
335
336 @Test
337 public void testAnyWithSet() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000338 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000339 .testStatement("any(set([0]))", false)
340 .testStatement("any(set([1, 0]))", true);
341 }
342
343 @Test
344 public void testAnyWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000345 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000346 .testStatement("any({1 : None, '' : None})", true)
347 .testStatement("any({None : 1, '' : 2})", false);
348 }
349
350 @Test
Florian Weikert90a15962015-09-11 13:43:10 +0000351 public void testStackTraceLocation() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000352 new SkylarkTest()
353 .testIfErrorContains(
Yun Penge7e55bb2016-09-09 09:11:42 +0000354 "Traceback (most recent call last):"
Yun Pengfc610052016-06-20 11:44:06 +0000355 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000356 + "\tFile \"<unknown>\", line 8"
Yun Pengfc610052016-06-20 11:44:06 +0000357 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000358 + "\t\tfoo()"
359 + LINE_SEPARATOR
360 + "\tFile \"<unknown>\", line 2, in foo"
361 + LINE_SEPARATOR
362 + "\t\tbar(1)"
363 + LINE_SEPARATOR
364 + "\tFile \"<unknown>\", line 7, in bar"
Yun Pengfc610052016-06-20 11:44:06 +0000365 + LINE_SEPARATOR
366 + "\t\t'test'.index(x)",
367 "def foo():",
368 " bar(1)",
369 "def bar(x):",
370 " if x == 1:",
371 " a = x",
372 " b = 2",
373 " 'test'.index(x)",
374 "foo()");
Florian Weikert90a15962015-09-11 13:43:10 +0000375 }
376
377 @Test
378 public void testStackTraceWithIf() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000379 new SkylarkTest()
380 .testIfErrorContains(
381 "File \"<unknown>\", line 5"
382 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000383 + "\t\tfoo()"
384 + LINE_SEPARATOR
385 + "\tFile \"<unknown>\", line 3, in foo"
Yun Pengfc610052016-06-20 11:44:06 +0000386 + LINE_SEPARATOR
387 + "\t\ts[0]",
388 "def foo():",
389 " s = set()",
390 " if s[0] == 1:",
391 " x = 1",
392 "foo()");
Florian Weikert90a15962015-09-11 13:43:10 +0000393 }
394
395 @Test
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000396 public void testStackTraceSkipBuiltInOnly() throws Exception {
397 // The error message should not include the stack trace when there is
398 // only one built-in function.
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000399 new BothModesTest()
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000400 .testIfExactError(
401 "Method string.index(sub: string, start: int, end: int or NoneType) is not applicable "
402 + "for arguments (int, int, NoneType): 'sub' is int, but should be string",
403 "'test'.index(1)");
404 }
405
406 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000407 public void testStackTrace() throws Exception {
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000408 // Unlike SkylarintegrationTests#testStackTraceErrorInFunction(), this test
409 // has neither a BUILD nor a bzl file.
410 new SkylarkTest()
411 .testIfExactError(
Yun Penge7e55bb2016-09-09 09:11:42 +0000412 "Traceback (most recent call last):"
413 + LINE_SEPARATOR
Yun Pengfc610052016-06-20 11:44:06 +0000414 + "\tFile \"<unknown>\", line 6"
415 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000416 + "\t\tfoo()"
417 + LINE_SEPARATOR
Yun Pengfc610052016-06-20 11:44:06 +0000418 + "\tFile \"<unknown>\", line 2, in foo"
419 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000420 + "\t\tbar(1)"
421 + LINE_SEPARATOR
Yun Pengfc610052016-06-20 11:44:06 +0000422 + "\tFile \"<unknown>\", line 5, in bar"
423 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000424 + "\t\t'test'.index(x)"
425 + LINE_SEPARATOR
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000426 + "Method string.index(sub: string, start: int, end: int or NoneType) "
427 + "is not applicable "
428 + "for arguments (int, int, NoneType): 'sub' is int, but should be string",
429 "def foo():",
Florian Weikert90a15962015-09-11 13:43:10 +0000430 " bar(1)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000431 "def bar(x):",
Florian Weikert90a15962015-09-11 13:43:10 +0000432 " if 1 == 1:",
433 " 'test'.index(x)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000434 "foo()");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000435 }
436
437 @Test
438 public void testBuiltinFunctionErrorMessage() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000439 new BothModesTest()
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000440 .testIfErrorContains(
Francois-Rene Rideauab049e02016-02-17 16:13:46 +0000441 "Method set.union(new_elements: Iterable) is not applicable for arguments (string): "
442 + "'new_elements' is string, but should be Iterable",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000443 "set([]).union('a')")
444 .testIfErrorContains(
445 "Method string.startswith(sub: string, start: int, end: int or NoneType) is not "
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000446 + "applicable for arguments (int, int, NoneType): 'sub' is int, "
447 + "but should be string",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000448 "'test'.startswith(1)")
449 .testIfErrorContains(
Florian Weikert1c07e322015-09-25 11:59:40 +0000450 "expected value of type 'list(object)' for parameter args in dict(), "
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000451 + "but got \"a\" (string)",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000452 "dict('a')");
453 }
454
455 @Test
456 public void testHasAttr() throws Exception {
457 new SkylarkTest()
458 .testStatement("hasattr(set(), 'union')", Boolean.TRUE)
459 .testStatement("hasattr('test', 'count')", Boolean.TRUE)
460 .testStatement("hasattr(dict(a = 1, b = 2), 'items')", Boolean.TRUE)
461 .testStatement("hasattr({}, 'items')", Boolean.TRUE);
462 }
463
464 @Test
Florian Weikerte5e3e912016-03-08 03:08:26 +0000465 public void testGetAttrMissingField() throws Exception {
466 new SkylarkTest()
467 .testIfExactError(
468 "Object of type 'string' has no attribute \"not_there\"",
469 "getattr('a string', 'not_there')")
Jon Brandveinad81cff2016-07-26 13:04:10 +0000470 .testStatement("getattr('a string', 'not_there', 'use this')", "use this")
471 .testStatement("getattr('a string', 'not there', None)", Runtime.NONE);
Florian Weikerte5e3e912016-03-08 03:08:26 +0000472 }
473
474 @Test
475 public void testGetAttrWithMethods() throws Exception {
476 String msg =
477 "Object of type 'string' has no attribute \"count\", however, "
478 + "a method of that name exists";
479 new SkylarkTest()
480 .testIfExactError(msg, "getattr('a string', 'count')")
Jon Brandvein29bb6622016-10-27 13:55:43 +0000481 .testStatement("getattr('a string', 'count', 'default')", "default");
Florian Weikerte5e3e912016-03-08 03:08:26 +0000482 }
483
484 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000485 public void testDir() throws Exception {
Laurent Le Brunb525bee2016-03-07 17:14:10 +0000486 new SkylarkTest()
487 .testStatement(
488 "str(dir({}))",
Vladimir Moskva8d610c62016-09-15 14:36:41 +0000489 "[\"clear\", \"get\", \"items\", \"keys\","
Laurent Le Brunb525bee2016-03-07 17:14:10 +0000490 + " \"pop\", \"popitem\", \"setdefault\", \"update\", \"values\"]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000491 }
492
493 @Test
494 public void testBoolean() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000495 new BothModesTest().testStatement("False", Boolean.FALSE).testStatement("True", Boolean.TRUE);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000496 }
497
498 @Test
499 public void testBooleanUnsupportedOperationFails() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000500 new BothModesTest()
501 .testIfErrorContains("unsupported operand type(s) for +: 'bool' and 'bool'", "True + True");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000502 }
503
504 @Test
505 public void testPyStringJoin() throws Exception {
506 new BothModesTest().testStatement("'-'.join([ 'a', 'b', 'c' ])", "a-b-c");
507 }
508
509 @Test
510 public void testPyStringGlobalJoin() throws Exception {
511 // TODO(bazel-team): BUILD and Skylark should use the same code path (and same error message).
Yun Pengfc610052016-06-20 11:44:06 +0000512 new BuildTest()
513 .testIfErrorContains("name 'join' is not defined", "join(' ', [ 'a', 'b', 'c' ])");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000514
Yun Pengfc610052016-06-20 11:44:06 +0000515 new SkylarkTest()
516 .testIfErrorContains(
517 "ERROR 1:1: function 'join' does not exist", "join(' ', [ 'a', 'b', 'c' ])");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000518
519 new BothModesTest().testStatement("' '.join([ 'a', 'b', 'c' ])", "a b c");
520 }
521
522 @Test
523 public void testPyStringJoinCompr() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000524 new BothModesTest()
525 .testStatement("''.join([(x + '*') for x in ['a', 'b', 'c']])", "a*b*c*")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000526 .testStatement(
527 "''.join([(y + '*' + z + '|') " + "for y in ['a', 'b', 'c'] for z in ['d', 'e']])",
528 "a*d|a*e|b*d|b*e|c*d|c*e|");
529 }
530
531 @Test
532 public void testPyStringLower() throws Exception {
533 new BothModesTest().testStatement("'Blah Blah'.lower()", "blah blah");
534 }
535
536 @Test
537 public void testPyStringUpper() throws Exception {
538 new BothModesTest()
539 .testStatement("'ein bier'.upper()", "EIN BIER")
540 .testStatement("''.upper()", "");
541 }
542
543 @Test
544 public void testPyStringReplace() throws Exception {
545 new BothModesTest()
Yun Pengfc610052016-06-20 11:44:06 +0000546 .testStatement("'banana'.replace('a', 'e')", "benene")
547 .testStatement("'banana'.replace('a', '$()')", "b$()n$()n$()")
548 .testStatement("'banana'.replace('a', '$')", "b$n$n$")
549 .testStatement("'banana'.replace('a', '\\\\')", "b\\n\\n\\")
550 .testStatement("'b$()n$()n$()'.replace('$()', '$($())')", "b$($())n$($())n$($())")
551 .testStatement("'b\\\\n\\\\n\\\\'.replace('\\\\', '$()')", "b$()n$()n$()");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000552 }
553
554 @Test
555 public void testPyStringReplace2() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000556 new BothModesTest().testStatement("'banana'.replace('a', 'e', 2)", "benena");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000557 }
558
559 @Test
560 public void testPyStringSplit() throws Exception {
561 new BothModesTest().testEval("'h i'.split(' ')", "['h', 'i']");
562 }
563
564 @Test
565 public void testPyStringSplit2() throws Exception {
566 new BothModesTest().testEval("'h i p'.split(' ')", "['h', 'i', 'p']");
567 }
568
569 @Test
570 public void testPyStringSplit3() throws Exception {
571 new BothModesTest().testEval("'a,e,i,o,u'.split(',', 2)", "['a', 'e', 'i,o,u']");
572 }
573
574 @Test
575 public void testPyStringSplitNoSep() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000576 new BothModesTest()
577 .testEval("' 1 2 3 '.split(' ')", "['', '', '1', '', '2', '', '3', '', '']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000578 }
579
580 @Test
581 public void testPyStringRSplitRegex() throws Exception {
582 new BothModesTest()
583 .testEval("'foo/bar.lisp'.rsplit('.')", "['foo/bar', 'lisp']")
584 .testEval("'foo/bar.?lisp'.rsplit('.?')", "['foo/bar', 'lisp']")
585 .testEval("'fwe$foo'.rsplit('$')", "['fwe', 'foo']")
586 .testEval("'windows'.rsplit('\\w')", "['windows']");
587 }
588
589 @Test
590 public void testPyStringRSplitNoMatch() throws Exception {
591 new BothModesTest()
592 .testEval("''.rsplit('o')", "['']")
593 .testEval("'google'.rsplit('x')", "['google']");
594 }
595
596 @Test
597 public void testPyStringRSplitSeparator() throws Exception {
598 new BothModesTest()
599 .testEval("'xxxxxx'.rsplit('x')", "['', '', '', '', '', '', '']")
600 .testEval("'xxxxxx'.rsplit('x', 1)", "['xxxxx', '']")
601 .testEval("'xxxxxx'.rsplit('x', 2)", "['xxxx', '', '']")
602 .testEval("'xxxxxx'.rsplit('x', 3)", "['xxx', '', '', '']")
603 .testEval("'xxxxxx'.rsplit('x', 4)", "['xx', '', '', '', '']")
604 .testEval("'xxxxxx'.rsplit('x', 5)", "['x', '', '', '', '', '']")
605 .testEval("'xxxxxx'.rsplit('x', 6)", "['', '', '', '', '', '', '']")
606 .testEval("'xxxxxx'.rsplit('x', 7)", "['', '', '', '', '', '', '']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000607 }
608
609 @Test
610 public void testPyStringRSplitLongerSep() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000611 new BothModesTest()
612 .testEval("'abcdabef'.rsplit('ab')", "['', 'cd', 'ef']")
613 .testEval("'google_or_gogol'.rsplit('go')", "['', 'ogle_or_', '', 'l']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000614 }
615
616 @Test
617 public void testPyStringRSplitMaxSplit() throws Exception {
618 new BothModesTest()
619 .testEval("'google'.rsplit('o')", "['g', '', 'gle']")
620 .testEval("'google'.rsplit('o')", "['g', '', 'gle']")
621 .testEval("'google'.rsplit('o', 1)", "['go', 'gle']")
622 .testEval("'google'.rsplit('o', 2)", "['g', '', 'gle']")
623 .testEval("'google'.rsplit('o', 3)", "['g', '', 'gle']")
624 .testEval("'ogooglo'.rsplit('o')", "['', 'g', '', 'gl', '']")
625 .testEval("'ogooglo'.rsplit('o', 1)", "['ogoogl', '']")
626 .testEval("'ogooglo'.rsplit('o', 2)", "['ogo', 'gl', '']")
627 .testEval("'ogooglo'.rsplit('o', 3)", "['og', '', 'gl', '']")
628 .testEval("'ogooglo'.rsplit('o', 4)", "['', 'g', '', 'gl', '']")
629 .testEval("'ogooglo'.rsplit('o', 5)", "['', 'g', '', 'gl', '']")
630 .testEval("'google'.rsplit('google')", "['', '']")
631 .testEval("'google'.rsplit('google', 1)", "['', '']")
632 .testEval("'google'.rsplit('google', 2)", "['', '']");
633 }
634
635 @Test
636 public void testPyStringPartitionEasy() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000637 new BothModesTest()
638 .testEval("'lawl'.partition('a')", "['l', 'a', 'wl']")
639 .testEval("'lawl'.rpartition('a')", "['l', 'a', 'wl']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000640 }
641
642 @Test
643 public void testPyStringPartitionMultipleSep() throws Exception {
644 new BothModesTest()
645 .testEval("'google'.partition('o')", "['g', 'o', 'ogle']")
646 .testEval("'google'.rpartition('o')", "['go', 'o', 'gle']")
647 .testEval("'xxx'.partition('x')", "['', 'x', 'xx']")
648 .testEval("'xxx'.rpartition('x')", "['xx', 'x', '']");
649 }
650
651 @Test
652 public void testPyStringPartitionEmptyInput() throws Exception {
653 new BothModesTest()
654 .testEval("''.partition('a')", "['', '', '']")
655 .testEval("''.rpartition('a')", "['', '', '']");
656 }
657
658 @Test
659 public void testPyStringPartitionEmptySeparator() throws Exception {
660 new BothModesTest()
661 .testIfErrorContains("Empty separator", "'google'.partition('')")
662 .testIfErrorContains("Empty separator", "'google'.rpartition('')");
663 }
664
665 @Test
666 public void testPyStringPartitionDefaultSep() throws Exception {
667 new BothModesTest()
668 .testEval("'hi this is a test'.partition()", "['hi', ' ', 'this is a test']")
669 .testEval("'hi this is a test'.rpartition()", "['hi this is a', ' ', 'test']")
670 .testEval("'google'.partition()", "['google', '', '']")
671 .testEval("'google'.rpartition()", "['', '', 'google']");
672 }
673
674 @Test
675 public void testPyStringPartitionNoMatch() throws Exception {
676 new BothModesTest()
677 .testEval("'google'.partition('x')", "['google', '', '']")
678 .testEval("'google'.rpartition('x')", "['', '', 'google']");
679 }
680
681 @Test
682 public void testPyStringPartitionWordBoundaries() throws Exception {
683 new BothModesTest()
684 .testEval("'goog'.partition('g')", "['', 'g', 'oog']")
685 .testEval("'goog'.rpartition('g')", "['goo', 'g', '']")
686 .testEval("'plex'.partition('p')", "['', 'p', 'lex']")
687 .testEval("'plex'.rpartition('p')", "['', 'p', 'lex']")
688 .testEval("'plex'.partition('x')", "['ple', 'x', '']")
689 .testEval("'plex'.rpartition('x')", "['ple', 'x', '']");
690 }
691
692 @Test
693 public void testPyStringPartitionLongSep() throws Exception {
694 new BothModesTest()
695 .testEval("'google'.partition('oog')", "['g', 'oog', 'le']")
696 .testEval("'google'.rpartition('oog')", "['g', 'oog', 'le']")
697 .testEval(
698 "'lolgooglolgooglolgooglol'.partition('goog')", "['lol', 'goog', 'lolgooglolgooglol']")
699 .testEval(
700 "'lolgooglolgooglolgooglol'.rpartition('goog')",
701 "['lolgooglolgooglol', 'goog', 'lol']");
702 }
703
704 @Test
705 public void testPyStringPartitionCompleteString() throws Exception {
706 new BothModesTest()
707 .testEval("'google'.partition('google')", "['', 'google', '']")
708 .testEval("'google'.rpartition('google')", "['', 'google', '']");
709 }
710
711 @Test
712 public void testPyStringTitle() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000713 new BothModesTest()
714 .testStatement("'this is a very simple test'.title()", "This Is A Very Simple Test");
715 new BothModesTest()
716 .testStatement("'Do We Keep Capital Letters?'.title()", "Do We Keep Capital Letters?");
717 new BothModesTest()
718 .testStatement(
719 "'this isn\\'t just an ol\\' apostrophe test'.title()",
720 "This Isn'T Just An Ol' Apostrophe Test");
721 new BothModesTest()
722 .testStatement(
723 "'Let us test crazy characters: _bla.exe//foo:bla(test$class)'.title()",
724 "Let Us Test Crazy Characters: _Bla.Exe//Foo:Bla(Test$Class)");
725 new BothModesTest().testStatement("'any germans here? äöü'.title()", "Any Germans Here? Äöü");
726 new BothModesTest()
727 .testStatement(
728 "'WE HAve tO lOWERCASE soMEthING heRE, AI?'.title()",
729 "We Have To Lowercase Something Here, Ai?");
730 new BothModesTest()
731 .testStatement("'wh4t ab0ut s0me numb3rs'.title()", "Wh4T Ab0Ut S0Me Numb3Rs");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000732 }
733
734 @Test
Laurent Le Brunb4114cc2015-08-26 14:53:37 +0000735 public void testCapitalize() throws Exception {
736 new BothModesTest()
737 .testStatement("'hello world'.capitalize()", "Hello world")
738 .testStatement("'HELLO WORLD'.capitalize()", "Hello world")
739 .testStatement("''.capitalize()", "")
740 .testStatement("'12 lower UPPER 34'.capitalize()", "12 lower upper 34");
741 }
742
743 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000744 public void testPyStringRfind() throws Exception {
745 new BothModesTest()
746 .testStatement("'banana'.rfind('na')", 4)
747 .testStatement("'banana'.rfind('na', 3, 1)", -1)
748 .testStatement("'aaaa'.rfind('a', 1, 1)", -1)
749 .testStatement("'aaaa'.rfind('a', 1, 50)", 3)
750 .testStatement("'aaaa'.rfind('aaaaa')", -1)
751 .testStatement("'abababa'.rfind('ab', 1)", 4)
752 .testStatement("'abababa'.rfind('ab', 0)", 4)
753 .testStatement("'abababa'.rfind('ab', -1)", -1)
754 .testStatement("'abababa'.rfind('ab', -2)", -1)
755 .testStatement("'abababa'.rfind('ab', -3)", 4)
756 .testStatement("'abababa'.rfind('ab', 0, 1)", -1)
757 .testStatement("'abababa'.rfind('ab', 0, 2)", 0)
758 .testStatement("'abababa'.rfind('ab', -1000)", 4)
759 .testStatement("'abababa'.rfind('ab', 1000)", -1)
760 .testStatement("''.rfind('a', 1)", -1);
761 }
762
763 @Test
764 public void testPyStringFind() throws Exception {
765 new BothModesTest()
766 .testStatement("'banana'.find('na')", 2)
767 .testStatement("'banana'.find('na', 3, 1)", -1)
768 .testStatement("'aaaa'.find('a', 1, 1)", -1)
769 .testStatement("'aaaa'.find('a', 1, 50)", 1)
770 .testStatement("'aaaa'.find('aaaaa')", -1)
771 .testStatement("'abababa'.find('ab', 1)", 2)
772 .testStatement("'abababa'.find('ab', 0)", 0)
773 .testStatement("'abababa'.find('ab', -1)", -1)
774 .testStatement("'abababa'.find('ab', -2)", -1)
775 .testStatement("'abababa'.find('ab', -3)", 4)
776 .testStatement("'abababa'.find('ab', 0, 1)", -1)
777 .testStatement("'abababa'.find('ab', 0, 2)", 0)
778 .testStatement("'abababa'.find('ab', -1000)", 0)
779 .testStatement("'abababa'.find('ab', 1000)", -1)
780 .testStatement("''.find('a', 1)", -1);
781 }
782
783 @Test
784 public void testPyStringIndex() throws Exception {
785 new BothModesTest()
786 .testStatement("'banana'.index('na')", 2)
787 .testStatement("'abababa'.index('ab', 1)", 2)
788 .testIfErrorContains("substring \"foo\" not found in \"banana\"", "'banana'.index('foo')");
789 }
790
791 @Test
792 public void testPyStringRIndex() throws Exception {
793 new BothModesTest()
794 .testStatement("'banana'.rindex('na')", 4)
795 .testStatement("'abababa'.rindex('ab', 1)", 4)
796 .testIfErrorContains("substring \"foo\" not found in \"banana\"", "'banana'.rindex('foo')");
797 }
798
799 @Test
800 public void testPyStringEndswith() throws Exception {
801 new BothModesTest()
802 .testStatement("'Apricot'.endswith('cot')", true)
803 .testStatement("'a'.endswith('')", true)
804 .testStatement("''.endswith('')", true)
805 .testStatement("'Apricot'.endswith('co')", false)
806 .testStatement("'Apricot'.endswith('co', -1)", false)
807 .testStatement("'abcd'.endswith('c', -2, -1)", true)
808 .testStatement("'abcd'.endswith('c', 1, 8)", false)
809 .testStatement("'abcd'.endswith('d', 1, 8)", true);
810 }
811
812 @Test
813 public void testPyStringStartswith() throws Exception {
814 new BothModesTest()
815 .testStatement("'Apricot'.startswith('Apr')", true)
816 .testStatement("'Apricot'.startswith('A')", true)
817 .testStatement("'Apricot'.startswith('')", true)
818 .testStatement("'Apricot'.startswith('z')", false)
819 .testStatement("''.startswith('')", true)
820 .testStatement("''.startswith('a')", false);
821 }
822
823 @Test
824 public void testPySubstring() throws Exception {
825 new BothModesTest()
826 .testStatement("'012345678'[0:-1]", "01234567")
827 .testStatement("'012345678'[2:4]", "23")
828 .testStatement("'012345678'[-5:-3]", "45")
829 .testStatement("'012345678'[2:2]", "")
830 .testStatement("'012345678'[2:]", "2345678")
831 .testStatement("'012345678'[:3]", "012")
832 .testStatement("'012345678'[-1:]", "8")
833 .testStatement("'012345678'[:]", "012345678")
834 .testStatement("'012345678'[-1:2]", "")
835 .testStatement("'012345678'[4:2]", "");
836 }
837
838 @Test
839 public void testPyStringFormatEscaping() throws Exception {
840 new BothModesTest()
841 .testStatement("'{{}}'.format()", "{}")
842 .testStatement("'{{}}'.format(42)", "{}")
843 .testStatement("'{{ }}'.format()", "{ }")
844 .testStatement("'{{ }}'.format(42)", "{ }")
845 .testStatement("'{{{{}}}}'.format()", "{{}}")
846 .testStatement("'{{{{}}}}'.format(42)", "{{}}")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000847 .testStatement("'{{0}}'.format(42)", "{0}")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000848 .testStatement("'{{}}'.format(42)", "{}")
849 .testStatement("'{{{}}}'.format(42)", "{42}")
850 .testStatement("'{{ '.format(42)", "{ ")
851 .testStatement("' }}'.format(42)", " }")
852 .testStatement("'{{ {}'.format(42)", "{ 42")
853 .testStatement("'{} }}'.format(42)", "42 }")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000854 .testStatement("'{{0}}'.format(42)", "{0}")
855 .testStatement("'{{{0}}}'.format(42)", "{42}")
856 .testStatement("'{{ 0'.format(42)", "{ 0")
857 .testStatement("'0 }}'.format(42)", "0 }")
858 .testStatement("'{{ {0}'.format(42)", "{ 42")
859 .testStatement("'{0} }}'.format(42)", "42 }")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000860 .testStatement("'{{test}}'.format(test = 42)", "{test}")
861 .testStatement("'{{{test}}}'.format(test = 42)", "{42}")
862 .testStatement("'{{ test'.format(test = 42)", "{ test")
863 .testStatement("'test }}'.format(test = 42)", "test }")
864 .testStatement("'{{ {test}'.format(test = 42)", "{ 42")
865 .testStatement("'{test} }}'.format(test = 42)", "42 }")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000866 .testIfErrorContains("Found '}' without matching '{'", "'{{}'.format(1)")
867 .testIfErrorContains("Found '}' without matching '{'", "'{}}'.format(1)");
868 }
869
870 @Test
871 public void testPyStringFormatManualPositionals() throws Exception {
872 new BothModesTest()
873 .testStatement(
874 "'{0}, {1} {2} {3} test'.format('hi', 'this', 'is', 'a')", "hi, this is a test")
875 .testStatement(
876 "'{3}, {2} {1} {0} test'.format('a', 'is', 'this', 'hi')", "hi, this is a test")
877 .testStatement(
878 "'skip some {0}'.format('arguments', 'obsolete', 'deprecated')", "skip some arguments")
879 .testStatement(
880 "'{0} can be reused: {0}'.format('this', 'obsolete')", "this can be reused: this");
881 }
882
883 @Test
884 public void testPyStringFormatManualPositionalsErrors() throws Exception {
885 new BothModesTest()
886 .testIfErrorContains("No replacement found for index 0", "'{0}'.format()")
887 .testIfErrorContains("No replacement found for index 1", "'{0} and {1}'.format('this')")
888 .testIfErrorContains(
889 "No replacement found for index 2", "'{0} and {2}'.format('this', 'that')")
890 .testIfErrorContains(
891 "No replacement found for index -1", "'{-0} and {-1}'.format('this', 'that')")
892 .testIfErrorContains(
893 "Invalid character ',' inside replacement field",
894 "'{0,1} and {1}'.format('this', 'that')")
895 .testIfErrorContains(
896 "Invalid character '.' inside replacement field",
897 "'{0.1} and {1}'.format('this', 'that')");
898 }
899
900 @Test
901 public void testPyStringFormatAutomaticPositionals() throws Exception {
902 new BothModesTest()
903 .testStatement("'{}, {} {} {} test'.format('hi', 'this', 'is', 'a')", "hi, this is a test")
904 .testStatement(
905 "'skip some {}'.format('arguments', 'obsolete', 'deprecated')", "skip some arguments");
906 }
907
908 @Test
909 public void testPyStringFormatAutomaticPositionalsError() throws Exception {
910 new BothModesTest()
911 .testIfErrorContains("No replacement found for index 0", "'{}'.format()")
912 .testIfErrorContains("No replacement found for index 1", "'{} and {}'.format('this')");
913 }
914
915 @Test
916 public void testPyStringFormatMixedFields() throws Exception {
917 new BothModesTest()
918 .testStatement("'{test} and {}'.format(2, test = 1)", "1 and 2")
919 .testStatement("'{test} and {0}'.format(2, test = 1)", "1 and 2")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000920 .testIfErrorContains(
921 "non-keyword arg after keyword arg", "'{test} and {}'.format(test = 1, 2)")
922 .testIfErrorContains(
923 "non-keyword arg after keyword arg", "'{test} and {0}'.format(test = 1, 2)")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000924 .testIfErrorContains(
925 "Cannot mix manual and automatic numbering of positional fields",
926 "'{} and {1}'.format(1, 2)")
927 .testIfErrorContains(
928 "Cannot mix manual and automatic numbering of positional fields",
929 "'{1} and {}'.format(1, 2)");
930 }
931
932 @Test
933 public void testPyStringFormatInvalidFields() throws Exception {
934 for (char unsupported : new char[] {'.', '[', ']', ','}) {
Yun Pengfc610052016-06-20 11:44:06 +0000935 new BothModesTest()
936 .testIfErrorContains(
937 String.format("Invalid character '%c' inside replacement field", unsupported),
938 String.format("'{test%ctest}'.format(test = 1)", unsupported));
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000939 }
940
Yun Pengfc610052016-06-20 11:44:06 +0000941 new BothModesTest()
942 .testIfErrorContains("Nested replacement fields are not supported", "'{ {} }'.format(42)");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000943 }
944
945 @Test
946 public void testPyStringFormat() throws Exception {
947 new BothModesTest()
948 .testStatement("'abc'.format()", "abc")
949 .testStatement("'x{key}x'.format(key = 2)", "x2x")
950 .testStatement("'x{key}x'.format(key = 'abc')", "xabcx")
951 .testStatement("'{a}{b}{a}{b}'.format(a = 3, b = True)", "3True3True")
952 .testStatement("'{a}{b}{a}{b}'.format(a = 3, b = True)", "3True3True")
953 .testStatement("'{s1}{s2}'.format(s1 = ['a'], s2 = 'a')", "[\"a\"]a")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000954 .testIfErrorContains("Missing argument 'b'", "'{a}{b}'.format(a = 5)")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000955 .testStatement("'{a}'.format(a = '$')", "$")
956 .testStatement("'{a}'.format(a = '$a')", "$a")
957 .testStatement("'{a}$'.format(a = '$a')", "$a$");
958
959 // The test below is using **kwargs, which is not available in BUILD mode.
960 new SkylarkTest().testStatement("'{(}'.format(**{'(': 2})", "2");
961 }
962
963 @Test
Florian Weikertd5e33502015-12-14 12:06:10 +0000964 public void testReversedWithInvalidTypes() throws Exception {
965 new BothModesTest()
966 .testIfExactError("type 'NoneType' is not iterable", "reversed(None)")
967 .testIfExactError("type 'int' is not iterable", "reversed(1)")
968 .testIfExactError(
969 "Argument to reversed() must be a sequence, not a dictionary.", "reversed({1: 3})");
970 new SkylarkTest()
971 .testIfExactError(
972 "Argument to reversed() must be a sequence, not a set.", "reversed(set([1]))");
973 }
974
975 @Test
976 public void testReversedWithLists() throws Exception {
977 new BothModesTest()
978 .testEval("reversed([])", "[]")
979 .testEval("reversed([1])", "[1]")
980 .testEval("reversed([1, 2, 3, 4, 5])", "[5, 4, 3, 2, 1]")
981 .testEval("reversed([[1, 2], 3, 4, [5]])", "[[5], 4, 3, [1, 2]]")
982 .testEval("reversed([1, 1, 1, 1, 2])", "[2, 1, 1, 1, 1]");
983 }
984
985 @Test
986 public void testReversedWithStrings() throws Exception {
987 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000988 .testEval("reversed('')", "[]")
Florian Weikertd5e33502015-12-14 12:06:10 +0000989 .testEval("reversed('a')", "['a']")
990 .testEval("reversed('abc')", "['c', 'b', 'a']")
991 .testEval("reversed('__test ')", "[' ', ' ', 't', 's', 'e', 't', '_', '_']")
992 .testEval("reversed('bbb')", "['b', 'b', 'b']");
993 }
994
995 @Test
996 public void testReversedNoSideEffects() throws Exception {
997 new SkylarkTest()
998 .testEval(
999 "def foo():\n"
1000 + " x = ['a', 'b']\n"
1001 + " y = reversed(x)\n"
1002 + " y += ['c']\n"
1003 + " return x\n"
1004 + "foo()",
1005 "['a', 'b']");
1006 }
1007
1008 @Test
Florian Weikerte3421962015-12-17 12:46:08 +00001009 public void testEquivalenceOfReversedAndSlice() throws Exception {
1010 String[] data = new String[] {"[]", "[1]", "[1, 2, 3]"};
1011 for (String toBeReversed : data) {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001012 new BothModesTest()
1013 .testEval(
1014 String.format("reversed(%s)", toBeReversed), String.format("%s[::-1]", toBeReversed));
Florian Weikerte3421962015-12-17 12:46:08 +00001015 }
1016 }
1017
1018 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001019 public void testListSlice() throws Exception {
1020 new BothModesTest()
Florian Weikerte3421962015-12-17 12:46:08 +00001021 .testEval("[0, 1, 2, 3][0:-1]", "[0, 1, 2]")
1022 .testEval("[0, 1, 2, 3, 4, 5][2:4]", "[2, 3]")
1023 .testEval("[0, 1, 2, 3, 4, 5][-2:-1]", "[4]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001024 .testEval("[][1:2]", "[]")
Florian Weikerte3421962015-12-17 12:46:08 +00001025 .testEval("[0, 1, 2, 3][-10:10]", "[0, 1, 2, 3]");
1026 }
1027
1028 @Test
1029 public void testListSlice_WrongType() throws Exception {
1030 new BothModesTest()
Jon Brandveinfab84872016-11-11 16:27:01 +00001031 .testIfExactError("Slice start must be an integer, not 'a'", "'123'['a'::]")
1032 .testIfExactError("Slice end must be an integer, not 'b'", "'123'[:'b':]");
Florian Weikerte3421962015-12-17 12:46:08 +00001033 }
1034
1035 @Test
1036 public void testListSliceStep() throws Exception {
1037 new BothModesTest()
1038 .testEval("[1, 2, 3, 4, 5][::1]", "[1, 2, 3, 4, 5]")
1039 .testEval("[1, 2, 3, 4, 5][1::1]", "[2, 3, 4, 5]")
1040 .testEval("[1, 2, 3, 4, 5][:2:1]", "[1, 2]")
1041 .testEval("[1, 2, 3, 4, 5][1:3:1]", "[2, 3]")
1042 .testEval("[1, 2, 3, 4, 5][-4:-2:1]", "[2, 3]")
1043 .testEval("[1, 2, 3, 4, 5][-10:10:1]", "[1, 2, 3, 4, 5]")
1044 .testEval("[1, 2, 3, 4, 5][::42]", "[1]");
1045 }
1046
1047 @Test
1048 public void testListSliceStep_EmptyList() throws Exception {
1049 new BothModesTest().testEval("[][::1]", "[]").testEval("[][::-1]", "[]");
1050 }
1051
1052 @Test
1053 public void testListSliceStep_SkipValues() throws Exception {
1054 new BothModesTest()
1055 .testEval("[1, 2, 3, 4, 5, 6, 7][::3]", "[1, 4, 7]")
1056 .testEval("[1, 2, 3, 4, 5, 6, 7, 8, 9][1:7:3]", "[2, 5]");
1057 }
1058
1059 @Test
1060 public void testListSliceStep_Negative() throws Exception {
1061 new BothModesTest()
1062 .testEval("[1, 2, 3, 4, 5][::-1]", "[5, 4, 3, 2, 1]")
1063 .testEval("[1, 2, 3, 4, 5][4::-1]", "[5, 4, 3, 2, 1]")
1064 .testEval("[1, 2, 3, 4, 5][:0:-1]", "[5, 4, 3, 2]")
1065 .testEval("[1, 2, 3, 4, 5][3:1:-1]", "[4, 3]")
1066 .testEval("[1, 2, 3, 4, 5][::-2]", "[5, 3, 1]")
1067 .testEval("[1, 2, 3, 4, 5][::-10]", "[5]");
1068 }
1069
1070 @Test
1071 public void testListSlice_WrongOrder() throws Exception {
1072 new BothModesTest().testEval("[1, 2, 3][3:1:1]", "[]").testEval("[1, 2, 3][1:3:-1]", "[]");
1073 }
1074
1075 @Test
1076 public void testListSliceStep_InvalidStep() throws Exception {
Jon Brandveinfab84872016-11-11 16:27:01 +00001077 String msg = "Slice step cannot be zero";
Florian Weikerte3421962015-12-17 12:46:08 +00001078 new BothModesTest()
1079 .testIfExactError(msg, "[1, 2, 3][::0]")
1080 .testIfExactError(msg, "[1, 2, 3][1::0]")
1081 .testIfExactError(msg, "[1, 2, 3][:3:0]")
1082 .testIfExactError(msg, "[1, 2, 3][1:3:0]");
1083 }
1084
1085 @Test
1086 public void testTupleSlice() throws Exception {
1087 // Not as comprehensive as the tests for slicing lists since the underlying mechanism is the
1088 // same.
1089 new BothModesTest()
1090 .testEval("()[1:2]", "()")
1091 .testEval("()[::1]", "()")
1092 .testEval("(0, 1, 2, 3)[0:-1]", "(0, 1, 2)")
1093 .testEval("(0, 1, 2, 3, 4, 5)[2:4]", "(2, 3)")
1094 .testEval("(0, 1, 2, 3)[-10:10]", "(0, 1, 2, 3)")
1095 .testEval("(1, 2, 3, 4, 5)[-10:10:1]", "(1, 2, 3, 4, 5)")
1096 .testEval("(1, 2, 3, 4, 5, 6, 7, 8, 9)[1:7:3]", "(2, 5)")
1097 .testEval("(1, 2, 3, 4, 5)[::-1]", "(5, 4, 3, 2, 1)")
1098 .testEval("(1, 2, 3, 4, 5)[3:1:-1]", "(4, 3)")
1099 .testEval("(1, 2, 3, 4, 5)[::-2]", "(5, 3, 1)")
1100 .testEval("(1, 2, 3, 4, 5)[::-10]", "(5,)")
Jon Brandveinfab84872016-11-11 16:27:01 +00001101 .testIfExactError("Slice step cannot be zero", "(1, 2, 3)[1::0]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001102 }
1103
1104 @Test
1105 public void testListSort() throws Exception {
1106 new BothModesTest()
1107 .testEval("sorted([0,1,2,3])", "[0, 1, 2, 3]")
1108 .testEval("sorted([])", "[]")
1109 .testEval("sorted([3, 2, 1, 0])", "[0, 1, 2, 3]")
1110 .testEval("sorted([[1], [], [2], [1, 2]])", "[[], [1], [1, 2], [2]]")
1111 .testEval("sorted([True, False, True])", "[False, True, True]")
1112 .testEval("sorted(['a','x','b','z'])", "[\"a\", \"b\", \"x\", \"z\"]")
1113 .testEval("sorted([sorted, sorted])", "[sorted, sorted]")
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001114 .testEval("sorted({1: True, 5: True, 4: False})", "[1, 4, 5]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001115 .testEval("sorted(set([1, 5, 4]))", "[1, 4, 5]");
1116 }
1117
1118 @Test
Florian Weikert1c07e322015-09-25 11:59:40 +00001119 public void testDictionaryCopy() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001120 new BothModesTest()
Florian Weikert1c07e322015-09-25 11:59:40 +00001121 .setUp("x = {1 : 2}", "y = dict(x)")
1122 .testEval("x[1] == 2 and y[1] == 2", "True");
1123 }
1124
1125 @Test
1126 public void testDictionaryCopyKeyCollision() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001127 new BothModesTest()
Florian Weikert1c07e322015-09-25 11:59:40 +00001128 .setUp("x = {'test' : 2}", "y = dict(x, test = 3)")
1129 .testEval("y['test']", "3");
1130 }
1131
1132 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001133 public void testDictionaryWithMultipleKeys() throws Exception {
1134 new BothModesTest().testStatement("{0: 'a', 1: 'b', 0: 'c'}[0]", "c");
1135 }
1136
1137 @Test
1138 public void testDictionaryKeyNotFound() throws Exception {
1139 new BothModesTest()
1140 .testIfErrorContains("Key \"0\" not found in dictionary", "{}['0']")
1141 .testIfErrorContains("Key 0 not found in dictionary", "{'0': 1, 2: 3, 4: 5}[0]");
1142 }
1143
1144 @Test
1145 public void testListAccessBadIndex() throws Exception {
Laurent Le Brun3a837472015-12-22 17:58:40 +00001146 new BothModesTest()
1147 .testIfErrorContains(
Jon Brandveinfab84872016-11-11 16:27:01 +00001148 "Indices must be integers, not string",
Laurent Le Brun3a837472015-12-22 17:58:40 +00001149 "[[1], [2]]['a']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001150 }
1151
1152 @Test
1153 public void testDictionaryAccess() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001154 new BothModesTest()
1155 .testEval("{1: ['foo']}[1]", "['foo']")
1156 .testStatement("{'4': 8}['4']", 8)
1157 .testStatement("{'a': 'aa', 'b': 'bb', 'c': 'cc'}['b']", "bb");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001158 }
1159
1160 @Test
1161 public void testDictionaryVariableAccess() throws Exception {
1162 new BothModesTest().setUp("d = {'a' : 1}", "a = d['a']\n").testLookup("a", 1);
1163 }
1164
1165 @Test
1166 public void testStringIndexing() throws Exception {
1167 new BothModesTest()
1168 .testStatement("'somestring'[0]", "s")
1169 .testStatement("'somestring'[1]", "o")
1170 .testStatement("'somestring'[4]", "s")
1171 .testStatement("'somestring'[9]", "g")
1172 .testStatement("'somestring'[-1]", "g")
1173 .testStatement("'somestring'[-2]", "n")
1174 .testStatement("'somestring'[-10]", "s");
1175 }
1176
1177 @Test
1178 public void testStringIndexingOutOfRange() throws Exception {
1179 new BothModesTest()
Jon Brandveinfab84872016-11-11 16:27:01 +00001180 .testIfErrorContains("Index out of range", "'abcdef'[10]")
1181 .testIfErrorContains("Index out of range", "'abcdef'[-11]")
1182 .testIfErrorContains("Index out of range", "'abcdef'[42]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001183 }
1184
1185 @Test
Florian Weikerte3421962015-12-17 12:46:08 +00001186 public void testStringSlice() throws Exception {
1187 new BothModesTest()
1188 .testStatement("'0123'[0:-1]", "012")
1189 .testStatement("'012345'[2:4]", "23")
1190 .testStatement("'012345'[-2:-1]", "4")
1191 .testStatement("''[1:2]", "")
1192 .testStatement("'012'[1:0]", "")
1193 .testStatement("'0123'[-10:10]", "0123");
1194 }
1195
1196 @Test
1197 public void testStringSlice_WrongType() throws Exception {
1198 new BothModesTest()
Jon Brandveinfab84872016-11-11 16:27:01 +00001199 .testIfExactError("Slice start must be an integer, not 'a'", "'123'['a'::]")
1200 .testIfExactError("Slice end must be an integer, not 'b'", "'123'[:'b':]");
Florian Weikerte3421962015-12-17 12:46:08 +00001201 }
1202
1203 @Test
1204 public void testStringSliceStep() throws Exception {
1205 new BothModesTest()
1206 .testStatement("'01234'[::1]", "01234")
1207 .testStatement("'01234'[1::1]", "1234")
1208 .testStatement("'01234'[:2:1]", "01")
1209 .testStatement("'01234'[1:3:1]", "12")
1210 .testStatement("'01234'[-4:-2:1]", "12")
1211 .testStatement("'01234'[-10:10:1]", "01234")
1212 .testStatement("'01234'[::42]", "0");
1213 }
1214
1215 @Test
1216 public void testStringSliceStep_EmptyString() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001217 new BothModesTest().testStatement("''[::1]", "").testStatement("''[::-1]", "");
Florian Weikerte3421962015-12-17 12:46:08 +00001218 }
1219
1220 @Test
1221 public void testStringSliceStep_SkipValues() throws Exception {
1222 new BothModesTest()
1223 .testStatement("'0123456'[::3]", "036")
1224 .testStatement("'01234567'[1:7:3]", "14");
1225 }
1226
1227 @Test
1228 public void testStringSliceStep_Negative() throws Exception {
1229 new BothModesTest()
1230 .testStatement("'01234'[::-1]", "43210")
1231 .testStatement("'01234'[4::-1]", "43210")
1232 .testStatement("'01234'[:0:-1]", "4321")
1233 .testStatement("'01234'[3:1:-1]", "32")
1234 .testStatement("'01234'[::-2]", "420")
1235 .testStatement("'01234'[::-10]", "4");
1236 }
1237
1238 @Test
1239 public void testStringSliceStep_WrongOrder() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001240 new BothModesTest().testStatement("'123'[3:1:1]", "").testStatement("'123'[1:3:-1]", "");
Florian Weikerte3421962015-12-17 12:46:08 +00001241 }
1242
1243 @Test
1244 public void testStringSliceStep_InvalidStep() throws Exception {
Jon Brandveinfab84872016-11-11 16:27:01 +00001245 String msg = "Slice step cannot be zero";
Florian Weikerte3421962015-12-17 12:46:08 +00001246 new BothModesTest()
1247 .testIfExactError(msg, "'123'[::0]")
1248 .testIfExactError(msg, "'123'[1::0]")
1249 .testIfExactError(msg, "'123'[:3:0]")
1250 .testIfExactError(msg, "'123'[1:3:0]");
1251 }
1252
1253 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001254 public void testDictionaryCreation() throws Exception {
1255 String expected = "{'a': 1, 'b': 2, 'c': 3}";
1256
1257 new BothModesTest()
1258 .testEval("dict([('a', 1), ('b', 2), ('c', 3)])", expected)
1259 .testEval("dict(a = 1, b = 2, c = 3)", expected)
1260 .testEval("dict([('a', 1)], b = 2, c = 3)", expected);
1261 }
1262
1263 @Test
1264 public void testDictionaryCreationInnerLists() throws Exception {
1265 new BothModesTest().testEval("dict([[1, 2], [3, 4]], a = 5)", "{1: 2, 3: 4, 'a': 5}");
1266 }
1267
1268 @Test
1269 public void testDictionaryCreationEmpty() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001270 new BothModesTest().testEval("dict()", "{}").testEval("dict([])", "{}");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001271 }
1272
1273 @Test
1274 public void testDictionaryCreationDifferentKeyTypes() throws Exception {
1275 String expected = "{'a': 1, 2: 3}";
1276
1277 new BothModesTest()
1278 .testEval("dict([('a', 1), (2, 3)])", expected)
1279 .testEval("dict([(2, 3)], a = 1)", expected);
1280 }
1281
1282 @Test
1283 public void testDictionaryCreationKeyCollision() throws Exception {
1284 String expected = "{'a': 1, 'b': 2, 'c': 3}";
1285
1286 new BothModesTest()
1287 .testEval("dict([('a', 42), ('b', 2), ('a', 1), ('c', 3)])", expected)
1288 .testEval("dict([('a', 42)], a = 1, b = 2, c = 3)", expected);
Yun Pengfc610052016-06-20 11:44:06 +00001289 new SkylarkTest().testEval("dict([('a', 42)], **{'a': 1, 'b': 2, 'c': 3})", expected);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001290 }
1291
1292 @Test
1293 public void testDictionaryCreationInvalidPositional() throws Exception {
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001294 new BothModesTest()
1295 .testIfErrorContains(
Florian Weikert1c07e322015-09-25 11:59:40 +00001296 "expected value of type 'list(object)' for parameter args in dict(), "
Yun Pengfc610052016-06-20 11:44:06 +00001297 + "but got \"a\" (string)",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001298 "dict('a')")
Florian Weikert1c07e322015-09-25 11:59:40 +00001299 .testIfErrorContains(
1300 "Cannot convert dictionary update sequence element #0 to a sequence", "dict(['a'])")
1301 .testIfErrorContains(
1302 "Cannot convert dictionary update sequence element #0 to a sequence", "dict([('a')])")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001303 .testIfErrorContains("too many (3) positional arguments", "dict((3,4), (3,2), (1,2))")
1304 .testIfErrorContains(
Florian Weikert1c07e322015-09-25 11:59:40 +00001305 "Sequence #0 has length 3, but exactly two elements are required",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001306 "dict([('a', 'b', 'c')])");
1307 }
1308
1309 @Test
1310 public void testDictionaryValues() throws Exception {
1311 new BothModesTest()
1312 .testEval("{1: 'foo'}.values()", "['foo']")
1313 .testEval("{}.values()", "[]")
1314 .testEval("{True: 3, False: 5}.values()", "[5, 3]")
1315 .testEval("{'a': 5, 'c': 2, 'b': 4, 'd': 3}.values()", "[5, 4, 2, 3]");
1316 // sorted by keys
1317 }
1318
1319 @Test
1320 public void testDictionaryKeys() throws Exception {
1321 new BothModesTest()
1322 .testEval("{1: 'foo'}.keys()", "[1]")
1323 .testEval("{}.keys()", "[]")
1324 .testEval("{True: 3, False: 5}.keys()", "[False, True]")
1325 .testEval(
1326 "{1:'a', 2:'b', 6:'c', 0:'d', 5:'e', 4:'f', 3:'g'}.keys()", "[0, 1, 2, 3, 4, 5, 6]");
1327 }
1328
1329 @Test
1330 public void testDictionaryGet() throws Exception {
1331 new BuildTest()
1332 .testStatement("{1: 'foo'}.get(1)", "foo")
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +00001333 .testStatement("{1: 'foo'}.get(2)", Runtime.NONE)
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001334 .testStatement("{1: 'foo'}.get(2, 'a')", "a")
1335 .testStatement("{1: 'foo'}.get(2, default='a')", "a")
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +00001336 .testStatement("{1: 'foo'}.get(2, default=None)", Runtime.NONE);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001337 }
1338
1339 @Test
1340 public void testDictionaryItems() throws Exception {
1341 new BothModesTest()
1342 .testEval("{'a': 'foo'}.items()", "[('a', 'foo')]")
1343 .testEval("{}.items()", "[]")
1344 .testEval("{1: 3, 2: 5}.items()", "[(1, 3), (2, 5)]")
1345 .testEval("{'a': 5, 'c': 2, 'b': 4}.items()", "[('a', 5), ('b', 4), ('c', 2)]");
1346 }
1347
1348 @Test
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001349 public void testDictionaryClear() throws Exception {
1350 new SkylarkTest()
1351 .testEval(
1352 "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n"
Yun Pengfc610052016-06-20 11:44:06 +00001353 + "if len(d) != 3: fail('clear 1')\n"
1354 + "if d.clear() != None: fail('clear 2')\n"
1355 + "d",
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001356 "{}");
1357 }
1358
1359 @Test
1360 public void testDictionaryPop() throws Exception {
1361 new SkylarkTest()
1362 .testIfErrorContains(
1363 "KeyError: 1",
1364 "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n"
Yun Pengfc610052016-06-20 11:44:06 +00001365 + "if len(d) != 3: fail('pop 1')\n"
1366 + "if d.pop(2) != 'bar': fail('pop 2')\n"
1367 + "if d.pop(3, 'quux') != 'baz': fail('pop 3a')\n"
1368 + "if d.pop(3, 'quux') != 'quux': fail('pop 3b')\n"
1369 + "if d.pop(1) != 'foo': fail('pop 1')\n"
1370 + "if d != {}: fail('pop 0')\n"
1371 + "d.pop(1)");
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001372 }
1373
1374 @Test
1375 public void testDictionaryPopItem() throws Exception {
1376 new SkylarkTest()
1377 .testIfErrorContains(
1378 "popitem(): dictionary is empty",
1379 "d = {2: 'bar', 3: 'baz', 1: 'foo'}\n"
Yun Pengfc610052016-06-20 11:44:06 +00001380 + "if len(d) != 3: fail('popitem 0')\n"
1381 + "if d.popitem() != (1, 'foo'): fail('popitem 1')\n"
1382 + "if d.popitem() != (2, 'bar'): fail('popitem 2')\n"
1383 + "if d.popitem() != (3, 'baz'): fail('popitem 3')\n"
1384 + "if d != {}: fail('popitem 4')\n"
1385 + "d.popitem()");
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001386 }
1387
1388 @Test
Laurent Le Brunb525bee2016-03-07 17:14:10 +00001389 public void testDictionaryUpdate() throws Exception {
1390 new BothModesTest()
1391 .setUp("foo = {'a': 2}")
1392 .testEval("foo.update({'b': 4}); foo", "{'a': 2, 'b': 4}");
1393 new BothModesTest()
1394 .setUp("foo = {'a': 2}")
1395 .testEval("foo.update({'a': 3, 'b': 4}); foo", "{'a': 3, 'b': 4}");
1396 }
1397
1398 @Test
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001399 public void testDictionarySetDefault() throws Exception {
1400 new SkylarkTest()
1401 .testEval(
1402 "d = {2: 'bar', 1: 'foo'}\n"
Yun Pengfc610052016-06-20 11:44:06 +00001403 + "if len(d) != 2: fail('setdefault 0')\n"
1404 + "if d.setdefault(1, 'a') != 'foo': fail('setdefault 1')\n"
1405 + "if d.setdefault(2) != 'bar': fail('setdefault 2')\n"
1406 + "if d.setdefault(3) != None: fail('setdefault 3')\n"
1407 + "if d.setdefault(4, 'b') != 'b': fail('setdefault 4')\n"
1408 + "d",
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001409 "{1: 'foo', 2: 'bar', 3: None, 4: 'b'}");
1410 }
1411
1412 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001413 public void testSetUnionWithList() throws Exception {
1414 evaluateSet("set([]).union(['a', 'b', 'c'])", "a", "b", "c");
1415 evaluateSet("set(['a']).union(['b', 'c'])", "a", "b", "c");
1416 evaluateSet("set(['a', 'b']).union(['c'])", "a", "b", "c");
1417 evaluateSet("set(['a', 'b', 'c']).union([])", "a", "b", "c");
1418 }
1419
1420 @Test
1421 public void testSetUnionWithSet() throws Exception {
1422 evaluateSet("set([]).union(set(['a', 'b', 'c']))", "a", "b", "c");
1423 evaluateSet("set(['a']).union(set(['b', 'c']))", "a", "b", "c");
1424 evaluateSet("set(['a', 'b']).union(set(['c']))", "a", "b", "c");
1425 evaluateSet("set(['a', 'b', 'c']).union(set([]))", "a", "b", "c");
1426 }
1427
1428 @Test
1429 public void testSetUnionDuplicates() throws Exception {
1430 evaluateSet("set(['a', 'b', 'c']).union(['a', 'b', 'c'])", "a", "b", "c");
1431 evaluateSet("set(['a', 'a', 'a']).union(['a', 'a'])", "a");
1432
1433 evaluateSet("set(['a', 'b', 'c']).union(set(['a', 'b', 'c']))", "a", "b", "c");
1434 evaluateSet("set(['a', 'a', 'a']).union(set(['a', 'a']))", "a");
1435 }
1436
1437 @Test
1438 public void testSetUnionError() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001439 new BothModesTest()
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001440 .testIfErrorContains("insufficient arguments received by union", "set(['a']).union()")
1441 .testIfErrorContains(
Francois-Rene Rideauab049e02016-02-17 16:13:46 +00001442 "Method set.union(new_elements: Iterable) is not applicable for arguments (string): "
1443 + "'new_elements' is string, but should be Iterable",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001444 "set(['a']).union('b')");
1445 }
1446
1447 @Test
1448 public void testSetUnionSideEffects() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001449 eval("def func():", " n1 = set(['a'])", " n2 = n1.union(['b'])", " return n1", "n = func()");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001450 assertEquals(ImmutableList.of("a"), ((SkylarkNestedSet) lookup("n")).toCollection());
1451 }
1452
1453 private void evaluateSet(String statement, Object... expectedElements) throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001454 new BothModesTest().testCollection(statement, expectedElements);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001455 }
1456
1457 @Test
Laurent Le Brun3ef1eea2015-11-09 14:35:54 +00001458 public void testListIndexMethod() throws Exception {
1459 new BothModesTest()
1460 .testStatement("['a', 'b', 'c'].index('a')", 0)
1461 .testStatement("['a', 'b', 'c'].index('b')", 1)
1462 .testStatement("['a', 'b', 'c'].index('c')", 2)
1463 .testStatement("[2, 4, 6].index(4)", 1)
1464 .testStatement("[2, 4, 6].index(4)", 1)
1465 .testStatement("[0, 1, [1]].index([1])", 2)
1466 .testIfErrorContains("Item \"a\" not found in list", "[1, 2].index('a')")
1467 .testIfErrorContains("Item 0 not found in list", "[].index(0)");
1468 }
1469
1470 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001471 public void testListIndex() throws Exception {
1472 new BothModesTest()
1473 .testStatement("['a', 'b', 'c', 'd'][0]", "a")
1474 .testStatement("['a', 'b', 'c', 'd'][1]", "b")
1475 .testStatement("['a', 'b', 'c', 'd'][-1]", "d")
1476 .testStatement("['a', 'b', 'c', 'd'][-2]", "c")
1477 .testStatement("[0, 1, 2][-3]", 0)
1478 .testStatement("[0, 1, 2][-2]", 1)
1479 .testStatement("[0, 1, 2][-1]", 2)
1480 .testStatement("[0, 1, 2][0]", 0);
1481 }
1482
1483 @Test
1484 public void testListIndexOutOfRange() throws Exception {
1485 new BothModesTest()
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001486 .testIfErrorContains(
Jon Brandveinfab84872016-11-11 16:27:01 +00001487 "Index out of range (index is 3, but sequence has 3 elements)", "[0, 1, 2][3]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001488 .testIfErrorContains(
Jon Brandveinfab84872016-11-11 16:27:01 +00001489 "Index out of range (index is -4, but sequence has 3 elements)", "[0, 1, 2][-4]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001490 .testIfErrorContains(
Jon Brandveinfab84872016-11-11 16:27:01 +00001491 "Index out of range (index is -2, but sequence has 1 elements)", "[0][-2]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001492 .testIfErrorContains(
Jon Brandveinfab84872016-11-11 16:27:01 +00001493 "Index out of range (index is 1, but sequence has 1 elements)", "[0][1]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001494 .testIfErrorContains(
Jon Brandveinfab84872016-11-11 16:27:01 +00001495 "Index out of range (index is 1, but sequence has 0 elements)", "[][1]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001496 }
1497
1498 @Test
Jon Brandvein9c4629d2016-07-20 20:16:33 +00001499 public void testHash() throws Exception {
Jon Brandvein3bdb4c32016-07-21 16:41:01 +00001500 // We specify the same string hashing algorithm as String.hashCode().
Jon Brandvein9c4629d2016-07-20 20:16:33 +00001501 new SkylarkTest()
1502 .testStatement("hash('skylark')", "skylark".hashCode())
1503 .testStatement("hash('google')", "google".hashCode())
1504 .testIfErrorContains(
1505 "Method hash(value: string) is not applicable for arguments (NoneType): "
1506 + "'value' is NoneType, but should be string",
1507 "hash(None)");
1508 }
1509
1510 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001511 public void testRange() throws Exception {
1512 new BothModesTest()
1513 .testStatement("str(range(5))", "[0, 1, 2, 3, 4]")
1514 .testStatement("str(range(0))", "[]")
1515 .testStatement("str(range(1))", "[0]")
1516 .testStatement("str(range(-2))", "[]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001517 .testStatement("str(range(-3, 2))", "[-3, -2, -1, 0, 1]")
1518 .testStatement("str(range(3, 2))", "[]")
1519 .testStatement("str(range(3, 3))", "[]")
1520 .testStatement("str(range(3, 4))", "[3]")
1521 .testStatement("str(range(3, 5))", "[3, 4]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001522 .testStatement("str(range(-3, 5, 2))", "[-3, -1, 1, 3]")
1523 .testStatement("str(range(-3, 6, 2))", "[-3, -1, 1, 3, 5]")
1524 .testStatement("str(range(5, 0, -1))", "[5, 4, 3, 2, 1]")
1525 .testStatement("str(range(5, 0, -10))", "[5]")
1526 .testStatement("str(range(0, -3, -2))", "[0, -2]")
1527 .testIfErrorContains("step cannot be 0", "range(2, 3, 0)");
1528 }
1529
1530 @Test
1531 public void testEnumerate() throws Exception {
1532 new BothModesTest()
1533 .testStatement("str(enumerate([]))", "[]")
1534 .testStatement("str(enumerate([5]))", "[(0, 5)]")
1535 .testStatement("str(enumerate([5, 3]))", "[(0, 5), (1, 3)]")
1536 .testStatement("str(enumerate(['a', 'b', 'c']))", "[(0, \"a\"), (1, \"b\"), (2, \"c\")]")
1537 .testStatement("str(enumerate(['a']) + [(1, 'b')])", "[(0, \"a\"), (1, \"b\")]");
1538 }
1539
1540 @Test
1541 public void testEnumerateBadArg() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001542 new BothModesTest()
1543 .testIfErrorContains(
1544 "Method enumerate(list: sequence) is not applicable for arguments (string): "
1545 + "'list' is string, but should be sequence",
1546 "enumerate('a')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001547 }
1548
1549 @Test
1550 public void testPyListAppend() throws Exception {
1551 new BuildTest()
Yue Gan6c2276a2016-04-07 08:02:00 +00001552 .setUp("FOO = ['a', 'b']", "FOO.insert(0, 'c')")
1553 .testLookup("FOO", MutableList.of(env, "c", "a", "b"))
1554 .setUp("FOO.insert(1, 'd')")
1555 .testLookup("FOO", MutableList.of(env, "c", "d", "a", "b"))
1556 .setUp("FOO.insert(4, 'e')")
1557 .testLookup("FOO", MutableList.of(env, "c", "d", "a", "b", "e"))
1558 .setUp("FOO.insert(-10, 'f')")
1559 .testLookup("FOO", MutableList.of(env, "f", "c", "d", "a", "b", "e"))
1560 .setUp("FOO.insert(10, 'g')")
1561 .testLookup("FOO", MutableList.of(env, "f", "c", "d", "a", "b", "e", "g"))
1562 .testIfErrorContains("Type tuple has no function insert(int)", "(1, 2).insert(3)");
1563 }
1564
1565 @Test
1566 public void testPyListInsert() throws Exception {
1567 new BuildTest()
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001568 .setUp("FOO = ['a', 'b']", "FOO.append('c')")
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00001569 .testLookup("FOO", MutableList.of(env, "a", "b", "c"))
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001570 .testIfErrorContains("Type tuple has no function append(int)", "(1, 2).append(3)");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001571 }
1572
1573 @Test
1574 public void testPyListExtend() throws Exception {
1575 new BuildTest()
1576 .setUp("FOO = ['a', 'b']", "FOO.extend(['c', 'd'])")
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00001577 .testLookup("FOO", MutableList.of(env, "a", "b", "c", "d"))
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001578 .testIfErrorContains("Type tuple has no function extend(list)", "(1, 2).extend([3, 4])");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001579 }
1580
1581 @Test
Laurent Le Brun8853df92015-12-16 15:02:03 +00001582 public void testListRemove() throws Exception {
1583 new BothModesTest()
1584 .setUp("foo = ['a', 'b', 'c', 'b']", "foo.remove('b')")
1585 .testLookup("foo", MutableList.of(env, "a", "c", "b"))
1586 .setUp("foo.remove('c')")
1587 .testLookup("foo", MutableList.of(env, "a", "b"))
1588 .setUp("foo.remove('a')")
1589 .testLookup("foo", MutableList.of(env, "b"))
1590 .setUp("foo.remove('b')")
1591 .testLookup("foo", MutableList.of(env))
1592 .testIfErrorContains("Item 3 not found in list", "[1, 2].remove(3)");
1593
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001594 new BothModesTest()
Laurent Le Brun8853df92015-12-16 15:02:03 +00001595 .testIfErrorContains("Type tuple has no function remove(int)", "(1, 2).remove(3)");
1596 }
1597
1598 @Test
Laurent Le Brun3a837472015-12-22 17:58:40 +00001599 public void testListPop() throws Exception {
1600 new BothModesTest()
1601 .setUp("li = [2, 3, 4]; ret = li.pop()")
1602 .testLookup("li", MutableList.of(env, 2, 3))
1603 .testLookup("ret", 4);
1604 new BothModesTest()
1605 .setUp("li = [2, 3, 4]; ret = li.pop(-2)")
1606 .testLookup("li", MutableList.of(env, 2, 4))
1607 .testLookup("ret", 3);
1608 new BothModesTest()
1609 .setUp("li = [2, 3, 4]; ret = li.pop(1)")
1610 .testLookup("li", MutableList.of(env, 2, 4))
1611 .testLookup("ret", 3);
1612 new BothModesTest()
1613 .testIfErrorContains(
Jon Brandveinfab84872016-11-11 16:27:01 +00001614 "Index out of range (index is 3, but sequence has 2 elements)", "[1, 2].pop(3)");
Laurent Le Brun3a837472015-12-22 17:58:40 +00001615
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001616 new BothModesTest().testIfErrorContains("Type tuple has no function pop()", "(1, 2).pop()");
Laurent Le Brun3a837472015-12-22 17:58:40 +00001617 }
1618
1619 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001620 public void testReassignmentOfPrimitivesNotForbiddenByCoreLanguage() throws Exception {
1621 new BuildTest()
1622 .setUp("cc_binary = (['hello.cc'])")
1623 .testIfErrorContains(
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00001624 "'list' object is not callable",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001625 "cc_binary(name = 'hello', srcs=['hello.cc'], malloc = '//base:system_malloc')");
1626 }
1627
1628 @Test
1629 public void testLenOnString() throws Exception {
1630 new BothModesTest().testStatement("len('abc')", 3);
1631 }
1632
1633 @Test
1634 public void testLenOnList() throws Exception {
1635 new BothModesTest().testStatement("len([1,2,3])", 3);
1636 }
1637
1638 @Test
1639 public void testLenOnDict() throws Exception {
1640 new BothModesTest().testStatement("len({'a' : 1, 'b' : 2})", 2);
1641 }
1642
1643 @Test
1644 public void testLenOnBadType() throws Exception {
1645 new BothModesTest().testIfErrorContains("int is not iterable", "len(1)");
1646 }
1647
1648 @Test
1649 public void testIndexOnFunction() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001650 new BothModesTest()
1651 .testIfErrorContains("Type function has no operator [](int)", "len[1]")
1652 .testIfErrorContains("Type function has no operator [:](int, int, int)", "len[1:4]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001653 }
1654
1655 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001656 public void testBool() throws Exception {
1657 new BothModesTest()
1658 .testStatement("bool(1)", Boolean.TRUE)
1659 .testStatement("bool(0)", Boolean.FALSE)
1660 .testStatement("bool([1, 2])", Boolean.TRUE)
1661 .testStatement("bool([])", Boolean.FALSE)
1662 .testStatement("bool(None)", Boolean.FALSE);
1663 }
1664
1665 @Test
1666 public void testStr() throws Exception {
1667 new BothModesTest()
1668 .testStatement("str(1)", "1")
1669 .testStatement("str(-2)", "-2")
1670 .testStatement("str([1, 2])", "[1, 2]")
1671 .testStatement("str(True)", "True")
1672 .testStatement("str(False)", "False")
1673 .testStatement("str(None)", "None")
1674 .testStatement("str(str)", "<function str>");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001675 }
1676
1677 @Test
1678 public void testInt() throws Exception {
1679 new BothModesTest()
1680 .testStatement("int('1')", 1)
1681 .testStatement("int('-1234')", -1234)
Florian Weikertbc1ff692016-07-01 19:11:24 +00001682 .testIfErrorContains("invalid literal for int() with base 10: \"1.5\"", "int('1.5')")
1683 .testIfErrorContains("invalid literal for int() with base 10: \"ab\"", "int('ab')")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001684 .testStatement("int(42)", 42)
1685 .testStatement("int(-1)", -1)
1686 .testStatement("int(True)", 1)
1687 .testStatement("int(False)", 0)
1688 .testIfErrorContains("None is not of type string or int or bool", "int(None)");
1689 }
1690
1691 @Test
Florian Weikertbc1ff692016-07-01 19:11:24 +00001692 public void testIntWithBase() throws Exception {
1693 new BothModesTest()
1694 .testStatement("int('11', 2)", 3)
1695 .testStatement("int('11', 9)", 10)
1696 .testStatement("int('AF', 16)", 175)
1697 .testStatement("int('11', 36)", 37)
1698 .testStatement("int('az', 36)", 395);
1699 }
1700
1701 @Test
1702 public void testIntWithBase_InvalidBase() throws Exception {
1703 new BothModesTest()
1704 .testIfExactError("invalid literal for int() with base 3: \"123\"", "int('123', 3)")
1705 .testIfExactError("invalid literal for int() with base 15: \"FF\"", "int('FF', 15)")
1706 .testIfExactError("int() base must be >= 2 and <= 36", "int('123', -1)")
1707 .testIfExactError("int() base must be >= 2 and <= 36", "int('123', 1)")
1708 .testIfExactError("int() base must be >= 2 and <= 36", "int('123', 37)");
1709 }
1710
1711 @Test
1712 public void testIntWithBase_Prefix() throws Exception {
1713 new BothModesTest()
1714 .testStatement("int('0b11', 0)", 3)
1715 .testStatement("int('0B11', 2)", 3)
1716 .testStatement("int('0o11', 0)", 9)
1717 .testStatement("int('0O11', 8)", 9)
1718 .testStatement("int('0XFF', 0)", 255)
1719 .testStatement("int('0xFF', 16)", 255)
1720 .testIfExactError("invalid literal for int() with base 8: \"0xFF\"", "int('0xFF', 8)");
1721 }
1722
1723 @Test
1724 public void testIntWithBase_NoString() throws Exception {
1725 new BothModesTest()
1726 .testIfExactError("int() can't convert non-string with explicit base", "int(True, 2)")
1727 .testIfExactError("int() can't convert non-string with explicit base", "int(1, 2)");
1728 }
1729
1730 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001731 public void testStrFunction() throws Exception {
1732 new SkylarkTest().testStatement("def foo(x): return x\nstr(foo)", "<function foo>");
1733 }
1734
1735 @Test
1736 public void testType() throws Exception {
1737 new SkylarkTest()
1738 .testStatement("type(1)", "int")
1739 .testStatement("type('a')", "string")
1740 .testStatement("type([1, 2])", "list")
1741 .testStatement("type((1, 2))", "tuple")
1742 .testStatement("type(True)", "bool")
1743 .testStatement("type(None)", "NoneType")
1744 .testStatement("type(str)", "function");
1745 }
1746
1747 @Test
1748 public void testSelectFunction() throws Exception {
1749 enableSkylarkMode();
1750 eval("a = select({'a': 1})");
1751 SelectorList result = (SelectorList) lookup("a");
1752 assertThat(((SelectorValue) Iterables.getOnlyElement(result.getElements())).getDictionary())
1753 .isEqualTo(ImmutableMap.of("a", 1));
1754 }
1755
1756 @Test
1757 public void testCountFunction() throws Exception {
1758 new BothModesTest()
1759 .testStatement("'abc'.count('')", 4)
1760 .testStatement("'abc'.count('a')", 1)
1761 .testStatement("'abc'.count('b')", 1)
1762 .testStatement("'abc'.count('c')", 1)
1763 .testStatement("'abbc'.count('b')", 2)
1764 .testStatement("'aba'.count('a')", 2)
1765 .testStatement("'aaa'.count('aa')", 1)
1766 .testStatement("'aaaa'.count('aa')", 2)
1767 .testStatement("'abc'.count('a', 0)", 1)
1768 .testStatement("'abc'.count('a', 1)", 0)
1769 .testStatement("'abc'.count('c', 0, 3)", 1)
1770 .testStatement("'abc'.count('c', 0, 2)", 0)
1771 .testStatement("'abc'.count('a', -1)", 0)
1772 .testStatement("'abc'.count('c', -1)", 1)
1773 .testStatement("'abc'.count('c', 0, 5)", 1)
1774 .testStatement("'abc'.count('c', 0, -1)", 0)
1775 .testStatement("'abc'.count('a', 0, -1)", 1);
1776 }
1777
1778 @Test
1779 public void testZipFunction() throws Exception {
1780 new BothModesTest()
1781 .testStatement("str(zip())", "[]")
1782 .testStatement("str(zip([1, 2]))", "[(1,), (2,)]")
1783 .testStatement("str(zip([1, 2], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]")
1784 .testStatement("str(zip([1, 2, 3], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]")
1785 .testStatement("str(zip([1], [2], [3]))", "[(1, 2, 3)]")
1786 .testStatement("str(zip([1], {2: 'a'}))", "[(1, 2)]")
1787 .testStatement("str(zip([1], []))", "[]")
1788 .testIfErrorContains("type 'int' is not iterable", "zip(123)")
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001789 .testIfErrorContains("type 'int' is not iterable", "zip([1], 1)")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001790 .testStatement("str(zip([1], set([2])))", "[(1, 2)]");
1791 }
Googler8e8fa052015-09-03 18:36:33 +00001792
1793 @Test
1794 public void testIsAlphaFunction() throws Exception {
1795 new BothModesTest()
1796 .testStatement("''.isalpha()", false)
1797 .testStatement("'abz'.isalpha()", true)
1798 .testStatement("'a1'.isalpha()", false)
1799 .testStatement("'a '.isalpha()", false)
1800 .testStatement("'A'.isalpha()", true)
1801 .testStatement("'AbZ'.isalpha()", true);
1802 }
Laurent Le Brunad849742015-10-15 11:36:01 +00001803
1804 @Test
1805 public void testLStrip() throws Exception {
1806 new BothModesTest()
Googler84075f32015-10-20 20:51:27 +00001807 .testStatement("'a b c'.lstrip('')", "a b c")
Laurent Le Brunad849742015-10-15 11:36:01 +00001808 .testStatement("'abcba'.lstrip('ba')", "cba")
1809 .testStatement("'abc'.lstrip('xyz')", "abc")
Googler84075f32015-10-20 20:51:27 +00001810 .testStatement("' a b c '.lstrip()", "a b c ")
1811 // the "\\"s are because Java absorbs one level of "\"s
1812 .testStatement("' \\t\\na b c '.lstrip()", "a b c ")
1813 .testStatement("' a b c '.lstrip('')", " a b c ");
Laurent Le Brunad849742015-10-15 11:36:01 +00001814 }
1815
1816 @Test
1817 public void testRStrip() throws Exception {
1818 new BothModesTest()
Googler84075f32015-10-20 20:51:27 +00001819 .testStatement("'a b c'.rstrip('')", "a b c")
Laurent Le Brunad849742015-10-15 11:36:01 +00001820 .testStatement("'abcba'.rstrip('ba')", "abc")
1821 .testStatement("'abc'.rstrip('xyz')", "abc")
Googler84075f32015-10-20 20:51:27 +00001822 .testStatement("' a b c '.rstrip()", " a b c")
1823 // the "\\"s are because Java absorbs one level of "\"s
1824 .testStatement("' a b c \\t \\n'.rstrip()", " a b c")
1825 .testStatement("' a b c '.rstrip('')", " a b c ");
Laurent Le Brunad849742015-10-15 11:36:01 +00001826 }
1827
1828 @Test
1829 public void testStrip() throws Exception {
1830 new BothModesTest()
Googler84075f32015-10-20 20:51:27 +00001831 .testStatement("'a b c'.strip('')", "a b c")
Laurent Le Brunad849742015-10-15 11:36:01 +00001832 .testStatement("'abcba'.strip('ba')", "c")
1833 .testStatement("'abc'.strip('xyz')", "abc")
Googler84075f32015-10-20 20:51:27 +00001834 .testStatement("' a b c '.strip()", "a b c")
1835 .testStatement("' a b c\\t'.strip()", "a b c")
1836 .testStatement("'a b c'.strip('.')", "a b c")
1837 // the "\\"s are because Java absorbs one level of "\"s
1838 .testStatement("' \\t\\n\\ra b c \\t\\n\\r'.strip()", "a b c")
1839 .testStatement("' a b c '.strip('')", " a b c ");
Laurent Le Brunad849742015-10-15 11:36:01 +00001840 }
Laurent Le Brunfe206a42016-05-23 17:03:49 +00001841
1842 @Test
1843 public void testFail() throws Exception {
1844 new SkylarkTest()
1845 .testIfErrorContains("abc", "fail('abc')")
1846 .testIfErrorContains("18", "fail(18)");
1847 }
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001848}