Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 1 | // Copyright 2015 Google Inc. All rights reserved. |
| 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 | package com.google.devtools.build.lib.syntax; |
| 15 | |
| 16 | import static com.google.common.truth.Truth.assertThat; |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 17 | import static org.junit.Assert.assertEquals; |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 18 | import static org.junit.Assert.assertTrue; |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 19 | |
| 20 | import com.google.common.collect.ImmutableCollection; |
| 21 | import com.google.common.collect.ImmutableList; |
| 22 | import com.google.common.collect.ImmutableMap; |
| 23 | import com.google.common.collect.ImmutableSet; |
| 24 | import com.google.devtools.build.lib.actions.Artifact; |
| 25 | import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact; |
| 26 | import com.google.devtools.build.lib.analysis.FileConfiguredTarget; |
| 27 | import com.google.devtools.build.lib.analysis.RuleConfiguredTarget; |
| 28 | import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; |
| 29 | import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 30 | import com.google.devtools.build.lib.syntax.ClassObject.SkylarkClassObject; |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 31 | import com.google.devtools.build.lib.testutil.TestMode; |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 32 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 33 | import org.junit.Test; |
| 34 | import org.junit.runner.RunWith; |
| 35 | import org.junit.runners.JUnit4; |
| 36 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 37 | /** |
| 38 | * Evaluation tests with Skylark Environment. |
| 39 | */ |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 40 | @RunWith(JUnit4.class) |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 41 | public class SkylarkEvaluationTest extends EvaluationTest { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 42 | public SkylarkEvaluationTest() throws Exception { |
| 43 | setMode(TestMode.SKYLARK); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 44 | } |
| 45 | |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 46 | /** |
| 47 | * Creates an instance of {@code SkylarkTest} in order to run the tests from the base class in a |
| 48 | * Skylark context |
| 49 | */ |
| 50 | @Override |
| 51 | protected ModalTestCase newTest() { |
| 52 | return new SkylarkTest(); |
| 53 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 54 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 55 | @SkylarkModule(name = "Mock", doc = "") |
| 56 | static class Mock { |
| 57 | @SkylarkCallable(doc = "") |
| 58 | public static Integer valueOf(String str) { |
| 59 | return Integer.valueOf(str); |
| 60 | } |
| 61 | @SkylarkCallable(doc = "") |
| 62 | public Boolean isEmpty(String str) { |
| 63 | return str.isEmpty(); |
| 64 | } |
| 65 | public void value() {} |
| 66 | @SkylarkCallable(doc = "") |
| 67 | public Mock returnMutable() { |
| 68 | return new Mock(); |
| 69 | } |
| 70 | @SkylarkCallable(name = "struct_field", doc = "", structField = true) |
| 71 | public String structField() { |
| 72 | return "a"; |
| 73 | } |
| 74 | @SkylarkCallable(name = "function", doc = "", structField = false) |
| 75 | public String function() { |
| 76 | return "a"; |
| 77 | } |
| 78 | @SuppressWarnings("unused") |
| 79 | @SkylarkCallable(name = "nullfunc_failing", doc = "", allowReturnNones = false) |
| 80 | public Object nullfuncFailing(String p1, Integer p2) { |
| 81 | return null; |
| 82 | } |
| 83 | @SkylarkCallable(name = "nullfunc_working", doc = "", allowReturnNones = true) |
| 84 | public Object nullfuncWorking() { |
| 85 | return null; |
| 86 | } |
| 87 | @SkylarkCallable(name = "voidfunc", doc = "") |
| 88 | public void voidfunc() {} |
| 89 | @SkylarkCallable(name = "string_list", doc = "") |
| 90 | public ImmutableList<String> stringList() { |
| 91 | return ImmutableList.<String>of("a", "b"); |
| 92 | } |
| 93 | @SkylarkCallable(name = "string", doc = "") |
| 94 | public String string() { |
| 95 | return "a"; |
| 96 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 97 | @Override |
| 98 | public String toString() { |
| 99 | return "<mock>"; |
| 100 | } |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | @SkylarkModule(name = "MockInterface", doc = "") |
| 104 | static interface MockInterface { |
| 105 | @SkylarkCallable(doc = "") |
| 106 | public Boolean isEmptyInterface(String str); |
| 107 | } |
| 108 | |
| 109 | static final class MockSubClass extends Mock implements MockInterface { |
| 110 | @Override |
| 111 | public Boolean isEmpty(String str) { |
| 112 | return str.isEmpty(); |
| 113 | } |
| 114 | @Override |
| 115 | public Boolean isEmptyInterface(String str) { |
| 116 | return str.isEmpty(); |
| 117 | } |
| 118 | @SkylarkCallable(doc = "") |
| 119 | public Boolean isEmptyClassNotAnnotated(String str) { |
| 120 | return str.isEmpty(); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | static final class MockClassObject implements ClassObject { |
| 125 | @Override |
| 126 | public Object getValue(String name) { |
| 127 | switch (name) { |
| 128 | case "field": return "a"; |
| 129 | case "nset": return NestedSetBuilder.stableOrder().build(); |
| 130 | } |
| 131 | throw new IllegalStateException(); |
| 132 | } |
| 133 | |
| 134 | @Override |
| 135 | public ImmutableCollection<String> getKeys() { |
| 136 | return ImmutableList.of("field", "nset"); |
| 137 | } |
| 138 | |
| 139 | @Override |
| 140 | public String errorMessage(String name) { |
| 141 | return null; |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | @SkylarkModule(name = "MockMultipleMethodClass", doc = "") |
| 146 | static final class MockMultipleMethodClass { |
| 147 | @SuppressWarnings("unused") |
| 148 | @SkylarkCallable(doc = "") |
| 149 | public void method(Object o) {} |
| 150 | @SuppressWarnings("unused") |
| 151 | @SkylarkCallable(doc = "") |
| 152 | public void method(String i) {} |
| 153 | } |
| 154 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 155 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 156 | public void testSimpleIf() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 157 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 158 | " a = 0", |
| 159 | " x = 0", |
| 160 | " if x: a = 5", |
| 161 | " return a", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 162 | "a = foo()").testLookup("a", 0); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 163 | } |
| 164 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 165 | @Test |
Laurent Le Brun | 0942ee9 | 2015-03-17 20:22:16 +0000 | [diff] [blame] | 166 | public void testIfPass() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 167 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 168 | " a = 1", |
| 169 | " x = True", |
| 170 | " if x: pass", |
| 171 | " return a", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 172 | "a = foo()").testLookup("a", 1); |
Laurent Le Brun | 0942ee9 | 2015-03-17 20:22:16 +0000 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 176 | public void testNestedIf() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 177 | executeNestedIf(0, 0, 0); |
| 178 | executeNestedIf(1, 0, 3); |
| 179 | executeNestedIf(1, 1, 5); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 180 | } |
| 181 | |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 182 | private void executeNestedIf(int x, int y, int expected) throws Exception { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 183 | String fun = String.format("foo%s%s", x, y); |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 184 | new SkylarkTest().setUp("def " + fun + "():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 185 | " x = " + x, |
| 186 | " y = " + y, |
| 187 | " a = 0", |
| 188 | " b = 0", |
| 189 | " if x:", |
| 190 | " if y:", |
| 191 | " a = 2", |
| 192 | " b = 3", |
| 193 | " return a + b", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 194 | "x = " + fun + "()").testLookup("x", expected); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 195 | } |
| 196 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 197 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 198 | public void testIfElse() throws Exception { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 199 | executeIfElse("foo", "something", 2); |
| 200 | executeIfElse("bar", "", 3); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 201 | } |
| 202 | |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 203 | private void executeIfElse(String fun, String y, int expected) throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 204 | new SkylarkTest().setUp("def " + fun + "():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 205 | " y = '" + y + "'", |
| 206 | " x = 5", |
| 207 | " if x:", |
| 208 | " if y: a = 2", |
| 209 | " else: a = 3", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 210 | " return a", |
| 211 | "z = " + fun + "()").testLookup("z", expected); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 212 | } |
| 213 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 214 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 215 | public void testIfElifElse_IfExecutes() throws Exception { |
| 216 | execIfElifElse(1, 0, 1); |
| 217 | } |
| 218 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 219 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 220 | public void testIfElifElse_ElifExecutes() throws Exception { |
| 221 | execIfElifElse(0, 1, 2); |
| 222 | } |
| 223 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 224 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 225 | public void testIfElifElse_ElseExecutes() throws Exception { |
| 226 | execIfElifElse(0, 0, 3); |
| 227 | } |
| 228 | |
| 229 | private void execIfElifElse(int x, int y, int v) throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 230 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 231 | " x = " + x + "", |
| 232 | " y = " + y + "", |
| 233 | " if x:", |
| 234 | " return 1", |
| 235 | " elif y:", |
| 236 | " return 2", |
| 237 | " else:", |
| 238 | " return 3", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 239 | "v = foo()").testLookup("v", v); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 240 | } |
| 241 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 242 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 243 | public void testForOnList() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 244 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 245 | " s = ''", |
| 246 | " for i in ['hello', ' ', 'world']:", |
| 247 | " s = s + i", |
| 248 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 249 | "s = foo()").testLookup("s", "hello world"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 250 | } |
| 251 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 252 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 253 | public void testForOnString() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 254 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 255 | " s = []", |
| 256 | " for i in 'abc':", |
| 257 | " s = s + [i]", |
| 258 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 259 | "s = foo()").testExactOrder("s", "a", "b", "c"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 260 | } |
| 261 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 262 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 263 | public void testForAssignmentList() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 264 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 265 | " d = ['a', 'b', 'c']", |
| 266 | " s = ''", |
| 267 | " for i in d:", |
| 268 | " s = s + i", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 269 | " d = ['d', 'e', 'f']", // check that we use the old list |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 270 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 271 | "s = foo()").testLookup("s", "abc"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 272 | } |
| 273 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 274 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 275 | public void testForAssignmentDict() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 276 | new SkylarkTest().setUp("def func():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 277 | " d = {'a' : 1, 'b' : 2, 'c' : 3}", |
| 278 | " s = ''", |
| 279 | " for i in d:", |
| 280 | " s = s + i", |
| 281 | " d = {'d' : 1, 'e' : 2, 'f' : 3}", |
| 282 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 283 | "s = func()").testLookup("s", "abc"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 284 | } |
| 285 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 286 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 287 | public void testForNotIterable() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 288 | new SkylarkTest() |
| 289 | .update("mock", new Mock()) |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 290 | .testIfErrorContains( |
| 291 | "type 'int' is not iterable", |
| 292 | "def func():", |
| 293 | " for i in mock.value_of('1'): a = i", |
| 294 | "func()\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 295 | } |
| 296 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 297 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 298 | public void testForOnDictionary() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 299 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 300 | " d = {1: 'a', 2: 'b', 3: 'c'}", |
| 301 | " s = ''", |
| 302 | " for i in d: s = s + d[i]", |
| 303 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 304 | "s = foo()").testLookup("s", "abc"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 305 | } |
| 306 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 307 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 308 | public void testForLoopReuseVariable() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 309 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 310 | " s = ''", |
| 311 | " for i in ['a', 'b']:", |
| 312 | " for i in ['c', 'd']: s = s + i", |
| 313 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 314 | "s = foo()").testLookup("s", "cdcd"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 315 | } |
| 316 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 317 | @Test |
Laurent Le Brun | 741824b | 2015-03-20 15:10:19 +0000 | [diff] [blame] | 318 | public void testForLoopMultipleVariables() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 319 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 320 | " s = ''", |
| 321 | " for [i, j] in [[1, 2], [3, 4]]:", |
| 322 | " s = s + str(i) + str(j) + '.'", |
| 323 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 324 | "s = foo()").testLookup("s", "12.34."); |
Laurent Le Brun | 741824b | 2015-03-20 15:10:19 +0000 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | @Test |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 328 | public void testForLoopBreak() throws Exception { |
| 329 | simpleFlowTest("break", 1); |
| 330 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 331 | |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 332 | @Test |
| 333 | public void testForLoopContinue() throws Exception { |
| 334 | simpleFlowTest("continue", 10); |
| 335 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 336 | |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 337 | @SuppressWarnings("unchecked") |
| 338 | private void simpleFlowTest(String statement, int expected) throws Exception { |
| 339 | eval("def foo():", |
| 340 | " s = 0", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 341 | " hit = 0", |
| 342 | " for i in range(0, 10):", |
| 343 | " s = s + 1", |
| 344 | " " + statement + "", |
| 345 | " hit = 1", |
| 346 | " return [s, hit]", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 347 | "x = foo()"); |
| 348 | assertThat((Iterable<Object>) lookup("x")).containsExactly(expected, 0).inOrder(); |
| 349 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 350 | |
| 351 | @Test |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 352 | public void testForLoopBreakFromDeeperBlock() throws Exception { |
| 353 | flowFromDeeperBlock("break", 1); |
| 354 | flowFromNestedBlocks("break", 29); |
| 355 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 356 | |
| 357 | @Test |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 358 | public void testForLoopContinueFromDeeperBlock() throws Exception { |
| 359 | flowFromDeeperBlock("continue", 5); |
| 360 | flowFromNestedBlocks("continue", 39); |
| 361 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 362 | |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 363 | private void flowFromDeeperBlock(String statement, int expected) throws Exception { |
| 364 | eval("def foo():", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 365 | " s = 0", |
| 366 | " for i in range(0, 10):", |
| 367 | " if i % 2 != 0:", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 368 | " " + statement + "", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 369 | " s = s + 1", |
| 370 | " return s", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 371 | "x = foo()"); |
| 372 | assertThat(lookup("x")).isEqualTo(expected); |
| 373 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 374 | |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 375 | private void flowFromNestedBlocks(String statement, int expected) throws Exception { |
| 376 | eval("def foo2():", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 377 | " s = 0", |
| 378 | " for i in range(1, 41):", |
| 379 | " if i % 2 == 0:", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 380 | " if i % 3 == 0:", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 381 | " if i % 5 == 0:", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 382 | " " + statement + "", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 383 | " s = s + 1", |
| 384 | " return s", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 385 | "y = foo2()"); |
| 386 | assertThat(lookup("y")).isEqualTo(expected); |
| 387 | } |
| 388 | |
| 389 | @Test |
| 390 | public void testNestedForLoopsMultipleBreaks() throws Exception { |
| 391 | nestedLoopsTest("break", 2, 6, 6); |
| 392 | } |
| 393 | |
| 394 | @Test |
| 395 | public void testNestedForLoopsMultipleContinues() throws Exception { |
| 396 | nestedLoopsTest("continue", 4, 20, 20); |
| 397 | } |
| 398 | |
| 399 | @SuppressWarnings("unchecked") |
| 400 | private void nestedLoopsTest(String statement, Integer outerExpected, int firstExpected, |
| 401 | int secondExpected) throws Exception { |
| 402 | eval("def foo():", |
| 403 | " outer = 0", |
| 404 | " first = 0", |
| 405 | " second = 0", |
| 406 | " for i in range(0, 5):", |
| 407 | " for j in range(0, 5):", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 408 | " if j == 2:", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 409 | " " + statement + "", |
| 410 | " first = first + 1", |
| 411 | " for k in range(0, 5):", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 412 | " if k == 2:", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 413 | " " + statement + "", |
| 414 | " second = second + 1", |
| 415 | " if i == 2:", |
| 416 | " " + statement + "", |
| 417 | " outer = outer + 1", |
| 418 | " return [outer, first, second]", |
| 419 | "x = foo()"); |
| 420 | assertThat((Iterable<Object>) lookup("x")) |
| 421 | .containsExactly(outerExpected, firstExpected, secondExpected).inOrder(); |
| 422 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 423 | |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 424 | @Test |
| 425 | public void testForLoopBreakError() throws Exception { |
| 426 | flowStatementInsideFunction("break"); |
| 427 | flowStatementAfterLoop("break"); |
| 428 | } |
| 429 | |
| 430 | @Test |
| 431 | public void testForLoopContinueError() throws Exception { |
| 432 | flowStatementInsideFunction("continue"); |
| 433 | flowStatementAfterLoop("continue"); |
| 434 | } |
| 435 | |
| 436 | private void flowStatementInsideFunction(String statement) throws Exception { |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 437 | checkEvalErrorContains(statement + " statement must be inside a for loop", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 438 | "def foo():", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 439 | " " + statement + "", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 440 | "x = foo()"); |
| 441 | } |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 442 | |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 443 | private void flowStatementAfterLoop(String statement) throws Exception { |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 444 | checkEvalErrorContains(statement + " statement must be inside a for loop", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 445 | "def foo2():", |
| 446 | " for i in range(0, 3):", |
| 447 | " pass", |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 448 | " " + statement + "", |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 449 | "y = foo2()"); |
| 450 | } |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 451 | |
Florian Weikert | 917ceaa | 2015-06-10 13:54:26 +0000 | [diff] [blame] | 452 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 453 | public void testNoneAssignment() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 454 | new SkylarkTest() |
| 455 | .setUp("def foo(x=None):", " x = 1", " x = None", " return 2", "s = foo()") |
| 456 | .testLookup("s", 2); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 457 | } |
| 458 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 459 | @Test |
Laurent Le Brun | 88014fe | 2015-06-17 16:02:16 +0000 | [diff] [blame] | 460 | public void testReassignment() throws Exception { |
| 461 | eval("def foo(x=None):", |
| 462 | " x = 1", |
| 463 | " x = [1, 2]", |
| 464 | " x = 'str'", |
| 465 | " return x", |
| 466 | "s = foo()"); |
| 467 | assertThat(lookup("s")).isEqualTo("str"); |
| 468 | } |
| 469 | |
| 470 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 471 | public void testJavaCalls() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 472 | new SkylarkTest() |
| 473 | .update("mock", new Mock()) |
| 474 | .setUp("b = mock.is_empty('a')") |
| 475 | .testLookup("b", Boolean.FALSE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 476 | } |
| 477 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 478 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 479 | public void testJavaCallsOnSubClass() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 480 | new SkylarkTest() |
| 481 | .update("mock", new MockSubClass()) |
| 482 | .setUp("b = mock.is_empty('a')") |
| 483 | .testLookup("b", Boolean.FALSE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 484 | } |
| 485 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 486 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 487 | public void testJavaCallsOnInterface() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 488 | new SkylarkTest() |
| 489 | .update("mock", new MockSubClass()) |
| 490 | .setUp("b = mock.is_empty_interface('a')") |
| 491 | .testLookup("b", Boolean.FALSE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 492 | } |
| 493 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 494 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 495 | public void testJavaCallsNotSkylarkCallable() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 496 | new SkylarkTest() |
| 497 | .update("mock", new Mock()) |
| 498 | .testIfExactError("No matching method found for value() in Mock", "mock.value()"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 499 | } |
| 500 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 501 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 502 | public void testJavaCallsNoMethod() throws Exception { |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 503 | new SkylarkTest() |
| 504 | .update("mock", new Mock()) |
| 505 | .testIfExactError("No matching method found for bad() in Mock", "mock.bad()"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 506 | } |
| 507 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 508 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 509 | public void testJavaCallsNoMethodErrorMsg() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 510 | new SkylarkTest().testIfExactError( |
| 511 | "No matching method found for bad(string, string, string) in int", |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 512 | "s = 3.bad('a', 'b', 'c')"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 513 | } |
| 514 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 515 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 516 | public void testJavaCallsMultipleMethod() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 517 | new SkylarkTest() |
| 518 | .update("mock", new MockMultipleMethodClass()) |
| 519 | .testIfExactError( |
| 520 | "Multiple matching methods for method(string) in MockMultipleMethodClass", |
| 521 | "s = mock.method('string')"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 522 | } |
| 523 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 524 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 525 | public void testJavaCallWithKwargs() throws Exception { |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 526 | new SkylarkTest() |
| 527 | .update("mock", new Mock()) |
| 528 | .testIfExactError("Keyword arguments are not allowed when calling a java method" |
| 529 | + "\nwhile calling method 'string' on object of type Mock", |
| 530 | "mock.string(key=True)"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 531 | } |
| 532 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 533 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 534 | public void testNoJavaCallsWithoutSkylark() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 535 | new SkylarkTest().testIfExactError( |
| 536 | "No matching method found for to_string() in int", "s = 3.to_string()"); |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 537 | } |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 538 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 539 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 540 | public void testNoJavaCallsIfClassNotAnnotated() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 541 | new SkylarkTest() |
| 542 | .update("mock", new MockSubClass()) |
| 543 | .testIfExactError( |
| 544 | "No matching method found for is_empty_class_not_annotated(string) in MockSubClass", |
| 545 | "b = mock.is_empty_class_not_annotated('a')"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 546 | } |
| 547 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 548 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 549 | public void testStructAccess() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 550 | new SkylarkTest() |
| 551 | .update("mock", new Mock()) |
| 552 | .setUp("v = mock.struct_field") |
| 553 | .testLookup("v", "a"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 554 | } |
| 555 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 556 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 557 | public void testStructAccessAsFuncall() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 558 | new SkylarkTest() |
| 559 | .update("mock", new Mock()) |
| 560 | .testIfExactError( |
| 561 | "No matching method found for struct_field() in Mock", "v = mock.struct_field()"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 562 | } |
| 563 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 564 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 565 | public void testStructAccessOfMethod() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 566 | new SkylarkTest() |
| 567 | .update("mock", new Mock()) |
| 568 | .testIfExactError("Object of type 'Mock' has no field \"function\"", "v = mock.function"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 569 | } |
| 570 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 571 | @Test |
Laurent Le Brun | e314e250 | 2015-03-13 15:02:46 +0000 | [diff] [blame] | 572 | public void testConditionalStructConcatenation() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 573 | // TODO(fwe): cannot be handled by current testing suite |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 574 | eval("def func():", |
| 575 | " x = struct(a = 1, b = 2)", |
| 576 | " if True:", |
| 577 | " x += struct(c = 1, d = 2)", |
| 578 | " return x", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 579 | "x = func()"); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 580 | SkylarkClassObject x = (SkylarkClassObject) lookup("x"); |
Laurent Le Brun | e314e250 | 2015-03-13 15:02:46 +0000 | [diff] [blame] | 581 | assertEquals(1, x.getValue("a")); |
| 582 | assertEquals(2, x.getValue("b")); |
| 583 | assertEquals(1, x.getValue("c")); |
| 584 | assertEquals(2, x.getValue("d")); |
| 585 | } |
| 586 | |
| 587 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 588 | public void testJavaFunctionReturnsMutableObject() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 589 | new SkylarkTest() |
| 590 | .update("mock", new Mock()) |
| 591 | .testIfExactError( |
| 592 | "Method 'return_mutable' returns a mutable object (type of Mock)", |
| 593 | "mock.return_mutable()"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 594 | } |
| 595 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 596 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 597 | public void testJavaFunctionReturnsNullFails() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 598 | new SkylarkTest() |
| 599 | .update("mock", new Mock()) |
| 600 | .testIfExactError( |
| 601 | "Method invocation returned None," |
| 602 | + " please contact Skylark developers: nullfunc_failing(\"abc\", 1)", |
| 603 | "mock.nullfunc_failing('abc', 1)"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 604 | } |
| 605 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 606 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 607 | public void testClassObjectAccess() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 608 | new SkylarkTest() |
| 609 | .update("mock", new MockClassObject()) |
| 610 | .setUp("v = mock.field") |
| 611 | .testLookup("v", "a"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 612 | } |
| 613 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 614 | @Test |
Laurent Le Brun | ab0ca1a | 2015-03-31 17:13:25 +0000 | [diff] [blame] | 615 | public void testInSet() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 616 | new SkylarkTest().testStatement("'b' in set(['a', 'b'])", Boolean.TRUE) |
| 617 | .testStatement("'c' in set(['a', 'b'])", Boolean.FALSE) |
| 618 | .testStatement("1 in set(['a', 'b'])", Boolean.FALSE); |
Laurent Le Brun | ab0ca1a | 2015-03-31 17:13:25 +0000 | [diff] [blame] | 619 | } |
| 620 | |
| 621 | @Test |
Laurent Le Brun | 092f13b | 2015-08-24 14:50:00 +0000 | [diff] [blame] | 622 | public void testUnionSet() throws Exception { |
| 623 | new SkylarkTest() |
| 624 | .testStatement("str(set([1, 3]) | set([1, 2]))", "set([1, 2, 3])") |
| 625 | .testStatement("str(set([1, 2]) | [1, 3])", "set([1, 2, 3])") |
| 626 | .testIfExactError("unsupported operand type(s) for |: 'int' and 'int'", "2 | 4"); |
| 627 | } |
| 628 | |
| 629 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 630 | public void testClassObjectCannotAccessNestedSet() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 631 | new SkylarkTest() |
| 632 | .update("mock", new MockClassObject()) |
| 633 | .testIfExactError("Type is not allowed in Skylark: EmptyNestedSet", "v = mock.nset"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 634 | } |
| 635 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 636 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 637 | public void testJavaFunctionReturnsNone() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 638 | new SkylarkTest() |
| 639 | .update("mock", new Mock()) |
| 640 | .setUp("v = mock.nullfunc_working()") |
| 641 | .testLookup("v", Environment.NONE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 642 | } |
| 643 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 644 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 645 | public void testVoidJavaFunctionReturnsNone() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 646 | new SkylarkTest() |
| 647 | .update("mock", new Mock()) |
| 648 | .setUp("v = mock.voidfunc()") |
| 649 | .testLookup("v", Environment.NONE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 650 | } |
| 651 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 652 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 653 | public void testAugmentedAssignment() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 654 | new SkylarkTest().setUp("def f1(x):", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 655 | " x += 1", |
| 656 | " return x", |
| 657 | "", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 658 | "foo = f1(41)").testLookup("foo", 42); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 659 | } |
| 660 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 661 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 662 | public void testStaticDirectJavaCall() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 663 | new SkylarkTest().update("Mock", Mock.class).setUp("val = Mock.value_of('8')") |
| 664 | .testLookup("val", 8); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 665 | } |
| 666 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 667 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 668 | public void testStaticDirectJavaCallMethodIsNonStatic() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 669 | new SkylarkTest().update("Mock", Mock.class).testIfExactError("Method 'is_empty' is not static", |
| 670 | "val = Mock.is_empty('a')"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 671 | } |
| 672 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 673 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 674 | public void testDictComprehensions_IterationOrder() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 675 | new SkylarkTest().setUp("def foo():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 676 | " d = {x : x for x in ['c', 'a', 'b']}", |
| 677 | " s = ''", |
| 678 | " for a in d:", |
| 679 | " s += a", |
| 680 | " return s", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 681 | "s = foo()").testLookup("s", "abc"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 682 | } |
| 683 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 684 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 685 | public void testStructCreation() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 686 | // TODO(fwe): cannot be handled by current testing suite |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 687 | eval("x = struct(a = 1, b = 2)"); |
| 688 | assertThat(lookup("x")).isInstanceOf(ClassObject.class); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 689 | } |
| 690 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 691 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 692 | public void testStructFields() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 693 | // TODO(fwe): cannot be handled by current testing suite |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 694 | eval("x = struct(a = 1, b = 2)"); |
| 695 | ClassObject x = (ClassObject) lookup("x"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 696 | assertEquals(1, x.getValue("a")); |
| 697 | assertEquals(2, x.getValue("b")); |
| 698 | } |
| 699 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 700 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 701 | public void testStructAccessingFieldsFromSkylark() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 702 | new SkylarkTest() |
| 703 | .setUp("x = struct(a = 1, b = 2)", "x1 = x.a", "x2 = x.b") |
| 704 | .testLookup("x1", 1) |
| 705 | .testLookup("x2", 2); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 706 | } |
| 707 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 708 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 709 | public void testStructAccessingUnknownField() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 710 | new SkylarkTest().testIfExactError( |
| 711 | "Object of type 'struct' has no field \"c\"", "x = struct(a = 1, b = 2)", "y = x.c"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 712 | } |
| 713 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 714 | @Test |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 715 | public void testStructAccessingUnknownFieldWithArgs() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 716 | new SkylarkTest().testIfExactError( |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 717 | "struct has no method 'c'", "x = struct(a = 1, b = 2)", "y = x.c()"); |
| 718 | } |
| 719 | |
| 720 | @Test |
| 721 | public void testStructAccessingNonFunctionFieldWithArgs() throws Exception { |
| 722 | new SkylarkTest().testIfExactError( |
| 723 | "struct field 'a' is not a function", "x = struct(a = 1, b = 2)", "x1 = x.a(1)"); |
| 724 | } |
| 725 | |
| 726 | @Test |
| 727 | public void testStructAccessingFunctionFieldWithArgs() throws Exception { |
| 728 | new SkylarkTest() |
| 729 | .setUp("def f(x): return x+5", "x = struct(a = f, b = 2)", "x1 = x.a(1)") |
| 730 | .testLookup("x1", 6); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 731 | } |
| 732 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 733 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 734 | public void testStructPosArgs() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 735 | new SkylarkTest().testIfExactError( |
| 736 | "struct(**kwargs) does not accept positional arguments, but got 1", "x = struct(1, b = 2)"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 737 | } |
| 738 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 739 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 740 | public void testStructConcatenationFieldNames() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 741 | // TODO(fwe): cannot be handled by current testing suite |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 742 | eval("x = struct(a = 1, b = 2)", |
| 743 | "y = struct(c = 1, d = 2)", |
| 744 | "z = x + y\n"); |
| 745 | SkylarkClassObject z = (SkylarkClassObject) lookup("z"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 746 | assertEquals(ImmutableSet.of("a", "b", "c", "d"), z.getKeys()); |
| 747 | } |
| 748 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 749 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 750 | public void testStructConcatenationFieldValues() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 751 | // TODO(fwe): cannot be handled by current testing suite |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 752 | eval("x = struct(a = 1, b = 2)", |
| 753 | "y = struct(c = 1, d = 2)", |
| 754 | "z = x + y\n"); |
| 755 | SkylarkClassObject z = (SkylarkClassObject) lookup("z"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 756 | assertEquals(1, z.getValue("a")); |
| 757 | assertEquals(2, z.getValue("b")); |
| 758 | assertEquals(1, z.getValue("c")); |
| 759 | assertEquals(2, z.getValue("d")); |
| 760 | } |
| 761 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 762 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 763 | public void testStructConcatenationCommonFields() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 764 | new SkylarkTest().testIfExactError("Cannot concat structs with common field(s): a", |
| 765 | "x = struct(a = 1, b = 2)", "y = struct(c = 1, a = 2)", "z = x + y\n"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 766 | } |
| 767 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 768 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 769 | public void testDotExpressionOnNonStructObject() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 770 | new SkylarkTest().testIfExactError("Object of type 'string' has no field \"field\"", |
| 771 | "x = 'a'.field"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 772 | } |
| 773 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 774 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 775 | public void testPlusEqualsOnDict() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 776 | new SkylarkTest().setUp("def func():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 777 | " d = {'a' : 1}", |
| 778 | " d += {'b' : 2}", |
| 779 | " return d", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 780 | "d = func()") |
| 781 | .testLookup("d", ImmutableMap.of("a", 1, "b", 2)); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 782 | } |
| 783 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 784 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 785 | public void testDictAssignmentAsLValue() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 786 | new SkylarkTest().setUp("def func():", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 787 | " d = {'a' : 1}", |
| 788 | " d['b'] = 2", |
| 789 | " return d", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 790 | "d = func()").testLookup("d", ImmutableMap.of("a", 1, "b", 2)); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 791 | } |
| 792 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 793 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 794 | public void testDictAssignmentAsLValueNoSideEffects() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 795 | new SkylarkTest().setUp("def func(d):", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 796 | " d['b'] = 2", |
| 797 | "d = {'a' : 1}", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 798 | "func(d)").testLookup("d", ImmutableMap.of("a", 1)); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 799 | } |
| 800 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 801 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 802 | public void testListIndexAsLValueAsLValue() throws Exception { |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 803 | new SkylarkTest() |
| 804 | .testIfErrorContains( |
| 805 | "unsupported operand type(s) for +: 'list' and 'dict'", |
| 806 | "def id(l):", |
| 807 | " return l", |
| 808 | "def func():", |
| 809 | " l = id([1])", |
| 810 | " l[0] = 2", |
| 811 | " return l", |
| 812 | "l = func()"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 813 | } |
| 814 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 815 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 816 | public void testTopLevelDict() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 817 | new SkylarkTest().setUp("if 1:", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 818 | " v = 'a'", |
| 819 | "else:", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 820 | " v = 'b'").testLookup("v", "a"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 821 | } |
| 822 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 823 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 824 | public void testUserFunctionKeywordArgs() throws Exception { |
Francois-Rene Rideau | 676905a | 2015-08-31 15:39:09 +0000 | [diff] [blame^] | 825 | new SkylarkTest().setUp("def foo(a, b, c):", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 826 | " return a + b + c", "s = foo(1, c=2, b=3)") |
| 827 | .testLookup("s", 6); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 828 | } |
| 829 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 830 | @Test |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 831 | public void testFunctionCallOrdering() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 832 | new SkylarkTest().setUp("def func(): return foo() * 2", |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 833 | "def foo(): return 2", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 834 | "x = func()") |
| 835 | .testLookup("x", 4); |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 836 | } |
| 837 | |
| 838 | @Test |
| 839 | public void testFunctionCallBadOrdering() throws Exception { |
Florian Weikert | 3f610e8 | 2015-08-18 14:37:46 +0000 | [diff] [blame] | 840 | new SkylarkTest().testIfErrorContains("name 'foo' is not defined", |
Laurent Le Brun | 6874316 | 2015-05-13 13:18:09 +0000 | [diff] [blame] | 841 | "def func(): return foo() * 2", |
| 842 | "x = func()", |
| 843 | "def foo(): return 2"); |
| 844 | } |
| 845 | |
| 846 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 847 | public void testNoneTrueFalseInSkylark() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 848 | new SkylarkTest().setUp("a = None", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 849 | "b = True", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 850 | "c = False") |
| 851 | .testLookup("a", Environment.NONE) |
| 852 | .testLookup("b", Boolean.TRUE) |
| 853 | .testLookup("c", Boolean.FALSE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 854 | } |
| 855 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 856 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 857 | public void testHasattr() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 858 | new SkylarkTest().setUp("s = struct(a=1)", |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 859 | "x = hasattr(s, 'a')", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 860 | "y = hasattr(s, 'b')\n") |
| 861 | .testLookup("x", Boolean.TRUE) |
| 862 | .testLookup("y", Boolean.FALSE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 863 | } |
| 864 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 865 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 866 | public void testHasattrMethods() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 867 | new SkylarkTest() |
| 868 | .update("mock", new Mock()) |
| 869 | .setUp("a = hasattr(mock, 'struct_field')", "b = hasattr(mock, 'function')", |
| 870 | "c = hasattr(mock, 'is_empty')", "d = hasattr('str', 'replace')", |
| 871 | "e = hasattr(mock, 'other')\n") |
| 872 | .testLookup("a", Boolean.TRUE) |
| 873 | .testLookup("b", Boolean.TRUE) |
| 874 | .testLookup("c", Boolean.TRUE) |
| 875 | .testLookup("d", Boolean.TRUE) |
| 876 | .testLookup("e", Boolean.FALSE); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 877 | } |
| 878 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 879 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 880 | public void testGetattr() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 881 | new SkylarkTest() |
| 882 | .setUp("s = struct(a='val')", "x = getattr(s, 'a')", "y = getattr(s, 'b', 'def')", |
| 883 | "z = getattr(s, 'b', default = 'def')", "w = getattr(s, 'a', default='ignored')") |
| 884 | .testLookup("x", "val") |
| 885 | .testLookup("y", "def") |
| 886 | .testLookup("z", "def") |
| 887 | .testLookup("w", "val"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 888 | } |
| 889 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 890 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 891 | public void testGetattrNoAttr() throws Exception { |
Laurent Le Brun | faf7841 | 2015-07-28 16:13:00 +0000 | [diff] [blame] | 892 | new SkylarkTest().testIfExactError("Object of type 'struct' has no attribute \"b\"", |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 893 | "s = struct(a='val')", "getattr(s, 'b')"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 894 | } |
| 895 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 896 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 897 | public void testListAnTupleConcatenationDoesNotWorkInSkylark() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 898 | new SkylarkTest().testIfExactError("cannot concatenate lists and tuples", "[1, 2] + (3, 4)"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 899 | } |
| 900 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 901 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 902 | public void testCannotCreateMixedListInSkylark() throws Exception { |
Laurent Le Brun | e083a91 | 2015-08-10 15:13:34 +0000 | [diff] [blame] | 903 | new SkylarkTest().testExactOrder("['a', 'b', 1, 2]", "a", "b", 1, 2); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 904 | } |
| 905 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 906 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 907 | public void testCannotConcatListInSkylarkWithDifferentGenericTypes() throws Exception { |
Laurent Le Brun | e083a91 | 2015-08-10 15:13:34 +0000 | [diff] [blame] | 908 | new SkylarkTest().testExactOrder("[1, 2] + ['a', 'b']", 1, 2, "a", "b"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 909 | } |
| 910 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 911 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 912 | public void testConcatEmptyListWithNonEmptyWorks() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 913 | new SkylarkTest().testExactOrder("[] + ['a', 'b']", "a", "b"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 914 | } |
| 915 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 916 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 917 | public void testFormatStringWithTuple() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 918 | new SkylarkTest().setUp("v = '%s%s' % ('a', 1)").testLookup("v", "a1"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 919 | } |
| 920 | |
Francois-Rene Rideau | e8cfead | 2015-03-17 16:01:47 +0000 | [diff] [blame] | 921 | @Test |
| 922 | public void testSingletonTuple() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 923 | new SkylarkTest().testExactOrder("(1,)", 1); |
Francois-Rene Rideau | e8cfead | 2015-03-17 16:01:47 +0000 | [diff] [blame] | 924 | } |
| 925 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 926 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 927 | public void testDirFindsClassObjectFields() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 928 | new SkylarkTest().update("mock", new MockClassObject()).setUp() |
| 929 | .testExactOrder("dir(mock)", "field", "nset"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 930 | } |
| 931 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 932 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 933 | public void testDirFindsJavaObjectStructFieldsAndMethods() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 934 | new SkylarkTest().update("mock", new Mock()).testExactOrder("dir(mock)", |
| 935 | "function", |
| 936 | "is_empty", |
| 937 | "nullfunc_failing", |
| 938 | "nullfunc_working", |
| 939 | "return_mutable", |
| 940 | "string", |
| 941 | "string_list", |
| 942 | "struct_field", |
| 943 | "value_of", |
| 944 | "voidfunc"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 945 | } |
| 946 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 947 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 948 | public void testPrint() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 949 | // TODO(fwe): cannot be handled by current testing suite |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 950 | setFailFast(false); |
| 951 | eval("print('hello')"); |
| 952 | assertContainsEvent("hello"); |
| 953 | eval("print('a', 'b')"); |
| 954 | assertContainsEvent("a b"); |
| 955 | eval("print('a', 'b', sep='x')"); |
| 956 | assertContainsEvent("axb"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 957 | } |
| 958 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 959 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 960 | public void testPrintBadKwargs() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 961 | new SkylarkTest().testIfExactError( |
Francois-Rene Rideau | 537a90b | 2015-04-22 06:47:31 +0000 | [diff] [blame] | 962 | "unexpected keywords 'end', 'other' in call to print(*args, sep: string = \" \")", |
| 963 | "print(end='x', other='y')"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 964 | } |
| 965 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 966 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 967 | public void testSkylarkTypes() { |
| 968 | assertEquals(TransitiveInfoCollection.class, |
| 969 | EvalUtils.getSkylarkType(FileConfiguredTarget.class)); |
| 970 | assertEquals(TransitiveInfoCollection.class, |
| 971 | EvalUtils.getSkylarkType(RuleConfiguredTarget.class)); |
| 972 | assertEquals(Artifact.class, EvalUtils.getSkylarkType(SpecialArtifact.class)); |
| 973 | } |
| 974 | |
| 975 | // Override tests in EvaluationTest incompatible with Skylark |
| 976 | |
| 977 | @SuppressWarnings("unchecked") |
| 978 | @Override |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 979 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 980 | public void testConcatLists() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 981 | new SkylarkTest().testExactOrder("[1,2] + [3,4]", 1, 2, 3, 4).testExactOrder("(1,2)", 1, 2) |
| 982 | .testExactOrder("(1,2) + (3,4)", 1, 2, 3, 4); |
| 983 | |
| 984 | // TODO(fwe): cannot be handled by current testing suite |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 985 | // list |
| 986 | Object x = eval("[1,2] + [3,4]"); |
| 987 | assertThat((Iterable<Object>) x).containsExactly(1, 2, 3, 4).inOrder(); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 988 | |
| 989 | // tuple |
| 990 | x = eval("(1,2)"); |
| 991 | assertThat((Iterable<Object>) x).containsExactly(1, 2).inOrder(); |
| 992 | assertTrue(((SkylarkList) x).isTuple()); |
| 993 | |
| 994 | x = eval("(1,2) + (3,4)"); |
| 995 | assertThat((Iterable<Object>) x).containsExactly(1, 2, 3, 4).inOrder(); |
| 996 | assertTrue(((SkylarkList) x).isTuple()); |
| 997 | } |
| 998 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 999 | @Override |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 1000 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 1001 | public void testListConcatenation() throws Exception {} |
| 1002 | |
Florian Weikert | f07e544 | 2015-07-01 13:08:43 +0000 | [diff] [blame] | 1003 | @Override |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1004 | @Test |
| 1005 | public void testInFail() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 1006 | new SkylarkTest().testIfExactError( |
| 1007 | "in operator only works on strings if the left operand is also a string", "1 in '123'"); |
| 1008 | new SkylarkTest().testIfExactError( |
| 1009 | "in operator only works on lists, tuples, sets, dicts and strings", "'a' in 1"); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1010 | } |
| 1011 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 1012 | @Override |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 1013 | @Test |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1014 | public void testListComprehensionsMultipleVariablesFail() throws Exception { |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 1015 | new SkylarkTest() |
| 1016 | .testIfErrorContains( |
| 1017 | "lvalue has length 3, but rvalue has has length 2", |
| 1018 | "def foo (): return [x + y for x, y, z in [(1, 2), (3, 4)]]", |
| 1019 | "foo()"); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1020 | |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 1021 | new SkylarkTest() |
| 1022 | .testIfErrorContains( |
| 1023 | "type 'int' is not a collection", |
| 1024 | "def bar (): return [x + y for x, y in (1, 2)]", |
| 1025 | "bar()"); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1026 | |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 1027 | new SkylarkTest() |
| 1028 | .testIfErrorContains( |
| 1029 | "lvalue has length 3, but rvalue has has length 2", |
| 1030 | "[x + y for x, y, z in [(1, 2), (3, 4)]]"); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1031 | |
| 1032 | // can't reuse the same local variable twice(!) |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 1033 | new SkylarkTest() |
| 1034 | .testIfErrorContains( |
| 1035 | "ERROR 2:1: Variable x is read only", |
| 1036 | "[x + y for x, y in (1, 2)]", |
| 1037 | "[x + y for x, y in (1, 2)]"); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1038 | |
Florian Weikert | c1d54ec | 2015-08-26 14:06:58 +0000 | [diff] [blame] | 1039 | new SkylarkTest() |
| 1040 | .testIfErrorContains("type 'int' is not a collection", "[x2 + y2 for x2, y2 in (1, 2)]"); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1041 | } |
| 1042 | |
| 1043 | @Override |
| 1044 | @Test |
| 1045 | public void testNotCallInt() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 1046 | new SkylarkTest().setUp("sum = 123456").testLookup("sum", 123456) |
| 1047 | .testIfExactError("'int' object is not callable", "sum(1, 2, 3, 4, 5, 6)") |
| 1048 | .testStatement("sum", 123456); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 1049 | } |
Francois-Rene Rideau | 6fc5ee7 | 2015-03-12 20:55:17 +0000 | [diff] [blame] | 1050 | |
| 1051 | @Test |
| 1052 | public void testConditionalExpressionAtToplevel() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 1053 | new SkylarkTest().setUp("x = 1 if 2 else 3").testLookup("x", 1); |
Francois-Rene Rideau | 6fc5ee7 | 2015-03-12 20:55:17 +0000 | [diff] [blame] | 1054 | } |
| 1055 | |
| 1056 | @Test |
| 1057 | public void testConditionalExpressionInFunction() throws Exception { |
Florian Weikert | 28da365 | 2015-07-01 14:52:30 +0000 | [diff] [blame] | 1058 | new SkylarkTest().setUp("def foo(a, b, c): return a+b if c else a-b\n").testStatement( |
| 1059 | "foo(23, 5, 0)", 18); |
Francois-Rene Rideau | 6fc5ee7 | 2015-03-12 20:55:17 +0000 | [diff] [blame] | 1060 | } |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 1061 | } |