blob: a373ba7adebb6bdfee7209bd2e405824d394e42e [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;
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +000020import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000021import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000022import org.junit.Before;
23import org.junit.Test;
24import org.junit.runner.RunWith;
25import org.junit.runners.JUnit4;
26
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000027/**
28 * Tests for MethodLibrary.
29 */
30@RunWith(JUnit4.class)
31public class MethodLibraryTest extends EvaluationTestCase {
32
Yun Pengfc610052016-06-20 11:44:06 +000033 private static final String LINE_SEPARATOR = System.lineSeparator();
34
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000035 @Before
Florian Weikertb4c59042015-12-01 10:47:18 +000036 public final void setFailFast() throws Exception {
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +000037 setFailFast(true);
38 }
39
40 @Test
Florian Weikert5e8752b2015-12-11 21:54:43 +000041 public void testMinWithInvalidArgs() throws Exception {
42 new SkylarkTest()
43 .testIfExactError("type 'int' is not iterable", "min(1)")
Jon Brandvein3cfeeec2017-01-20 04:23:37 +000044 .testIfExactError("expected at least one item", "min([])");
Florian Weikert5e8752b2015-12-11 21:54:43 +000045 }
46
47 @Test
48 public void testMinWithString() throws Exception {
49 new SkylarkTest()
50 .testStatement("min('abcdefxyz')", "a")
51 .testStatement("min('test', 'xyz')", "test");
52 }
53
54 @Test
55 public void testMinWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000056 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +000057 .testEval("min([4, 5], [1])", "[1]")
58 .testEval("min([1, 2], [3])", "[1, 2]")
59 .testEval("min([1, 5], [1, 6], [2, 4], [0, 6])", "[0, 6]")
60 .testStatement("min([-1])", -1)
61 .testStatement("min([5, 2, 3])", 2);
62 }
63
64 @Test
65 public void testMinWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000066 new BothModesTest().testStatement("min({1: 2, -1 : 3})", -1).testStatement("min({2: None})", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +000067 }
68
69 @Test
70 public void testMinWithSet() throws Exception {
Vladimir Moskvad200daf2016-12-23 16:35:37 +000071 new BothModesTest()
72 .testStatement("min(depset([-1]))", -1)
73 .testStatement("min(depset([5, 2, 3]))", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +000074 }
75
76 @Test
77 public void testMinWithPositionalArguments() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000078 new BothModesTest().testStatement("min(-1, 2)", -1).testStatement("min(5, 2, 3)", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +000079 }
80
81 @Test
82 public void testMinWithSameValues() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000083 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +000084 .testStatement("min(1, 1, 1, 1, 1, 1)", 1)
85 .testStatement("min([1, 1, 1, 1, 1, 1])", 1);
86 }
87
88 @Test
89 public void testMinWithDifferentTypes() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000090 new BothModesTest()
Vladimir Moskva7f0cd622017-02-16 13:48:37 +000091 .testIfExactError("Cannot compare int with string", "min(1, '2', True)")
92 .testIfExactError("Cannot compare int with string", "min([1, '2', True])");
Florian Weikert5e8752b2015-12-11 21:54:43 +000093 }
94
95 @Test
96 public void testMaxWithInvalidArgs() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +000097 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +000098 .testIfExactError("type 'int' is not iterable", "max(1)")
Jon Brandvein3cfeeec2017-01-20 04:23:37 +000099 .testIfExactError("expected at least one item", "max([])");
Florian Weikert5e8752b2015-12-11 21:54:43 +0000100 }
101
102 @Test
103 public void testMaxWithString() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000104 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +0000105 .testStatement("max('abcdefxyz')", "z")
106 .testStatement("max('test', 'xyz')", "xyz");
107 }
108
109 @Test
110 public void testMaxWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000111 new BothModesTest()
Florian Weikert5e8752b2015-12-11 21:54:43 +0000112 .testEval("max([1, 2], [5])", "[5]")
113 .testStatement("max([-1])", -1)
114 .testStatement("max([5, 2, 3])", 5);
115 }
116
117 @Test
118 public void testMaxWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000119 new BothModesTest().testStatement("max({1: 2, -1 : 3})", 1).testStatement("max({2: None})", 2);
Florian Weikert5e8752b2015-12-11 21:54:43 +0000120 }
121
122 @Test
123 public void testMaxWithSet() throws Exception {
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000124 new BothModesTest()
125 .testStatement("max(depset([-1]))", -1)
126 .testStatement("max(depset([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()
Vladimir Moskva7f0cd622017-02-16 13:48:37 +0000144 .testIfExactError("Cannot compare int with string", "max(1, '2', True)")
145 .testIfExactError("Cannot compare int with string", "max([1, '2', True])");
Florian Weikert5e8752b2015-12-11 21:54:43 +0000146 }
147
148 @Test
Florian Weikertcb8f2782015-12-10 23:30:23 +0000149 public void testSplitLines_EmptyLine() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000150 new BothModesTest().testEval("''.splitlines()", "[]").testEval("'\\n'.splitlines()", "['']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000151 }
152
153 @Test
154 public void testSplitLines_StartsWithLineBreak() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000155 new BothModesTest().testEval("'\\ntest'.splitlines()", "['', 'test']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000156 }
157
158 @Test
159 public void testSplitLines_EndsWithLineBreak() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000160 new BothModesTest().testEval("'test\\n'.splitlines()", "['test']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000161 }
162
163 @Test
164 public void testSplitLines_DifferentLineBreaks() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000165 new BothModesTest()
166 .testEval("'this\\nis\\na\\ntest'.splitlines()", "['this', 'is', 'a', 'test']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000167 }
168
169 @Test
170 public void testSplitLines_OnlyLineBreaks() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000171 new BothModesTest()
Florian Weikertcb8f2782015-12-10 23:30:23 +0000172 .testEval("'\\n\\n\\n'.splitlines()", "['', '', '']")
173 .testEval("'\\r\\r\\r'.splitlines()", "['', '', '']")
174 .testEval("'\\n\\r\\n\\r'.splitlines()", "['', '', '']")
175 .testEval("'\\r\\n\\r\\n\\r\\n'.splitlines()", "['', '', '']");
176 }
177
178 @Test
179 public void testSplitLines_EscapedSequences() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000180 new BothModesTest().testEval("'\\n\\\\n\\\\\\n'.splitlines()", "['', '\\\\n\\\\']");
Florian Weikertcb8f2782015-12-10 23:30:23 +0000181 }
182
183 @Test
184 public void testSplitLines_KeepEnds() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000185 new BothModesTest()
Florian Weikertcb8f2782015-12-10 23:30:23 +0000186 .testEval("''.splitlines(True)", "[]")
187 .testEval("'\\n'.splitlines(True)", "['\\n']")
188 .testEval(
189 "'this\\nis\\r\\na\\rtest'.splitlines(True)", "['this\\n', 'is\\r\\n', 'a\\r', 'test']")
190 .testEval("'\\ntest'.splitlines(True)", "['\\n', 'test']")
191 .testEval("'test\\n'.splitlines(True)", "['test\\n']")
192 .testEval("'\\n\\\\n\\\\\\n'.splitlines(True)", "['\\n', '\\\\n\\\\\\n']");
193 }
194
195 @Test
Florian Weikert532d3ba2015-12-17 10:36:45 +0000196 public void testStringIsAlnum() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000197 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000198 .testStatement("''.isalnum()", false)
199 .testStatement("'a0 33'.isalnum()", false)
200 .testStatement("'1'.isalnum()", true)
201 .testStatement("'a033'.isalnum()", true);
202 }
203
204 @Test
205 public void testStringIsDigit() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000206 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000207 .testStatement("''.isdigit()", false)
208 .testStatement("' '.isdigit()", false)
209 .testStatement("'a'.isdigit()", false)
210 .testStatement("'0234325.33'.isdigit()", false)
211 .testStatement("'1'.isdigit()", true)
212 .testStatement("'033'.isdigit()", true);
213 }
214
215 @Test
216 public void testStringIsSpace() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000217 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000218 .testStatement("''.isspace()", false)
219 .testStatement("'a'.isspace()", false)
220 .testStatement("'1'.isspace()", false)
221 .testStatement("'\\ta\\n'.isspace()", false)
222 .testStatement("' '.isspace()", true)
223 .testStatement("'\\t\\n'.isspace()", true);
224 }
225
226 @Test
227 public void testStringIsLower() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000228 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000229 .testStatement("''.islower()", false)
230 .testStatement("' '.islower()", false)
231 .testStatement("'1'.islower()", false)
232 .testStatement("'Almost'.islower()", false)
233 .testStatement("'abc'.islower()", true)
234 .testStatement("' \\nabc'.islower()", true)
235 .testStatement("'abc def\\n'.islower()", true)
236 .testStatement("'\\ta\\n'.islower()", true);
237 }
238
239 @Test
240 public void testStringIsUpper() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000241 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000242 .testStatement("''.isupper()", false)
243 .testStatement("' '.isupper()", false)
244 .testStatement("'1'.isupper()", false)
245 .testStatement("'aLMOST'.isupper()", false)
246 .testStatement("'ABC'.isupper()", true)
247 .testStatement("' \\nABC'.isupper()", true)
248 .testStatement("'ABC DEF\\n'.isupper()", true)
249 .testStatement("'\\tA\\n'.isupper()", true);
250 }
251
252 @Test
253 public void testStringIsTitle() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000254 new BothModesTest()
Florian Weikert532d3ba2015-12-17 10:36:45 +0000255 .testStatement("''.istitle()", false)
256 .testStatement("' '.istitle()", false)
257 .testStatement("'134'.istitle()", false)
258 .testStatement("'almost Correct'.istitle()", false)
259 .testStatement("'1nope Nope Nope'.istitle()", false)
260 .testStatement("'NO Way'.istitle()", false)
261 .testStatement("'T'.istitle()", true)
262 .testStatement("'Correct'.istitle()", true)
263 .testStatement("'Very Correct! Yes\\nIndeed1X'.istitle()", true)
264 .testStatement("'1234Ab Ab'.istitle()", true)
265 .testStatement("'\\tA\\n'.istitle()", true);
266 }
267
268 @Test
Florian Weikert233a46e2015-12-16 12:38:38 +0000269 public void testAllWithEmptyValue() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000270 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000271 .testStatement("all('')", true)
272 .testStatement("all([])", true)
273 .testIfExactError("type 'NoneType' is not iterable", "any(None)");
274 }
275
276 @Test
277 public void testAllWithPrimitiveType() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000278 new BothModesTest().testStatement("all('test')", true).testIfErrorContains("", "all(1)");
Florian Weikert233a46e2015-12-16 12:38:38 +0000279 }
280
281 @Test
282 public void testAllWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000283 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000284 .testStatement("all([False])", false)
285 .testStatement("all([True, False])", false)
286 .testStatement("all([False, False])", false)
287 .testStatement("all([False, True])", false)
288 .testStatement("all(['', True])", false)
289 .testStatement("all([0, True])", false)
290 .testStatement("all([[], True])", false)
291 .testStatement("all([True, 't', 1])", true);
292 }
293
294 @Test
295 public void testAllWithSet() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000296 new BothModesTest()
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000297 .testStatement("all(depset([0]))", false)
298 .testStatement("all(depset([1, 0]))", false)
299 .testStatement("all(depset([1]))", true);
Florian Weikert233a46e2015-12-16 12:38:38 +0000300 }
301
302 @Test
303 public void testAllWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000304 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000305 .testStatement("all({1 : None})", true)
306 .testStatement("all({None : 1})", false);
307 }
308
309 @Test
310 public void testAnyWithEmptyValue() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000311 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000312 .testStatement("any('')", false)
313 .testStatement("any([])", false)
314 .testIfExactError("type 'NoneType' is not iterable", "any(None)");
315 }
316
317 @Test
318 public void testAnyWithPrimitiveType() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000319 new BothModesTest().testStatement("any('test')", true).testIfErrorContains("", "any(1)");
Florian Weikert233a46e2015-12-16 12:38:38 +0000320 }
321
322 @Test
323 public void testAnyWithList() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000324 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000325 .testStatement("any([False])", false)
326 .testStatement("any([0])", false)
327 .testStatement("any([''])", false)
328 .testStatement("any([[]])", false)
329 .testStatement("any([True, False])", true)
330 .testStatement("any([False, False])", false)
331 .testStatement("any([False, '', 0])", false)
332 .testStatement("any([False, '', 42])", true);
333 }
334
335 @Test
336 public void testAnyWithSet() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000337 new BothModesTest()
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000338 .testStatement("any(depset([0]))", false)
339 .testStatement("any(depset([1, 0]))", true);
Florian Weikert233a46e2015-12-16 12:38:38 +0000340 }
341
342 @Test
343 public void testAnyWithDict() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000344 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000345 .testStatement("any({1 : None, '' : None})", true)
346 .testStatement("any({None : 1, '' : 2})", false);
347 }
348
349 @Test
Florian Weikert90a15962015-09-11 13:43:10 +0000350 public void testStackTraceLocation() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000351 new SkylarkTest()
352 .testIfErrorContains(
Yun Penge7e55bb2016-09-09 09:11:42 +0000353 "Traceback (most recent call last):"
Yun Pengfc610052016-06-20 11:44:06 +0000354 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000355 + "\tFile \"\", line 8"
Yun Pengfc610052016-06-20 11:44:06 +0000356 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000357 + "\t\tfoo()"
358 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000359 + "\tFile \"\", line 2, in foo"
Yun Penge7e55bb2016-09-09 09:11:42 +0000360 + LINE_SEPARATOR
361 + "\t\tbar(1)"
362 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000363 + "\tFile \"\", line 7, in bar"
Yun Pengfc610052016-06-20 11:44:06 +0000364 + LINE_SEPARATOR
Michajlo Matijkiw8c539ea2017-02-22 23:02:46 +0000365 + "\t\t\"test\".index(x)",
Yun Pengfc610052016-06-20 11:44:06 +0000366 "def foo():",
367 " bar(1)",
368 "def bar(x):",
369 " if x == 1:",
370 " a = x",
371 " b = 2",
372 " 'test'.index(x)",
373 "foo()");
Florian Weikert90a15962015-09-11 13:43:10 +0000374 }
375
376 @Test
377 public void testStackTraceWithIf() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000378 new SkylarkTest()
379 .testIfErrorContains(
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000380 "File \"\", line 5"
Yun Pengfc610052016-06-20 11:44:06 +0000381 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000382 + "\t\tfoo()"
383 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000384 + "\tFile \"\", line 3, in foo"
Yun Pengfc610052016-06-20 11:44:06 +0000385 + LINE_SEPARATOR
386 + "\t\ts[0]",
387 "def foo():",
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000388 " s = depset()",
Yun Pengfc610052016-06-20 11:44:06 +0000389 " if s[0] == 1:",
390 " x = 1",
391 "foo()");
Florian Weikert90a15962015-09-11 13:43:10 +0000392 }
393
394 @Test
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000395 public void testStackTraceSkipBuiltInOnly() throws Exception {
396 // The error message should not include the stack trace when there is
397 // only one built-in function.
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000398 new BothModesTest()
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000399 .testIfExactError(
laurentlb9e540882017-07-07 06:58:45 -0400400 "argument 'sub' has type 'int', but should be 'string'\n"
401 + "in call to builtin method string.index(sub, start, end)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000402 "'test'.index(1)");
403 }
404
405 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000406 public void testStackTrace() throws Exception {
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000407 // Unlike SkylarintegrationTests#testStackTraceErrorInFunction(), this test
408 // has neither a BUILD nor a bzl file.
409 new SkylarkTest()
410 .testIfExactError(
Yun Penge7e55bb2016-09-09 09:11:42 +0000411 "Traceback (most recent call last):"
412 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000413 + "\tFile \"\", line 6"
Yun Pengfc610052016-06-20 11:44:06 +0000414 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000415 + "\t\tfoo()"
416 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000417 + "\tFile \"\", line 2, in foo"
Yun Pengfc610052016-06-20 11:44:06 +0000418 + LINE_SEPARATOR
Yun Penge7e55bb2016-09-09 09:11:42 +0000419 + "\t\tbar(1)"
420 + LINE_SEPARATOR
Carmi Grushko46bf88c2017-02-20 22:37:15 +0000421 + "\tFile \"\", line 5, in bar"
Yun Pengfc610052016-06-20 11:44:06 +0000422 + LINE_SEPARATOR
Michajlo Matijkiw8c539ea2017-02-22 23:02:46 +0000423 + "\t\t\"test\".index(x)"
Yun Penge7e55bb2016-09-09 09:11:42 +0000424 + LINE_SEPARATOR
laurentlb9e540882017-07-07 06:58:45 -0400425 + "argument 'sub' has type 'int', but should be 'string'\n"
426 + "in call to builtin method string.index(sub, start, end)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000427 "def foo():",
Florian Weikert90a15962015-09-11 13:43:10 +0000428 " bar(1)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000429 "def bar(x):",
Florian Weikert90a15962015-09-11 13:43:10 +0000430 " if 1 == 1:",
431 " 'test'.index(x)",
Florian Weikertc1d54ec2015-08-26 14:06:58 +0000432 "foo()");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000433 }
434
435 @Test
436 public void testBuiltinFunctionErrorMessage() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000437 new BothModesTest()
laurentlb9e540882017-07-07 06:58:45 -0400438 .testIfErrorContains("substring \"z\" not found in \"abc\"", "'abc'.index('z')")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000439 .testIfErrorContains(
laurentlb9e540882017-07-07 06:58:45 -0400440 "argument 'sub' has type 'int', but should be 'string'\n"
441 + "in call to builtin method string.startswith(sub, start, end)",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000442 "'test'.startswith(1)")
443 .testIfErrorContains(
Florian Weikert1c07e322015-09-25 11:59:40 +0000444 "expected value of type 'list(object)' for parameter args in dict(), "
Laurent Le Brun88df1f52015-12-23 13:31:44 +0000445 + "but got \"a\" (string)",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000446 "dict('a')");
447 }
448
449 @Test
450 public void testHasAttr() throws Exception {
451 new SkylarkTest()
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000452 .testStatement("hasattr(depset(), 'union')", Boolean.TRUE)
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000453 .testStatement("hasattr('test', 'count')", Boolean.TRUE)
454 .testStatement("hasattr(dict(a = 1, b = 2), 'items')", Boolean.TRUE)
455 .testStatement("hasattr({}, 'items')", Boolean.TRUE);
456 }
457
458 @Test
Florian Weikerte5e3e912016-03-08 03:08:26 +0000459 public void testGetAttrMissingField() throws Exception {
460 new SkylarkTest()
461 .testIfExactError(
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000462 "object of type 'string' has no attribute \"not_there\"",
Florian Weikerte5e3e912016-03-08 03:08:26 +0000463 "getattr('a string', 'not_there')")
Jon Brandveinad81cff2016-07-26 13:04:10 +0000464 .testStatement("getattr('a string', 'not_there', 'use this')", "use this")
465 .testStatement("getattr('a string', 'not there', None)", Runtime.NONE);
Florian Weikerte5e3e912016-03-08 03:08:26 +0000466 }
467
468 @Test
469 public void testGetAttrWithMethods() throws Exception {
470 String msg =
Laurent Le Brunc31f3512016-12-29 21:41:33 +0000471 "object of type 'string' has no attribute \"count\", however, "
Florian Weikerte5e3e912016-03-08 03:08:26 +0000472 + "a method of that name exists";
473 new SkylarkTest()
474 .testIfExactError(msg, "getattr('a string', 'count')")
Jon Brandvein29bb6622016-10-27 13:55:43 +0000475 .testStatement("getattr('a string', 'count', 'default')", "default");
Florian Weikerte5e3e912016-03-08 03:08:26 +0000476 }
477
478 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000479 public void testDir() throws Exception {
Laurent Le Brunb525bee2016-03-07 17:14:10 +0000480 new SkylarkTest()
481 .testStatement(
482 "str(dir({}))",
Vladimir Moskva8d610c62016-09-15 14:36:41 +0000483 "[\"clear\", \"get\", \"items\", \"keys\","
Laurent Le Brunb525bee2016-03-07 17:14:10 +0000484 + " \"pop\", \"popitem\", \"setdefault\", \"update\", \"values\"]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000485 }
486
487 @Test
488 public void testBoolean() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000489 new BothModesTest().testStatement("False", Boolean.FALSE).testStatement("True", Boolean.TRUE);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000490 }
491
492 @Test
493 public void testBooleanUnsupportedOperationFails() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000494 new BothModesTest()
495 .testIfErrorContains("unsupported operand type(s) for +: 'bool' and 'bool'", "True + True");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000496 }
497
498 @Test
499 public void testPyStringJoin() throws Exception {
Laurent Le Brund4d7fca2017-02-14 19:12:02 +0000500 new BothModesTest().testStatement("'-'.join(['a', 'b', 'c'])", "a-b-c");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000501 }
502
503 @Test
504 public void testPyStringGlobalJoin() throws Exception {
Laurent Le Brund4d7fca2017-02-14 19:12:02 +0000505 new BothModesTest()
506 .testIfErrorContains("name 'join' is not defined", "join(' ', ['a', 'b', 'c'])")
507 .testStatement("' '.join(['a', 'b', 'c'])", "a b c");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000508 }
509
510 @Test
511 public void testPyStringJoinCompr() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000512 new BothModesTest()
513 .testStatement("''.join([(x + '*') for x in ['a', 'b', 'c']])", "a*b*c*")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000514 .testStatement(
515 "''.join([(y + '*' + z + '|') " + "for y in ['a', 'b', 'c'] for z in ['d', 'e']])",
516 "a*d|a*e|b*d|b*e|c*d|c*e|");
517 }
518
519 @Test
520 public void testPyStringLower() throws Exception {
521 new BothModesTest().testStatement("'Blah Blah'.lower()", "blah blah");
522 }
523
524 @Test
525 public void testPyStringUpper() throws Exception {
526 new BothModesTest()
527 .testStatement("'ein bier'.upper()", "EIN BIER")
528 .testStatement("''.upper()", "");
529 }
530
531 @Test
532 public void testPyStringReplace() throws Exception {
533 new BothModesTest()
Yun Pengfc610052016-06-20 11:44:06 +0000534 .testStatement("'banana'.replace('a', 'e')", "benene")
535 .testStatement("'banana'.replace('a', '$()')", "b$()n$()n$()")
536 .testStatement("'banana'.replace('a', '$')", "b$n$n$")
537 .testStatement("'banana'.replace('a', '\\\\')", "b\\n\\n\\")
538 .testStatement("'b$()n$()n$()'.replace('$()', '$($())')", "b$($())n$($())n$($())")
539 .testStatement("'b\\\\n\\\\n\\\\'.replace('\\\\', '$()')", "b$()n$()n$()");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000540 }
541
542 @Test
543 public void testPyStringReplace2() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000544 new BothModesTest().testStatement("'banana'.replace('a', 'e', 2)", "benena");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000545 }
546
547 @Test
548 public void testPyStringSplit() throws Exception {
549 new BothModesTest().testEval("'h i'.split(' ')", "['h', 'i']");
550 }
551
552 @Test
553 public void testPyStringSplit2() throws Exception {
554 new BothModesTest().testEval("'h i p'.split(' ')", "['h', 'i', 'p']");
555 }
556
557 @Test
558 public void testPyStringSplit3() throws Exception {
559 new BothModesTest().testEval("'a,e,i,o,u'.split(',', 2)", "['a', 'e', 'i,o,u']");
560 }
561
562 @Test
563 public void testPyStringSplitNoSep() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000564 new BothModesTest()
565 .testEval("' 1 2 3 '.split(' ')", "['', '', '1', '', '2', '', '3', '', '']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000566 }
567
568 @Test
569 public void testPyStringRSplitRegex() throws Exception {
570 new BothModesTest()
571 .testEval("'foo/bar.lisp'.rsplit('.')", "['foo/bar', 'lisp']")
572 .testEval("'foo/bar.?lisp'.rsplit('.?')", "['foo/bar', 'lisp']")
573 .testEval("'fwe$foo'.rsplit('$')", "['fwe', 'foo']")
574 .testEval("'windows'.rsplit('\\w')", "['windows']");
575 }
576
577 @Test
578 public void testPyStringRSplitNoMatch() throws Exception {
579 new BothModesTest()
580 .testEval("''.rsplit('o')", "['']")
581 .testEval("'google'.rsplit('x')", "['google']");
582 }
583
584 @Test
585 public void testPyStringRSplitSeparator() throws Exception {
586 new BothModesTest()
587 .testEval("'xxxxxx'.rsplit('x')", "['', '', '', '', '', '', '']")
588 .testEval("'xxxxxx'.rsplit('x', 1)", "['xxxxx', '']")
589 .testEval("'xxxxxx'.rsplit('x', 2)", "['xxxx', '', '']")
590 .testEval("'xxxxxx'.rsplit('x', 3)", "['xxx', '', '', '']")
591 .testEval("'xxxxxx'.rsplit('x', 4)", "['xx', '', '', '', '']")
592 .testEval("'xxxxxx'.rsplit('x', 5)", "['x', '', '', '', '', '']")
593 .testEval("'xxxxxx'.rsplit('x', 6)", "['', '', '', '', '', '', '']")
594 .testEval("'xxxxxx'.rsplit('x', 7)", "['', '', '', '', '', '', '']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000595 }
596
597 @Test
598 public void testPyStringRSplitLongerSep() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000599 new BothModesTest()
600 .testEval("'abcdabef'.rsplit('ab')", "['', 'cd', 'ef']")
601 .testEval("'google_or_gogol'.rsplit('go')", "['', 'ogle_or_', '', 'l']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000602 }
603
604 @Test
605 public void testPyStringRSplitMaxSplit() throws Exception {
606 new BothModesTest()
607 .testEval("'google'.rsplit('o')", "['g', '', 'gle']")
608 .testEval("'google'.rsplit('o')", "['g', '', 'gle']")
609 .testEval("'google'.rsplit('o', 1)", "['go', 'gle']")
610 .testEval("'google'.rsplit('o', 2)", "['g', '', 'gle']")
611 .testEval("'google'.rsplit('o', 3)", "['g', '', 'gle']")
612 .testEval("'ogooglo'.rsplit('o')", "['', 'g', '', 'gl', '']")
613 .testEval("'ogooglo'.rsplit('o', 1)", "['ogoogl', '']")
614 .testEval("'ogooglo'.rsplit('o', 2)", "['ogo', 'gl', '']")
615 .testEval("'ogooglo'.rsplit('o', 3)", "['og', '', 'gl', '']")
616 .testEval("'ogooglo'.rsplit('o', 4)", "['', 'g', '', 'gl', '']")
617 .testEval("'ogooglo'.rsplit('o', 5)", "['', 'g', '', 'gl', '']")
618 .testEval("'google'.rsplit('google')", "['', '']")
619 .testEval("'google'.rsplit('google', 1)", "['', '']")
620 .testEval("'google'.rsplit('google', 2)", "['', '']");
621 }
622
623 @Test
624 public void testPyStringPartitionEasy() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000625 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000626 .testEval("'lawl'.partition('a')", "('l', 'a', 'wl')")
627 .testEval("'lawl'.rpartition('a')", "('l', 'a', 'wl')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000628 }
629
630 @Test
631 public void testPyStringPartitionMultipleSep() throws Exception {
632 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000633 .testEval("'google'.partition('o')", "('g', 'o', 'ogle')")
634 .testEval("'google'.rpartition('o')", "('go', 'o', 'gle')")
635 .testEval("'xxx'.partition('x')", "('', 'x', 'xx')")
636 .testEval("'xxx'.rpartition('x')", "('xx', 'x', '')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000637 }
638
639 @Test
640 public void testPyStringPartitionEmptyInput() throws Exception {
641 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000642 .testEval("''.partition('a')", "('', '', '')")
643 .testEval("''.rpartition('a')", "('', '', '')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000644 }
645
646 @Test
647 public void testPyStringPartitionEmptySeparator() throws Exception {
648 new BothModesTest()
649 .testIfErrorContains("Empty separator", "'google'.partition('')")
650 .testIfErrorContains("Empty separator", "'google'.rpartition('')");
651 }
652
653 @Test
654 public void testPyStringPartitionDefaultSep() throws Exception {
655 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000656 .testEval("'hi this is a test'.partition()", "('hi', ' ', 'this is a test')")
657 .testEval("'hi this is a test'.rpartition()", "('hi this is a', ' ', 'test')")
658 .testEval("'google'.partition()", "('google', '', '')")
659 .testEval("'google'.rpartition()", "('', '', 'google')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000660 }
661
662 @Test
663 public void testPyStringPartitionNoMatch() throws Exception {
664 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000665 .testEval("'google'.partition('x')", "('google', '', '')")
666 .testEval("'google'.rpartition('x')", "('', '', 'google')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000667 }
668
669 @Test
670 public void testPyStringPartitionWordBoundaries() throws Exception {
671 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000672 .testEval("'goog'.partition('g')", "('', 'g', 'oog')")
673 .testEval("'goog'.rpartition('g')", "('goo', 'g', '')")
674 .testEval("'plex'.partition('p')", "('', 'p', 'lex')")
675 .testEval("'plex'.rpartition('p')", "('', 'p', 'lex')")
676 .testEval("'plex'.partition('x')", "('ple', 'x', '')")
677 .testEval("'plex'.rpartition('x')", "('ple', 'x', '')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000678 }
679
680 @Test
681 public void testPyStringPartitionLongSep() throws Exception {
682 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000683 .testEval("'google'.partition('oog')", "('g', 'oog', 'le')")
684 .testEval("'google'.rpartition('oog')", "('g', 'oog', 'le')")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000685 .testEval(
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000686 "'lolgooglolgooglolgooglol'.partition('goog')", "('lol', 'goog', 'lolgooglolgooglol')")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000687 .testEval(
688 "'lolgooglolgooglolgooglol'.rpartition('goog')",
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000689 "('lolgooglolgooglol', 'goog', 'lol')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000690 }
691
692 @Test
693 public void testPyStringPartitionCompleteString() throws Exception {
694 new BothModesTest()
Vladimir Moskvaf2eacf02017-02-22 23:57:49 +0000695 .testEval("'google'.partition('google')", "('', 'google', '')")
696 .testEval("'google'.rpartition('google')", "('', 'google', '')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000697 }
698
699 @Test
700 public void testPyStringTitle() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +0000701 new BothModesTest()
702 .testStatement("'this is a very simple test'.title()", "This Is A Very Simple Test");
703 new BothModesTest()
704 .testStatement("'Do We Keep Capital Letters?'.title()", "Do We Keep Capital Letters?");
705 new BothModesTest()
706 .testStatement(
707 "'this isn\\'t just an ol\\' apostrophe test'.title()",
708 "This Isn'T Just An Ol' Apostrophe Test");
709 new BothModesTest()
710 .testStatement(
711 "'Let us test crazy characters: _bla.exe//foo:bla(test$class)'.title()",
712 "Let Us Test Crazy Characters: _Bla.Exe//Foo:Bla(Test$Class)");
713 new BothModesTest().testStatement("'any germans here? äöü'.title()", "Any Germans Here? Äöü");
714 new BothModesTest()
715 .testStatement(
716 "'WE HAve tO lOWERCASE soMEthING heRE, AI?'.title()",
717 "We Have To Lowercase Something Here, Ai?");
718 new BothModesTest()
719 .testStatement("'wh4t ab0ut s0me numb3rs'.title()", "Wh4T Ab0Ut S0Me Numb3Rs");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000720 }
721
722 @Test
Laurent Le Brunb4114cc2015-08-26 14:53:37 +0000723 public void testCapitalize() throws Exception {
724 new BothModesTest()
725 .testStatement("'hello world'.capitalize()", "Hello world")
726 .testStatement("'HELLO WORLD'.capitalize()", "Hello world")
727 .testStatement("''.capitalize()", "")
728 .testStatement("'12 lower UPPER 34'.capitalize()", "12 lower upper 34");
729 }
730
731 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000732 public void testPyStringRfind() throws Exception {
733 new BothModesTest()
734 .testStatement("'banana'.rfind('na')", 4)
735 .testStatement("'banana'.rfind('na', 3, 1)", -1)
736 .testStatement("'aaaa'.rfind('a', 1, 1)", -1)
737 .testStatement("'aaaa'.rfind('a', 1, 50)", 3)
738 .testStatement("'aaaa'.rfind('aaaaa')", -1)
739 .testStatement("'abababa'.rfind('ab', 1)", 4)
740 .testStatement("'abababa'.rfind('ab', 0)", 4)
741 .testStatement("'abababa'.rfind('ab', -1)", -1)
742 .testStatement("'abababa'.rfind('ab', -2)", -1)
743 .testStatement("'abababa'.rfind('ab', -3)", 4)
744 .testStatement("'abababa'.rfind('ab', 0, 1)", -1)
745 .testStatement("'abababa'.rfind('ab', 0, 2)", 0)
746 .testStatement("'abababa'.rfind('ab', -1000)", 4)
747 .testStatement("'abababa'.rfind('ab', 1000)", -1)
748 .testStatement("''.rfind('a', 1)", -1);
749 }
750
751 @Test
752 public void testPyStringFind() throws Exception {
753 new BothModesTest()
754 .testStatement("'banana'.find('na')", 2)
755 .testStatement("'banana'.find('na', 3, 1)", -1)
756 .testStatement("'aaaa'.find('a', 1, 1)", -1)
757 .testStatement("'aaaa'.find('a', 1, 50)", 1)
758 .testStatement("'aaaa'.find('aaaaa')", -1)
759 .testStatement("'abababa'.find('ab', 1)", 2)
760 .testStatement("'abababa'.find('ab', 0)", 0)
761 .testStatement("'abababa'.find('ab', -1)", -1)
762 .testStatement("'abababa'.find('ab', -2)", -1)
763 .testStatement("'abababa'.find('ab', -3)", 4)
764 .testStatement("'abababa'.find('ab', 0, 1)", -1)
765 .testStatement("'abababa'.find('ab', 0, 2)", 0)
766 .testStatement("'abababa'.find('ab', -1000)", 0)
767 .testStatement("'abababa'.find('ab', 1000)", -1)
768 .testStatement("''.find('a', 1)", -1);
769 }
770
771 @Test
772 public void testPyStringIndex() throws Exception {
773 new BothModesTest()
774 .testStatement("'banana'.index('na')", 2)
775 .testStatement("'abababa'.index('ab', 1)", 2)
776 .testIfErrorContains("substring \"foo\" not found in \"banana\"", "'banana'.index('foo')");
777 }
778
779 @Test
780 public void testPyStringRIndex() throws Exception {
781 new BothModesTest()
782 .testStatement("'banana'.rindex('na')", 4)
783 .testStatement("'abababa'.rindex('ab', 1)", 4)
784 .testIfErrorContains("substring \"foo\" not found in \"banana\"", "'banana'.rindex('foo')");
785 }
786
787 @Test
788 public void testPyStringEndswith() throws Exception {
789 new BothModesTest()
790 .testStatement("'Apricot'.endswith('cot')", true)
791 .testStatement("'a'.endswith('')", true)
792 .testStatement("''.endswith('')", true)
793 .testStatement("'Apricot'.endswith('co')", false)
794 .testStatement("'Apricot'.endswith('co', -1)", false)
795 .testStatement("'abcd'.endswith('c', -2, -1)", true)
796 .testStatement("'abcd'.endswith('c', 1, 8)", false)
797 .testStatement("'abcd'.endswith('d', 1, 8)", true);
798 }
799
800 @Test
801 public void testPyStringStartswith() throws Exception {
802 new BothModesTest()
803 .testStatement("'Apricot'.startswith('Apr')", true)
804 .testStatement("'Apricot'.startswith('A')", true)
805 .testStatement("'Apricot'.startswith('')", true)
806 .testStatement("'Apricot'.startswith('z')", false)
807 .testStatement("''.startswith('')", true)
808 .testStatement("''.startswith('a')", false);
809 }
810
811 @Test
812 public void testPySubstring() throws Exception {
813 new BothModesTest()
814 .testStatement("'012345678'[0:-1]", "01234567")
815 .testStatement("'012345678'[2:4]", "23")
816 .testStatement("'012345678'[-5:-3]", "45")
817 .testStatement("'012345678'[2:2]", "")
818 .testStatement("'012345678'[2:]", "2345678")
819 .testStatement("'012345678'[:3]", "012")
820 .testStatement("'012345678'[-1:]", "8")
821 .testStatement("'012345678'[:]", "012345678")
822 .testStatement("'012345678'[-1:2]", "")
823 .testStatement("'012345678'[4:2]", "");
824 }
825
826 @Test
827 public void testPyStringFormatEscaping() throws Exception {
828 new BothModesTest()
829 .testStatement("'{{}}'.format()", "{}")
830 .testStatement("'{{}}'.format(42)", "{}")
831 .testStatement("'{{ }}'.format()", "{ }")
832 .testStatement("'{{ }}'.format(42)", "{ }")
833 .testStatement("'{{{{}}}}'.format()", "{{}}")
834 .testStatement("'{{{{}}}}'.format(42)", "{{}}")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000835 .testStatement("'{{0}}'.format(42)", "{0}")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000836 .testStatement("'{{}}'.format(42)", "{}")
837 .testStatement("'{{{}}}'.format(42)", "{42}")
838 .testStatement("'{{ '.format(42)", "{ ")
839 .testStatement("' }}'.format(42)", " }")
840 .testStatement("'{{ {}'.format(42)", "{ 42")
841 .testStatement("'{} }}'.format(42)", "42 }")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000842 .testStatement("'{{0}}'.format(42)", "{0}")
843 .testStatement("'{{{0}}}'.format(42)", "{42}")
844 .testStatement("'{{ 0'.format(42)", "{ 0")
845 .testStatement("'0 }}'.format(42)", "0 }")
846 .testStatement("'{{ {0}'.format(42)", "{ 42")
847 .testStatement("'{0} }}'.format(42)", "42 }")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000848 .testStatement("'{{test}}'.format(test = 42)", "{test}")
849 .testStatement("'{{{test}}}'.format(test = 42)", "{42}")
850 .testStatement("'{{ test'.format(test = 42)", "{ test")
851 .testStatement("'test }}'.format(test = 42)", "test }")
852 .testStatement("'{{ {test}'.format(test = 42)", "{ 42")
853 .testStatement("'{test} }}'.format(test = 42)", "42 }")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000854 .testIfErrorContains("Found '}' without matching '{'", "'{{}'.format(1)")
855 .testIfErrorContains("Found '}' without matching '{'", "'{}}'.format(1)");
856 }
857
858 @Test
859 public void testPyStringFormatManualPositionals() throws Exception {
860 new BothModesTest()
861 .testStatement(
862 "'{0}, {1} {2} {3} test'.format('hi', 'this', 'is', 'a')", "hi, this is a test")
863 .testStatement(
864 "'{3}, {2} {1} {0} test'.format('a', 'is', 'this', 'hi')", "hi, this is a test")
865 .testStatement(
866 "'skip some {0}'.format('arguments', 'obsolete', 'deprecated')", "skip some arguments")
867 .testStatement(
868 "'{0} can be reused: {0}'.format('this', 'obsolete')", "this can be reused: this");
869 }
870
871 @Test
872 public void testPyStringFormatManualPositionalsErrors() throws Exception {
873 new BothModesTest()
874 .testIfErrorContains("No replacement found for index 0", "'{0}'.format()")
875 .testIfErrorContains("No replacement found for index 1", "'{0} and {1}'.format('this')")
876 .testIfErrorContains(
877 "No replacement found for index 2", "'{0} and {2}'.format('this', 'that')")
878 .testIfErrorContains(
879 "No replacement found for index -1", "'{-0} and {-1}'.format('this', 'that')")
880 .testIfErrorContains(
881 "Invalid character ',' inside replacement field",
882 "'{0,1} and {1}'.format('this', 'that')")
883 .testIfErrorContains(
884 "Invalid character '.' inside replacement field",
885 "'{0.1} and {1}'.format('this', 'that')");
886 }
887
888 @Test
889 public void testPyStringFormatAutomaticPositionals() throws Exception {
890 new BothModesTest()
891 .testStatement("'{}, {} {} {} test'.format('hi', 'this', 'is', 'a')", "hi, this is a test")
892 .testStatement(
893 "'skip some {}'.format('arguments', 'obsolete', 'deprecated')", "skip some arguments");
894 }
895
896 @Test
897 public void testPyStringFormatAutomaticPositionalsError() throws Exception {
898 new BothModesTest()
899 .testIfErrorContains("No replacement found for index 0", "'{}'.format()")
900 .testIfErrorContains("No replacement found for index 1", "'{} and {}'.format('this')");
901 }
902
903 @Test
904 public void testPyStringFormatMixedFields() throws Exception {
905 new BothModesTest()
906 .testStatement("'{test} and {}'.format(2, test = 1)", "1 and 2")
907 .testStatement("'{test} and {0}'.format(2, test = 1)", "1 and 2")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000908 .testIfErrorContains(
909 "non-keyword arg after keyword arg", "'{test} and {}'.format(test = 1, 2)")
910 .testIfErrorContains(
911 "non-keyword arg after keyword arg", "'{test} and {0}'.format(test = 1, 2)")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000912 .testIfErrorContains(
913 "Cannot mix manual and automatic numbering of positional fields",
914 "'{} and {1}'.format(1, 2)")
915 .testIfErrorContains(
916 "Cannot mix manual and automatic numbering of positional fields",
917 "'{1} and {}'.format(1, 2)");
918 }
919
920 @Test
921 public void testPyStringFormatInvalidFields() throws Exception {
922 for (char unsupported : new char[] {'.', '[', ']', ','}) {
Yun Pengfc610052016-06-20 11:44:06 +0000923 new BothModesTest()
924 .testIfErrorContains(
925 String.format("Invalid character '%c' inside replacement field", unsupported),
926 String.format("'{test%ctest}'.format(test = 1)", unsupported));
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000927 }
928
Yun Pengfc610052016-06-20 11:44:06 +0000929 new BothModesTest()
930 .testIfErrorContains("Nested replacement fields are not supported", "'{ {} }'.format(42)");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000931 }
932
933 @Test
934 public void testPyStringFormat() throws Exception {
935 new BothModesTest()
936 .testStatement("'abc'.format()", "abc")
937 .testStatement("'x{key}x'.format(key = 2)", "x2x")
938 .testStatement("'x{key}x'.format(key = 'abc')", "xabcx")
939 .testStatement("'{a}{b}{a}{b}'.format(a = 3, b = True)", "3True3True")
940 .testStatement("'{a}{b}{a}{b}'.format(a = 3, b = True)", "3True3True")
941 .testStatement("'{s1}{s2}'.format(s1 = ['a'], s2 = 'a')", "[\"a\"]a")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000942 .testIfErrorContains("Missing argument 'b'", "'{a}{b}'.format(a = 5)")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +0000943 .testStatement("'{a}'.format(a = '$')", "$")
944 .testStatement("'{a}'.format(a = '$a')", "$a")
945 .testStatement("'{a}$'.format(a = '$a')", "$a$");
946
947 // The test below is using **kwargs, which is not available in BUILD mode.
948 new SkylarkTest().testStatement("'{(}'.format(**{'(': 2})", "2");
949 }
950
951 @Test
Florian Weikertd5e33502015-12-14 12:06:10 +0000952 public void testReversedWithInvalidTypes() throws Exception {
953 new BothModesTest()
954 .testIfExactError("type 'NoneType' is not iterable", "reversed(None)")
955 .testIfExactError("type 'int' is not iterable", "reversed(1)")
956 .testIfExactError(
957 "Argument to reversed() must be a sequence, not a dictionary.", "reversed({1: 3})");
958 new SkylarkTest()
959 .testIfExactError(
Vladimir Moskvad200daf2016-12-23 16:35:37 +0000960 "Argument to reversed() must be a sequence, not a depset.", "reversed(depset([1]))");
Florian Weikertd5e33502015-12-14 12:06:10 +0000961 }
962
963 @Test
964 public void testReversedWithLists() throws Exception {
965 new BothModesTest()
966 .testEval("reversed([])", "[]")
967 .testEval("reversed([1])", "[1]")
968 .testEval("reversed([1, 2, 3, 4, 5])", "[5, 4, 3, 2, 1]")
969 .testEval("reversed([[1, 2], 3, 4, [5]])", "[[5], 4, 3, [1, 2]]")
970 .testEval("reversed([1, 1, 1, 1, 2])", "[2, 1, 1, 1, 1]");
971 }
972
973 @Test
974 public void testReversedWithStrings() throws Exception {
975 new BothModesTest()
Florian Weikert233a46e2015-12-16 12:38:38 +0000976 .testEval("reversed('')", "[]")
Florian Weikertd5e33502015-12-14 12:06:10 +0000977 .testEval("reversed('a')", "['a']")
978 .testEval("reversed('abc')", "['c', 'b', 'a']")
979 .testEval("reversed('__test ')", "[' ', ' ', 't', 's', 'e', 't', '_', '_']")
980 .testEval("reversed('bbb')", "['b', 'b', 'b']");
981 }
982
983 @Test
984 public void testReversedNoSideEffects() throws Exception {
985 new SkylarkTest()
986 .testEval(
987 "def foo():\n"
988 + " x = ['a', 'b']\n"
989 + " y = reversed(x)\n"
990 + " y += ['c']\n"
991 + " return x\n"
992 + "foo()",
993 "['a', 'b']");
994 }
995
996 @Test
Florian Weikerte3421962015-12-17 12:46:08 +0000997 public void testEquivalenceOfReversedAndSlice() throws Exception {
998 String[] data = new String[] {"[]", "[1]", "[1, 2, 3]"};
999 for (String toBeReversed : data) {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001000 new BothModesTest()
1001 .testEval(
1002 String.format("reversed(%s)", toBeReversed), String.format("%s[::-1]", toBeReversed));
Florian Weikerte3421962015-12-17 12:46:08 +00001003 }
1004 }
1005
1006 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001007 public void testListSlice() throws Exception {
1008 new BothModesTest()
Florian Weikerte3421962015-12-17 12:46:08 +00001009 .testEval("[0, 1, 2, 3][0:-1]", "[0, 1, 2]")
1010 .testEval("[0, 1, 2, 3, 4, 5][2:4]", "[2, 3]")
1011 .testEval("[0, 1, 2, 3, 4, 5][-2:-1]", "[4]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001012 .testEval("[][1:2]", "[]")
Florian Weikerte3421962015-12-17 12:46:08 +00001013 .testEval("[0, 1, 2, 3][-10:10]", "[0, 1, 2, 3]");
1014 }
1015
1016 @Test
1017 public void testListSlice_WrongType() throws Exception {
1018 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001019 .testIfExactError("slice start must be an integer, not 'a'", "'123'['a'::]")
1020 .testIfExactError("slice end must be an integer, not 'b'", "'123'[:'b':]");
Florian Weikerte3421962015-12-17 12:46:08 +00001021 }
1022
1023 @Test
1024 public void testListSliceStep() throws Exception {
1025 new BothModesTest()
1026 .testEval("[1, 2, 3, 4, 5][::1]", "[1, 2, 3, 4, 5]")
1027 .testEval("[1, 2, 3, 4, 5][1::1]", "[2, 3, 4, 5]")
1028 .testEval("[1, 2, 3, 4, 5][:2:1]", "[1, 2]")
1029 .testEval("[1, 2, 3, 4, 5][1:3:1]", "[2, 3]")
1030 .testEval("[1, 2, 3, 4, 5][-4:-2:1]", "[2, 3]")
1031 .testEval("[1, 2, 3, 4, 5][-10:10:1]", "[1, 2, 3, 4, 5]")
1032 .testEval("[1, 2, 3, 4, 5][::42]", "[1]");
1033 }
1034
1035 @Test
1036 public void testListSliceStep_EmptyList() throws Exception {
1037 new BothModesTest().testEval("[][::1]", "[]").testEval("[][::-1]", "[]");
1038 }
1039
1040 @Test
1041 public void testListSliceStep_SkipValues() throws Exception {
1042 new BothModesTest()
1043 .testEval("[1, 2, 3, 4, 5, 6, 7][::3]", "[1, 4, 7]")
1044 .testEval("[1, 2, 3, 4, 5, 6, 7, 8, 9][1:7:3]", "[2, 5]");
1045 }
1046
1047 @Test
1048 public void testListSliceStep_Negative() throws Exception {
1049 new BothModesTest()
1050 .testEval("[1, 2, 3, 4, 5][::-1]", "[5, 4, 3, 2, 1]")
1051 .testEval("[1, 2, 3, 4, 5][4::-1]", "[5, 4, 3, 2, 1]")
1052 .testEval("[1, 2, 3, 4, 5][:0:-1]", "[5, 4, 3, 2]")
1053 .testEval("[1, 2, 3, 4, 5][3:1:-1]", "[4, 3]")
1054 .testEval("[1, 2, 3, 4, 5][::-2]", "[5, 3, 1]")
1055 .testEval("[1, 2, 3, 4, 5][::-10]", "[5]");
1056 }
1057
1058 @Test
1059 public void testListSlice_WrongOrder() throws Exception {
1060 new BothModesTest().testEval("[1, 2, 3][3:1:1]", "[]").testEval("[1, 2, 3][1:3:-1]", "[]");
1061 }
1062
1063 @Test
1064 public void testListSliceStep_InvalidStep() throws Exception {
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001065 String msg = "slice step cannot be zero";
Florian Weikerte3421962015-12-17 12:46:08 +00001066 new BothModesTest()
1067 .testIfExactError(msg, "[1, 2, 3][::0]")
1068 .testIfExactError(msg, "[1, 2, 3][1::0]")
1069 .testIfExactError(msg, "[1, 2, 3][:3:0]")
1070 .testIfExactError(msg, "[1, 2, 3][1:3:0]");
1071 }
1072
1073 @Test
1074 public void testTupleSlice() throws Exception {
1075 // Not as comprehensive as the tests for slicing lists since the underlying mechanism is the
1076 // same.
1077 new BothModesTest()
1078 .testEval("()[1:2]", "()")
1079 .testEval("()[::1]", "()")
1080 .testEval("(0, 1, 2, 3)[0:-1]", "(0, 1, 2)")
1081 .testEval("(0, 1, 2, 3, 4, 5)[2:4]", "(2, 3)")
1082 .testEval("(0, 1, 2, 3)[-10:10]", "(0, 1, 2, 3)")
1083 .testEval("(1, 2, 3, 4, 5)[-10:10:1]", "(1, 2, 3, 4, 5)")
1084 .testEval("(1, 2, 3, 4, 5, 6, 7, 8, 9)[1:7:3]", "(2, 5)")
1085 .testEval("(1, 2, 3, 4, 5)[::-1]", "(5, 4, 3, 2, 1)")
1086 .testEval("(1, 2, 3, 4, 5)[3:1:-1]", "(4, 3)")
1087 .testEval("(1, 2, 3, 4, 5)[::-2]", "(5, 3, 1)")
1088 .testEval("(1, 2, 3, 4, 5)[::-10]", "(5,)")
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001089 .testIfExactError("slice step cannot be zero", "(1, 2, 3)[1::0]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001090 }
1091
1092 @Test
1093 public void testListSort() throws Exception {
1094 new BothModesTest()
1095 .testEval("sorted([0,1,2,3])", "[0, 1, 2, 3]")
1096 .testEval("sorted([])", "[]")
1097 .testEval("sorted([3, 2, 1, 0])", "[0, 1, 2, 3]")
1098 .testEval("sorted([[1], [], [2], [1, 2]])", "[[], [1], [1, 2], [2]]")
1099 .testEval("sorted([True, False, True])", "[False, True, True]")
1100 .testEval("sorted(['a','x','b','z'])", "[\"a\", \"b\", \"x\", \"z\"]")
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001101 .testEval("sorted({1: True, 5: True, 4: False})", "[1, 4, 5]")
Vladimir Moskva7f0cd622017-02-16 13:48:37 +00001102 .testEval("sorted(depset([1, 5, 4]))", "[1, 4, 5]")
1103 .testIfExactError("Cannot compare function with function", "sorted([sorted, sorted])");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001104 }
1105
1106 @Test
Florian Weikert1c07e322015-09-25 11:59:40 +00001107 public void testDictionaryCopy() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001108 new BothModesTest()
Florian Weikert1c07e322015-09-25 11:59:40 +00001109 .setUp("x = {1 : 2}", "y = dict(x)")
1110 .testEval("x[1] == 2 and y[1] == 2", "True");
1111 }
1112
1113 @Test
1114 public void testDictionaryCopyKeyCollision() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001115 new BothModesTest()
Florian Weikert1c07e322015-09-25 11:59:40 +00001116 .setUp("x = {'test' : 2}", "y = dict(x, test = 3)")
1117 .testEval("y['test']", "3");
1118 }
1119
1120 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001121 public void testDictionaryKeyNotFound() throws Exception {
1122 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001123 .testIfErrorContains("key \"0\" not found in dictionary", "{}['0']")
1124 .testIfErrorContains("key 0 not found in dictionary", "{'0': 1, 2: 3, 4: 5}[0]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001125 }
1126
1127 @Test
1128 public void testListAccessBadIndex() throws Exception {
Laurent Le Brun3a837472015-12-22 17:58:40 +00001129 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001130 .testIfErrorContains("indices must be integers, not string", "[[1], [2]]['a']");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001131 }
1132
1133 @Test
1134 public void testDictionaryAccess() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001135 new BothModesTest()
1136 .testEval("{1: ['foo']}[1]", "['foo']")
1137 .testStatement("{'4': 8}['4']", 8)
1138 .testStatement("{'a': 'aa', 'b': 'bb', 'c': 'cc'}['b']", "bb");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001139 }
1140
1141 @Test
1142 public void testDictionaryVariableAccess() throws Exception {
1143 new BothModesTest().setUp("d = {'a' : 1}", "a = d['a']\n").testLookup("a", 1);
1144 }
1145
1146 @Test
1147 public void testStringIndexing() throws Exception {
1148 new BothModesTest()
1149 .testStatement("'somestring'[0]", "s")
1150 .testStatement("'somestring'[1]", "o")
1151 .testStatement("'somestring'[4]", "s")
1152 .testStatement("'somestring'[9]", "g")
1153 .testStatement("'somestring'[-1]", "g")
1154 .testStatement("'somestring'[-2]", "n")
1155 .testStatement("'somestring'[-10]", "s");
1156 }
1157
1158 @Test
1159 public void testStringIndexingOutOfRange() throws Exception {
1160 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001161 .testIfErrorContains("index out of range", "'abcdef'[10]")
1162 .testIfErrorContains("index out of range", "'abcdef'[-11]")
1163 .testIfErrorContains("index out of range", "'abcdef'[42]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001164 }
1165
1166 @Test
Florian Weikerte3421962015-12-17 12:46:08 +00001167 public void testStringSlice() throws Exception {
1168 new BothModesTest()
1169 .testStatement("'0123'[0:-1]", "012")
1170 .testStatement("'012345'[2:4]", "23")
1171 .testStatement("'012345'[-2:-1]", "4")
1172 .testStatement("''[1:2]", "")
1173 .testStatement("'012'[1:0]", "")
1174 .testStatement("'0123'[-10:10]", "0123");
1175 }
1176
1177 @Test
1178 public void testStringSlice_WrongType() throws Exception {
1179 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001180 .testIfExactError("slice start must be an integer, not 'a'", "'123'['a'::]")
1181 .testIfExactError("slice end must be an integer, not 'b'", "'123'[:'b':]");
Florian Weikerte3421962015-12-17 12:46:08 +00001182 }
1183
1184 @Test
1185 public void testStringSliceStep() throws Exception {
1186 new BothModesTest()
1187 .testStatement("'01234'[::1]", "01234")
1188 .testStatement("'01234'[1::1]", "1234")
1189 .testStatement("'01234'[:2:1]", "01")
1190 .testStatement("'01234'[1:3:1]", "12")
1191 .testStatement("'01234'[-4:-2:1]", "12")
1192 .testStatement("'01234'[-10:10:1]", "01234")
1193 .testStatement("'01234'[::42]", "0");
1194 }
1195
1196 @Test
1197 public void testStringSliceStep_EmptyString() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001198 new BothModesTest().testStatement("''[::1]", "").testStatement("''[::-1]", "");
Florian Weikerte3421962015-12-17 12:46:08 +00001199 }
1200
1201 @Test
1202 public void testStringSliceStep_SkipValues() throws Exception {
1203 new BothModesTest()
1204 .testStatement("'0123456'[::3]", "036")
1205 .testStatement("'01234567'[1:7:3]", "14");
1206 }
1207
1208 @Test
1209 public void testStringSliceStep_Negative() throws Exception {
1210 new BothModesTest()
1211 .testStatement("'01234'[::-1]", "43210")
1212 .testStatement("'01234'[4::-1]", "43210")
1213 .testStatement("'01234'[:0:-1]", "4321")
1214 .testStatement("'01234'[3:1:-1]", "32")
1215 .testStatement("'01234'[::-2]", "420")
1216 .testStatement("'01234'[::-10]", "4");
1217 }
1218
1219 @Test
1220 public void testStringSliceStep_WrongOrder() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001221 new BothModesTest().testStatement("'123'[3:1:1]", "").testStatement("'123'[1:3:-1]", "");
Florian Weikerte3421962015-12-17 12:46:08 +00001222 }
1223
1224 @Test
1225 public void testStringSliceStep_InvalidStep() throws Exception {
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001226 String msg = "slice step cannot be zero";
Florian Weikerte3421962015-12-17 12:46:08 +00001227 new BothModesTest()
1228 .testIfExactError(msg, "'123'[::0]")
1229 .testIfExactError(msg, "'123'[1::0]")
1230 .testIfExactError(msg, "'123'[:3:0]")
1231 .testIfExactError(msg, "'123'[1:3:0]");
1232 }
1233
1234 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001235 public void testDictionaryCreation() throws Exception {
1236 String expected = "{'a': 1, 'b': 2, 'c': 3}";
1237
1238 new BothModesTest()
1239 .testEval("dict([('a', 1), ('b', 2), ('c', 3)])", expected)
1240 .testEval("dict(a = 1, b = 2, c = 3)", expected)
1241 .testEval("dict([('a', 1)], b = 2, c = 3)", expected);
1242 }
1243
1244 @Test
1245 public void testDictionaryCreationInnerLists() throws Exception {
1246 new BothModesTest().testEval("dict([[1, 2], [3, 4]], a = 5)", "{1: 2, 3: 4, 'a': 5}");
1247 }
1248
1249 @Test
1250 public void testDictionaryCreationEmpty() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001251 new BothModesTest().testEval("dict()", "{}").testEval("dict([])", "{}");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001252 }
1253
1254 @Test
1255 public void testDictionaryCreationDifferentKeyTypes() throws Exception {
1256 String expected = "{'a': 1, 2: 3}";
1257
1258 new BothModesTest()
1259 .testEval("dict([('a', 1), (2, 3)])", expected)
1260 .testEval("dict([(2, 3)], a = 1)", expected);
1261 }
1262
1263 @Test
1264 public void testDictionaryCreationKeyCollision() throws Exception {
1265 String expected = "{'a': 1, 'b': 2, 'c': 3}";
1266
1267 new BothModesTest()
1268 .testEval("dict([('a', 42), ('b', 2), ('a', 1), ('c', 3)])", expected)
1269 .testEval("dict([('a', 42)], a = 1, b = 2, c = 3)", expected);
Yun Pengfc610052016-06-20 11:44:06 +00001270 new SkylarkTest().testEval("dict([('a', 42)], **{'a': 1, 'b': 2, 'c': 3})", expected);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001271 }
1272
1273 @Test
1274 public void testDictionaryCreationInvalidPositional() throws Exception {
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001275 new BothModesTest()
1276 .testIfErrorContains(
Florian Weikert1c07e322015-09-25 11:59:40 +00001277 "expected value of type 'list(object)' for parameter args in dict(), "
Yun Pengfc610052016-06-20 11:44:06 +00001278 + "but got \"a\" (string)",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001279 "dict('a')")
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001280 .testIfErrorContains("cannot convert item #0 to a sequence", "dict(['a'])")
1281 .testIfErrorContains("cannot convert item #0 to a sequence", "dict([('a')])")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001282 .testIfErrorContains("too many (3) positional arguments", "dict((3,4), (3,2), (1,2))")
1283 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001284 "item #0 has length 3, but exactly two elements are required",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001285 "dict([('a', 'b', 'c')])");
1286 }
1287
1288 @Test
1289 public void testDictionaryValues() throws Exception {
1290 new BothModesTest()
1291 .testEval("{1: 'foo'}.values()", "['foo']")
1292 .testEval("{}.values()", "[]")
Vladimir Moskva76e31d12016-12-05 16:28:37 +00001293 .testEval("{True: 3, False: 5}.values()", "[3, 5]")
1294 .testEval("{'a': 5, 'c': 2, 'b': 4, 'd': 3}.values()", "[5, 2, 4, 3]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001295 // sorted by keys
1296 }
1297
1298 @Test
1299 public void testDictionaryKeys() throws Exception {
1300 new BothModesTest()
1301 .testEval("{1: 'foo'}.keys()", "[1]")
1302 .testEval("{}.keys()", "[]")
Vladimir Moskva76e31d12016-12-05 16:28:37 +00001303 .testEval("{True: 3, False: 5}.keys()", "[True, False]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001304 .testEval(
Vladimir Moskva76e31d12016-12-05 16:28:37 +00001305 "{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 +00001306 }
1307
1308 @Test
1309 public void testDictionaryGet() throws Exception {
1310 new BuildTest()
1311 .testStatement("{1: 'foo'}.get(1)", "foo")
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +00001312 .testStatement("{1: 'foo'}.get(2)", Runtime.NONE)
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001313 .testStatement("{1: 'foo'}.get(2, 'a')", "a")
1314 .testStatement("{1: 'foo'}.get(2, default='a')", "a")
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +00001315 .testStatement("{1: 'foo'}.get(2, default=None)", Runtime.NONE);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001316 }
1317
1318 @Test
1319 public void testDictionaryItems() throws Exception {
1320 new BothModesTest()
1321 .testEval("{'a': 'foo'}.items()", "[('a', 'foo')]")
1322 .testEval("{}.items()", "[]")
1323 .testEval("{1: 3, 2: 5}.items()", "[(1, 3), (2, 5)]")
Vladimir Moskva76e31d12016-12-05 16:28:37 +00001324 .testEval("{'a': 5, 'c': 2, 'b': 4}.items()", "[('a', 5), ('c', 2), ('b', 4)]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001325 }
1326
1327 @Test
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001328 public void testDictionaryClear() throws Exception {
1329 new SkylarkTest()
1330 .testEval(
1331 "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n"
laurentlb85151182017-08-16 20:24:04 +02001332 + "len(d) == 3 or fail('clear 1')\n"
1333 + "d.clear() == None or fail('clear 2')\n"
Yun Pengfc610052016-06-20 11:44:06 +00001334 + "d",
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001335 "{}");
1336 }
1337
1338 @Test
1339 public void testDictionaryPop() throws Exception {
1340 new SkylarkTest()
1341 .testIfErrorContains(
1342 "KeyError: 1",
1343 "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n"
laurentlb85151182017-08-16 20:24:04 +02001344 + "len(d) == 3 or fail('pop 1')\n"
1345 + "d.pop(2) == 'bar' or fail('pop 2')\n"
1346 + "d.pop(3, 'quux') == 'baz' or fail('pop 3a')\n"
1347 + "d.pop(3, 'quux') == 'quux' or fail('pop 3b')\n"
1348 + "d.pop(1) == 'foo' or fail('pop 1')\n"
1349 + "d == {} or fail('pop 0')\n"
Yun Pengfc610052016-06-20 11:44:06 +00001350 + "d.pop(1)");
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001351 }
1352
1353 @Test
1354 public void testDictionaryPopItem() throws Exception {
1355 new SkylarkTest()
1356 .testIfErrorContains(
1357 "popitem(): dictionary is empty",
1358 "d = {2: 'bar', 3: 'baz', 1: 'foo'}\n"
laurentlb85151182017-08-16 20:24:04 +02001359 + "len(d) == 3 or fail('popitem 0')\n"
1360 + "d.popitem() == (2, 'bar') or fail('popitem 2')\n"
1361 + "d.popitem() == (3, 'baz') or fail('popitem 3')\n"
1362 + "d.popitem() == (1, 'foo') or fail('popitem 1')\n"
1363 + "d == {} or fail('popitem 4')\n"
Yun Pengfc610052016-06-20 11:44:06 +00001364 + "d.popitem()");
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001365 }
1366
1367 @Test
Laurent Le Brunb525bee2016-03-07 17:14:10 +00001368 public void testDictionaryUpdate() throws Exception {
1369 new BothModesTest()
1370 .setUp("foo = {'a': 2}")
1371 .testEval("foo.update({'b': 4}); foo", "{'a': 2, 'b': 4}");
1372 new BothModesTest()
1373 .setUp("foo = {'a': 2}")
1374 .testEval("foo.update({'a': 3, 'b': 4}); foo", "{'a': 3, 'b': 4}");
1375 }
1376
1377 @Test
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001378 public void testDictionarySetDefault() throws Exception {
1379 new SkylarkTest()
1380 .testEval(
1381 "d = {2: 'bar', 1: 'foo'}\n"
laurentlb85151182017-08-16 20:24:04 +02001382 + "len(d) == 2 or fail('setdefault 0')\n"
1383 + "d.setdefault(1, 'a') == 'foo' or fail('setdefault 1')\n"
1384 + "d.setdefault(2) == 'bar' or fail('setdefault 2')\n"
1385 + "d.setdefault(3) == None or fail('setdefault 3')\n"
1386 + "d.setdefault(4, 'b') == 'b' or fail('setdefault 4')\n"
Yun Pengfc610052016-06-20 11:44:06 +00001387 + "d",
Francois-Rene Rideau432d7152016-02-18 16:33:03 +00001388 "{1: 'foo', 2: 'bar', 3: None, 4: 'b'}");
1389 }
1390
1391 @Test
Laurent Le Brun3ef1eea2015-11-09 14:35:54 +00001392 public void testListIndexMethod() throws Exception {
1393 new BothModesTest()
1394 .testStatement("['a', 'b', 'c'].index('a')", 0)
1395 .testStatement("['a', 'b', 'c'].index('b')", 1)
1396 .testStatement("['a', 'b', 'c'].index('c')", 2)
1397 .testStatement("[2, 4, 6].index(4)", 1)
1398 .testStatement("[2, 4, 6].index(4)", 1)
1399 .testStatement("[0, 1, [1]].index([1])", 2)
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001400 .testIfErrorContains("item \"a\" not found in list", "[1, 2].index('a')")
1401 .testIfErrorContains("item 0 not found in list", "[].index(0)");
Laurent Le Brun3ef1eea2015-11-09 14:35:54 +00001402 }
1403
1404 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001405 public void testListIndex() throws Exception {
1406 new BothModesTest()
1407 .testStatement("['a', 'b', 'c', 'd'][0]", "a")
1408 .testStatement("['a', 'b', 'c', 'd'][1]", "b")
1409 .testStatement("['a', 'b', 'c', 'd'][-1]", "d")
1410 .testStatement("['a', 'b', 'c', 'd'][-2]", "c")
1411 .testStatement("[0, 1, 2][-3]", 0)
1412 .testStatement("[0, 1, 2][-2]", 1)
1413 .testStatement("[0, 1, 2][-1]", 2)
1414 .testStatement("[0, 1, 2][0]", 0);
1415 }
1416
1417 @Test
1418 public void testListIndexOutOfRange() throws Exception {
1419 new BothModesTest()
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001420 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001421 "index out of range (index is 3, but sequence has 3 elements)", "[0, 1, 2][3]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001422 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001423 "index out of range (index is -4, but sequence has 3 elements)", "[0, 1, 2][-4]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001424 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001425 "index out of range (index is -2, but sequence has 1 elements)", "[0][-2]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001426 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001427 "index out of range (index is 1, but sequence has 1 elements)", "[0][1]")
Vladimir Moskva8d610c62016-09-15 14:36:41 +00001428 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001429 "index out of range (index is 1, but sequence has 0 elements)", "[][1]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001430 }
1431
1432 @Test
Jon Brandvein9c4629d2016-07-20 20:16:33 +00001433 public void testHash() throws Exception {
Jon Brandvein3bdb4c32016-07-21 16:41:01 +00001434 // We specify the same string hashing algorithm as String.hashCode().
Jon Brandvein9c4629d2016-07-20 20:16:33 +00001435 new SkylarkTest()
1436 .testStatement("hash('skylark')", "skylark".hashCode())
1437 .testStatement("hash('google')", "google".hashCode())
1438 .testIfErrorContains(
laurentlb9e540882017-07-07 06:58:45 -04001439 "argument 'value' has type 'NoneType', but should be 'string'\n"
1440 + "in call to builtin function hash(value)",
Jon Brandvein9c4629d2016-07-20 20:16:33 +00001441 "hash(None)");
1442 }
1443
1444 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001445 public void testRange() throws Exception {
1446 new BothModesTest()
1447 .testStatement("str(range(5))", "[0, 1, 2, 3, 4]")
1448 .testStatement("str(range(0))", "[]")
1449 .testStatement("str(range(1))", "[0]")
1450 .testStatement("str(range(-2))", "[]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001451 .testStatement("str(range(-3, 2))", "[-3, -2, -1, 0, 1]")
1452 .testStatement("str(range(3, 2))", "[]")
1453 .testStatement("str(range(3, 3))", "[]")
1454 .testStatement("str(range(3, 4))", "[3]")
1455 .testStatement("str(range(3, 5))", "[3, 4]")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001456 .testStatement("str(range(-3, 5, 2))", "[-3, -1, 1, 3]")
1457 .testStatement("str(range(-3, 6, 2))", "[-3, -1, 1, 3, 5]")
1458 .testStatement("str(range(5, 0, -1))", "[5, 4, 3, 2, 1]")
1459 .testStatement("str(range(5, 0, -10))", "[5]")
1460 .testStatement("str(range(0, -3, -2))", "[0, -2]")
1461 .testIfErrorContains("step cannot be 0", "range(2, 3, 0)");
1462 }
1463
1464 @Test
1465 public void testEnumerate() throws Exception {
1466 new BothModesTest()
1467 .testStatement("str(enumerate([]))", "[]")
1468 .testStatement("str(enumerate([5]))", "[(0, 5)]")
1469 .testStatement("str(enumerate([5, 3]))", "[(0, 5), (1, 3)]")
1470 .testStatement("str(enumerate(['a', 'b', 'c']))", "[(0, \"a\"), (1, \"b\"), (2, \"c\")]")
1471 .testStatement("str(enumerate(['a']) + [(1, 'b')])", "[(0, \"a\"), (1, \"b\")]");
1472 }
1473
1474 @Test
1475 public void testEnumerateBadArg() throws Exception {
Yun Pengfc610052016-06-20 11:44:06 +00001476 new BothModesTest()
1477 .testIfErrorContains(
laurentlb9e540882017-07-07 06:58:45 -04001478 "argument 'list' has type 'string', but should be 'sequence'\n"
1479 + "in call to builtin function enumerate(list)",
Yun Pengfc610052016-06-20 11:44:06 +00001480 "enumerate('a')");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001481 }
1482
1483 @Test
1484 public void testPyListAppend() throws Exception {
1485 new BuildTest()
Yue Gan6c2276a2016-04-07 08:02:00 +00001486 .setUp("FOO = ['a', 'b']", "FOO.insert(0, 'c')")
1487 .testLookup("FOO", MutableList.of(env, "c", "a", "b"))
1488 .setUp("FOO.insert(1, 'd')")
1489 .testLookup("FOO", MutableList.of(env, "c", "d", "a", "b"))
1490 .setUp("FOO.insert(4, 'e')")
1491 .testLookup("FOO", MutableList.of(env, "c", "d", "a", "b", "e"))
1492 .setUp("FOO.insert(-10, 'f')")
1493 .testLookup("FOO", MutableList.of(env, "f", "c", "d", "a", "b", "e"))
1494 .setUp("FOO.insert(10, 'g')")
1495 .testLookup("FOO", MutableList.of(env, "f", "c", "d", "a", "b", "e", "g"))
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001496 .testIfErrorContains("type 'tuple' has no method insert(int)", "(1, 2).insert(3)");
Yue Gan6c2276a2016-04-07 08:02:00 +00001497 }
1498
1499 @Test
1500 public void testPyListInsert() throws Exception {
1501 new BuildTest()
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001502 .setUp("FOO = ['a', 'b']", "FOO.append('c')")
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00001503 .testLookup("FOO", MutableList.of(env, "a", "b", "c"))
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001504 .testIfErrorContains("type 'tuple' has no method append(int)", "(1, 2).append(3)");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001505 }
1506
1507 @Test
1508 public void testPyListExtend() throws Exception {
1509 new BuildTest()
Vladimir Moskva71536642016-12-19 13:51:57 +00001510 .setUp("FOO = ['a', 'b']", "FOO.extend(['c', 'd'])", "FOO.extend(('e', 'f'))")
1511 .testLookup("FOO", MutableList.of(env, "a", "b", "c", "d", "e", "f"))
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001512 .testIfErrorContains("type 'tuple' has no method extend(list)", "(1, 2).extend([3, 4])")
Vladimir Moskva71536642016-12-19 13:51:57 +00001513 .testIfErrorContains(
laurentlb9e540882017-07-07 06:58:45 -04001514 "argument 'items' has type 'int', but should be 'sequence'\n"
1515 + "in call to builtin method list.extend(items)",
Vladimir Moskva71536642016-12-19 13:51:57 +00001516 "[1, 2].extend(3)");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001517 }
1518
1519 @Test
Laurent Le Brun8853df92015-12-16 15:02:03 +00001520 public void testListRemove() throws Exception {
1521 new BothModesTest()
1522 .setUp("foo = ['a', 'b', 'c', 'b']", "foo.remove('b')")
1523 .testLookup("foo", MutableList.of(env, "a", "c", "b"))
1524 .setUp("foo.remove('c')")
1525 .testLookup("foo", MutableList.of(env, "a", "b"))
1526 .setUp("foo.remove('a')")
1527 .testLookup("foo", MutableList.of(env, "b"))
1528 .setUp("foo.remove('b')")
1529 .testLookup("foo", MutableList.of(env))
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001530 .testIfErrorContains("item 3 not found in list", "[1, 2].remove(3)");
Laurent Le Brun8853df92015-12-16 15:02:03 +00001531
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001532 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001533 .testIfErrorContains("type 'tuple' has no method remove(int)", "(1, 2).remove(3)");
Laurent Le Brun8853df92015-12-16 15:02:03 +00001534 }
1535
1536 @Test
Laurent Le Brun3a837472015-12-22 17:58:40 +00001537 public void testListPop() throws Exception {
1538 new BothModesTest()
1539 .setUp("li = [2, 3, 4]; ret = li.pop()")
1540 .testLookup("li", MutableList.of(env, 2, 3))
1541 .testLookup("ret", 4);
1542 new BothModesTest()
1543 .setUp("li = [2, 3, 4]; ret = li.pop(-2)")
1544 .testLookup("li", MutableList.of(env, 2, 4))
1545 .testLookup("ret", 3);
1546 new BothModesTest()
1547 .setUp("li = [2, 3, 4]; ret = li.pop(1)")
1548 .testLookup("li", MutableList.of(env, 2, 4))
1549 .testLookup("ret", 3);
1550 new BothModesTest()
1551 .testIfErrorContains(
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001552 "index out of range (index is 3, but sequence has 2 elements)", "[1, 2].pop(3)");
Laurent Le Brun3a837472015-12-22 17:58:40 +00001553
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001554 new BothModesTest().testIfErrorContains("type 'tuple' has no method pop()", "(1, 2).pop()");
Laurent Le Brun3a837472015-12-22 17:58:40 +00001555 }
1556
1557 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001558 public void testReassignmentOfPrimitivesNotForbiddenByCoreLanguage() throws Exception {
1559 new BuildTest()
1560 .setUp("cc_binary = (['hello.cc'])")
1561 .testIfErrorContains(
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00001562 "'list' object is not callable",
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001563 "cc_binary(name = 'hello', srcs=['hello.cc'], malloc = '//base:system_malloc')");
1564 }
1565
1566 @Test
1567 public void testLenOnString() throws Exception {
1568 new BothModesTest().testStatement("len('abc')", 3);
1569 }
1570
1571 @Test
1572 public void testLenOnList() throws Exception {
1573 new BothModesTest().testStatement("len([1,2,3])", 3);
1574 }
1575
1576 @Test
1577 public void testLenOnDict() throws Exception {
1578 new BothModesTest().testStatement("len({'a' : 1, 'b' : 2})", 2);
1579 }
1580
1581 @Test
1582 public void testLenOnBadType() throws Exception {
1583 new BothModesTest().testIfErrorContains("int is not iterable", "len(1)");
1584 }
1585
1586 @Test
1587 public void testIndexOnFunction() throws Exception {
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001588 new BothModesTest()
Laurent Le Brunc31f3512016-12-29 21:41:33 +00001589 .testIfErrorContains("type 'function' has no operator [](int)", "len[1]")
1590 .testIfErrorContains("type 'function' has no operator [:](int, int, int)", "len[1:4]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001591 }
1592
1593 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001594 public void testBool() throws Exception {
1595 new BothModesTest()
1596 .testStatement("bool(1)", Boolean.TRUE)
1597 .testStatement("bool(0)", Boolean.FALSE)
1598 .testStatement("bool([1, 2])", Boolean.TRUE)
1599 .testStatement("bool([])", Boolean.FALSE)
1600 .testStatement("bool(None)", Boolean.FALSE);
1601 }
1602
1603 @Test
1604 public void testStr() throws Exception {
vladmosaf624112017-08-25 16:41:47 +02001605 new BothModesTest("--incompatible_descriptive_string_representations=true")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001606 .testStatement("str(1)", "1")
1607 .testStatement("str(-2)", "-2")
1608 .testStatement("str([1, 2])", "[1, 2]")
1609 .testStatement("str(True)", "True")
1610 .testStatement("str(False)", "False")
1611 .testStatement("str(None)", "None")
vladmosaf624112017-08-25 16:41:47 +02001612 .testStatement("str(str)", "<built-in function str>");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001613 }
1614
1615 @Test
1616 public void testInt() throws Exception {
1617 new BothModesTest()
1618 .testStatement("int('1')", 1)
1619 .testStatement("int('-1234')", -1234)
Florian Weikertbc1ff692016-07-01 19:11:24 +00001620 .testIfErrorContains("invalid literal for int() with base 10: \"1.5\"", "int('1.5')")
1621 .testIfErrorContains("invalid literal for int() with base 10: \"ab\"", "int('ab')")
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001622 .testStatement("int(42)", 42)
1623 .testStatement("int(-1)", -1)
1624 .testStatement("int(True)", 1)
1625 .testStatement("int(False)", 0)
1626 .testIfErrorContains("None is not of type string or int or bool", "int(None)");
1627 }
1628
1629 @Test
Florian Weikertbc1ff692016-07-01 19:11:24 +00001630 public void testIntWithBase() throws Exception {
1631 new BothModesTest()
1632 .testStatement("int('11', 2)", 3)
1633 .testStatement("int('11', 9)", 10)
1634 .testStatement("int('AF', 16)", 175)
1635 .testStatement("int('11', 36)", 37)
1636 .testStatement("int('az', 36)", 395);
1637 }
1638
1639 @Test
1640 public void testIntWithBase_InvalidBase() throws Exception {
1641 new BothModesTest()
1642 .testIfExactError("invalid literal for int() with base 3: \"123\"", "int('123', 3)")
1643 .testIfExactError("invalid literal for int() with base 15: \"FF\"", "int('FF', 15)")
1644 .testIfExactError("int() base must be >= 2 and <= 36", "int('123', -1)")
1645 .testIfExactError("int() base must be >= 2 and <= 36", "int('123', 1)")
1646 .testIfExactError("int() base must be >= 2 and <= 36", "int('123', 37)");
1647 }
1648
1649 @Test
1650 public void testIntWithBase_Prefix() throws Exception {
1651 new BothModesTest()
1652 .testStatement("int('0b11', 0)", 3)
1653 .testStatement("int('0B11', 2)", 3)
1654 .testStatement("int('0o11', 0)", 9)
1655 .testStatement("int('0O11', 8)", 9)
1656 .testStatement("int('0XFF', 0)", 255)
1657 .testStatement("int('0xFF', 16)", 255)
1658 .testIfExactError("invalid literal for int() with base 8: \"0xFF\"", "int('0xFF', 8)");
1659 }
1660
1661 @Test
1662 public void testIntWithBase_NoString() throws Exception {
1663 new BothModesTest()
1664 .testIfExactError("int() can't convert non-string with explicit base", "int(True, 2)")
1665 .testIfExactError("int() can't convert non-string with explicit base", "int(1, 2)");
1666 }
1667
1668 @Test
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001669 public void testStrFunction() throws Exception {
1670 new SkylarkTest().testStatement("def foo(x): return x\nstr(foo)", "<function foo>");
1671 }
1672
1673 @Test
1674 public void testType() throws Exception {
1675 new SkylarkTest()
1676 .testStatement("type(1)", "int")
1677 .testStatement("type('a')", "string")
1678 .testStatement("type([1, 2])", "list")
1679 .testStatement("type((1, 2))", "tuple")
1680 .testStatement("type(True)", "bool")
1681 .testStatement("type(None)", "NoneType")
1682 .testStatement("type(str)", "function");
1683 }
1684
Jon Brandvein5b792dc2017-01-12 20:22:07 +00001685 // TODO(bazel-team): Move this into a new BazelLibraryTest.java file, or at least out of
1686 // MethodLibraryTest.java.
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001687 @Test
1688 public void testSelectFunction() throws Exception {
1689 enableSkylarkMode();
1690 eval("a = select({'a': 1})");
1691 SelectorList result = (SelectorList) lookup("a");
1692 assertThat(((SelectorValue) Iterables.getOnlyElement(result.getElements())).getDictionary())
lberkiaea56b32017-05-30 12:35:33 +02001693 .containsExactly("a", 1);
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001694 }
1695
1696 @Test
1697 public void testCountFunction() throws Exception {
1698 new BothModesTest()
1699 .testStatement("'abc'.count('')", 4)
1700 .testStatement("'abc'.count('a')", 1)
1701 .testStatement("'abc'.count('b')", 1)
1702 .testStatement("'abc'.count('c')", 1)
1703 .testStatement("'abbc'.count('b')", 2)
1704 .testStatement("'aba'.count('a')", 2)
1705 .testStatement("'aaa'.count('aa')", 1)
1706 .testStatement("'aaaa'.count('aa')", 2)
1707 .testStatement("'abc'.count('a', 0)", 1)
1708 .testStatement("'abc'.count('a', 1)", 0)
1709 .testStatement("'abc'.count('c', 0, 3)", 1)
1710 .testStatement("'abc'.count('c', 0, 2)", 0)
1711 .testStatement("'abc'.count('a', -1)", 0)
1712 .testStatement("'abc'.count('c', -1)", 1)
1713 .testStatement("'abc'.count('c', 0, 5)", 1)
1714 .testStatement("'abc'.count('c', 0, -1)", 0)
1715 .testStatement("'abc'.count('a', 0, -1)", 1);
1716 }
1717
1718 @Test
1719 public void testZipFunction() throws Exception {
1720 new BothModesTest()
1721 .testStatement("str(zip())", "[]")
1722 .testStatement("str(zip([1, 2]))", "[(1,), (2,)]")
1723 .testStatement("str(zip([1, 2], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]")
1724 .testStatement("str(zip([1, 2, 3], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]")
1725 .testStatement("str(zip([1], [2], [3]))", "[(1, 2, 3)]")
1726 .testStatement("str(zip([1], {2: 'a'}))", "[(1, 2)]")
1727 .testStatement("str(zip([1], []))", "[]")
1728 .testIfErrorContains("type 'int' is not iterable", "zip(123)")
Laurent Le Brun88df1f52015-12-23 13:31:44 +00001729 .testIfErrorContains("type 'int' is not iterable", "zip([1], 1)")
Vladimir Moskvad200daf2016-12-23 16:35:37 +00001730 .testStatement("str(zip([1], depset([2])))", "[(1, 2)]");
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001731 }
Googler8e8fa052015-09-03 18:36:33 +00001732
1733 @Test
1734 public void testIsAlphaFunction() throws Exception {
1735 new BothModesTest()
1736 .testStatement("''.isalpha()", false)
1737 .testStatement("'abz'.isalpha()", true)
1738 .testStatement("'a1'.isalpha()", false)
1739 .testStatement("'a '.isalpha()", false)
1740 .testStatement("'A'.isalpha()", true)
1741 .testStatement("'AbZ'.isalpha()", true);
1742 }
Laurent Le Brunad849742015-10-15 11:36:01 +00001743
Jon Brandvein36ecf162017-01-02 18:43:42 +00001744 /**
1745 * Assert that lstrip(), rstrip(), and strip() produce the expected result for a given input
1746 * string and chars argument. If chars is null no argument is passed.
1747 */
1748 private void checkStrip(
1749 String input, Object chars,
1750 String expLeft, String expRight, String expBoth) throws Exception {
1751 if (chars == null) {
1752 new BothModesTest()
1753 .update("s", input)
1754 .testStatement("s.lstrip()", expLeft)
1755 .testStatement("s.rstrip()", expRight)
1756 .testStatement("s.strip()", expBoth);
1757 } else {
1758 new BothModesTest()
1759 .update("s", input)
1760 .update("chars", chars)
1761 .testStatement("s.lstrip(chars)", expLeft)
1762 .testStatement("s.rstrip(chars)", expRight)
1763 .testStatement("s.strip(chars)", expBoth);
1764 }
Laurent Le Brunad849742015-10-15 11:36:01 +00001765 }
1766
1767 @Test
1768 public void testStrip() throws Exception {
Jon Brandvein36ecf162017-01-02 18:43:42 +00001769 // Strip nothing.
1770 checkStrip("a b c", "", "a b c", "a b c", "a b c");
1771 checkStrip(" a b c ", "", " a b c ", " a b c ", " a b c ");
1772 // Normal case, found and not found.
1773 checkStrip("abcba", "ba", "cba", "abc", "c");
1774 checkStrip("abc", "xyz", "abc", "abc", "abc");
1775 // Default whitespace.
1776 checkStrip(" a b c ", null, "a b c ", " a b c", "a b c");
1777 checkStrip(" a b c ", Runtime.NONE, "a b c ", " a b c", "a b c");
1778 // Default whitespace with full range of Latin-1 whitespace chars.
1779 String whitespace = "\u0009\n\u000B\u000C\r\u001C\u001D\u001E\u001F\u0020\u0085\u00A0";
1780 checkStrip(
1781 whitespace + "a" + whitespace, null,
1782 "a" + whitespace, whitespace + "a", "a");
1783 checkStrip(
1784 whitespace + "a" + whitespace, Runtime.NONE,
1785 "a" + whitespace, whitespace + "a", "a");
1786 // Empty cases.
1787 checkStrip("", "", "", "", "");
1788 checkStrip("abc", "abc", "", "", "");
1789 checkStrip("", "xyz", "", "", "");
1790 checkStrip("", null, "", "", "");
Laurent Le Brunad849742015-10-15 11:36:01 +00001791 }
Laurent Le Brunfe206a42016-05-23 17:03:49 +00001792
1793 @Test
1794 public void testFail() throws Exception {
1795 new SkylarkTest()
1796 .testIfErrorContains("abc", "fail('abc')")
1797 .testIfErrorContains("18", "fail(18)");
1798 }
Googlerde689132016-12-12 18:15:52 +00001799
1800 @Test
1801 public void testTupleCoercion() throws Exception {
1802 new BothModesTest()
1803 .testStatement("tuple([1, 2]) == (1, 2)", true)
Vladimir Moskvad200daf2016-12-23 16:35:37 +00001804 .testStatement("tuple(depset([1, 2])) == (1, 2)", true)
Googlerde689132016-12-12 18:15:52 +00001805 // Depends on current implementation of dict
1806 .testStatement("tuple({1: 'foo', 2: 'bar'}) == (1, 2)", true);
1807 }
Francois-Rene Rideaub5c3b3a2015-08-26 13:37:30 +00001808}