Laurent Le Brun | ad84974 | 2015-10-15 11:36:01 +0000 | [diff] [blame] | 1 | // Copyright 2006 The Bazel Authors. All Rights Reserved. |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package com.google.devtools.build.lib.syntax; |
| 16 | |
| 17 | import static com.google.common.truth.Truth.assertThat; |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 18 | |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 19 | import com.google.common.collect.Iterables; |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 20 | import com.google.devtools.build.lib.syntax.util.EvaluationTestCase; |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 21 | import org.junit.Before; |
| 22 | import org.junit.Test; |
| 23 | import org.junit.runner.RunWith; |
| 24 | import org.junit.runners.JUnit4; |
| 25 | |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 26 | /** |
| 27 | * Tests for MethodLibrary. |
| 28 | */ |
| 29 | @RunWith(JUnit4.class) |
| 30 | public class MethodLibraryTest extends EvaluationTestCase { |
| 31 | |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 32 | private static final String LINE_SEPARATOR = System.lineSeparator(); |
| 33 | |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 34 | @Before |
Florian Weikert | b4c5904 | 2015-12-01 10:47:18 +0000 | [diff] [blame] | 35 | public final void setFailFast() throws Exception { |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 36 | setFailFast(true); |
| 37 | } |
| 38 | |
| 39 | @Test |
Florian Weikert | 90a1596 | 2015-09-11 13:43:10 +0000 | [diff] [blame] | 40 | public void testStackTraceLocation() throws Exception { |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 41 | new SkylarkTest() |
| 42 | .testIfErrorContains( |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 43 | "Traceback (most recent call last):" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 44 | + LINE_SEPARATOR |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 45 | + "\tFile \"\", line 8" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 46 | + LINE_SEPARATOR |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 47 | + "\t\tfoo()" |
| 48 | + LINE_SEPARATOR |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 49 | + "\tFile \"\", line 2, in foo" |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 50 | + LINE_SEPARATOR |
| 51 | + "\t\tbar(1)" |
| 52 | + LINE_SEPARATOR |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 53 | + "\tFile \"\", line 7, in bar" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 54 | + LINE_SEPARATOR |
Michajlo Matijkiw | 8c539ea | 2017-02-22 23:02:46 +0000 | [diff] [blame] | 55 | + "\t\t\"test\".index(x)", |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 56 | "def foo():", |
| 57 | " bar(1)", |
| 58 | "def bar(x):", |
| 59 | " if x == 1:", |
| 60 | " a = x", |
| 61 | " b = 2", |
| 62 | " 'test'.index(x)", |
| 63 | "foo()"); |
Florian Weikert | 90a1596 | 2015-09-11 13:43:10 +0000 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | @Test |
| 67 | public void testStackTraceWithIf() throws Exception { |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 68 | new SkylarkTest() |
| 69 | .testIfErrorContains( |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 70 | "File \"\", line 5" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 71 | + LINE_SEPARATOR |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 72 | + "\t\tfoo()" |
| 73 | + LINE_SEPARATOR |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 74 | + "\tFile \"\", line 3, in foo" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 75 | + LINE_SEPARATOR |
| 76 | + "\t\ts[0]", |
| 77 | "def foo():", |
Vladimir Moskva | d200daf | 2016-12-23 16:35:37 +0000 | [diff] [blame] | 78 | " s = depset()", |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 79 | " if s[0] == 1:", |
| 80 | " x = 1", |
| 81 | "foo()"); |
Florian Weikert | 90a1596 | 2015-09-11 13:43:10 +0000 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | @Test |
vladmos | aa12ec3 | 2017-09-25 21:11:31 +0200 | [diff] [blame] | 85 | public void testStackTraceWithAugmentedAssignment() throws Exception { |
| 86 | new SkylarkTest() |
| 87 | .testIfErrorContains( |
| 88 | "File \"\", line 4" |
| 89 | + LINE_SEPARATOR |
| 90 | + "\t\tfoo()" |
| 91 | + LINE_SEPARATOR |
| 92 | + "\tFile \"\", line 3, in foo" |
| 93 | + LINE_SEPARATOR |
| 94 | + "\t\ts += \"2\"" |
| 95 | + LINE_SEPARATOR |
| 96 | + "unsupported operand type(s) for +: 'int' and 'string'", |
| 97 | "def foo():", |
| 98 | " s = 1", |
| 99 | " s += '2'", |
| 100 | "foo()"); |
| 101 | } |
| 102 | |
| 103 | @Test |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 104 | public void testStackTraceSkipBuiltInOnly() throws Exception { |
| 105 | // The error message should not include the stack trace when there is |
| 106 | // only one built-in function. |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 107 | new BothModesTest() |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 108 | .testIfExactError( |
cparsons | 0fcad77 | 2018-04-11 14:24:00 -0700 | [diff] [blame^] | 109 | "expected value of type 'string' for parameter 'sub', " |
| 110 | + "in method call index(int) of 'string'", |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 111 | "'test'.index(1)"); |
| 112 | } |
| 113 | |
| 114 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 115 | public void testStackTrace() throws Exception { |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 116 | // Unlike SkylarintegrationTests#testStackTraceErrorInFunction(), this test |
| 117 | // has neither a BUILD nor a bzl file. |
| 118 | new SkylarkTest() |
| 119 | .testIfExactError( |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 120 | "Traceback (most recent call last):" |
| 121 | + LINE_SEPARATOR |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 122 | + "\tFile \"\", line 6" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 123 | + LINE_SEPARATOR |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 124 | + "\t\tfoo()" |
| 125 | + LINE_SEPARATOR |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 126 | + "\tFile \"\", line 2, in foo" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 127 | + LINE_SEPARATOR |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 128 | + "\t\tbar(1)" |
| 129 | + LINE_SEPARATOR |
Carmi Grushko | 46bf88c | 2017-02-20 22:37:15 +0000 | [diff] [blame] | 130 | + "\tFile \"\", line 5, in bar" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 131 | + LINE_SEPARATOR |
Michajlo Matijkiw | 8c539ea | 2017-02-22 23:02:46 +0000 | [diff] [blame] | 132 | + "\t\t\"test\".index(x)" |
Yun Peng | e7e55bb | 2016-09-09 09:11:42 +0000 | [diff] [blame] | 133 | + LINE_SEPARATOR |
cparsons | 0fcad77 | 2018-04-11 14:24:00 -0700 | [diff] [blame^] | 134 | + "expected value of type 'string' for parameter 'sub', " |
| 135 | + "in method call index(int) of 'string'", |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 136 | "def foo():", |
Florian Weikert | 90a1596 | 2015-09-11 13:43:10 +0000 | [diff] [blame] | 137 | " bar(1)", |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 138 | "def bar(x):", |
Florian Weikert | 90a1596 | 2015-09-11 13:43:10 +0000 | [diff] [blame] | 139 | " if 1 == 1:", |
| 140 | " 'test'.index(x)", |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 141 | "foo()"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | @Test |
| 145 | public void testBuiltinFunctionErrorMessage() throws Exception { |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 146 | new BothModesTest() |
laurentlb | 9e54088 | 2017-07-07 06:58:45 -0400 | [diff] [blame] | 147 | .testIfErrorContains("substring \"z\" not found in \"abc\"", "'abc'.index('z')") |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 148 | .testIfErrorContains( |
cparsons | 0fcad77 | 2018-04-11 14:24:00 -0700 | [diff] [blame^] | 149 | "expected value of type 'string' for parameter 'sub', " |
| 150 | + "in method call startswith(int) of 'string'", |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 151 | "'test'.startswith(1)") |
| 152 | .testIfErrorContains( |
Florian Weikert | 1c07e32 | 2015-09-25 11:59:40 +0000 | [diff] [blame] | 153 | "expected value of type 'list(object)' for parameter args in dict(), " |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 154 | + "but got \"a\" (string)", |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 155 | "dict('a')"); |
| 156 | } |
| 157 | |
| 158 | @Test |
| 159 | public void testHasAttr() throws Exception { |
| 160 | new SkylarkTest() |
Vladimir Moskva | d200daf | 2016-12-23 16:35:37 +0000 | [diff] [blame] | 161 | .testStatement("hasattr(depset(), 'union')", Boolean.TRUE) |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 162 | .testStatement("hasattr('test', 'count')", Boolean.TRUE) |
| 163 | .testStatement("hasattr(dict(a = 1, b = 2), 'items')", Boolean.TRUE) |
| 164 | .testStatement("hasattr({}, 'items')", Boolean.TRUE); |
| 165 | } |
| 166 | |
| 167 | @Test |
Florian Weikert | e5e3e91 | 2016-03-08 03:08:26 +0000 | [diff] [blame] | 168 | public void testGetAttrMissingField() throws Exception { |
| 169 | new SkylarkTest() |
| 170 | .testIfExactError( |
Laurent Le Brun | c31f351 | 2016-12-29 21:41:33 +0000 | [diff] [blame] | 171 | "object of type 'string' has no attribute \"not_there\"", |
Florian Weikert | e5e3e91 | 2016-03-08 03:08:26 +0000 | [diff] [blame] | 172 | "getattr('a string', 'not_there')") |
Jon Brandvein | ad81cff | 2016-07-26 13:04:10 +0000 | [diff] [blame] | 173 | .testStatement("getattr('a string', 'not_there', 'use this')", "use this") |
| 174 | .testStatement("getattr('a string', 'not there', None)", Runtime.NONE); |
Florian Weikert | e5e3e91 | 2016-03-08 03:08:26 +0000 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | @Test |
| 178 | public void testGetAttrWithMethods() throws Exception { |
| 179 | String msg = |
Laurent Le Brun | c31f351 | 2016-12-29 21:41:33 +0000 | [diff] [blame] | 180 | "object of type 'string' has no attribute \"count\", however, " |
Florian Weikert | e5e3e91 | 2016-03-08 03:08:26 +0000 | [diff] [blame] | 181 | + "a method of that name exists"; |
| 182 | new SkylarkTest() |
| 183 | .testIfExactError(msg, "getattr('a string', 'count')") |
Jon Brandvein | 29bb662 | 2016-10-27 13:55:43 +0000 | [diff] [blame] | 184 | .testStatement("getattr('a string', 'count', 'default')", "default"); |
Florian Weikert | e5e3e91 | 2016-03-08 03:08:26 +0000 | [diff] [blame] | 185 | } |
| 186 | |
| 187 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 188 | public void testDir() throws Exception { |
Laurent Le Brun | b525bee | 2016-03-07 17:14:10 +0000 | [diff] [blame] | 189 | new SkylarkTest() |
| 190 | .testStatement( |
| 191 | "str(dir({}))", |
Vladimir Moskva | 8d610c6 | 2016-09-15 14:36:41 +0000 | [diff] [blame] | 192 | "[\"clear\", \"get\", \"items\", \"keys\"," |
Laurent Le Brun | b525bee | 2016-03-07 17:14:10 +0000 | [diff] [blame] | 193 | + " \"pop\", \"popitem\", \"setdefault\", \"update\", \"values\"]"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 194 | } |
| 195 | |
| 196 | @Test |
| 197 | public void testBoolean() throws Exception { |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 198 | new BothModesTest().testStatement("False", Boolean.FALSE).testStatement("True", Boolean.TRUE); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 199 | } |
| 200 | |
| 201 | @Test |
| 202 | public void testBooleanUnsupportedOperationFails() throws Exception { |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 203 | new BothModesTest() |
| 204 | .testIfErrorContains("unsupported operand type(s) for +: 'bool' and 'bool'", "True + True"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 208 | public void testListSort() throws Exception { |
| 209 | new BothModesTest() |
| 210 | .testEval("sorted([0,1,2,3])", "[0, 1, 2, 3]") |
| 211 | .testEval("sorted([])", "[]") |
| 212 | .testEval("sorted([3, 2, 1, 0])", "[0, 1, 2, 3]") |
| 213 | .testEval("sorted([[1], [], [2], [1, 2]])", "[[], [1], [1, 2], [2]]") |
| 214 | .testEval("sorted([True, False, True])", "[False, True, True]") |
| 215 | .testEval("sorted(['a','x','b','z'])", "[\"a\", \"b\", \"x\", \"z\"]") |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 216 | .testEval("sorted({1: True, 5: True, 4: False})", "[1, 4, 5]") |
Vladimir Moskva | 7f0cd62 | 2017-02-16 13:48:37 +0000 | [diff] [blame] | 217 | .testEval("sorted(depset([1, 5, 4]))", "[1, 4, 5]") |
| 218 | .testIfExactError("Cannot compare function with function", "sorted([sorted, sorted])"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 219 | } |
| 220 | |
| 221 | @Test |
Florian Weikert | 1c07e32 | 2015-09-25 11:59:40 +0000 | [diff] [blame] | 222 | public void testDictionaryCopy() throws Exception { |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 223 | new BothModesTest() |
Florian Weikert | 1c07e32 | 2015-09-25 11:59:40 +0000 | [diff] [blame] | 224 | .setUp("x = {1 : 2}", "y = dict(x)") |
| 225 | .testEval("x[1] == 2 and y[1] == 2", "True"); |
| 226 | } |
| 227 | |
| 228 | @Test |
| 229 | public void testDictionaryCopyKeyCollision() throws Exception { |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 230 | new BothModesTest() |
Florian Weikert | 1c07e32 | 2015-09-25 11:59:40 +0000 | [diff] [blame] | 231 | .setUp("x = {'test' : 2}", "y = dict(x, test = 3)") |
| 232 | .testEval("y['test']", "3"); |
| 233 | } |
| 234 | |
| 235 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 236 | public void testDictionaryKeyNotFound() throws Exception { |
| 237 | new BothModesTest() |
Laurent Le Brun | c31f351 | 2016-12-29 21:41:33 +0000 | [diff] [blame] | 238 | .testIfErrorContains("key \"0\" not found in dictionary", "{}['0']") |
| 239 | .testIfErrorContains("key 0 not found in dictionary", "{'0': 1, 2: 3, 4: 5}[0]"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 243 | public void testDictionaryAccess() throws Exception { |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 244 | new BothModesTest() |
| 245 | .testEval("{1: ['foo']}[1]", "['foo']") |
| 246 | .testStatement("{'4': 8}['4']", 8) |
| 247 | .testStatement("{'a': 'aa', 'b': 'bb', 'c': 'cc'}['b']", "bb"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 248 | } |
| 249 | |
| 250 | @Test |
| 251 | public void testDictionaryVariableAccess() throws Exception { |
| 252 | new BothModesTest().setUp("d = {'a' : 1}", "a = d['a']\n").testLookup("a", 1); |
| 253 | } |
| 254 | |
| 255 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 256 | public void testDictionaryCreation() throws Exception { |
| 257 | String expected = "{'a': 1, 'b': 2, 'c': 3}"; |
| 258 | |
| 259 | new BothModesTest() |
| 260 | .testEval("dict([('a', 1), ('b', 2), ('c', 3)])", expected) |
| 261 | .testEval("dict(a = 1, b = 2, c = 3)", expected) |
| 262 | .testEval("dict([('a', 1)], b = 2, c = 3)", expected); |
| 263 | } |
| 264 | |
| 265 | @Test |
| 266 | public void testDictionaryCreationInnerLists() throws Exception { |
| 267 | new BothModesTest().testEval("dict([[1, 2], [3, 4]], a = 5)", "{1: 2, 3: 4, 'a': 5}"); |
| 268 | } |
| 269 | |
| 270 | @Test |
| 271 | public void testDictionaryCreationEmpty() throws Exception { |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 272 | new BothModesTest().testEval("dict()", "{}").testEval("dict([])", "{}"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | @Test |
| 276 | public void testDictionaryCreationDifferentKeyTypes() throws Exception { |
| 277 | String expected = "{'a': 1, 2: 3}"; |
| 278 | |
| 279 | new BothModesTest() |
| 280 | .testEval("dict([('a', 1), (2, 3)])", expected) |
| 281 | .testEval("dict([(2, 3)], a = 1)", expected); |
| 282 | } |
| 283 | |
| 284 | @Test |
| 285 | public void testDictionaryCreationKeyCollision() throws Exception { |
| 286 | String expected = "{'a': 1, 'b': 2, 'c': 3}"; |
| 287 | |
| 288 | new BothModesTest() |
| 289 | .testEval("dict([('a', 42), ('b', 2), ('a', 1), ('c', 3)])", expected) |
| 290 | .testEval("dict([('a', 42)], a = 1, b = 2, c = 3)", expected); |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 291 | new SkylarkTest().testEval("dict([('a', 42)], **{'a': 1, 'b': 2, 'c': 3})", expected); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | @Test |
| 295 | public void testDictionaryCreationInvalidPositional() throws Exception { |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 296 | new BothModesTest() |
| 297 | .testIfErrorContains( |
Florian Weikert | 1c07e32 | 2015-09-25 11:59:40 +0000 | [diff] [blame] | 298 | "expected value of type 'list(object)' for parameter args in dict(), " |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 299 | + "but got \"a\" (string)", |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 300 | "dict('a')") |
Laurent Le Brun | c31f351 | 2016-12-29 21:41:33 +0000 | [diff] [blame] | 301 | .testIfErrorContains("cannot convert item #0 to a sequence", "dict(['a'])") |
| 302 | .testIfErrorContains("cannot convert item #0 to a sequence", "dict([('a')])") |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 303 | .testIfErrorContains("too many (3) positional arguments", "dict((3,4), (3,2), (1,2))") |
| 304 | .testIfErrorContains( |
Laurent Le Brun | c31f351 | 2016-12-29 21:41:33 +0000 | [diff] [blame] | 305 | "item #0 has length 3, but exactly two elements are required", |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 306 | "dict([('a', 'b', 'c')])"); |
| 307 | } |
| 308 | |
| 309 | @Test |
| 310 | public void testDictionaryValues() throws Exception { |
| 311 | new BothModesTest() |
| 312 | .testEval("{1: 'foo'}.values()", "['foo']") |
| 313 | .testEval("{}.values()", "[]") |
Vladimir Moskva | 76e31d1 | 2016-12-05 16:28:37 +0000 | [diff] [blame] | 314 | .testEval("{True: 3, False: 5}.values()", "[3, 5]") |
| 315 | .testEval("{'a': 5, 'c': 2, 'b': 4, 'd': 3}.values()", "[5, 2, 4, 3]"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 316 | // sorted by keys |
| 317 | } |
| 318 | |
| 319 | @Test |
| 320 | public void testDictionaryKeys() throws Exception { |
| 321 | new BothModesTest() |
| 322 | .testEval("{1: 'foo'}.keys()", "[1]") |
| 323 | .testEval("{}.keys()", "[]") |
Vladimir Moskva | 76e31d1 | 2016-12-05 16:28:37 +0000 | [diff] [blame] | 324 | .testEval("{True: 3, False: 5}.keys()", "[True, False]") |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 325 | .testEval( |
Vladimir Moskva | 76e31d1 | 2016-12-05 16:28:37 +0000 | [diff] [blame] | 326 | "{1:'a', 2:'b', 6:'c', 0:'d', 5:'e', 4:'f', 3:'g'}.keys()", "[1, 2, 6, 0, 5, 4, 3]"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 327 | } |
| 328 | |
| 329 | @Test |
| 330 | public void testDictionaryGet() throws Exception { |
| 331 | new BuildTest() |
| 332 | .testStatement("{1: 'foo'}.get(1)", "foo") |
Francois-Rene Rideau | 0f7ba34 | 2015-08-31 16:16:21 +0000 | [diff] [blame] | 333 | .testStatement("{1: 'foo'}.get(2)", Runtime.NONE) |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 334 | .testStatement("{1: 'foo'}.get(2, 'a')", "a") |
| 335 | .testStatement("{1: 'foo'}.get(2, default='a')", "a") |
Francois-Rene Rideau | 0f7ba34 | 2015-08-31 16:16:21 +0000 | [diff] [blame] | 336 | .testStatement("{1: 'foo'}.get(2, default=None)", Runtime.NONE); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 337 | } |
| 338 | |
| 339 | @Test |
| 340 | public void testDictionaryItems() throws Exception { |
| 341 | new BothModesTest() |
| 342 | .testEval("{'a': 'foo'}.items()", "[('a', 'foo')]") |
| 343 | .testEval("{}.items()", "[]") |
| 344 | .testEval("{1: 3, 2: 5}.items()", "[(1, 3), (2, 5)]") |
Vladimir Moskva | 76e31d1 | 2016-12-05 16:28:37 +0000 | [diff] [blame] | 345 | .testEval("{'a': 5, 'c': 2, 'b': 4}.items()", "[('a', 5), ('c', 2), ('b', 4)]"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 346 | } |
| 347 | |
| 348 | @Test |
Francois-Rene Rideau | 432d715 | 2016-02-18 16:33:03 +0000 | [diff] [blame] | 349 | public void testDictionaryClear() throws Exception { |
| 350 | new SkylarkTest() |
| 351 | .testEval( |
| 352 | "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n" |
laurentlb | 8515118 | 2017-08-16 20:24:04 +0200 | [diff] [blame] | 353 | + "len(d) == 3 or fail('clear 1')\n" |
| 354 | + "d.clear() == None or fail('clear 2')\n" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 355 | + "d", |
Francois-Rene Rideau | 432d715 | 2016-02-18 16:33:03 +0000 | [diff] [blame] | 356 | "{}"); |
| 357 | } |
| 358 | |
| 359 | @Test |
| 360 | public void testDictionaryPop() throws Exception { |
| 361 | new SkylarkTest() |
| 362 | .testIfErrorContains( |
| 363 | "KeyError: 1", |
| 364 | "d = {1: 'foo', 2: 'bar', 3: 'baz'}\n" |
laurentlb | 8515118 | 2017-08-16 20:24:04 +0200 | [diff] [blame] | 365 | + "len(d) == 3 or fail('pop 1')\n" |
| 366 | + "d.pop(2) == 'bar' or fail('pop 2')\n" |
| 367 | + "d.pop(3, 'quux') == 'baz' or fail('pop 3a')\n" |
| 368 | + "d.pop(3, 'quux') == 'quux' or fail('pop 3b')\n" |
| 369 | + "d.pop(1) == 'foo' or fail('pop 1')\n" |
| 370 | + "d == {} or fail('pop 0')\n" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 371 | + "d.pop(1)"); |
Francois-Rene Rideau | 432d715 | 2016-02-18 16:33:03 +0000 | [diff] [blame] | 372 | } |
| 373 | |
| 374 | @Test |
| 375 | public void testDictionaryPopItem() throws Exception { |
| 376 | new SkylarkTest() |
| 377 | .testIfErrorContains( |
| 378 | "popitem(): dictionary is empty", |
| 379 | "d = {2: 'bar', 3: 'baz', 1: 'foo'}\n" |
laurentlb | 8515118 | 2017-08-16 20:24:04 +0200 | [diff] [blame] | 380 | + "len(d) == 3 or fail('popitem 0')\n" |
| 381 | + "d.popitem() == (2, 'bar') or fail('popitem 2')\n" |
| 382 | + "d.popitem() == (3, 'baz') or fail('popitem 3')\n" |
| 383 | + "d.popitem() == (1, 'foo') or fail('popitem 1')\n" |
| 384 | + "d == {} or fail('popitem 4')\n" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 385 | + "d.popitem()"); |
Francois-Rene Rideau | 432d715 | 2016-02-18 16:33:03 +0000 | [diff] [blame] | 386 | } |
| 387 | |
| 388 | @Test |
Laurent Le Brun | b525bee | 2016-03-07 17:14:10 +0000 | [diff] [blame] | 389 | public void testDictionaryUpdate() throws Exception { |
| 390 | new BothModesTest() |
| 391 | .setUp("foo = {'a': 2}") |
| 392 | .testEval("foo.update({'b': 4}); foo", "{'a': 2, 'b': 4}"); |
| 393 | new BothModesTest() |
| 394 | .setUp("foo = {'a': 2}") |
| 395 | .testEval("foo.update({'a': 3, 'b': 4}); foo", "{'a': 3, 'b': 4}"); |
| 396 | } |
| 397 | |
| 398 | @Test |
Francois-Rene Rideau | 432d715 | 2016-02-18 16:33:03 +0000 | [diff] [blame] | 399 | public void testDictionarySetDefault() throws Exception { |
| 400 | new SkylarkTest() |
| 401 | .testEval( |
| 402 | "d = {2: 'bar', 1: 'foo'}\n" |
laurentlb | 8515118 | 2017-08-16 20:24:04 +0200 | [diff] [blame] | 403 | + "len(d) == 2 or fail('setdefault 0')\n" |
| 404 | + "d.setdefault(1, 'a') == 'foo' or fail('setdefault 1')\n" |
| 405 | + "d.setdefault(2) == 'bar' or fail('setdefault 2')\n" |
| 406 | + "d.setdefault(3) == None or fail('setdefault 3')\n" |
| 407 | + "d.setdefault(4, 'b') == 'b' or fail('setdefault 4')\n" |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 408 | + "d", |
Francois-Rene Rideau | 432d715 | 2016-02-18 16:33:03 +0000 | [diff] [blame] | 409 | "{1: 'foo', 2: 'bar', 3: None, 4: 'b'}"); |
| 410 | } |
| 411 | |
| 412 | @Test |
Laurent Le Brun | 3ef1eea | 2015-11-09 14:35:54 +0000 | [diff] [blame] | 413 | public void testListIndexMethod() throws Exception { |
| 414 | new BothModesTest() |
| 415 | .testStatement("['a', 'b', 'c'].index('a')", 0) |
| 416 | .testStatement("['a', 'b', 'c'].index('b')", 1) |
| 417 | .testStatement("['a', 'b', 'c'].index('c')", 2) |
| 418 | .testStatement("[2, 4, 6].index(4)", 1) |
| 419 | .testStatement("[2, 4, 6].index(4)", 1) |
| 420 | .testStatement("[0, 1, [1]].index([1])", 2) |
Laurent Le Brun | c31f351 | 2016-12-29 21:41:33 +0000 | [diff] [blame] | 421 | .testIfErrorContains("item \"a\" not found in list", "[1, 2].index('a')") |
| 422 | .testIfErrorContains("item 0 not found in list", "[].index(0)"); |
Laurent Le Brun | 3ef1eea | 2015-11-09 14:35:54 +0000 | [diff] [blame] | 423 | } |
| 424 | |
| 425 | @Test |
Jon Brandvein | 9c4629d | 2016-07-20 20:16:33 +0000 | [diff] [blame] | 426 | public void testHash() throws Exception { |
Jon Brandvein | 3bdb4c3 | 2016-07-21 16:41:01 +0000 | [diff] [blame] | 427 | // We specify the same string hashing algorithm as String.hashCode(). |
Jon Brandvein | 9c4629d | 2016-07-20 20:16:33 +0000 | [diff] [blame] | 428 | new SkylarkTest() |
| 429 | .testStatement("hash('skylark')", "skylark".hashCode()) |
| 430 | .testStatement("hash('google')", "google".hashCode()) |
| 431 | .testIfErrorContains( |
laurentlb | 9e54088 | 2017-07-07 06:58:45 -0400 | [diff] [blame] | 432 | "argument 'value' has type 'NoneType', but should be 'string'\n" |
| 433 | + "in call to builtin function hash(value)", |
Jon Brandvein | 9c4629d | 2016-07-20 20:16:33 +0000 | [diff] [blame] | 434 | "hash(None)"); |
| 435 | } |
| 436 | |
| 437 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 438 | public void testRange() throws Exception { |
| 439 | new BothModesTest() |
| 440 | .testStatement("str(range(5))", "[0, 1, 2, 3, 4]") |
| 441 | .testStatement("str(range(0))", "[]") |
| 442 | .testStatement("str(range(1))", "[0]") |
| 443 | .testStatement("str(range(-2))", "[]") |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 444 | .testStatement("str(range(-3, 2))", "[-3, -2, -1, 0, 1]") |
| 445 | .testStatement("str(range(3, 2))", "[]") |
| 446 | .testStatement("str(range(3, 3))", "[]") |
| 447 | .testStatement("str(range(3, 4))", "[3]") |
| 448 | .testStatement("str(range(3, 5))", "[3, 4]") |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 449 | .testStatement("str(range(-3, 5, 2))", "[-3, -1, 1, 3]") |
| 450 | .testStatement("str(range(-3, 6, 2))", "[-3, -1, 1, 3, 5]") |
| 451 | .testStatement("str(range(5, 0, -1))", "[5, 4, 3, 2, 1]") |
| 452 | .testStatement("str(range(5, 0, -10))", "[5]") |
| 453 | .testStatement("str(range(0, -3, -2))", "[0, -2]") |
| 454 | .testIfErrorContains("step cannot be 0", "range(2, 3, 0)"); |
| 455 | } |
| 456 | |
| 457 | @Test |
| 458 | public void testEnumerate() throws Exception { |
| 459 | new BothModesTest() |
| 460 | .testStatement("str(enumerate([]))", "[]") |
| 461 | .testStatement("str(enumerate([5]))", "[(0, 5)]") |
| 462 | .testStatement("str(enumerate([5, 3]))", "[(0, 5), (1, 3)]") |
| 463 | .testStatement("str(enumerate(['a', 'b', 'c']))", "[(0, \"a\"), (1, \"b\"), (2, \"c\")]") |
| 464 | .testStatement("str(enumerate(['a']) + [(1, 'b')])", "[(0, \"a\"), (1, \"b\")]"); |
| 465 | } |
| 466 | |
| 467 | @Test |
| 468 | public void testEnumerateBadArg() throws Exception { |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 469 | new BothModesTest() |
| 470 | .testIfErrorContains( |
laurentlb | 9e54088 | 2017-07-07 06:58:45 -0400 | [diff] [blame] | 471 | "argument 'list' has type 'string', but should be 'sequence'\n" |
| 472 | + "in call to builtin function enumerate(list)", |
Yun Peng | fc61005 | 2016-06-20 11:44:06 +0000 | [diff] [blame] | 473 | "enumerate('a')"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 474 | } |
| 475 | |
| 476 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 477 | public void testReassignmentOfPrimitivesNotForbiddenByCoreLanguage() throws Exception { |
| 478 | new BuildTest() |
| 479 | .setUp("cc_binary = (['hello.cc'])") |
| 480 | .testIfErrorContains( |
Francois-Rene Rideau | 93ed7f1 | 2015-10-20 15:39:33 +0000 | [diff] [blame] | 481 | "'list' object is not callable", |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 482 | "cc_binary(name = 'hello', srcs=['hello.cc'], malloc = '//base:system_malloc')"); |
| 483 | } |
| 484 | |
| 485 | @Test |
| 486 | public void testLenOnString() throws Exception { |
| 487 | new BothModesTest().testStatement("len('abc')", 3); |
| 488 | } |
| 489 | |
| 490 | @Test |
| 491 | public void testLenOnList() throws Exception { |
| 492 | new BothModesTest().testStatement("len([1,2,3])", 3); |
| 493 | } |
| 494 | |
| 495 | @Test |
| 496 | public void testLenOnDict() throws Exception { |
| 497 | new BothModesTest().testStatement("len({'a' : 1, 'b' : 2})", 2); |
| 498 | } |
| 499 | |
| 500 | @Test |
| 501 | public void testLenOnBadType() throws Exception { |
| 502 | new BothModesTest().testIfErrorContains("int is not iterable", "len(1)"); |
| 503 | } |
| 504 | |
| 505 | @Test |
| 506 | public void testIndexOnFunction() throws Exception { |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 507 | new BothModesTest() |
Laurent Le Brun | c31f351 | 2016-12-29 21:41:33 +0000 | [diff] [blame] | 508 | .testIfErrorContains("type 'function' has no operator [](int)", "len[1]") |
laurentlb | 9b96c0b | 2018-02-12 02:53:19 -0800 | [diff] [blame] | 509 | .testIfErrorContains("type 'function' has no operator [:](int, int, NoneType)", "len[1:4]"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 510 | } |
| 511 | |
| 512 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 513 | public void testBool() throws Exception { |
| 514 | new BothModesTest() |
| 515 | .testStatement("bool(1)", Boolean.TRUE) |
| 516 | .testStatement("bool(0)", Boolean.FALSE) |
| 517 | .testStatement("bool([1, 2])", Boolean.TRUE) |
| 518 | .testStatement("bool([])", Boolean.FALSE) |
| 519 | .testStatement("bool(None)", Boolean.FALSE); |
| 520 | } |
| 521 | |
| 522 | @Test |
| 523 | public void testStr() throws Exception { |
vladmos | cd6d8ae | 2017-10-12 15:35:17 +0200 | [diff] [blame] | 524 | new BothModesTest() |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 525 | .testStatement("str(1)", "1") |
| 526 | .testStatement("str(-2)", "-2") |
| 527 | .testStatement("str([1, 2])", "[1, 2]") |
| 528 | .testStatement("str(True)", "True") |
| 529 | .testStatement("str(False)", "False") |
| 530 | .testStatement("str(None)", "None") |
vladmos | af62411 | 2017-08-25 16:41:47 +0200 | [diff] [blame] | 531 | .testStatement("str(str)", "<built-in function str>"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 532 | } |
| 533 | |
| 534 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 535 | public void testStrFunction() throws Exception { |
| 536 | new SkylarkTest().testStatement("def foo(x): return x\nstr(foo)", "<function foo>"); |
| 537 | } |
| 538 | |
| 539 | @Test |
| 540 | public void testType() throws Exception { |
| 541 | new SkylarkTest() |
| 542 | .testStatement("type(1)", "int") |
| 543 | .testStatement("type('a')", "string") |
| 544 | .testStatement("type([1, 2])", "list") |
| 545 | .testStatement("type((1, 2))", "tuple") |
| 546 | .testStatement("type(True)", "bool") |
| 547 | .testStatement("type(None)", "NoneType") |
| 548 | .testStatement("type(str)", "function"); |
| 549 | } |
| 550 | |
Jon Brandvein | 5b792dc | 2017-01-12 20:22:07 +0000 | [diff] [blame] | 551 | // TODO(bazel-team): Move this into a new BazelLibraryTest.java file, or at least out of |
| 552 | // MethodLibraryTest.java. |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 553 | @Test |
| 554 | public void testSelectFunction() throws Exception { |
| 555 | enableSkylarkMode(); |
| 556 | eval("a = select({'a': 1})"); |
| 557 | SelectorList result = (SelectorList) lookup("a"); |
| 558 | assertThat(((SelectorValue) Iterables.getOnlyElement(result.getElements())).getDictionary()) |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 559 | .containsExactly("a", 1); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 560 | } |
| 561 | |
| 562 | @Test |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 563 | public void testZipFunction() throws Exception { |
| 564 | new BothModesTest() |
| 565 | .testStatement("str(zip())", "[]") |
| 566 | .testStatement("str(zip([1, 2]))", "[(1,), (2,)]") |
| 567 | .testStatement("str(zip([1, 2], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]") |
| 568 | .testStatement("str(zip([1, 2, 3], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]") |
| 569 | .testStatement("str(zip([1], [2], [3]))", "[(1, 2, 3)]") |
| 570 | .testStatement("str(zip([1], {2: 'a'}))", "[(1, 2)]") |
| 571 | .testStatement("str(zip([1], []))", "[]") |
| 572 | .testIfErrorContains("type 'int' is not iterable", "zip(123)") |
Laurent Le Brun | 88df1f5 | 2015-12-23 13:31:44 +0000 | [diff] [blame] | 573 | .testIfErrorContains("type 'int' is not iterable", "zip([1], 1)") |
Vladimir Moskva | d200daf | 2016-12-23 16:35:37 +0000 | [diff] [blame] | 574 | .testStatement("str(zip([1], depset([2])))", "[(1, 2)]"); |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 575 | } |
Googler | 8e8fa05 | 2015-09-03 18:36:33 +0000 | [diff] [blame] | 576 | |
Jon Brandvein | 36ecf16 | 2017-01-02 18:43:42 +0000 | [diff] [blame] | 577 | /** |
| 578 | * Assert that lstrip(), rstrip(), and strip() produce the expected result for a given input |
| 579 | * string and chars argument. If chars is null no argument is passed. |
| 580 | */ |
| 581 | private void checkStrip( |
| 582 | String input, Object chars, |
| 583 | String expLeft, String expRight, String expBoth) throws Exception { |
| 584 | if (chars == null) { |
| 585 | new BothModesTest() |
| 586 | .update("s", input) |
| 587 | .testStatement("s.lstrip()", expLeft) |
| 588 | .testStatement("s.rstrip()", expRight) |
| 589 | .testStatement("s.strip()", expBoth); |
| 590 | } else { |
| 591 | new BothModesTest() |
| 592 | .update("s", input) |
| 593 | .update("chars", chars) |
| 594 | .testStatement("s.lstrip(chars)", expLeft) |
| 595 | .testStatement("s.rstrip(chars)", expRight) |
| 596 | .testStatement("s.strip(chars)", expBoth); |
| 597 | } |
Laurent Le Brun | ad84974 | 2015-10-15 11:36:01 +0000 | [diff] [blame] | 598 | } |
| 599 | |
| 600 | @Test |
| 601 | public void testStrip() throws Exception { |
Jon Brandvein | 36ecf16 | 2017-01-02 18:43:42 +0000 | [diff] [blame] | 602 | // Strip nothing. |
| 603 | checkStrip("a b c", "", "a b c", "a b c", "a b c"); |
| 604 | checkStrip(" a b c ", "", " a b c ", " a b c ", " a b c "); |
| 605 | // Normal case, found and not found. |
| 606 | checkStrip("abcba", "ba", "cba", "abc", "c"); |
| 607 | checkStrip("abc", "xyz", "abc", "abc", "abc"); |
| 608 | // Default whitespace. |
| 609 | checkStrip(" a b c ", null, "a b c ", " a b c", "a b c"); |
| 610 | checkStrip(" a b c ", Runtime.NONE, "a b c ", " a b c", "a b c"); |
| 611 | // Default whitespace with full range of Latin-1 whitespace chars. |
| 612 | String whitespace = "\u0009\n\u000B\u000C\r\u001C\u001D\u001E\u001F\u0020\u0085\u00A0"; |
| 613 | checkStrip( |
| 614 | whitespace + "a" + whitespace, null, |
| 615 | "a" + whitespace, whitespace + "a", "a"); |
| 616 | checkStrip( |
| 617 | whitespace + "a" + whitespace, Runtime.NONE, |
| 618 | "a" + whitespace, whitespace + "a", "a"); |
| 619 | // Empty cases. |
| 620 | checkStrip("", "", "", "", ""); |
| 621 | checkStrip("abc", "abc", "", "", ""); |
| 622 | checkStrip("", "xyz", "", "", ""); |
| 623 | checkStrip("", null, "", "", ""); |
Laurent Le Brun | ad84974 | 2015-10-15 11:36:01 +0000 | [diff] [blame] | 624 | } |
Laurent Le Brun | fe206a4 | 2016-05-23 17:03:49 +0000 | [diff] [blame] | 625 | |
| 626 | @Test |
| 627 | public void testFail() throws Exception { |
| 628 | new SkylarkTest() |
| 629 | .testIfErrorContains("abc", "fail('abc')") |
| 630 | .testIfErrorContains("18", "fail(18)"); |
| 631 | } |
Googler | de68913 | 2016-12-12 18:15:52 +0000 | [diff] [blame] | 632 | |
| 633 | @Test |
| 634 | public void testTupleCoercion() throws Exception { |
| 635 | new BothModesTest() |
| 636 | .testStatement("tuple([1, 2]) == (1, 2)", true) |
Vladimir Moskva | d200daf | 2016-12-23 16:35:37 +0000 | [diff] [blame] | 637 | .testStatement("tuple(depset([1, 2])) == (1, 2)", true) |
Googler | de68913 | 2016-12-12 18:15:52 +0000 | [diff] [blame] | 638 | // Depends on current implementation of dict |
| 639 | .testStatement("tuple({1: 'foo', 2: 'bar'}) == (1, 2)", true); |
| 640 | } |
Francois-Rene Rideau | b5c3b3a | 2015-08-26 13:37:30 +0000 | [diff] [blame] | 641 | } |