bazel tests: delete TestMode and other test junk
The only differences in the test modes, BUILD and SKYLARK, were:
- the name of the Mutability, which is insignificant.
- whether "BUILD dialect checks", such as no def, no f(**kwargs),
are applied. These are moved from syntax.EvaluationTest to packages.PackageFactoryTest.
- whether validation errors were reported as events or a thrown exception.
Now it's always an exception.
- whether the validator gets the 'isBuildFile' flag.
This affects a small (and diminishing) set of things,
which should be checked directly.
The ModalTestCase hierarchy (base, BUILD only, Skylark only, both modes)
has been flattened into a single class, Scenario.
EvaluationTestCase:
- newStarlarkThreadWithSkylarkOptions is now setSemantics (stateful)
- inline the code formerly in TestMode and simplify newStarlarkThread et al.
- make bad dependencies on build-base explicit. (They are revealed, but not new.)
- hide fields
- simplify exec().
SkylarkEvaluationTest:
- break "extends EvaluationTest" edge:
There's no need to duplicate the whole suite for both modes;
nearly every test was independent of mode (and one suspects most
were added with no knowledge of the intended design).
- move tests of FlagGuardedValue into StarlarkFlagGuardingTest.
(They were the only tests to use the 'builtins' parameter, now removed.)
PiperOrigin-RevId: 294451364
diff --git a/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java b/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java
index 137d0f6..507990d 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/PackageFactoryTest.java
@@ -33,6 +33,7 @@
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -1209,4 +1210,56 @@
assertThat(globs).containsExactly("ab", "a", "**/*");
assertThat(globsWithDirs).containsExactly("c");
}
+
+ // Tests of BUILD file dialect checks:
+
+ @Test
+ public void testDefInBuild() throws Exception {
+ checkBuildDialectError(
+ "def func(): pass", //
+ "function definitions are not allowed in BUILD files");
+ }
+
+ @Test
+ public void testForStatementForbiddenInBuild() throws Exception {
+ checkBuildDialectError(
+ "for _ in []: pass", //
+ "for loops are not allowed");
+ }
+
+ @Test
+ public void testIfStatementForbiddenInBuild() throws Exception {
+ checkBuildDialectError(
+ "if False: pass", //
+ "if statements are not allowed");
+ }
+
+ @Test
+ public void testKwargsForbiddenInBuild() throws Exception {
+ checkBuildDialectError(
+ "print(**dict)", //
+ "**kwargs arguments are not allowed in BUILD files");
+ checkBuildDialectError(
+ "len(dict(**{'a': 1}))", //
+ "**kwargs arguments are not allowed in BUILD files");
+ }
+
+ @Test
+ public void testArgsForbiddenInBuild() throws Exception {
+ checkBuildDialectError(
+ "print(*['a'])", //
+ "*args arguments are not allowed in BUILD files");
+ }
+
+ // Asserts that evaluation of the specified BUILD file produces the expected error.
+ // Modifies: scratch, events, packages; be careful when calling more than once per @Test!
+ private void checkBuildDialectError(String content, String expectedError)
+ throws IOException, InterruptedException, NoSuchPackageException {
+ events.clear();
+ events.setFailFast(false);
+ Path file = scratch.overwriteFile("/p/BUILD", content);
+ Package pkg = packages.eval("p", RootedPath.toRootedPath(root, file));
+ assertThat(pkg.containsErrors()).isTrue();
+ events.assertContainsError(expectedError);
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java
index b670186..43b0bbe 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcToolchainConfigureTest.java
@@ -50,8 +50,8 @@
.testExpression("split_escaped('a%:', ':')", StarlarkList.of(mu, "a:"));
}
- private ModalTestCase newTest(String... skylarkOptions) throws IOException {
- return new SkylarkTest(skylarkOptions)
+ private Scenario newTest(String... skylarkOptions) throws IOException {
+ return new Scenario(skylarkOptions)
// A mock implementation of Label to be able to parse lib_cc_configure under default
// Skylark environment (lib_cc_configure is meant to be used from the repository
// environment).
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java b/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java
index 3f1432e..1bf36cc 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java
@@ -25,6 +25,7 @@
import com.google.devtools.build.lib.packages.SymbolGenerator;
import com.google.devtools.build.lib.rules.platform.PlatformCommon;
import com.google.devtools.build.lib.syntax.Module;
+import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
@@ -55,9 +56,10 @@
EvaluationTestCase ev =
new EvaluationTestCase() {
@Override
- public StarlarkThread newStarlarkThread() throws Exception {
+ public StarlarkThread newStarlarkThread() {
+ Mutability mu = Mutability.create("test");
StarlarkThread thread =
- StarlarkThread.builder(mutability)
+ StarlarkThread.builder(mu)
.setSemantics(getSkylarkSemantics())
.setGlobals(
globals.withLabel(
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java b/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java
index fb26b45..c9e633c 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java
@@ -136,23 +136,22 @@
@Test
public void testBadOrder() throws Exception {
- new BothModesTest().testIfExactError(
- "Invalid order: non_existing",
- "depset(['a'], order='non_existing')");
+ new Scenario()
+ .testIfExactError("Invalid order: non_existing", "depset(['a'], order='non_existing')");
}
@Test
public void testBadOrderDirect() throws Exception {
- new BothModesTest().testIfExactError(
- "Invalid order: non_existing",
- "depset(direct = ['a'], order='non_existing')");
+ new Scenario()
+ .testIfExactError(
+ "Invalid order: non_existing", "depset(direct = ['a'], order='non_existing')");
}
@Test
public void testBadOrderItems() throws Exception {
- new BothModesTest().testIfExactError(
- "Invalid order: non_existing",
- "depset(items = ['a'], order='non_existing')");
+ new Scenario()
+ .testIfExactError(
+ "Invalid order: non_existing", "depset(items = ['a'], order='non_existing')");
}
@Test
@@ -195,49 +194,53 @@
@Test
public void testBadGenericType() throws Exception {
- new BothModesTest().testIfExactError(
- "cannot add an item of type 'int' to a depset of 'string'",
- "depset(['a', 5])");
+ new Scenario()
+ .testIfExactError(
+ "cannot add an item of type 'int' to a depset of 'string'", "depset(['a', 5])");
}
@Test
public void testBadGenericTypeDirect() throws Exception {
- new BothModesTest().testIfExactError(
- "cannot add an item of type 'int' to a depset of 'string'",
- "depset(direct = ['a', 5])");
+ new Scenario()
+ .testIfExactError(
+ "cannot add an item of type 'int' to a depset of 'string'",
+ "depset(direct = ['a', 5])");
}
@Test
public void testBadGenericTypeItems() throws Exception {
- new BothModesTest().testIfExactError(
- "cannot add an item of type 'int' to a depset of 'string'",
- "depset(items = ['a', 5])");
+ new Scenario()
+ .testIfExactError(
+ "cannot add an item of type 'int' to a depset of 'string'", "depset(items = ['a', 5])");
}
@Test
public void testBadGenericTypeTransitive() throws Exception {
- new BothModesTest().testIfExactError(
- "cannot add an item of type 'int' to a depset of 'string'",
- "depset(['a', 'b'], transitive=[depset([1])])");
+ new Scenario()
+ .testIfExactError(
+ "cannot add an item of type 'int' to a depset of 'string'",
+ "depset(['a', 'b'], transitive=[depset([1])])");
}
@Test
public void testLegacyAndNewApi() throws Exception {
- new BothModesTest().testIfExactError(
- "Do not pass both 'direct' and 'items' argument to depset constructor.",
- "depset(['a', 'b'], direct = ['c', 'd'])");
+ new Scenario()
+ .testIfExactError(
+ "Do not pass both 'direct' and 'items' argument to depset constructor.",
+ "depset(['a', 'b'], direct = ['c', 'd'])");
}
@Test
public void testItemsAndTransitive() throws Exception {
- new BothModesTest().testIfExactError(
- "expected type 'sequence' for items but got type 'depset' instead",
- "depset(items = depset(), transitive = [depset()])");
+ new Scenario()
+ .testIfExactError(
+ "expected type 'sequence' for items but got type 'depset' instead",
+ "depset(items = depset(), transitive = [depset()])");
}
@Test
public void testTooManyPositionals() throws Exception {
- new BothModesTest()
+ new Scenario()
.testIfErrorContains(
"depset() accepts no more than 2 positional arguments but got 3",
"depset([], 'default', [])");
@@ -272,10 +275,10 @@
@Test
public void testIncompatibleUnion() throws Exception {
- new BothModesTest("--incompatible_depset_union=true")
+ new Scenario("--incompatible_depset_union=true")
.testIfErrorContains("`+` operator on a depset is forbidden", "depset([]) + ['a']");
- new BothModesTest("--incompatible_depset_union=true")
+ new Scenario("--incompatible_depset_union=true")
.testIfErrorContains("`|` operator on a depset is forbidden", "depset([]) | ['a']");
}
@@ -288,7 +291,7 @@
@Test
public void testUnionOrder() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"def func():",
" s1 = depset()",
@@ -303,7 +306,7 @@
@Test
public void testUnionIncompatibleOrder() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
checkEvalError(
"Order mismatch: topological != postorder",
"depset(['a', 'b'], order='postorder') + depset(['c', 'd'], order='topological')");
@@ -311,7 +314,7 @@
@Test
public void testFunctionReturnsDepset() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"def func():", //
" t = depset()",
@@ -324,7 +327,7 @@
@Test
public void testPlusEqualsWithList() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"def func():", //
" t = depset()",
@@ -336,7 +339,7 @@
@Test
public void testPlusEqualsNoSideEffects() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"def func():",
" s1 = depset()",
@@ -350,7 +353,7 @@
@Test
public void testFuncParamNoSideEffects() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"def func1(t):",
" t += ['b']",
@@ -365,7 +368,7 @@
@Test
public void testTransitiveOrdering() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"def func():",
" sa = depset(['a'], order='postorder')",
@@ -379,7 +382,7 @@
@Test
public void testLeftRightDirectOrdering() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"def func():",
" t = depset()",
@@ -394,7 +397,7 @@
@Test
public void testToString() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"s = depset() + [2, 4, 6] + [3, 4, 5]", //
"x = str(s)");
@@ -403,7 +406,7 @@
@Test
public void testToStringWithOrder() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"s = depset(order = 'topological') + [2, 4, 6] + [3, 4, 5]", //
"x = str(s)");
@@ -416,7 +419,7 @@
@Test
public void testToList() throws Exception {
- thread = newStarlarkThreadWithSkylarkOptions("--incompatible_depset_union=false");
+ setSemantics("--incompatible_depset_union=false");
exec(
"s = depset() + [2, 4, 6] + [3, 4, 5]", //
"x = s.to_list()");
@@ -520,8 +523,7 @@
@Test
public void testMutableDepsetElementsLegacyBehavior() throws Exception {
// See b/144992997 and github.com/bazelbuild/bazel/issues/10313.
- thread =
- newStarlarkThreadWithSkylarkOptions("--incompatible_always_check_depset_elements=false");
+ setSemantics("--incompatible_always_check_depset_elements=false");
// Test legacy depset(...) and new depset(direct=...) constructors.
@@ -554,8 +556,7 @@
@Test
public void testMutableDepsetElementsDesiredBehavior() throws Exception {
// See b/144992997 and github.com/bazelbuild/bazel/issues/10313.
- thread =
- newStarlarkThreadWithSkylarkOptions("--incompatible_always_check_depset_elements=true");
+ setSemantics("--incompatible_always_check_depset_elements=true");
// Test legacy depset(...) and new depset(direct=...) constructors.
@@ -588,7 +589,7 @@
@Test
public void testDepthExceedsLimitDuringIteration() throws Exception {
NestedSet.setApplicationDepthLimit(2000);
- new SkylarkTest()
+ new Scenario()
.setUp(
"def create_depset(depth):",
" x = depset([0])",
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvalUtilsTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EvalUtilsTest.java
index 677f90b..f2ee7d1 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/EvalUtilsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/EvalUtilsTest.java
@@ -74,19 +74,22 @@
assertThat(EvalUtils.isImmutable(makeList(null))).isTrue();
assertThat(EvalUtils.isImmutable(makeDict(null))).isTrue();
- assertThat(EvalUtils.isImmutable(makeList(thread.mutability()))).isFalse();
- assertThat(EvalUtils.isImmutable(makeDict(thread.mutability()))).isFalse();
+
+ Mutability mu = Mutability.create("test");
+ assertThat(EvalUtils.isImmutable(makeList(mu))).isFalse();
+ assertThat(EvalUtils.isImmutable(makeDict(mu))).isFalse();
}
@Test
public void testDatatypeMutabilityDeep() throws Exception {
+ Mutability mu = Mutability.create("test");
assertThat(EvalUtils.isImmutable(Tuple.of(makeList(null)))).isTrue();
-
- assertThat(EvalUtils.isImmutable(Tuple.of(makeList(thread.mutability())))).isFalse();
+ assertThat(EvalUtils.isImmutable(Tuple.of(makeList(mu)))).isFalse();
}
@Test
public void testComparatorWithDifferentTypes() throws Exception {
+ Mutability mu = Mutability.create("test");
Object[] objects = {
"1",
2,
@@ -94,10 +97,10 @@
Starlark.NONE,
Tuple.of(1, 2, 3),
Tuple.of("1", "2", "3"),
- StarlarkList.of(thread.mutability(), 1, 2, 3),
- StarlarkList.of(thread.mutability(), "1", "2", "3"),
- Dict.of(thread.mutability(), "key", 123),
- Dict.of(thread.mutability(), 123, "value"),
+ StarlarkList.of(mu, 1, 2, 3),
+ StarlarkList.of(mu, "1", "2", "3"),
+ Dict.of(mu, "key", 123),
+ Dict.of(mu, 123, "value"),
StructProvider.STRUCT.create(ImmutableMap.of("key", (Object) "value"), "no field %s"),
};
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
index e53b709..d4459f7 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
@@ -19,9 +19,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
-import com.google.devtools.build.lib.testutil.TestMode;
import java.util.Collections;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -29,29 +27,13 @@
/** Test of evaluation behavior. (Implicitly uses lexer + parser.) */
// TODO(adonovan): separate tests of parser, resolver, Starlark core evaluator,
// and BUILD and .bzl features.
-// TODO(adonovan): make final. Requires changing SkylarkEvaluationTest.
@RunWith(JUnit4.class)
-public class EvaluationTest extends EvaluationTestCase {
- @Before
- public final void setBuildMode() throws Exception {
- super.setMode(TestMode.BUILD);
- }
-
- /**
- * Creates a new instance of {@code ModalTestCase}.
- *
- * <p>If a test uses this method, it allows potential subclasses to run the very same test in a
- * different mode in subclasses
- */
- protected ModalTestCase newTest(String... skylarkOptions) {
- return new BuildTest(skylarkOptions);
- }
+public final class EvaluationTest extends EvaluationTestCase {
@Test
public void testExecutionStopsAtFirstError() throws Exception {
EventCollector printEvents = new EventCollector();
- StarlarkThread thread =
- createStarlarkThread(mutability, StarlarkThread.makeDebugPrintHandler(printEvents));
+ StarlarkThread thread = createStarlarkThread(StarlarkThread.makeDebugPrintHandler(printEvents));
ParserInput input = ParserInput.fromLines("print('hello'); x = 1//0; print('goodbye')");
assertThrows(EvalException.class, () -> EvalUtils.exec(input, thread));
@@ -64,8 +46,7 @@
@Test
public void testExecutionNotStartedOnInterrupt() throws Exception {
EventCollector printEvents = new EventCollector();
- StarlarkThread thread =
- createStarlarkThread(mutability, StarlarkThread.makeDebugPrintHandler(printEvents));
+ StarlarkThread thread = createStarlarkThread(StarlarkThread.makeDebugPrintHandler(printEvents));
ParserInput input = ParserInput.fromLines("print('hello');");
try {
@@ -81,7 +62,7 @@
@Test
public void testForLoopAbortedOnInterrupt() throws Exception {
- StarlarkThread thread = createStarlarkThread(mutability, (th, msg) -> {});
+ StarlarkThread thread = createStarlarkThread((th, msg) -> {});
InterruptFunction interruptFunction = new InterruptFunction();
thread.getGlobals().put("interrupt", interruptFunction);
@@ -104,7 +85,7 @@
@Test
public void testForComprehensionAbortedOnInterrupt() throws Exception {
- StarlarkThread thread = createStarlarkThread(mutability, (th, msg) -> {});
+ StarlarkThread thread = createStarlarkThread((th, msg) -> {});
InterruptFunction interruptFunction = new InterruptFunction();
thread.getGlobals().put("interrupt", interruptFunction);
@@ -122,7 +103,7 @@
@Test
public void testFunctionCallsNotStartedOnInterrupt() throws Exception {
- StarlarkThread thread = createStarlarkThread(mutability, (th, msg) -> {});
+ StarlarkThread thread = createStarlarkThread((th, msg) -> {});
InterruptFunction interruptFunction = new InterruptFunction();
thread.getGlobals().put("interrupt", interruptFunction);
@@ -159,10 +140,10 @@
}
}
- private static StarlarkThread createStarlarkThread(
- Mutability mutability, StarlarkThread.PrintHandler printHandler) {
+ private static StarlarkThread createStarlarkThread(StarlarkThread.PrintHandler printHandler) {
+ Mutability mu = Mutability.create("test");
StarlarkThread thread =
- StarlarkThread.builder(mutability)
+ StarlarkThread.builder(mu)
.useDefaultSemantics()
// Provide the UNIVERSE for print... this should not be necessary
.setGlobals(Module.createForBuiltins(Starlark.UNIVERSE))
@@ -173,7 +154,7 @@
@Test
public void testExprs() throws Exception {
- newTest()
+ new Scenario()
.testExpression("'%sx' % 'foo' + 'bar1'", "fooxbar1")
.testExpression("('%sx' % 'foo') + 'bar2'", "fooxbar2")
.testExpression("'%sx' % ('foo' + 'bar3')", "foobar3x")
@@ -187,17 +168,17 @@
@Test
public void testListExprs() throws Exception {
- newTest().testExactOrder("[1, 2, 3]", 1, 2, 3).testExactOrder("(1, 2, 3)", 1, 2, 3);
+ new Scenario().testExactOrder("[1, 2, 3]", 1, 2, 3).testExactOrder("(1, 2, 3)", 1, 2, 3);
}
@Test
public void testStringFormatMultipleArgs() throws Exception {
- newTest().testExpression("'%sY%s' % ('X', 'Z')", "XYZ");
+ new Scenario().testExpression("'%sY%s' % ('X', 'Z')", "XYZ");
}
@Test
public void testConditionalExpressions() throws Exception {
- newTest()
+ new Scenario()
.testExpression("1 if True else 2", 1)
.testExpression("1 if False else 2", 2)
.testExpression("1 + 2 if 3 + 4 else 5 + 6", 3);
@@ -205,7 +186,7 @@
@Test
public void testListComparison() throws Exception {
- newTest()
+ new Scenario()
.testExpression("[] < [1]", true)
.testExpression("[1] < [1, 1]", true)
.testExpression("[1, 1] < [1, 2]", true)
@@ -225,7 +206,7 @@
@Test
public void testSetComparison() throws Exception {
- newTest().testIfExactError("Cannot compare depsets", "depset([1, 2]) < depset([3, 4])");
+ new Scenario().testIfExactError("Cannot compare depsets", "depset([1, 2]) < depset([3, 4])");
}
@Test
@@ -247,7 +228,7 @@
}
};
- newTest()
+ new Scenario()
.update(sum.getName(), sum)
.testExpression("sum(1, 2, 3, 4, 5, 6)", 21)
.testExpression("sum", sum)
@@ -256,7 +237,7 @@
@Test
public void testNotCallInt() throws Exception {
- newTest()
+ new Scenario()
.setUp("sum = 123456")
.testLookup("sum", 123456)
.testIfExactError("'int' object is not callable", "sum(1, 2, 3, 4, 5, 6)")
@@ -265,7 +246,8 @@
@Test
public void testComplexFunctionCall() throws Exception {
- newTest().setUp("functions = [min, max]", "l = [1,2]")
+ new Scenario()
+ .setUp("functions = [min, max]", "l = [1,2]")
.testEval("(functions[0](l), functions[1](l))", "(1, 2)");
}
@@ -288,7 +270,7 @@
}
};
- newTest()
+ new Scenario()
.update(kwargs.getName(), kwargs)
.testEval(
"kwargs(foo=1, bar='bar', wiz=[1,2,3]).items()",
@@ -300,7 +282,7 @@
@Test
public void testModulo() throws Exception {
- newTest()
+ new Scenario()
.testExpression("6 % 2", 0)
.testExpression("6 % 4", 2)
.testExpression("3 % 6", 3)
@@ -312,7 +294,7 @@
@Test
public void testMult() throws Exception {
- newTest()
+ new Scenario()
.testExpression("6 * 7", 42)
.testExpression("3 * 'ab'", "ababab")
.testExpression("0 * 'ab'", "")
@@ -323,12 +305,12 @@
@Test
public void testSlashOperatorIsForbidden() throws Exception {
- newTest().testIfErrorContains("The `/` operator is not allowed.", "5 / 2");
+ new Scenario().testIfErrorContains("The `/` operator is not allowed.", "5 / 2");
}
@Test
public void testFloorDivision() throws Exception {
- newTest()
+ new Scenario()
.testExpression("6 // 2", 3)
.testExpression("6 // 4", 1)
.testExpression("3 // 6", 0)
@@ -342,7 +324,7 @@
@Test
public void testCheckedArithmetic() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains("integer overflow", "2000000000 + 2000000000")
.testIfErrorContains("integer overflow", "1234567890 * 987654321")
.testIfErrorContains("integer overflow", "- 2000000000 - 2000000000")
@@ -354,7 +336,7 @@
@Test
public void testOperatorPrecedence() throws Exception {
- newTest()
+ new Scenario()
.testExpression("2 + 3 * 4", 14)
.testExpression("2 + 3 // 4", 2)
.testExpression("2 * 3 + 4 // -2", 4);
@@ -362,21 +344,27 @@
@Test
public void testConcatStrings() throws Exception {
- newTest().testExpression("'foo' + 'bar'", "foobar");
+ new Scenario().testExpression("'foo' + 'bar'", "foobar");
}
- @SuppressWarnings("unchecked")
@Test
public void testConcatLists() throws Exception {
+ new Scenario()
+ .testExactOrder("[1,2] + [3,4]", 1, 2, 3, 4)
+ .testExactOrder("(1,2)", 1, 2)
+ .testExactOrder("(1,2) + (3,4)", 1, 2, 3, 4);
+
// TODO(fwe): cannot be handled by current testing suite
// list
Object x = eval("[1,2] + [3,4]");
- assertThat((Iterable<Object>) x).containsExactly(1, 2, 3, 4).inOrder();
- assertThat(x).isEqualTo(StarlarkList.of(thread.mutability(), 1, 2, 3, 4));
+ assertThat((Iterable<?>) x).containsExactly(1, 2, 3, 4).inOrder();
+ assertThat(x).isInstanceOf(StarlarkList.class);
assertThat(EvalUtils.isImmutable(x)).isFalse();
// tuple
x = eval("(1,2) + (3,4)");
+ assertThat((Iterable<?>) x).containsExactly(1, 2, 3, 4).inOrder();
+ assertThat(x).isInstanceOf(Tuple.class);
assertThat(x).isEqualTo(Tuple.of(1, 2, 3, 4));
assertThat(EvalUtils.isImmutable(x)).isTrue();
@@ -385,28 +373,30 @@
@Test
public void testListComprehensions() throws Exception {
- newTest()
+ new Scenario()
.testExactOrder("['foo/%s.java' % x for x in []]")
- .testExactOrder("['foo/%s.java' % y for y in ['bar', 'wiz', 'quux']]", "foo/bar.java",
- "foo/wiz.java", "foo/quux.java")
- .testExactOrder("['%s/%s.java' % (z, t) for z in ['foo', 'bar'] "
- + "for t in ['baz', 'wiz', 'quux']]",
+ .testExactOrder(
+ "['foo/%s.java' % y for y in ['bar', 'wiz', 'quux']]",
+ "foo/bar.java", "foo/wiz.java", "foo/quux.java")
+ .testExactOrder(
+ "['%s/%s.java' % (z, t) for z in ['foo', 'bar'] " + "for t in ['baz', 'wiz', 'quux']]",
"foo/baz.java",
"foo/wiz.java",
"foo/quux.java",
"bar/baz.java",
"bar/wiz.java",
"bar/quux.java")
- .testExactOrder("['%s/%s.java' % (b, b) for a in ['foo', 'bar'] "
- + "for b in ['baz', 'wiz', 'quux']]",
+ .testExactOrder(
+ "['%s/%s.java' % (b, b) for a in ['foo', 'bar'] " + "for b in ['baz', 'wiz', 'quux']]",
"baz/baz.java",
"wiz/wiz.java",
"quux/quux.java",
"baz/baz.java",
"wiz/wiz.java",
"quux/quux.java")
- .testExactOrder("['%s/%s.%s' % (c, d, e) for c in ['foo', 'bar'] "
- + "for d in ['baz', 'wiz', 'quux'] for e in ['java', 'cc']]",
+ .testExactOrder(
+ "['%s/%s.%s' % (c, d, e) for c in ['foo', 'bar'] "
+ + "for d in ['baz', 'wiz', 'quux'] for e in ['java', 'cc']]",
"foo/baz.java",
"foo/baz.cc",
"foo/wiz.java",
@@ -425,10 +415,10 @@
@Test
public void testNestedListComprehensions() throws Exception {
- newTest()
+ new Scenario()
.setUp("li = [[1, 2], [3, 4]]")
.testExactOrder("[j for i in li for j in i]", 1, 2, 3, 4);
- newTest()
+ new Scenario()
.setUp("input = [['abc'], ['def', 'ghi']]\n")
.testExactOrder(
"['%s %s' % (b, c) for a in input for b in a for c in b.elems()]",
@@ -437,48 +427,92 @@
@Test
public void testListComprehensionsMultipleVariables() throws Exception {
- newTest().testEval("[x + y for x, y in [(1, 2), (3, 4)]]", "[3, 7]")
+ new Scenario()
+ .testEval("[x + y for x, y in [(1, 2), (3, 4)]]", "[3, 7]")
.testEval("[z + t for (z, t) in [[1, 2], [3, 4]]]", "[3, 7]");
}
@Test
public void testListComprehensionsMultipleVariablesFail() throws Exception {
- newTest()
+ new Scenario()
.testIfErrorContains(
"assignment length mismatch: left-hand side has length 3, but right-hand side"
+ " evaluates to value of length 2",
"[x + y for x, y, z in [(1, 2), (3, 4)]]")
.testIfExactError("type 'int' is not iterable", "[x + y for x, y in (1, 2)]");
+
+ new Scenario()
+ .testIfErrorContains(
+ "assignment length mismatch: left-hand side has length 3, but right-hand side "
+ + "evaluates to value of length 2",
+ "def foo (): return [x + y for x, y, z in [(1, 2), (3, 4)]]",
+ "foo()");
+
+ new Scenario()
+ .testIfErrorContains(
+ "type 'int' is not iterable", "def bar (): return [x + y for x, y in (1, 2)]", "bar()");
+
+ new Scenario()
+ .testIfErrorContains(
+ "assignment length mismatch: left-hand side has length 3, but right-hand side "
+ + "evaluates to value of length 2",
+ "[x + y for x, y, z in [(1, 2), (3, 4)]]");
+
+ new Scenario()
+ .testIfErrorContains("type 'int' is not iterable", "[x2 + y2 for x2, y2 in (1, 2)]");
+
+ new Scenario()
+ // returns [2] in Python, it's an error in Skylark
+ .testIfErrorContains("must have at least one item", "[2 for [] in [()]]");
}
@Test
public void testListComprehensionsWithFiltering() throws Exception {
- newTest()
+ new Scenario()
.setUp("range3 = [0, 1, 2]")
.testEval("[a for a in (4, None, 2, None, 1) if a != None]", "[4, 2, 1]")
.testEval("[b+c for b in [0, 1, 2] for c in [0, 1, 2] if b + c > 2]", "[3, 3, 4]")
.testEval("[d+e for d in range3 if d % 2 == 1 for e in range3]", "[1, 2, 3]")
- .testEval("[[f,g] for f in [0, 1, 2, 3, 4] if f for g in [5, 6, 7, 8] if f * g % 12 == 0 ]",
+ .testEval(
+ "[[f,g] for f in [0, 1, 2, 3, 4] if f for g in [5, 6, 7, 8] if f * g % 12 == 0 ]",
"[[2, 6], [3, 8], [4, 6]]")
.testEval("[h for h in [4, 2, 0, 1] if h]", "[4, 2, 1]");
}
@Test
public void testListComprehensionDefinitionOrder() throws Exception {
- new BuildTest()
- .testIfErrorContains(
- "variable 'y' is referenced before assignment", //
- "[x for x in (1, 2) if y for y in (3, 4)]");
-
- new SkylarkTest()
+ // This exercises the .bzl file behavior. This is a dynamic error.
+ // (The error message for BUILD files is slightly different (no "local")
+ // because it doesn't record the scope in the syntax tree.)
+ new Scenario()
.testIfErrorContains(
"local variable 'y' is referenced before assignment", //
"[x for x in (1, 2) if y for y in (3, 4)]");
+
+ // This is the corresponding test for BUILD files.
+ EvalException ex =
+ assertThrows(
+ EvalException.class, () -> execBUILD("[x for x in (1, 2) if y for y in (3, 4)]"));
+ assertThat(ex).hasMessageThat().isEqualTo("variable 'y' is referenced before assignment");
+ }
+
+ private static void execBUILD(String... lines)
+ throws SyntaxError, EvalException, InterruptedException {
+ ParserInput input = ParserInput.fromLines(lines);
+ StarlarkFile file = StarlarkFile.parse(input);
+ StarlarkSemantics semantics = StarlarkSemantics.DEFAULT_SEMANTICS;
+ StarlarkThread thread =
+ StarlarkThread.builder(Mutability.create("test")).setSemantics(semantics).build();
+ ValidationEnvironment.validateFile(file, thread.getGlobals(), semantics, /*isBuildFile=*/ true);
+ if (!file.ok()) {
+ throw new SyntaxError(file.errors());
+ }
+ EvalUtils.exec(file, thread);
}
@Test
public void testTupleDestructuring() throws Exception {
- newTest()
+ new Scenario()
.setUp("a, b = 1, 2")
.testLookup("a", 1)
.testLookup("b", 2)
@@ -489,30 +523,32 @@
@Test
public void testSingleTuple() throws Exception {
- newTest().setUp("(a,) = [1]").testLookup("a", 1);
+ new Scenario().setUp("(a,) = [1]").testLookup("a", 1);
}
@Test
public void testHeterogeneousDict() throws Exception {
- newTest().setUp("d = {'str': 1, 2: 3}", "a = d['str']", "b = d[2]").testLookup("a", 1)
+ new Scenario()
+ .setUp("d = {'str': 1, 2: 3}", "a = d['str']", "b = d[2]")
+ .testLookup("a", 1)
.testLookup("b", 3);
}
@Test
public void testAccessDictWithATupleKey() throws Exception {
- newTest().setUp("x = {(1, 2): 3}[1, 2]").testLookup("x", 3);
+ new Scenario().setUp("x = {(1, 2): 3}[1, 2]").testLookup("x", 3);
}
@Test
public void testDictWithDuplicatedKey() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"Duplicated key \"str\" when creating dictionary", "{'str': 1, 'x': 2, 'str': 3}");
}
@Test
public void testRecursiveTupleDestructuring() throws Exception {
- newTest()
+ new Scenario()
.setUp("((a, b), (c, d)) = [(1, 2), (3, 4)]")
.testLookup("a", 1)
.testLookup("b", 2)
@@ -523,13 +559,15 @@
@Test
public void testListComprehensionAtTopLevel() throws Exception {
// It is allowed to have a loop variable with the same name as a global variable.
- newTest().update("x", 42).setUp("y = [x + 1 for x in [1,2,3]]")
+ new Scenario()
+ .update("x", 42)
+ .setUp("y = [x + 1 for x in [1,2,3]]")
.testExactOrder("y", 2, 3, 4);
}
@Test
public void testDictComprehensions() throws Exception {
- newTest()
+ new Scenario()
.testExpression("{a : a for a in []}", Collections.emptyMap())
.testExpression("{b : b for b in [1, 2]}", ImmutableMap.of(1, 1, 2, 2))
.testExpression(
@@ -544,12 +582,12 @@
@Test
public void testDictComprehensionOnNonIterable() throws Exception {
- newTest().testIfExactError("type 'int' is not iterable", "{k : k for k in 3}");
+ new Scenario().testIfExactError("type 'int' is not iterable", "{k : k for k in 3}");
}
@Test
public void testDictComprehension_ManyClauses() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testExpression(
"{x : x * y for x in range(1, 10) if x % 2 == 0 for y in range(1, 10) if y == x}",
ImmutableMap.of(2, 4, 4, 16, 6, 36, 8, 64));
@@ -557,7 +595,7 @@
@Test
public void testDictComprehensions_MultipleKey() throws Exception {
- newTest()
+ new Scenario()
.testExpression("{x : x for x in [1, 2, 1]}", ImmutableMap.of(1, 1, 2, 2))
.testExpression(
"{y : y for y in ['ab', 'c', 'a' + 'b']}", ImmutableMap.of("ab", "ab", "c", "c"));
@@ -565,8 +603,8 @@
@Test
public void testListConcatenation() throws Exception {
- newTest()
- .testExpression("[1, 2] + [3, 4]", StarlarkList.of(thread.mutability(), 1, 2, 3, 4))
+ new Scenario()
+ .testExpression("[1, 2] + [3, 4]", StarlarkList.of(null, 1, 2, 3, 4))
.testExpression("(1, 2) + (3, 4)", Tuple.of(1, 2, 3, 4))
.testIfExactError("unsupported binary operation: list + tuple", "[1, 2] + (3, 4)")
.testIfExactError("unsupported binary operation: tuple + list", "(1, 2) + [3, 4]");
@@ -574,8 +612,8 @@
@Test
public void testListMultiply() throws Exception {
- Mutability mu = thread.mutability();
- newTest()
+ Mutability mu = Mutability.create("test");
+ new Scenario()
.testExpression("[1, 2, 3] * 1", StarlarkList.of(mu, 1, 2, 3))
.testExpression("[1, 2] * 2", StarlarkList.of(mu, 1, 2, 1, 2))
.testExpression("[1, 2] * 3", StarlarkList.of(mu, 1, 2, 1, 2, 1, 2))
@@ -592,7 +630,7 @@
@Test
public void testTupleMultiply() throws Exception {
- newTest()
+ new Scenario()
.testExpression("(1, 2, 3) * 1", Tuple.of(1, 2, 3))
.testExpression("(1, 2) * 2", Tuple.of(1, 2, 1, 2))
.testExpression("(1, 2) * 3", Tuple.of(1, 2, 1, 2, 1, 2))
@@ -609,53 +647,52 @@
@Test
public void testListComprehensionFailsOnNonSequence() throws Exception {
- newTest().testIfErrorContains("type 'int' is not iterable", "[x + 1 for x in 123]");
+ new Scenario().testIfErrorContains("type 'int' is not iterable", "[x + 1 for x in 123]");
}
@Test
public void testListComprehensionOnStringIsForbidden() throws Exception {
- newTest().testIfErrorContains("type 'string' is not iterable", "[x for x in 'abc']");
+ new Scenario().testIfErrorContains("type 'string' is not iterable", "[x for x in 'abc']");
}
@Test
public void testInvalidAssignment() throws Exception {
- newTest().testIfErrorContains(
- "cannot assign to 'x + 1'", "x + 1 = 2");
+ new Scenario().testIfErrorContains("cannot assign to 'x + 1'", "x + 1 = 2");
}
@Test
public void testListComprehensionOnDictionary() throws Exception {
- newTest().testExactOrder("['var_' + n for n in {'a':1,'b':2}]", "var_a", "var_b");
+ new Scenario().testExactOrder("['var_' + n for n in {'a':1,'b':2}]", "var_a", "var_b");
}
@Test
public void testListComprehensionOnDictionaryCompositeExpression() throws Exception {
- new BuildTest()
+ new Scenario()
.setUp("d = {1:'a',2:'b'}", "l = [d[x] for x in d]")
- .testLookup("l", StarlarkList.of(thread.mutability(), "a", "b"));
+ .testLookup("l", StarlarkList.of(null, "a", "b"));
}
@Test
public void testListComprehensionUpdate() throws Exception {
- new BuildTest()
+ new Scenario()
.setUp("xs = [1, 2, 3]")
- .testIfErrorContains("trying to mutate a locked object",
- "[xs.append(4) for x in xs]");
+ .testIfErrorContains("trying to mutate a locked object", "[xs.append(4) for x in xs]");
}
@Test
public void testNestedListComprehensionUpdate() throws Exception {
- new BuildTest()
+ new Scenario()
.setUp("xs = [1, 2, 3]")
- .testIfErrorContains("trying to mutate a locked object",
- "[xs.append(4) for x in xs for y in xs]");
+ .testIfErrorContains(
+ "trying to mutate a locked object", "[xs.append(4) for x in xs for y in xs]");
}
@Test
public void testListComprehensionUpdateInClause() throws Exception {
- new BuildTest()
+ new Scenario()
.setUp("xs = [1, 2, 3]")
- .testIfErrorContains("trying to mutate a locked object",
+ .testIfErrorContains(
+ "trying to mutate a locked object",
// Use short-circuiting to produce valid output in the event
// the exception is not raised.
"[y for x in xs for y in (xs.append(4) or xs)]");
@@ -663,16 +700,15 @@
@Test
public void testDictComprehensionUpdate() throws Exception {
- new BuildTest()
+ new Scenario()
.setUp("xs = {1:1, 2:2, 3:3}")
- .testIfErrorContains("trying to mutate a locked object",
- "[xs.popitem() for x in xs]");
+ .testIfErrorContains("trying to mutate a locked object", "[xs.popitem() for x in xs]");
}
@Test
public void testListComprehensionScope() throws Exception {
// Test list comprehension creates a scope, so outer variables kept unchanged
- new BuildTest()
+ new Scenario()
.setUp("x = 1", "l = [x * 3 for x in [2]]", "y = x")
.testEval("y", "1")
.testEval("l", "[6]");
@@ -680,7 +716,7 @@
@Test
public void testInOperator() throws Exception {
- newTest()
+ new Scenario()
.testExpression("'b' in ['a', 'b']", Boolean.TRUE)
.testExpression("'c' in ['a', 'b']", Boolean.FALSE)
.testExpression("'b' in ('a', 'b')", Boolean.TRUE)
@@ -694,7 +730,7 @@
@Test
public void testNotInOperator() throws Exception {
- newTest()
+ new Scenario()
.testExpression("'b' not in ['a', 'b']", Boolean.FALSE)
.testExpression("'c' not in ['a', 'b']", Boolean.TRUE)
.testExpression("'b' not in ('a', 'b')", Boolean.FALSE)
@@ -708,7 +744,7 @@
@Test
public void testInFail() throws Exception {
- newTest()
+ new Scenario()
.testIfErrorContains(
"'in <string>' requires string as left operand, not 'int'", "1 in '123'")
.testIfErrorContains("unsupported binary operation: string in int", "'a' in 1");
@@ -716,7 +752,7 @@
@Test
public void testInCompositeForPrecedence() throws Exception {
- newTest().testExpression("not 'a' in ['a'] or 0", 0);
+ new Scenario().testExpression("not 'a' in ['a'] or 0", 0);
}
private StarlarkValue createObjWithStr() {
@@ -732,8 +768,8 @@
@Test
public void testPercentOnDummyValue() throws Exception {
- newTest().update("obj", createObjWithStr()).testExpression("'%s' % obj", "<str marker>");
- newTest()
+ new Scenario().update("obj", createObjWithStr()).testExpression("'%s' % obj", "<str marker>");
+ new Scenario()
.update("unknown", new Dummy())
.testExpression(
"'%s' % unknown",
@@ -742,10 +778,10 @@
@Test
public void testPercentOnTupleOfDummyValues() throws Exception {
- newTest()
+ new Scenario()
.update("obj", createObjWithStr())
.testExpression("'%s %s' % (obj, obj)", "<str marker> <str marker>");
- newTest()
+ new Scenario()
.update("unknown", new Dummy())
.testExpression(
"'%s %s' % (unknown, unknown)",
@@ -755,24 +791,25 @@
@Test
public void testPercOnObjectInvalidFormat() throws Exception {
- newTest()
+ new Scenario()
.update("obj", createObjWithStr())
.testIfExactError("invalid argument <str marker> for format pattern %d", "'%d' % obj");
}
@Test
public void testDictKeys() throws Exception {
- newTest().testExactOrder("{'a': 1}.keys() + ['b', 'c']", "a", "b", "c");
+ new Scenario().testExactOrder("{'a': 1}.keys() + ['b', 'c']", "a", "b", "c");
}
@Test
public void testDictKeysTooManyArgs() throws Exception {
- newTest().testIfExactError("keys() got unexpected positional argument", "{'a': 1}.keys('abc')");
+ new Scenario()
+ .testIfExactError("keys() got unexpected positional argument", "{'a': 1}.keys('abc')");
}
@Test
public void testDictKeysTooManyKeyArgs() throws Exception {
- newTest()
+ new Scenario()
.testIfExactError(
"keys() got unexpected keyword argument 'arg'", "{'a': 1}.keys(arg='abc')");
}
@@ -780,56 +817,23 @@
@Test
public void testDictKeysDuplicateKeyArgs() throws Exception {
// TODO(adonovan): when the duplication is literal, this should be caught by a static check.
- newTest()
+ new Scenario()
.testIfExactError(
"int() got multiple values for argument 'base'", "int('1', base=10, base=16)");
- new SkylarkTest()
+ new Scenario()
.testIfExactError(
"int() got multiple values for argument 'base'", "int('1', base=10, **dict(base=16))");
}
@Test
public void testArgBothPosKey() throws Exception {
- newTest()
+ new Scenario()
.testIfErrorContains(
"int() got multiple values for argument 'base'", "int('2', 3, base=3)");
}
@Test
public void testStaticNameResolution() throws Exception {
- newTest().testIfErrorContains("name 'foo' is not defined", "[foo for x in []]");
- }
-
- @Test
- public void testDefInBuild() throws Exception {
- new BuildTest()
- .testIfErrorContains(
- "function definitions are not allowed in BUILD files", "def func(): pass");
- }
-
- @Test
- public void testForStatementForbiddenInBuild() throws Exception {
- new BuildTest().testIfErrorContains("for loops are not allowed", "for _ in []: pass");
- }
-
- @Test
- public void testIfStatementForbiddenInBuild() throws Exception {
- new BuildTest().testIfErrorContains("if statements are not allowed", "if False: pass");
- }
-
- @Test
- public void testKwargsForbiddenInBuild() throws Exception {
- new BuildTest()
- .testIfErrorContains("**kwargs arguments are not allowed in BUILD files", "print(**dict)");
-
- new BuildTest()
- .testIfErrorContains(
- "**kwargs arguments are not allowed in BUILD files", "len(dict(**{'a': 1}))");
- }
-
- @Test
- public void testArgsForbiddenInBuild() throws Exception {
- new BuildTest()
- .testIfErrorContains("*args arguments are not allowed in BUILD files", "print(*['a'])");
+ new Scenario().testIfErrorContains("name 'foo' is not defined", "[foo for x in []]");
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
index 11e049d..e180595 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
@@ -37,7 +37,7 @@
@Test
public void testStackTraceLocation() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"Traceback (most recent call last):"
+ LINE_SEPARATOR
@@ -64,7 +64,7 @@
@Test
public void testStackTraceWithIf() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"File \"\", line 5"
+ LINE_SEPARATOR
@@ -82,7 +82,7 @@
@Test
public void testStackTraceWithAugmentedAssignment() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"File \"\", line 4"
+ LINE_SEPARATOR
@@ -103,7 +103,7 @@
public void testStackTraceSkipBuiltInOnly() throws Exception {
// The error message should not include the stack trace when there is
// only one built-in function.
- new BothModesTest()
+ new Scenario()
.testIfExactError(
"in call to index(), parameter 'sub' got value of type 'int', want 'string'",
"'test'.index(1)");
@@ -113,7 +113,7 @@
public void testStackTrace() throws Exception {
// Unlike SkylarintegrationTests#testStackTraceErrorInFunction(), this test
// has neither a BUILD nor a bzl file.
- new SkylarkTest()
+ new Scenario()
.testIfExactError(
"Traceback (most recent call last):"
+ LINE_SEPARATOR
@@ -140,7 +140,7 @@
@Test
public void testBuiltinFunctionErrorMessage() throws Exception {
- new BothModesTest()
+ new Scenario()
.testIfErrorContains("substring \"z\" not found in \"abc\"", "'abc'.index('z')")
.testIfErrorContains(
"in call to startswith(), parameter 'sub' got value of type 'int', want 'string or"
@@ -151,7 +151,7 @@
@Test
public void testHasAttr() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testExpression("hasattr(depset(), 'to_list')", Boolean.TRUE)
.testExpression("hasattr('test', 'count')", Boolean.TRUE)
.testExpression("hasattr(dict(a = 1, b = 2), 'items')", Boolean.TRUE)
@@ -160,7 +160,7 @@
@Test
public void testGetAttrMissingField() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfExactError(
"'string' value has no field or method 'not_there'", "getattr('a string', 'not_there')")
.testExpression("getattr('a string', 'not_there', 'use this')", "use this")
@@ -192,7 +192,7 @@
@Test
public void testGetAttrMissingField_typoDetection() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("s", new AStruct())
.testIfExactError(
"'AStruct' value has no field or method 'feild' (did you mean 'field'?)",
@@ -202,14 +202,14 @@
@Test
public void testGetAttrWithMethods() throws Exception {
String msg = "'string' value has no field or method 'cnt'";
- new SkylarkTest()
+ new Scenario()
.testIfExactError(msg, "getattr('a string', 'cnt')")
.testExpression("getattr('a string', 'cnt', 'default')", "default");
}
@Test
public void testDir() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testExpression(
"str(dir({}))",
"[\"clear\", \"get\", \"items\", \"keys\","
@@ -218,18 +218,17 @@
@Test
public void testBoolean() throws Exception {
- new BothModesTest().testExpression("False", Boolean.FALSE).testExpression("True", Boolean.TRUE);
+ new Scenario().testExpression("False", Boolean.FALSE).testExpression("True", Boolean.TRUE);
}
@Test
public void testBooleanUnsupportedOperationFails() throws Exception {
- new BothModesTest()
- .testIfErrorContains("unsupported binary operation: bool + bool", "True + True");
+ new Scenario().testIfErrorContains("unsupported binary operation: bool + bool", "True + True");
}
@Test
public void testListSort() throws Exception {
- new BothModesTest()
+ new Scenario()
.testEval("sorted([0,1,2,3])", "[0, 1, 2, 3]")
.testEval("sorted([])", "[]")
.testEval("sorted([3, 2, 1, 0])", "[0, 1, 2, 3]")
@@ -245,28 +244,24 @@
@Test
public void testDictionaryCopy() throws Exception {
- new BothModesTest()
- .setUp("x = {1 : 2}", "y = dict(x)")
- .testEval("x[1] == 2 and y[1] == 2", "True");
+ new Scenario().setUp("x = {1 : 2}", "y = dict(x)").testEval("x[1] == 2 and y[1] == 2", "True");
}
@Test
public void testDictionaryCopyKeyCollision() throws Exception {
- new BothModesTest()
- .setUp("x = {'test' : 2}", "y = dict(x, test = 3)")
- .testEval("y['test']", "3");
+ new Scenario().setUp("x = {'test' : 2}", "y = dict(x, test = 3)").testEval("y['test']", "3");
}
@Test
public void testDictionaryKeyNotFound() throws Exception {
- new BothModesTest()
+ new Scenario()
.testIfErrorContains("key \"0\" not found in dictionary", "{}['0']")
.testIfErrorContains("key 0 not found in dictionary", "{'0': 1, 2: 3, 4: 5}[0]");
}
@Test
public void testDictionaryAccess() throws Exception {
- new BothModesTest()
+ new Scenario()
.testEval("{1: ['foo']}[1]", "['foo']")
.testExpression("{'4': 8}['4']", 8)
.testExpression("{'a': 'aa', 'b': 'bb', 'c': 'cc'}['b']", "bb");
@@ -274,14 +269,14 @@
@Test
public void testDictionaryVariableAccess() throws Exception {
- new BothModesTest().setUp("d = {'a' : 1}", "a = d['a']").testLookup("a", 1);
+ new Scenario().setUp("d = {'a' : 1}", "a = d['a']").testLookup("a", 1);
}
@Test
public void testDictionaryCreation() throws Exception {
String expected = "{'a': 1, 'b': 2, 'c': 3}";
- new BothModesTest()
+ new Scenario()
.testEval("dict([('a', 1), ('b', 2), ('c', 3)])", expected)
.testEval("dict(a = 1, b = 2, c = 3)", expected)
.testEval("dict([('a', 1)], b = 2, c = 3)", expected);
@@ -289,19 +284,19 @@
@Test
public void testDictionaryCreationInnerLists() throws Exception {
- new BothModesTest().testEval("dict([[1, 2], [3, 4]], a = 5)", "{1: 2, 3: 4, 'a': 5}");
+ new Scenario().testEval("dict([[1, 2], [3, 4]], a = 5)", "{1: 2, 3: 4, 'a': 5}");
}
@Test
public void testDictionaryCreationEmpty() throws Exception {
- new BothModesTest().testEval("dict()", "{}").testEval("dict([])", "{}");
+ new Scenario().testEval("dict()", "{}").testEval("dict([])", "{}");
}
@Test
public void testDictionaryCreationDifferentKeyTypes() throws Exception {
String expected = "{'a': 1, 2: 3}";
- new BothModesTest()
+ new Scenario()
.testEval("dict([('a', 1), (2, 3)])", expected)
.testEval("dict([(2, 3)], a = 1)", expected);
}
@@ -310,15 +305,15 @@
public void testDictionaryCreationKeyCollision() throws Exception {
String expected = "{'a': 1, 'b': 2, 'c': 3}";
- new BothModesTest()
+ new Scenario()
.testEval("dict([('a', 42), ('b', 2), ('a', 1), ('c', 3)])", expected)
.testEval("dict([('a', 42)], a = 1, b = 2, c = 3)", expected);
- new SkylarkTest().testEval("dict([('a', 42)], **{'a': 1, 'b': 2, 'c': 3})", expected);
+ new Scenario().testEval("dict([('a', 42)], **{'a': 1, 'b': 2, 'c': 3})", expected);
}
@Test
public void testDictionaryCreationInvalidPositional() throws Exception {
- new BothModesTest()
+ new Scenario()
.testIfErrorContains("in dict, got string, want iterable", "dict('a')")
.testIfErrorContains(
"in dict, dictionary update sequence element #0 is not iterable (string)",
@@ -336,7 +331,7 @@
@Test
public void testDictionaryValues() throws Exception {
- new BothModesTest()
+ new Scenario()
.testEval("{1: 'foo'}.values()", "['foo']")
.testEval("{}.values()", "[]")
.testEval("{True: 3, False: 5}.values()", "[3, 5]")
@@ -346,7 +341,7 @@
@Test
public void testDictionaryKeys() throws Exception {
- new BothModesTest()
+ new Scenario()
.testEval("{1: 'foo'}.keys()", "[1]")
.testEval("{}.keys()", "[]")
.testEval("{True: 3, False: 5}.keys()", "[True, False]")
@@ -356,7 +351,7 @@
@Test
public void testDictionaryGet() throws Exception {
- new BuildTest()
+ new Scenario()
.testExpression("{1: 'foo'}.get(1)", "foo")
.testExpression("{1: 'foo'}.get(2)", Starlark.NONE)
.testExpression("{1: 'foo'}.get(2, 'a')", "a")
@@ -366,7 +361,7 @@
@Test
public void testDictionaryItems() throws Exception {
- new BothModesTest()
+ new Scenario()
.testEval("{'a': 'foo'}.items()", "[('a', 'foo')]")
.testEval("{}.items()", "[]")
.testEval("{1: 3, 2: 5}.items()", "[(1, 3), (2, 5)]")
@@ -375,7 +370,7 @@
@Test
public void testDictionaryClear() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp(
"d = {1: 'foo', 2: 'bar', 3: 'baz'}",
"len(d) == 3 or fail('clear 1')",
@@ -385,7 +380,7 @@
@Test
public void testDictionaryPop() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"KeyError: 1",
"d = {1: 'foo', 2: 'bar', 3: 'baz'}\n"
@@ -400,7 +395,7 @@
@Test
public void testDictionaryPopItem() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"popitem(): dictionary is empty",
"d = {2: 'bar', 3: 'baz', 1: 'foo'}\n"
@@ -414,17 +409,17 @@
@Test
public void testDictionaryUpdate() throws Exception {
- new BothModesTest()
+ new Scenario()
.setUp("foo = {'a': 2}", "foo.update({'b': 4})")
.testEval("foo", "{'a': 2, 'b': 4}");
- new BothModesTest()
+ new Scenario()
.setUp("foo = {'a': 2}", "foo.update({'a': 3, 'b': 4})")
.testEval("foo", "{'a': 3, 'b': 4}");
}
@Test
public void testDictionarySetDefault() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp(
"d = {2: 'bar', 1: 'foo'}",
"len(d) == 2 or fail('setdefault 0')",
@@ -437,7 +432,7 @@
@Test
public void testListIndexMethod() throws Exception {
- new BothModesTest()
+ new Scenario()
.testExpression("['a', 'b', 'c'].index('a')", 0)
.testExpression("['a', 'b', 'c'].index('b')", 1)
.testExpression("['a', 'b', 'c'].index('c')", 2)
@@ -451,7 +446,7 @@
@Test
public void testHash() throws Exception {
// We specify the same string hashing algorithm as String.hashCode().
- new SkylarkTest()
+ new Scenario()
.testExpression("hash('skylark')", "skylark".hashCode())
.testExpression("hash('google')", "google".hashCode())
.testIfErrorContains(
@@ -461,7 +456,7 @@
@Test
public void testRangeType() throws Exception {
- new BothModesTest()
+ new Scenario()
.setUp("a = range(3)")
.testExpression("len(a)", 3)
.testExpression("str(a)", "range(0, 3)")
@@ -532,7 +527,7 @@
@Test
public void testEnumerate() throws Exception {
- new BothModesTest()
+ new Scenario()
.testExpression("str(enumerate([]))", "[]")
.testExpression("str(enumerate([5]))", "[(0, 5)]")
.testExpression("str(enumerate([5, 3]))", "[(0, 5), (1, 3)]")
@@ -542,12 +537,12 @@
@Test
public void testEnumerateBadArg() throws Exception {
- new BothModesTest().testIfErrorContains("type 'string' is not iterable", "enumerate('a')");
+ new Scenario().testIfErrorContains("type 'string' is not iterable", "enumerate('a')");
}
@Test
public void testReassignmentOfPrimitivesNotForbiddenByCoreLanguage() throws Exception {
- new BuildTest()
+ new Scenario()
.setUp("cc_binary = (['hello.cc'])")
.testIfErrorContains(
"'list' object is not callable",
@@ -556,34 +551,34 @@
@Test
public void testLenOnString() throws Exception {
- new BothModesTest().testExpression("len('abc')", 3);
+ new Scenario().testExpression("len('abc')", 3);
}
@Test
public void testLenOnList() throws Exception {
- new BothModesTest().testExpression("len([1,2,3])", 3);
+ new Scenario().testExpression("len([1,2,3])", 3);
}
@Test
public void testLenOnDict() throws Exception {
- new BothModesTest().testExpression("len({'a' : 1, 'b' : 2})", 2);
+ new Scenario().testExpression("len({'a' : 1, 'b' : 2})", 2);
}
@Test
public void testLenOnBadType() throws Exception {
- new BothModesTest().testIfErrorContains("int is not iterable", "len(1)");
+ new Scenario().testIfErrorContains("int is not iterable", "len(1)");
}
@Test
public void testIndexOnFunction() throws Exception {
- new BothModesTest()
+ new Scenario()
.testIfErrorContains("type 'function' has no operator [](int)", "len[1]")
.testIfErrorContains("invalid slice operand: function", "len[1:4]");
}
@Test
public void testBool() throws Exception {
- new BothModesTest()
+ new Scenario()
.testExpression("bool(1)", Boolean.TRUE)
.testExpression("bool(0)", Boolean.FALSE)
.testExpression("bool([1, 2])", Boolean.TRUE)
@@ -593,7 +588,7 @@
@Test
public void testStr() throws Exception {
- new BothModesTest()
+ new Scenario()
.testExpression("str(1)", "1")
.testExpression("str(-2)", "-2")
.testExpression("str([1, 2])", "[1, 2]")
@@ -605,12 +600,12 @@
@Test
public void testStrFunction() throws Exception {
- new SkylarkTest().setUp("def foo(x): pass").testExpression("str(foo)", "<function foo>");
+ new Scenario().setUp("def foo(x): pass").testExpression("str(foo)", "<function foo>");
}
@Test
public void testType() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testExpression("type(1)", "int")
.testExpression("type('a')", "string")
.testExpression("type([1, 2])", "list")
@@ -622,7 +617,7 @@
@Test
public void testZipFunction() throws Exception {
- new BothModesTest()
+ new Scenario()
.testExpression("str(zip())", "[]")
.testExpression("str(zip([1, 2]))", "[(1,), (2,)]")
.testExpression("str(zip([1, 2], ['a', 'b']))", "[(1, \"a\"), (2, \"b\")]")
@@ -642,13 +637,13 @@
String input, Object chars,
String expLeft, String expRight, String expBoth) throws Exception {
if (chars == null) {
- new BothModesTest()
+ new Scenario()
.update("s", input)
.testExpression("s.lstrip()", expLeft)
.testExpression("s.rstrip()", expRight)
.testExpression("s.strip()", expBoth);
} else {
- new BothModesTest()
+ new Scenario()
.update("s", input)
.update("chars", chars)
.testExpression("s.lstrip(chars)", expLeft)
@@ -684,14 +679,12 @@
@Test
public void testFail() throws Exception {
- new SkylarkTest()
- .testIfErrorContains("abc", "fail('abc')")
- .testIfErrorContains("18", "fail(18)");
+ new Scenario().testIfErrorContains("abc", "fail('abc')").testIfErrorContains("18", "fail(18)");
}
@Test
public void testTupleCoercion() throws Exception {
- new BothModesTest()
+ new Scenario()
.testExpression("tuple([1, 2]) == (1, 2)", true)
// Depends on current implementation of dict
.testExpression("tuple({1: 'foo', 2: 'bar'}) == (1, 2)", true);
@@ -702,7 +695,7 @@
// keyword, or may be None, even in places where it does not quite make sense.
@Test
public void testLegacyNamed() throws Exception {
- new SkylarkTest("--incompatible_restrict_named_params=false")
+ new Scenario("--incompatible_restrict_named_params=false")
// Parameters which may be specified by keyword but are not explicitly 'named'.
.testExpression("all(elements=[True, True])", Boolean.TRUE)
.testExpression("any(elements=[True, False])", Boolean.TRUE)
@@ -740,7 +733,7 @@
@Test
public void testExperimentalStarlarkConfig() throws Exception {
- new SkylarkTest("--incompatible_restrict_named_params")
+ new Scenario("--incompatible_restrict_named_params")
.testIfErrorContains(
"join() got named argument for positional-only parameter 'elements'",
"','.join(elements=['foo', 'bar'])");
@@ -748,14 +741,14 @@
@Test
public void testStringJoinRequiresStrings() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"expected string for sequence element 1, got 'int'", "', '.join(['foo', 2])");
}
@Test
public void testDepsetItemsKeywordAndPositional() throws Exception {
- new SkylarkTest("--incompatible_disable_depset_items=false")
+ new Scenario("--incompatible_disable_depset_items=false")
.testIfErrorContains(
"parameter 'items' cannot be specified both positionally and by keyword",
"depset([0, 1], 'default', items=[0,1])");
@@ -763,7 +756,7 @@
@Test
public void testDepsetDirectInvalidType() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"expected type 'sequence' for direct but got type 'string' instead",
"depset(direct='hello')");
@@ -771,7 +764,7 @@
@Test
public void testDisableDepsetItems() throws Exception {
- new SkylarkTest("--incompatible_disable_depset_items")
+ new Scenario("--incompatible_disable_depset_items")
.setUp("x = depset([0])", "y = depset(direct = [1])")
.testEval("depset([2, 3], transitive = [x, y]).to_list()", "[0, 1, 2, 3]")
.testIfErrorContains(
@@ -787,7 +780,7 @@
@Test
public void testDepsetDepthLimit() throws Exception {
NestedSet.setApplicationDepthLimit(2000);
- new SkylarkTest()
+ new Scenario()
.setUp(
"def create_depset(depth):",
" x = depset([0])",
@@ -806,7 +799,7 @@
@Test
public void testDepsetDebugDepth() throws Exception {
NestedSet.setApplicationDepthLimit(2000);
- new SkylarkTest("--debug_depset_depth=true")
+ new Scenario("--debug_depset_depth=true")
.setUp(
"def create_depset(depth):",
" x = depset([0])",
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
index 7256e3c..403fbce 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -35,35 +35,19 @@
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
-import com.google.devtools.build.lib.testutil.TestMode;
+import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
import java.util.List;
import java.util.Map;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests of Starlark evaluation. */
-// This test uses 'extends' to make a copy of EvaluationTest whose
-// mode is overridden to SKYLARK, changing various environmental parameters.
+// There is no clear distinction between this and EvaluationTest.
+// TODO(adonovan): reorganize.
@SkylarkGlobalLibrary // required for @SkylarkCallable-annotated methods
@RunWith(JUnit4.class)
-public final class SkylarkEvaluationTest extends EvaluationTest {
-
- @Before
- public final void setup() throws Exception {
- setMode(TestMode.SKYLARK);
- }
-
- /**
- * Creates an instance of {@code SkylarkTest} in order to run the tests from the base class in a
- * Skylark context
- */
- @Override
- protected ModalTestCase newTest(String... skylarkOptions) {
- return new SkylarkTest(skylarkOptions);
- }
+public final class SkylarkEvaluationTest extends EvaluationTestCase {
@Immutable
static class Bad {
@@ -543,7 +527,7 @@
// declaration, due to the interface's method declaration being generic.
@Test
public void testParameterizedMock() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new ParameterizedMock())
.setUp("result = mock.method('bar')")
.testLookup("result", "bar");
@@ -551,22 +535,16 @@
@Test
public void testSimpleIf() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " a = 0",
- " x = 0",
- " if x: a = 5",
- " return a",
- "a = foo()").testLookup("a", 0);
+ new Scenario()
+ .setUp("def foo():", " a = 0", " x = 0", " if x: a = 5", " return a", "a = foo()")
+ .testLookup("a", 0);
}
@Test
public void testIfPass() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " a = 1",
- " x = True",
- " if x: pass",
- " return a",
- "a = foo()").testLookup("a", 1);
+ new Scenario()
+ .setUp("def foo():", " a = 1", " x = True", " if x: pass", " return a", "a = foo()")
+ .testLookup("a", 1);
}
@Test
@@ -578,17 +556,20 @@
private void executeNestedIf(int x, int y, int expected) throws Exception {
String fun = String.format("foo%s%s", x, y);
- new SkylarkTest().setUp("def " + fun + "():",
- " x = " + x,
- " y = " + y,
- " a = 0",
- " b = 0",
- " if x:",
- " if y:",
- " a = 2",
- " b = 3",
- " return a + b",
- "x = " + fun + "()").testLookup("x", expected);
+ new Scenario()
+ .setUp(
+ "def " + fun + "():",
+ " x = " + x,
+ " y = " + y,
+ " a = 0",
+ " b = 0",
+ " if x:",
+ " if y:",
+ " a = 2",
+ " b = 3",
+ " return a + b",
+ "x = " + fun + "()")
+ .testLookup("x", expected);
}
@Test
@@ -598,14 +579,17 @@
}
private void executeIfElse(String fun, String y, int expected) throws Exception {
- new SkylarkTest().setUp("def " + fun + "():",
- " y = '" + y + "'",
- " x = 5",
- " if x:",
- " if y: a = 2",
- " else: a = 3",
- " return a",
- "z = " + fun + "()").testLookup("z", expected);
+ new Scenario()
+ .setUp(
+ "def " + fun + "():",
+ " y = '" + y + "'",
+ " x = 5",
+ " if x:",
+ " if y: a = 2",
+ " else: a = 3",
+ " return a",
+ "z = " + fun + "()")
+ .testLookup("z", expected);
}
@Test
@@ -624,147 +608,172 @@
}
private void execIfElifElse(int x, int y, int v) throws Exception {
- new SkylarkTest().setUp("def foo():",
- " x = " + x + "",
- " y = " + y + "",
- " if x:",
- " return 1",
- " elif y:",
- " return 2",
- " else:",
- " return 3",
- "v = foo()").testLookup("v", v);
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " x = " + x + "",
+ " y = " + y + "",
+ " if x:",
+ " return 1",
+ " elif y:",
+ " return 2",
+ " else:",
+ " return 3",
+ "v = foo()")
+ .testLookup("v", v);
}
@Test
public void testForOnList() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " s = ''",
- " for i in ['hello', ' ', 'world']:",
- " s = s + i",
- " return s",
- "s = foo()").testLookup("s", "hello world");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " s = ''",
+ " for i in ['hello', ' ', 'world']:",
+ " s = s + i",
+ " return s",
+ "s = foo()")
+ .testLookup("s", "hello world");
}
@Test
public void testForAssignmentList() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " d = ['a', 'b', 'c']",
- " s = ''",
- " for i in d:",
- " s = s + i",
- " d = ['d', 'e', 'f']", // check that we use the old list
- " return s",
- "s = foo()").testLookup("s", "abc");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " d = ['a', 'b', 'c']",
+ " s = ''",
+ " for i in d:",
+ " s = s + i",
+ " d = ['d', 'e', 'f']", // check that we use the old list
+ " return s",
+ "s = foo()")
+ .testLookup("s", "abc");
}
@Test
public void testForAssignmentDict() throws Exception {
- new SkylarkTest().setUp("def func():",
- " d = {'a' : 1, 'b' : 2, 'c' : 3}",
- " s = ''",
- " for i in d:",
- " s = s + i",
- " d = {'d' : 1, 'e' : 2, 'f' : 3}",
- " return s",
- "s = func()").testLookup("s", "abc");
+ new Scenario()
+ .setUp(
+ "def func():",
+ " d = {'a' : 1, 'b' : 2, 'c' : 3}",
+ " s = ''",
+ " for i in d:",
+ " s = s + i",
+ " d = {'d' : 1, 'e' : 2, 'f' : 3}",
+ " return s",
+ "s = func()")
+ .testLookup("s", "abc");
}
@Test
public void testForUpdateList() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " xs = [1, 2, 3]",
- " for x in xs:",
- " if x == 1:",
- " xs.append(10)"
- ).testIfErrorContains("trying to mutate a locked object", "foo()");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " xs = [1, 2, 3]",
+ " for x in xs:",
+ " if x == 1:",
+ " xs.append(10)")
+ .testIfErrorContains("trying to mutate a locked object", "foo()");
}
@Test
public void testForUpdateDict() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " d = {'a': 1, 'b': 2, 'c': 3}",
- " for k in d:",
- " d[k] *= 2"
- ).testIfErrorContains("trying to mutate a locked object", "foo()");
+ new Scenario()
+ .setUp("def foo():", " d = {'a': 1, 'b': 2, 'c': 3}", " for k in d:", " d[k] *= 2")
+ .testIfErrorContains("trying to mutate a locked object", "foo()");
}
@Test
public void testForUnlockedAfterBreak() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " xs = [1, 2]",
- " for x in xs:",
- " break",
- " xs.append(3)",
- " return xs"
- ).testEval("foo()", "[1, 2, 3]");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " xs = [1, 2]",
+ " for x in xs:",
+ " break",
+ " xs.append(3)",
+ " return xs")
+ .testEval("foo()", "[1, 2, 3]");
}
@Test
public void testForNestedOnSameListStillLocked() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " xs = [1, 2]",
- " ys = []",
- " for x1 in xs:",
- " for x2 in xs:",
- " ys.append(x1 * x2)",
- " xs.append(4)",
- " return ys"
- ).testIfErrorContains("trying to mutate a locked object", "foo()");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " xs = [1, 2]",
+ " ys = []",
+ " for x1 in xs:",
+ " for x2 in xs:",
+ " ys.append(x1 * x2)",
+ " xs.append(4)",
+ " return ys")
+ .testIfErrorContains("trying to mutate a locked object", "foo()");
}
@Test
public void testForNestedOnSameListErrorMessage() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " xs = [1, 2]",
- " ys = []",
- " for x1 in xs:",
- " for x2 in xs:",
- " ys.append(x1 * x2)",
- " xs.append(4)",
- " return ys"
- // No file name in message, due to how test is set up.
- ).testIfErrorContains("Object locked at the following location(s): :4:3, :5:5", "foo()");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " xs = [1, 2]",
+ " ys = []",
+ " for x1 in xs:",
+ " for x2 in xs:",
+ " ys.append(x1 * x2)",
+ " xs.append(4)",
+ " return ys"
+ // No file name in message, due to how test is set up.
+ )
+ .testIfErrorContains("Object locked at the following location(s): :4:3, :5:5", "foo()");
}
@Test
public void testForNestedOnSameListUnlockedAtEnd() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " xs = [1, 2]",
- " ys = []",
- " for x1 in xs:",
- " for x2 in xs:",
- " ys.append(x1 * x2)",
- " xs.append(4)",
- " return ys"
- ).testEval("foo()", "[1, 2, 2, 4]");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " xs = [1, 2]",
+ " ys = []",
+ " for x1 in xs:",
+ " for x2 in xs:",
+ " ys.append(x1 * x2)",
+ " xs.append(4)",
+ " return ys")
+ .testEval("foo()", "[1, 2, 2, 4]");
}
@Test
public void testForNestedWithListCompGood() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " xs = [1, 2]",
- " ys = []",
- " for x in xs:",
- " zs = [None for x in xs for y in (ys.append(x) or ys)]",
- " return ys"
- ).testEval("foo()", "[1, 2, 1, 2]");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " xs = [1, 2]",
+ " ys = []",
+ " for x in xs:",
+ " zs = [None for x in xs for y in (ys.append(x) or ys)]",
+ " return ys")
+ .testEval("foo()", "[1, 2, 1, 2]");
}
@Test
public void testForNestedWithListCompBad() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " xs = [1, 2, 3]",
- " ys = []",
- " for x in xs:",
- " zs = [None for x in xs for y in (xs.append(x) or ys)]",
- " return ys"
- ).testIfErrorContains("trying to mutate a locked object", "foo()");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " xs = [1, 2, 3]",
+ " ys = []",
+ " for x in xs:",
+ " zs = [None for x in xs for y in (xs.append(x) or ys)]",
+ " return ys")
+ .testIfErrorContains("trying to mutate a locked object", "foo()");
}
@Test
public void testForDeepUpdate() throws Exception {
// Check that indirectly reachable values can still be manipulated as normal.
- new SkylarkTest()
+ new Scenario()
.setUp(
"def foo():",
" xs = [['a'], ['b'], ['c']]",
@@ -780,7 +789,7 @@
@Test
public void testForNotIterable() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfErrorContains(
"type 'int' is not iterable",
@@ -791,7 +800,7 @@
@Test
public void testForStringNotIterable() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfErrorContains(
"type 'string' is not iterable", "def func():", " for i in 'abc': a = i", "func()\n");
@@ -799,39 +808,46 @@
@Test
public void testForOnDictionary() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " d = {1: 'a', 2: 'b', 3: 'c'}",
- " s = ''",
- " for i in d: s = s + d[i]",
- " return s",
- "s = foo()").testLookup("s", "abc");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " d = {1: 'a', 2: 'b', 3: 'c'}",
+ " s = ''",
+ " for i in d: s = s + d[i]",
+ " return s",
+ "s = foo()")
+ .testLookup("s", "abc");
}
@Test
public void testBadDictKey() throws Exception {
- new SkylarkTest().testIfErrorContains(
- "unhashable type: 'list'",
- "{ [1, 2]: [3, 4] }");
+ new Scenario().testIfErrorContains("unhashable type: 'list'", "{ [1, 2]: [3, 4] }");
}
@Test
public void testForLoopReuseVariable() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " s = ''",
- " for i in ['a', 'b']:",
- " for i in ['c', 'd']: s = s + i",
- " return s",
- "s = foo()").testLookup("s", "cdcd");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " s = ''",
+ " for i in ['a', 'b']:",
+ " for i in ['c', 'd']: s = s + i",
+ " return s",
+ "s = foo()")
+ .testLookup("s", "cdcd");
}
@Test
public void testForLoopMultipleVariables() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " s = ''",
- " for [i, j] in [[1, 2], [3, 4]]:",
- " s = s + str(i) + str(j) + '.'",
- " return s",
- "s = foo()").testLookup("s", "12.34.");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " s = ''",
+ " for [i, j] in [[1, 2], [3, 4]]:",
+ " s = s + str(i) + str(j) + '.'",
+ " return s",
+ "s = foo()")
+ .testLookup("s", "12.34.");
}
@Test
@@ -980,7 +996,7 @@
@Test
public void testNoneAssignment() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp("def foo(x=None):", " x = 1", " x = None", " return 2", "s = foo()")
.testLookup("s", 2);
}
@@ -999,7 +1015,7 @@
@Test
public void testJavaCalls() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.is_empty('a')")
.testLookup("b", Boolean.FALSE);
@@ -1007,7 +1023,7 @@
@Test
public void testJavaCallsOnSubClass() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new MockSubClass())
.setUp("b = mock.is_empty('a')")
.testLookup("b", Boolean.FALSE);
@@ -1015,7 +1031,7 @@
@Test
public void testJavaCallsOnInterface() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new MockSubClass())
.setUp("b = mock.is_empty_interface('a')")
.testLookup("b", Boolean.FALSE);
@@ -1023,34 +1039,34 @@
@Test
public void testJavaCallsNotSkylarkCallable() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfExactError("'Mock' value has no field or method 'value'", "mock.value()");
}
@Test
public void testNoOperatorIndex() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfExactError("type 'Mock' has no operator [](int)", "mock[2]");
}
@Test
public void testJavaCallsNoMethod() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfExactError("'Mock' value has no field or method 'bad'", "mock.bad()");
}
@Test
public void testJavaCallsNoMethodErrorMsg() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfExactError("'int' value has no field or method 'bad'", "s = 3.bad('a', 'b', 'c')");
}
@Test
public void testJavaCallWithKwargs() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfExactError(
"'Mock' value has no field or method 'isEmpty'", "mock.isEmpty(str='abc')");
@@ -1058,7 +1074,7 @@
@Test
public void testStringListDictValues() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"def func(mock):",
@@ -1066,40 +1082,38 @@
" modified_list = v + ['extra_string']",
" return modified_list",
"m = func(mock)")
- .testLookup("m", StarlarkList.of(thread.mutability(), "b", "c", "extra_string"));
+ .testLookup("m", StarlarkList.of(null, "b", "c", "extra_string"));
}
@Test
public void testProxyMethodsObject() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
- .setUp(
- "m = mock.proxy_methods_object()",
- "b = m.with_params(1, True, named=True)")
+ .setUp("m = mock.proxy_methods_object()", "b = m.with_params(1, True, named=True)")
.testLookup("b", "with_params(1, true, false, true, false, a)");
}
@Test
public void testLegacyNamed() throws Exception {
- new SkylarkTest("--incompatible_restrict_named_params=false")
+ new Scenario("--incompatible_restrict_named_params=false")
.update("mock", new Mock())
.setUp("b = mock.legacy_method(True, legacyNamed=True, named=True)")
.testLookup("b", "legacy_method(true, true, true)");
- new SkylarkTest("--incompatible_restrict_named_params=false")
+ new Scenario("--incompatible_restrict_named_params=false")
.update("mock", new Mock())
.setUp("b = mock.legacy_method(True, True, named=True)")
.testLookup("b", "legacy_method(true, true, true)");
// Verify legacyNamed also works with proxy method objects.
- new SkylarkTest("--incompatible_restrict_named_params=false")
+ new Scenario("--incompatible_restrict_named_params=false")
.update("mock", new Mock())
.setUp(
"m = mock.proxy_methods_object()",
"b = m.legacy_method(True, legacyNamed=True, named=True)")
.testLookup("b", "legacy_method(true, true, true)");
- new SkylarkTest("--incompatible_restrict_named_params=false")
+ new Scenario("--incompatible_restrict_named_params=false")
.update("mock", new Mock())
.setUp("m = mock.proxy_methods_object()", "b = m.legacy_method(True, True, named=True)")
.testLookup("b", "legacy_method(true, true, true)");
@@ -1113,7 +1127,7 @@
public void testArgSpecifiedBothByNameAndPosition() throws Exception {
// in with_params, 'posOrNamed' is positional parameter index 2. So by specifying both
// posOrNamed by name and three positional parameters, there is a conflict.
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfErrorContains(
"with_params() got multiple values for argument 'posOrNamed'",
@@ -1122,19 +1136,19 @@
@Test
public void testTooManyPositionalArgs() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfErrorContains(
"with_params() accepts no more than 3 positional arguments but got 4",
"mock.with_params(1, True, True, 'toomany', named=True)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfErrorContains(
"with_params() accepts no more than 3 positional arguments but got 5",
"mock.with_params(1, True, True, 'toomany', 'alsotoomany', named=True)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfErrorContains(
"is_empty() accepts no more than 1 positional argument but got 2",
@@ -1143,68 +1157,68 @@
@Test
public void testJavaCallWithPositionalAndKwargs() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True)")
.testLookup("b", "with_params(1, true, false, true, false, a)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, multi=1)")
.testLookup("b", "with_params(1, true, false, true, false, a, 1)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, multi='abc')")
.testLookup("b", "with_params(1, true, false, true, false, a, abc)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, multi=[1,2,3])")
.testLookup("b", "with_params(1, true, false, true, false, a, [1, 2, 3])");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("")
.testIfExactError(
"with_params() missing 1 required named argument: named", "mock.with_params(1, True)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("")
.testIfExactError(
"with_params() missing 1 required named argument: named",
"mock.with_params(1, True, True)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, True, named=True)")
.testLookup("b", "with_params(1, true, true, true, false, a)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, posOrNamed=True)")
.testLookup("b", "with_params(1, true, true, true, false, a)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, posOrNamed=True, optionalNamed=True)")
.testLookup("b", "with_params(1, true, true, true, true, a)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("")
.testIfExactError(
"with_params() got unexpected keyword argument 'posornamed' (did you mean"
+ " 'posOrNamed'?)",
"mock.with_params(1, True, named=True, posornamed=True)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("")
.testIfExactError(
"with_params() got unexpected keyword argument 'n'",
"mock.with_params(1, True, named=True, posOrNamed=True, n=2)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("")
.testIfExactError(
"in call to with_params(), parameter 'nonNoneable' cannot be None",
"mock.with_params(1, True, True, named=True, optionalNamed=False, nonNoneable=None)");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("")
.testIfExactError(
@@ -1214,7 +1228,7 @@
// We do not enforce list item parameter type constraints.
// Test for this behavior.
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, multi=['a', 'b'])")
.testLookup("b", "with_params(1, true, false, true, false, a, [\"a\", \"b\"])");
@@ -1222,38 +1236,35 @@
@Test
public void testNoJavaCallsWithoutSkylark() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfExactError("'int' value has no field or method 'to_string'", "s = 3.to_string()");
}
@Test
public void testStructAccess() throws Exception {
- new SkylarkTest()
- .update("mock", new Mock())
- .setUp("v = mock.struct_field")
- .testLookup("v", "a");
+ new Scenario().update("mock", new Mock()).setUp("v = mock.struct_field").testLookup("v", "a");
}
@Test
public void testStructAccessAsFuncallNonCallable() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfExactError("'string' object is not callable", "v = mock.struct_field()");
}
@Test
public void testSelfCall() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("v = mock('bestmock')")
.testLookup("v", "I'm a mock named bestmock");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("mockfunction = mock", "v = mockfunction('bestmock')")
.testLookup("v", "I'm a mock named bestmock");
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfErrorContains(
"in call to MockFn(), parameter 'pos' got value of type 'int', want 'string'",
@@ -1262,7 +1273,7 @@
@Test
public void testStructAccessAsFuncall() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("v = mock.struct_field_callable()")
.testLookup("v", "foobar");
@@ -1288,7 +1299,7 @@
@Test
public void testJavaFunctionWithExtraInterpreterParams() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("v = mock.with_extra()")
.testLookup("v", "with_extra(1)");
@@ -1296,7 +1307,7 @@
@Test
public void testStructFieldWithExtraInterpreterParams() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("v = mock.struct_field_with_extra")
.testLookup("v", "struct_field_with_extra(true)");
@@ -1304,7 +1315,7 @@
@Test
public void testJavaFunctionWithParamsAndExtraInterpreterParams() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_params_and_extra(1, True, named=True)")
.testLookup("b", "with_params_and_extra(1, true, false, true, false, a, 1)");
@@ -1312,13 +1323,13 @@
@Test
public void testJavaFunctionWithExtraArgsAndThread() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_args_and_thread(1, True, 'extraArg1', 'extraArg2', named=True)")
.testLookup("b", "with_args_and_thread(1, true, true, args(extraArg1, extraArg2))");
// Use an args list.
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"myargs = ['extraArg2']",
@@ -1328,13 +1339,13 @@
@Test
public void testJavaFunctionWithExtraKwargs() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_kwargs(True, extraKey1=True, named=True, extraKey2='x')")
.testLookup("b", "with_kwargs(true, true, kwargs(extraKey1=true, extraKey2=x))");
// Use a kwargs dict.
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"mykwargs = {'extraKey2':'x', 'named':True}",
@@ -1345,14 +1356,14 @@
@Test
public void testJavaFunctionWithArgsAndKwargs() throws Exception {
// Foo is used positionally
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_args_and_kwargs('foo', 'bar', 'baz', extraKey1=True, extraKey2='x')")
.testLookup(
"b", "with_args_and_kwargs(foo, args(bar, baz), kwargs(extraKey1=true, extraKey2=x))");
// Use an args list and a kwargs dict
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"mykwargs = {'extraKey1':True}",
@@ -1362,13 +1373,13 @@
"b", "with_args_and_kwargs(foo, args(bar, baz), kwargs(extraKey2=x, extraKey1=true))");
// Foo is used by name
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_args_and_kwargs(foo='foo', extraKey1=True)")
.testLookup("b", "with_args_and_kwargs(foo, args(), kwargs(extraKey1=true))");
// Empty args and kwargs.
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("b = mock.with_args_and_kwargs('foo')")
.testLookup("b", "with_args_and_kwargs(foo, args(), kwargs())");
@@ -1377,7 +1388,7 @@
@Test
public void testProxyMethodsObjectWithArgsAndKwargs() throws Exception {
// Foo is used positionally
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"m = mock.proxy_methods_object()",
@@ -1386,7 +1397,7 @@
"b", "with_args_and_kwargs(foo, args(bar, baz), kwargs(extraKey1=true, extraKey2=x))");
// Use an args list and a kwargs dict
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"mykwargs = {'extraKey1':True}",
@@ -1397,7 +1408,7 @@
"b", "with_args_and_kwargs(foo, args(bar, baz), kwargs(extraKey2=x, extraKey1=true))");
// Foo is used by name
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"m = mock.proxy_methods_object()",
@@ -1405,7 +1416,7 @@
.testLookup("b", "with_args_and_kwargs(foo, args(), kwargs(extraKey1=true))");
// Empty args and kwargs.
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("m = mock.proxy_methods_object()", "b = m.with_args_and_kwargs('foo')")
.testLookup("b", "with_args_and_kwargs(foo, args(), kwargs())");
@@ -1413,13 +1424,13 @@
@Test
public void testStructAccessOfMethod() throws Exception {
- new SkylarkTest().update("mock", new Mock()).testExpression("type(mock.function)", "function");
- new SkylarkTest().update("mock", new Mock()).testExpression("mock.function()", "a");
+ new Scenario().update("mock", new Mock()).testExpression("type(mock.function)", "function");
+ new Scenario().update("mock", new Mock()).testExpression("mock.function()", "a");
}
@Test
public void testStructAccessTypo() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new MockClassObject())
.testIfExactError(
"'MockClassObject' value has no field or method 'fild' (did you mean 'field'?)",
@@ -1428,7 +1439,7 @@
@Test
public void testStructAccessType_nonClassObject() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testIfExactError(
"'Mock' value has no field or method 'sturct_field' (did you mean 'struct_field'?)",
@@ -1457,7 +1468,7 @@
@Test
public void testClassObjectAccess() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new MockClassObject())
.setUp("v = mock.field")
.testLookup("v", "a");
@@ -1465,7 +1476,7 @@
@Test
public void testUnionSet() throws Exception {
- new SkylarkTest("--incompatible_depset_union=false")
+ new Scenario("--incompatible_depset_union=false")
.testExpression("str(depset([1, 3]) | depset([1, 2]))", "depset([1, 2, 3])")
.testExpression("str(depset([1, 2]) | [1, 3])", "depset([1, 2, 3])")
.testIfExactError("unsupported binary operation: int | bool", "2 | False");
@@ -1473,7 +1484,7 @@
@Test
public void testSetIsNotIterable() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains("not iterable", "list(depset(['a', 'b']))")
.testIfErrorContains("not iterable", "max(depset([1, 2, 3]))")
.testIfErrorContains(
@@ -1498,7 +1509,7 @@
@Test
public void testJavaFunctionReturnsNone() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("v = mock.nullfunc_working()")
.testLookup("v", Starlark.NONE);
@@ -1506,7 +1517,7 @@
@Test
public void testVoidJavaFunctionReturnsNone() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp("v = mock.voidfunc()")
.testLookup("v", Starlark.NONE);
@@ -1514,17 +1525,15 @@
@Test
public void testAugmentedAssignment() throws Exception {
- new SkylarkTest().setUp("def f1(x):",
- " x += 1",
- " return x",
- "",
- "foo = f1(41)").testLookup("foo", 42);
+ new Scenario()
+ .setUp("def f1(x):", " x += 1", " return x", "", "foo = f1(41)")
+ .testLookup("foo", 42);
}
@Test
public void testAugmentedAssignmentHasNoSideEffects() throws Exception {
// Check object position.
- new SkylarkTest()
+ new Scenario()
.setUp(
"counter = [0]",
"value = [1, 2]",
@@ -1534,10 +1543,10 @@
" return value",
"",
"f()[1] += 1") // `f()` should be called only once here
- .testLookup("counter", StarlarkList.of(thread.mutability(), 1));
+ .testLookup("counter", StarlarkList.of(null, 1));
// Check key position.
- new SkylarkTest()
+ new Scenario()
.setUp(
"counter = [0]",
"value = [1, 2]",
@@ -1547,7 +1556,7 @@
" return 1",
"",
"value[f()] += 1") // `f()` should be called only once here
- .testLookup("counter", StarlarkList.of(thread.mutability(), 1));
+ .testLookup("counter", StarlarkList.of(null, 1));
}
@Test
@@ -1571,7 +1580,7 @@
@Test
public void testAssignmentEvaluationOrder() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp(
"ordinary = []",
"augmented = []",
@@ -1587,31 +1596,33 @@
"",
"f(ordinary)[0] = g(ordinary)[1]",
"f(augmented)[0] += g(augmented)[1]")
- .testLookup(
- "ordinary", StarlarkList.of(thread.mutability(), "g", "f")) // This order is consistent
- .testLookup("augmented", StarlarkList.of(thread.mutability(), "f", "g")); // with Python
+ .testLookup("ordinary", StarlarkList.of(null, "g", "f")) // This order is consistent
+ .testLookup("augmented", StarlarkList.of(null, "f", "g")); // with Python
}
@Test
public void testDictComprehensions_IterationOrder() throws Exception {
- new SkylarkTest().setUp("def foo():",
- " d = {x : x for x in ['c', 'a', 'b']}",
- " s = ''",
- " for a in d:",
- " s += a",
- " return s",
- "s = foo()").testLookup("s", "cab");
+ new Scenario()
+ .setUp(
+ "def foo():",
+ " d = {x : x for x in ['c', 'a', 'b']}",
+ " s = ''",
+ " for a in d:",
+ " s += a",
+ " return s",
+ "s = foo()")
+ .testLookup("s", "cab");
}
@Test
public void testDotExpressionOnNonStructObject() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfExactError("'string' value has no field or method 'field'", "x = 'a'.field");
}
@Test
public void testPlusEqualsOnListMutating() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp(
"def func():",
" l1 = [1, 2]",
@@ -1622,7 +1633,7 @@
.testLookup("lists", "([1, 2, 3, 4], [1, 2, 3, 4])");
// The same but with += after an IndexExpression
- new SkylarkTest()
+ new Scenario()
.setUp(
"def func():",
" l = [1, 2]",
@@ -1635,7 +1646,7 @@
@Test
public void testPlusEqualsOnTuple() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp(
"def func():",
" t1 = (1, 2)",
@@ -1648,9 +1659,9 @@
@Test
public void testPlusOnDictDeprecated() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains("unsupported binary operation: dict + dict", "{1: 2} + {3: 4}");
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"unsupported binary operation: dict + dict",
"def func():",
@@ -1661,93 +1672,96 @@
@Test
public void testDictAssignmentAsLValue() throws Exception {
- new SkylarkTest().setUp("def func():",
- " d = {'a' : 1}",
- " d['b'] = 2",
- " return d",
- "d = func()").testLookup("d", ImmutableMap.of("a", 1, "b", 2));
+ new Scenario()
+ .setUp("def func():", " d = {'a' : 1}", " d['b'] = 2", " return d", "d = func()")
+ .testLookup("d", ImmutableMap.of("a", 1, "b", 2));
}
@Test
public void testNestedDictAssignmentAsLValue() throws Exception {
- new SkylarkTest().setUp("def func():",
- " d = {'a' : 1}",
- " e = {'d': d}",
- " e['d']['b'] = 2",
- " return e",
- "e = func()").testLookup("e", ImmutableMap.of("d", ImmutableMap.of("a", 1, "b", 2)));
+ new Scenario()
+ .setUp(
+ "def func():",
+ " d = {'a' : 1}",
+ " e = {'d': d}",
+ " e['d']['b'] = 2",
+ " return e",
+ "e = func()")
+ .testLookup("e", ImmutableMap.of("d", ImmutableMap.of("a", 1, "b", 2)));
}
@Test
public void testListAssignmentAsLValue() throws Exception {
- new SkylarkTest().setUp("def func():",
- " a = [1, 2]",
- " a[1] = 3",
- " a[-2] = 4",
- " return a",
- "a = str(func())").testLookup("a", "[4, 3]");
+ new Scenario()
+ .setUp(
+ "def func():",
+ " a = [1, 2]",
+ " a[1] = 3",
+ " a[-2] = 4",
+ " return a",
+ "a = str(func())")
+ .testLookup("a", "[4, 3]");
}
@Test
public void testNestedListAssignmentAsLValue() throws Exception {
- new SkylarkTest().setUp("def func():",
- " d = [1, 2]",
- " e = [3, d]",
- " e[1][1] = 4",
- " return e",
- "e = str(func())").testLookup("e", "[3, [1, 4]]");
+ new Scenario()
+ .setUp(
+ "def func():",
+ " d = [1, 2]",
+ " e = [3, d]",
+ " e[1][1] = 4",
+ " return e",
+ "e = str(func())")
+ .testLookup("e", "[3, [1, 4]]");
}
@Test
public void testDictTupleAssignmentAsLValue() throws Exception {
- new SkylarkTest().setUp("def func():",
- " d = {'a' : 1}",
- " d['b'], d['c'] = 2, 3",
- " return d",
- "d = func()").testLookup("d", ImmutableMap.of("a", 1, "b", 2, "c", 3));
+ new Scenario()
+ .setUp(
+ "def func():", " d = {'a' : 1}", " d['b'], d['c'] = 2, 3", " return d", "d = func()")
+ .testLookup("d", ImmutableMap.of("a", 1, "b", 2, "c", 3));
}
@Test
public void testDictItemPlusEqual() throws Exception {
- new SkylarkTest().setUp("def func():",
- " d = {'a' : 2}",
- " d['a'] += 3",
- " return d",
- "d = func()").testLookup("d", ImmutableMap.of("a", 5));
+ new Scenario()
+ .setUp("def func():", " d = {'a' : 2}", " d['a'] += 3", " return d", "d = func()")
+ .testLookup("d", ImmutableMap.of("a", 5));
}
@Test
public void testDictAssignmentAsLValueSideEffects() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp("def func(d):", " d['b'] = 2", "d = {'a' : 1}", "func(d)")
.testLookup("d", Dict.of((Mutability) null, "a", 1, "b", 2));
}
@Test
public void testAssignmentToListInDictSideEffect() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp("l = [1, 2]", "d = {0: l}", "d[0].append(3)")
.testLookup("l", StarlarkList.of(null, 1, 2, 3));
}
@Test
public void testUserFunctionKeywordArgs() throws Exception {
- new SkylarkTest().setUp("def foo(a, b, c):",
- " return a + b + c", "s = foo(1, c=2, b=3)")
+ new Scenario()
+ .setUp("def foo(a, b, c):", " return a + b + c", "s = foo(1, c=2, b=3)")
.testLookup("s", 6);
}
@Test
public void testFunctionCallOrdering() throws Exception {
- new SkylarkTest().setUp("def func(): return foo() * 2",
- "def foo(): return 2",
- "x = func()")
- .testLookup("x", 4);
+ new Scenario()
+ .setUp("def func(): return foo() * 2", "def foo(): return 2", "x = func()")
+ .testLookup("x", 4);
}
@Test
public void testFunctionCallBadOrdering() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"global variable 'foo' is referenced before assignment.",
"def func(): return foo() * 2",
@@ -1757,7 +1771,7 @@
@Test
public void testLocalVariableDefinedBelow() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp(
"def beforeEven(li):", // returns the value before the first even number
" for i in li:",
@@ -1771,7 +1785,7 @@
@Test
public void testShadowisNotInitialized() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
/* error message */ "local variable 'gl' is referenced before assignment",
"gl = 5",
@@ -1783,7 +1797,7 @@
@Test
public void testShadowBuiltin() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"global variable 'len' is referenced before assignment",
"x = len('abc')",
@@ -1793,7 +1807,7 @@
@Test
public void testFunctionCallRecursion() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"function 'f' called recursively",
"def main():",
@@ -1817,7 +1831,7 @@
@Test
public void testNoneTrueFalseInSkylark() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp("a = None", "b = True", "c = False")
.testLookup("a", Starlark.NONE)
.testLookup("b", Boolean.TRUE)
@@ -1826,10 +1840,13 @@
@Test
public void testHasattrMethods() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
- .setUp("a = hasattr(mock, 'struct_field')", "b = hasattr(mock, 'function')",
- "c = hasattr(mock, 'is_empty')", "d = hasattr('str', 'replace')",
+ .setUp(
+ "a = hasattr(mock, 'struct_field')",
+ "b = hasattr(mock, 'function')",
+ "c = hasattr(mock, 'is_empty')",
+ "d = hasattr('str', 'replace')",
"e = hasattr(mock, 'other')\n")
.testLookup("a", Boolean.TRUE)
.testLookup("b", Boolean.TRUE)
@@ -1840,7 +1857,7 @@
@Test
public void testGetattrMethods() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.setUp(
"a = str(getattr(mock, 'struct_field', 'no'))",
@@ -1857,44 +1874,45 @@
@Test
public void testListAnTupleConcatenationDoesNotWorkInSkylark() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfExactError("unsupported binary operation: list + tuple", "[1, 2] + (3, 4)");
}
@Test
public void testCannotCreateMixedListInSkylark() throws Exception {
- new SkylarkTest().testExactOrder("['a', 'b', 1, 2]", "a", "b", 1, 2);
+ new Scenario().testExactOrder("['a', 'b', 1, 2]", "a", "b", 1, 2);
}
@Test
public void testCannotConcatListInSkylarkWithDifferentGenericTypes() throws Exception {
- new SkylarkTest().testExactOrder("[1, 2] + ['a', 'b']", 1, 2, "a", "b");
+ new Scenario().testExactOrder("[1, 2] + ['a', 'b']", 1, 2, "a", "b");
}
@Test
public void testConcatEmptyListWithNonEmptyWorks() throws Exception {
- new SkylarkTest().testExactOrder("[] + ['a', 'b']", "a", "b");
+ new Scenario().testExactOrder("[] + ['a', 'b']", "a", "b");
}
@Test
public void testFormatStringWithTuple() throws Exception {
- new SkylarkTest().setUp("v = '%s%s' % ('a', 1)").testLookup("v", "a1");
+ new Scenario().setUp("v = '%s%s' % ('a', 1)").testLookup("v", "a1");
}
@Test
public void testSingletonTuple() throws Exception {
- new SkylarkTest().testExactOrder("(1,)", 1);
+ new Scenario().testExactOrder("(1,)", 1);
}
@Test
public void testDirFindsClassObjectFields() throws Exception {
- new SkylarkTest().update("mock", new MockClassObject())
+ new Scenario()
+ .update("mock", new MockClassObject())
.testExactOrder("dir(mock)", "field", "nset");
}
@Test
public void testDirFindsJavaObjectStructFieldsAndMethods() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new Mock())
.testExactOrder(
"dir(mock)",
@@ -1925,7 +1943,7 @@
@Test
public void testStrNativeInfo() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new NativeInfoMock())
.testEval(
"str(mock)",
@@ -1935,7 +1953,7 @@
@Test
public void testNativeInfoAttrs() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("mock", new NativeInfoMock())
.testEval(
"dir(mock)",
@@ -1959,85 +1977,19 @@
@Test
public void testPrintBadKwargs() throws Exception {
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"print() got unexpected keyword argument 'end'", "print(end='x', other='y')");
}
- // Override tests in EvaluationTest incompatible with Skylark
-
- @SuppressWarnings("unchecked")
- @Override
- @Test
- public void testConcatLists() throws Exception {
- new SkylarkTest().testExactOrder("[1,2] + [3,4]", 1, 2, 3, 4).testExactOrder("(1,2)", 1, 2)
- .testExactOrder("(1,2) + (3,4)", 1, 2, 3, 4);
-
- // TODO(fwe): cannot be handled by current testing suite
- // list
- Object x = eval("[1,2] + [3,4]");
- assertThat((Iterable<Object>) x).containsExactly(1, 2, 3, 4).inOrder();
-
- // tuple
- x = eval("(1,2)");
- assertThat((Iterable<Object>) x).containsExactly(1, 2).inOrder();
- assertThat(x).isInstanceOf(Tuple.class);
-
- x = eval("(1,2) + (3,4)");
- assertThat((Iterable<Object>) x).containsExactly(1, 2, 3, 4).inOrder();
- assertThat(x).isInstanceOf(Tuple.class);
- }
-
- @Override
- @Test
- public void testListConcatenation() throws Exception {}
-
- @Override
- @Test
- public void testListComprehensionsMultipleVariablesFail() throws Exception {
- new SkylarkTest()
- .testIfErrorContains(
- "assignment length mismatch: left-hand side has length 3, but right-hand side "
- + "evaluates to value of length 2",
- "def foo (): return [x + y for x, y, z in [(1, 2), (3, 4)]]",
- "foo()");
-
- new SkylarkTest()
- .testIfErrorContains(
- "type 'int' is not iterable", "def bar (): return [x + y for x, y in (1, 2)]", "bar()");
-
- new SkylarkTest()
- .testIfErrorContains(
- "assignment length mismatch: left-hand side has length 3, but right-hand side "
- + "evaluates to value of length 2",
- "[x + y for x, y, z in [(1, 2), (3, 4)]]");
-
- new SkylarkTest()
- .testIfErrorContains("type 'int' is not iterable", "[x2 + y2 for x2, y2 in (1, 2)]");
-
- new SkylarkTest()
- // returns [2] in Python, it's an error in Skylark
- .testIfErrorContains("must have at least one item", "[2 for [] in [()]]");
- }
-
- @Override
- @Test
- public void testNotCallInt() throws Exception {
- new SkylarkTest()
- .setUp("sum = 123456")
- .testLookup("sum", 123456)
- .testIfExactError("'int' object is not callable", "sum(1, 2, 3, 4, 5, 6)")
- .testExpression("sum", 123456);
- }
-
@Test
public void testConditionalExpressionAtToplevel() throws Exception {
- new SkylarkTest().setUp("x = 1 if 2 else 3").testLookup("x", 1);
+ new Scenario().setUp("x = 1 if 2 else 3").testLookup("x", 1);
}
@Test
public void testConditionalExpressionInFunction() throws Exception {
- new SkylarkTest()
+ new Scenario()
.setUp("def foo(a, b, c): return a+b if c else a-b\n")
.testExpression("foo(23, 5, 0)", 18);
}
@@ -2118,7 +2070,7 @@
@Test
public void testStructFieldDefinedOnlyInValues() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("val", new SkylarkClassObjectWithSkylarkCallables())
.setUp("v = val.values_only_field")
.testLookup("v", "fromValues");
@@ -2126,7 +2078,7 @@
@Test
public void testStructMethodDefinedOnlyInValues() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("val", new SkylarkClassObjectWithSkylarkCallables())
.setUp("v = val.values_only_method()")
.testLookup("v", "fromValues");
@@ -2134,7 +2086,7 @@
@Test
public void testStructFieldDefinedOnlyInSkylarkCallable() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("val", new SkylarkClassObjectWithSkylarkCallables())
.setUp("v = val.callable_only_field")
.testLookup("v", "fromSkylarkCallable");
@@ -2142,7 +2094,7 @@
@Test
public void testStructMethodDefinedOnlyInSkylarkCallable() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("val", new SkylarkClassObjectWithSkylarkCallables())
.setUp("v = val.callable_only_method()")
.testLookup("v", "fromSkylarkCallable");
@@ -2153,7 +2105,7 @@
public void testStructMethodDefinedInValuesAndSkylarkCallable() throws Exception {
// This test exercises the resolution of ambiguity between @SkylarkCallable-annotated
// fields and those reported by ClassObject.getValue.
- new SkylarkTest()
+ new Scenario()
.update("val", new SkylarkClassObjectWithSkylarkCallables())
.setUp("v = val.collision_method()")
.testLookup("v", "fromSkylarkCallable");
@@ -2161,7 +2113,7 @@
@Test
public void testStructFieldNotDefined() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("val", new SkylarkClassObjectWithSkylarkCallables())
.testIfExactError(
// TODO(bazel-team): This should probably list callable_only_method as well.
@@ -2173,7 +2125,7 @@
@Test
public void testStructMethodNotDefined() throws Exception {
- new SkylarkTest()
+ new Scenario()
.update("val", new SkylarkClassObjectWithSkylarkCallables())
.testIfExactError(
"'struct_with_skylark_callables' value has no field or method 'nonexistent_method'\n"
@@ -2210,7 +2162,7 @@
AnalysisFailureInfo info = AnalysisFailureInfo.forAnalysisFailures(ImmutableList.of(cause));
- new SkylarkTest()
+ new Scenario()
.update("val", info)
.setUp(
"causes = val.causes",
@@ -2221,76 +2173,9 @@
}
@Test
- // TODO(adonovan): move to Validation tests.
- public void testExperimentalFlagGuardedValue() throws Exception {
- // This test uses an arbitrary experimental flag to verify this functionality. If this
- // experimental flag were to go away, this test may be updated to use any experimental flag.
- // The flag itself is unimportant to the test.
- FlagGuardedValue val =
- FlagGuardedValue.onlyWhenExperimentalFlagIsTrue(
- FlagIdentifier.EXPERIMENTAL_BUILD_SETTING_API, "foo");
- String errorMessage =
- "GlobalSymbol is experimental and thus unavailable with the current "
- + "flags. It may be enabled by setting --experimental_build_setting_api";
-
-
- new SkylarkTest(ImmutableMap.of("GlobalSymbol", val), "--experimental_build_setting_api=true")
- .setUp("var = GlobalSymbol")
- .testLookup("var", "foo");
-
- new SkylarkTest(ImmutableMap.of("GlobalSymbol", val), "--experimental_build_setting_api=false")
- .testIfErrorContains(errorMessage, "var = GlobalSymbol");
-
- new SkylarkTest(ImmutableMap.of("GlobalSymbol", val), "--experimental_build_setting_api=false")
- .testIfErrorContains(errorMessage, "def my_function():", " var = GlobalSymbol");
-
- new SkylarkTest(ImmutableMap.of("GlobalSymbol", val), "--experimental_build_setting_api=false")
- .setUp("GlobalSymbol = 'other'", "var = GlobalSymbol")
- .testLookup("var", "other");
- }
-
- @Test
- public void testIncompatibleFlagGuardedValue() throws Exception {
- // This test uses an arbitrary incompatible flag to verify this functionality. If this
- // incompatible flag were to go away, this test may be updated to use any incompatible flag.
- // The flag itself is unimportant to the test.
- FlagGuardedValue val = FlagGuardedValue.onlyWhenIncompatibleFlagIsFalse(
- FlagIdentifier.INCOMPATIBLE_NO_TARGET_OUTPUT_GROUP,
- "foo");
- String errorMessage = "GlobalSymbol is deprecated and will be removed soon. It may be "
- + "temporarily re-enabled by setting --incompatible_no_target_output_group=false";
-
- new SkylarkTest(
- ImmutableMap.of("GlobalSymbol", val),
- "--incompatible_no_target_output_group=false")
- .setUp("var = GlobalSymbol")
- .testLookup("var", "foo");
-
- new SkylarkTest(
- ImmutableMap.of("GlobalSymbol", val),
- "--incompatible_no_target_output_group=true")
- .testIfErrorContains(errorMessage,
- "var = GlobalSymbol");
-
- new SkylarkTest(
- ImmutableMap.of("GlobalSymbol", val),
- "--incompatible_no_target_output_group=true")
- .testIfErrorContains(errorMessage,
- "def my_function():",
- " var = GlobalSymbol");
-
- new SkylarkTest(
- ImmutableMap.of("GlobalSymbol", val),
- "--incompatible_no_target_output_group=true")
- .setUp("GlobalSymbol = 'other'",
- "var = GlobalSymbol")
- .testLookup("var", "other");
- }
-
- @Test
public void testFunctionEvaluatedBeforeArguments() throws Exception {
// ''.nonesuch must be evaluated (and fail) before f().
- new SkylarkTest()
+ new Scenario()
.testIfErrorContains(
"'string' value has no field or method 'nonesuch'",
"def f(): x = 1//0",
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkListTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkListTest.java
index 89c6a02..12720de 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkListTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkListTest.java
@@ -318,10 +318,9 @@
public void testGetSkylarkType_GivesExpectedClassesForListsAndTuples() throws Exception {
Class<?> emptyTupleClass = Tuple.empty().getClass();
Class<?> tupleClass = Tuple.of(1, "a", "b").getClass();
- Class<?> mutableListClass =
- StarlarkList.copyOf(thread.mutability(), Tuple.of(1, 2, 3)).getClass();
+ Class<?> listClass = StarlarkList.copyOf(null, Tuple.of(1, 2, 3)).getClass();
- assertThat(EvalUtils.getSkylarkType(mutableListClass)).isEqualTo(StarlarkList.class);
+ assertThat(EvalUtils.getSkylarkType(listClass)).isEqualTo(StarlarkList.class);
assertThat(EvalUtils.getSkylarkType(emptyTupleClass)).isEqualTo(Tuple.class);
assertThat(EvalUtils.getSkylarkType(tupleClass)).isEqualTo(Tuple.class);
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/StarlarkFlagGuardingTest.java b/src/test/java/com/google/devtools/build/lib/syntax/StarlarkFlagGuardingTest.java
index e84cc2b..57317cf 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/StarlarkFlagGuardingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/StarlarkFlagGuardingTest.java
@@ -18,8 +18,6 @@
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.syntax.StarlarkSemantics.FlagIdentifier;
import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
-import com.google.devtools.build.lib.testutil.TestMode;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -31,11 +29,6 @@
@RunWith(JUnit4.class)
public final class StarlarkFlagGuardingTest extends EvaluationTestCase {
- @Before
- public final void setup() throws Exception {
- setMode(TestMode.SKYLARK);
- }
-
/** Mock containing exposed methods for flag-guarding tests. */
@SkylarkModule(name = "Mock", doc = "")
public static class Mock implements StarlarkValue {
@@ -133,23 +126,23 @@
@Test
public void testPositionalsOnlyGuardedMethod() throws Exception {
- new SkylarkTest("--experimental_build_setting_api=true")
+ new Scenario("--experimental_build_setting_api=true")
.update("mock", new Mock())
.testEval(
"mock.positionals_only_method(1, True, 3)", "'positionals_only_method(1, true, 3)'");
- new SkylarkTest("--experimental_build_setting_api=true")
+ new Scenario("--experimental_build_setting_api=true")
.update("mock", new Mock())
.testIfErrorContains(
"in call to positionals_only_method(), parameter 'b' got value of type 'int', want"
+ " 'bool'",
"mock.positionals_only_method(1, 3)");
- new SkylarkTest("--experimental_build_setting_api=false")
+ new Scenario("--experimental_build_setting_api=false")
.update("mock", new Mock())
.testEval("mock.positionals_only_method(1, 3)", "'positionals_only_method(1, false, 3)'");
- new SkylarkTest("--experimental_build_setting_api=false")
+ new Scenario("--experimental_build_setting_api=false")
.update("mock", new Mock())
.testIfErrorContains(
"in call to positionals_only_method(), parameter 'c' got value of type 'bool', want"
@@ -159,22 +152,22 @@
@Test
public void testKeywordOnlyGuardedMethod() throws Exception {
- new SkylarkTest("--experimental_build_setting_api=true")
+ new Scenario("--experimental_build_setting_api=true")
.update("mock", new Mock())
.testEval(
"mock.keywords_only_method(a=1, b=True, c=3)", "'keywords_only_method(1, true, 3)'");
- new SkylarkTest("--experimental_build_setting_api=true")
+ new Scenario("--experimental_build_setting_api=true")
.update("mock", new Mock())
.testIfErrorContains(
"keywords_only_method() missing 1 required named argument: b",
"mock.keywords_only_method(a=1, c=3)");
- new SkylarkTest("--experimental_build_setting_api=false")
+ new Scenario("--experimental_build_setting_api=false")
.update("mock", new Mock())
.testEval("mock.keywords_only_method(a=1, c=3)", "'keywords_only_method(1, false, 3)'");
- new SkylarkTest("--experimental_build_setting_api=false")
+ new Scenario("--experimental_build_setting_api=false")
.update("mock", new Mock())
.testIfErrorContains(
"parameter 'b' is experimental and thus unavailable with the current "
@@ -186,13 +179,13 @@
@Test
public void testMixedParamsMethod() throws Exception {
// def mixed_params_method(a, b, c = ?, d = ?)
- new SkylarkTest("--experimental_build_setting_api=true")
+ new Scenario("--experimental_build_setting_api=true")
.update("mock", new Mock())
.testEval(
"mock.mixed_params_method(1, True, c=3, d=True)",
"'mixed_params_method(1, true, 3, true)'");
- new SkylarkTest("--experimental_build_setting_api=true")
+ new Scenario("--experimental_build_setting_api=true")
.update("mock", new Mock())
.testIfErrorContains(
// Missing named arguments (d) are not reported
@@ -201,18 +194,18 @@
"mock.mixed_params_method(1, c=3)");
// def mixed_params_method(a, b disabled = False, c disabled = 3, d = ?)
- new SkylarkTest("--experimental_build_setting_api=false")
+ new Scenario("--experimental_build_setting_api=false")
.update("mock", new Mock())
.testEval(
"mock.mixed_params_method(1, d=True)", "'mixed_params_method(1, false, 3, true)'");
- new SkylarkTest("--experimental_build_setting_api=false")
+ new Scenario("--experimental_build_setting_api=false")
.update("mock", new Mock())
.testIfErrorContains(
"mixed_params_method() accepts no more than 1 positional argument but got 2",
"mock.mixed_params_method(1, True, d=True)");
- new SkylarkTest("--experimental_build_setting_api=false")
+ new Scenario("--experimental_build_setting_api=false")
.update("mock", new Mock())
.testIfErrorContains(
"mixed_params_method() accepts no more than 1 positional argument but got 2",
@@ -221,27 +214,85 @@
@Test
public void testKeywordsMultipleFlags() throws Exception {
- new SkylarkTest("--experimental_build_setting_api=true", "--incompatible_no_attr_license=false")
+ new Scenario("--experimental_build_setting_api=true", "--incompatible_no_attr_license=false")
.update("mock", new Mock())
.testEval(
"mock.keywords_multiple_flags(a=42, b=True, c=0)",
"'keywords_multiple_flags(42, true, 0)'");
- new SkylarkTest("--experimental_build_setting_api=true", "--incompatible_no_attr_license=false")
+ new Scenario("--experimental_build_setting_api=true", "--incompatible_no_attr_license=false")
.update("mock", new Mock())
.testIfErrorContains(
"keywords_multiple_flags() missing 2 required named arguments: b, c",
"mock.keywords_multiple_flags(a=42)");
- new SkylarkTest("--experimental_build_setting_api=false", "--incompatible_no_attr_license=true")
+ new Scenario("--experimental_build_setting_api=false", "--incompatible_no_attr_license=true")
.update("mock", new Mock())
.testEval("mock.keywords_multiple_flags(a=42)", "'keywords_multiple_flags(42, false, 3)'");
- new SkylarkTest("--experimental_build_setting_api=false", "--incompatible_no_attr_license=true")
+ new Scenario("--experimental_build_setting_api=false", "--incompatible_no_attr_license=true")
.update("mock", new Mock())
.testIfErrorContains(
"parameter 'b' is deprecated and will be removed soon. It may be "
+ "temporarily re-enabled by setting --incompatible_no_attr_license=false",
"mock.keywords_multiple_flags(a=42, b=True, c=0)");
}
+
+ @Test
+ public void testExperimentalFlagGuardedValue() throws Exception {
+ // This test uses an arbitrary experimental flag to verify this functionality. If this
+ // experimental flag were to go away, this test may be updated to use any experimental flag.
+ // The flag itself is unimportant to the test.
+ predeclare(
+ "GlobalSymbol",
+ FlagGuardedValue.onlyWhenExperimentalFlagIsTrue(
+ FlagIdentifier.EXPERIMENTAL_BUILD_SETTING_API, "foo"));
+
+ String errorMessage =
+ "GlobalSymbol is experimental and thus unavailable with the current "
+ + "flags. It may be enabled by setting --experimental_build_setting_api";
+
+ new Scenario("--experimental_build_setting_api=true")
+ .setUp("var = GlobalSymbol")
+ .testLookup("var", "foo");
+
+ new Scenario("--experimental_build_setting_api=false")
+ .testIfErrorContains(errorMessage, "var = GlobalSymbol");
+
+ new Scenario("--experimental_build_setting_api=false")
+ .testIfErrorContains(errorMessage, "def my_function():", " var = GlobalSymbol");
+
+ new Scenario("--experimental_build_setting_api=false")
+ .setUp("GlobalSymbol = 'other'", "var = GlobalSymbol")
+ .testLookup("var", "other");
+ }
+
+ @Test
+ public void testIncompatibleFlagGuardedValue() throws Exception {
+ // This test uses an arbitrary incompatible flag to verify this functionality. If this
+ // incompatible flag were to go away, this test may be updated to use any incompatible flag.
+ // The flag itself is unimportant to the test.
+ predeclare(
+ "GlobalSymbol",
+ FlagGuardedValue.onlyWhenIncompatibleFlagIsFalse(
+ FlagIdentifier.INCOMPATIBLE_NO_TARGET_OUTPUT_GROUP, "foo"));
+
+ String errorMessage =
+ "GlobalSymbol is deprecated and will be removed soon. It may be "
+ + "temporarily re-enabled by setting --incompatible_no_target_output_group=false";
+
+ new Scenario("--incompatible_no_target_output_group=false")
+ .setUp("var = GlobalSymbol")
+ .testLookup("var", "foo");
+
+ new Scenario("--incompatible_no_target_output_group=true")
+ .testIfErrorContains(errorMessage, "var = GlobalSymbol");
+
+ new Scenario("--incompatible_no_target_output_group=true")
+ .testIfErrorContains(errorMessage, "def my_function():", " var = GlobalSymbol");
+
+ new Scenario("--incompatible_no_target_output_group=true")
+ .setUp("GlobalSymbol = 'other'", "var = GlobalSymbol")
+ .testLookup("var", "other");
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadTest.java b/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadTest.java
index d8806c5..12fb0d7 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/StarlarkThreadTest.java
@@ -172,7 +172,7 @@
@Test
public void testBuiltinsCanBeShadowed() throws Exception {
- StarlarkThread thread = newStarlarkThreadWithSkylarkOptions();
+ StarlarkThread thread = newStarlarkThread();
EvalUtils.exec(ParserInput.fromLines("True = 123"), thread);
assertThat(thread.getGlobals().lookup("True")).isEqualTo(123);
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java b/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java
index 7a1bfbc..10c391c 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java
@@ -17,23 +17,24 @@
import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.analysis.skylark.SkylarkModules; // a bad dependency
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
-import com.google.devtools.build.lib.packages.PackageFactory;
+import com.google.devtools.build.lib.packages.StarlarkSemanticsOptions;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Expression;
+import com.google.devtools.build.lib.syntax.Module;
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.ParserInput;
-import com.google.devtools.build.lib.syntax.StarlarkFile;
+import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.syntax.SyntaxError;
-import com.google.devtools.build.lib.syntax.ValidationEnvironment;
-import com.google.devtools.build.lib.testutil.TestMode;
-import java.util.ArrayList;
+import com.google.devtools.common.options.Options;
+import com.google.devtools.common.options.OptionsParsingException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -46,71 +47,54 @@
public class EvaluationTestCase {
private EventCollectionApparatus eventCollectionApparatus =
new EventCollectionApparatus(EventKind.ALL_EVENTS);
- private TestMode testMode = TestMode.SKYLARK;
- protected StarlarkThread thread;
- protected Mutability mutability = Mutability.create("test");
+
+ private StarlarkSemantics semantics = StarlarkSemantics.DEFAULT_SEMANTICS;
+ private final Map<String, Object> extraPredeclared = new HashMap<>();
+ private StarlarkThread thread;
@Before
- public final void initialize() throws Exception {
+ public final void initialize() {
+ // TODO(adonovan): clean up the lazy initialization of thread when we disentangle
+ // Module from it. Only the module need exist early; the thread can be created
+ // immediately before execution
thread = newStarlarkThread();
}
- /**
- * Creates a new StarlarkThread suitable for the test case. Subclasses may override it to fit
- * their purpose and e.g. call newBuildStarlarkThread or newStarlarkThread; or they may play with
- * the testMode to run tests in either or both kinds of StarlarkThread. Note that all
- * StarlarkThread-s may share the same Mutability, so don't close it.
- *
- * @return a fresh StarlarkThread.
- */
- public StarlarkThread newStarlarkThread() throws Exception {
- return newStarlarkThreadWithSkylarkOptions();
- }
-
- protected StarlarkThread newStarlarkThreadWithSkylarkOptions(String... skylarkOptions)
- throws Exception {
- return newStarlarkThreadWithBuiltinsAndSkylarkOptions(ImmutableMap.of(), skylarkOptions);
- }
-
- protected StarlarkThread newStarlarkThreadWithBuiltinsAndSkylarkOptions(
- Map<String, Object> builtins, String... skylarkOptions) throws Exception {
- if (testMode == null) {
- throw new IllegalArgumentException(
- "TestMode is null. Please set a Testmode via setMode() or set the "
- + "StarlarkThread manually by overriding newStarlarkThread()");
- }
- return testMode.createStarlarkThread(
- StarlarkThread.makeDebugPrintHandler(getEventHandler()), builtins, skylarkOptions);
+ // Adds a binding to the predeclared environment.
+ protected final void predeclare(String name, Object value) {
+ extraPredeclared.put(name, value);
}
/**
- * Sets the specified {@code TestMode} and tries to create the appropriate {@code StarlarkThread}
- *
- * @param testMode
- * @throws Exception
+ * Returns a new thread using the semantics set by setSemantics(), the predeclared environment of
+ * SkylarkModules and prior calls to predeclared(), and a new mutability. Overridden by
+ * subclasses.
*/
- protected void setMode(TestMode testMode, String... skylarkOptions) throws Exception {
- this.testMode = testMode;
- thread = newStarlarkThreadWithSkylarkOptions(skylarkOptions);
+ public StarlarkThread newStarlarkThread() {
+ ImmutableMap.Builder<String, Object> envBuilder = ImmutableMap.builder();
+ SkylarkModules.addSkylarkGlobalsToBuilder(envBuilder); // TODO(adonovan): break bad dependency
+ envBuilder.putAll(extraPredeclared);
+ Module module = Module.createForBuiltins(envBuilder.build());
+
+ StarlarkThread thread =
+ StarlarkThread.builder(Mutability.create("test"))
+ .setGlobals(module)
+ .setSemantics(semantics)
+ .build();
+ thread.setPrintHandler(StarlarkThread.makeDebugPrintHandler(getEventHandler()));
+ return thread;
}
- protected void setMode(TestMode testMode, Map<String, Object> builtins,
- String... skylarkOptions) throws Exception {
- this.testMode = testMode;
- thread = newStarlarkThreadWithBuiltinsAndSkylarkOptions(builtins, skylarkOptions);
- }
+ /**
+ * Parses the semantics flags and updates the semantics used for subsequent evaluations. Also
+ * reinitializes the thread.
+ */
+ protected final void setSemantics(String... options) throws OptionsParsingException {
+ this.semantics =
+ Options.parse(StarlarkSemanticsOptions.class, options).getOptions().toSkylarkSemantics();
- protected void enableSkylarkMode(Map<String, Object> builtins,
- String... skylarkOptions) throws Exception {
- setMode(TestMode.SKYLARK, builtins, skylarkOptions);
- }
-
- protected void enableSkylarkMode(String... skylarkOptions) throws Exception {
- setMode(TestMode.SKYLARK, skylarkOptions);
- }
-
- protected void enableBuildMode(String... skylarkOptions) throws Exception {
- setMode(TestMode.BUILD, skylarkOptions);
+ // Re-initialize the thread with the new semantics. See note at initialize.
+ thread = newStarlarkThread();
}
public ExtendedEventHandler getEventHandler() {
@@ -148,29 +132,9 @@
}
/** Joins the lines, parses them as a file, and executes it. */
- // TODO(adonovan): this function does too much:
- // - two modes, BUILD vs Skylark.
- // - parse + validate + BUILD dialect checks + execute.
- // Break the tests down into tests of just the scanner, parser, validator, build dialect checks,
- // or execution, and assert that all passes except the one of interest succeed.
- // All BUILD-dialect stuff belongs in bazel proper (lib.packages), not here.
- public final void exec(String... lines) throws Exception {
+ public final void exec(String... lines) throws SyntaxError, EvalException, InterruptedException {
ParserInput input = ParserInput.fromLines(lines);
- StarlarkFile file = StarlarkFile.parse(input);
- ValidationEnvironment.validateFile(
- file, thread.getGlobals(), thread.getSemantics(), testMode == TestMode.BUILD);
- if (testMode == TestMode.SKYLARK) { // .bzl and other dialects
- if (!file.ok()) {
- throw new SyntaxError(file.errors());
- }
- } else {
- // For BUILD mode, validation events are reported but don't (yet)
- // prevent execution. We also apply BUILD dialect syntax checks.
- Event.replayEventsOn(getEventHandler(), file.errors());
- List<String> globs = new ArrayList<>(); // unused
- PackageFactory.checkBuildSyntax(file, globs, globs, new HashMap<>(), getEventHandler());
- }
- EvalUtils.exec(file, thread);
+ EvalUtils.exec(input, thread);
}
public void checkEvalError(String msg, String... input) throws Exception {
@@ -231,36 +195,42 @@
return this;
}
- /**
- * Encapsulates a separate test which can be executed by a {@code TestMode}
- */
+ /** Encapsulates a separate test which can be executed by a Scenario. */
protected interface Testable {
- public void run() throws Exception;
+ void run() throws Exception;
}
/**
- * Base class for test cases that run in specific modes (e.g. Build and/or Skylark)
+ * A test scenario (a script of steps). Beware: Scenario is an inner class that mutates its
+ * enclosing EvaluationTestCase as it executes the script.
*/
- protected abstract class ModalTestCase {
- private final SetupActions setup;
+ public final class Scenario {
+ private final SetupActions setup = new SetupActions();
+ private final String[] skylarkOptions;
- protected ModalTestCase() {
- setup = new SetupActions();
+ public Scenario(String... skylarkOptions) {
+ this.skylarkOptions = skylarkOptions;
+ }
+
+ private void run(Testable testable) throws Exception {
+ setSemantics(skylarkOptions);
+ testable.run();
}
/** Allows the execution of several statements before each following test. */
- public ModalTestCase setUp(String... lines) {
+ public Scenario setUp(String... lines) {
setup.registerExec(lines);
return this;
}
/**
* Allows the update of the specified variable before each following test
+ *
* @param name The name of the variable that should be updated
* @param value The new value of the variable
- * @return This {@code ModalTestCase}
+ * @return This {@code Scenario}
*/
- public ModalTestCase update(String name, Object value) {
+ public Scenario update(String name, Object value) {
setup.registerUpdate(name, value);
return this;
}
@@ -270,41 +240,40 @@
*
* @param src The source expression to be evaluated
* @param expectedEvalString The expression of the expected result
- * @return This {@code ModalTestCase}
+ * @return This {@code Scenario}
* @throws Exception
*/
- public ModalTestCase testEval(String src, String expectedEvalString) throws Exception {
+ public Scenario testEval(String src, String expectedEvalString) throws Exception {
runTest(createComparisonTestable(src, expectedEvalString, true));
return this;
}
/** Evaluates an expression and compares its result to the expected object. */
- public ModalTestCase testExpression(String src, Object expected) throws Exception {
+ public Scenario testExpression(String src, Object expected) throws Exception {
runTest(createComparisonTestable(src, expected, false));
return this;
}
/** Evaluates an expression and compares its result to the ordered list of expected objects. */
- public ModalTestCase testExactOrder(String src, Object... items) throws Exception {
+ public Scenario testExactOrder(String src, Object... items) throws Exception {
runTest(collectionTestable(src, items));
return this;
}
/** Evaluates an expression and checks whether it fails with the expected error. */
- public ModalTestCase testIfExactError(String expectedError, String... lines) throws Exception {
+ public Scenario testIfExactError(String expectedError, String... lines) throws Exception {
runTest(errorTestable(true, expectedError, lines));
return this;
}
/** Evaluates the expresson and checks whether it fails with the expected error. */
- public ModalTestCase testIfErrorContains(String expectedError, String... lines)
- throws Exception {
+ public Scenario testIfErrorContains(String expectedError, String... lines) throws Exception {
runTest(errorTestable(false, expectedError, lines));
return this;
}
/** Looks up the value of the specified variable and compares it to the expected value. */
- public ModalTestCase testLookup(String name, Object expected) throws Exception {
+ public Scenario testLookup(String name, Object expected) throws Exception {
runTest(createLookUpTestable(name, expected));
return this;
}
@@ -394,8 +363,6 @@
protected void runTest(Testable testable) throws Exception {
run(new TestableDecorator(setup, testable));
}
-
- protected abstract void run(Testable testable) throws Exception;
}
/**
@@ -467,75 +434,4 @@
}
}
}
-
- /**
- * A class that executes each separate test in both modes (Build and Skylark)
- */
- protected class BothModesTest extends ModalTestCase {
- private final String[] skylarkOptions;
-
- public BothModesTest(String... skylarkOptions) {
- this.skylarkOptions = skylarkOptions;
- }
-
- /**
- * Executes the given Testable in both Build and Skylark mode
- */
- @Override
- protected void run(Testable testable) throws Exception {
- enableSkylarkMode(skylarkOptions);
- try {
- testable.run();
- } catch (Exception e) {
- throw new Exception("While in Skylark mode", e);
- }
-
- enableBuildMode(skylarkOptions);
- try {
- testable.run();
- } catch (Exception e) {
- throw new Exception("While in Build mode", e);
- }
- }
- }
-
- /**
- * A class that runs all tests in Build mode
- */
- protected class BuildTest extends ModalTestCase {
- private final String[] skylarkOptions;
-
- public BuildTest(String... skylarkOptions) {
- this.skylarkOptions = skylarkOptions;
- }
-
- @Override
- protected void run(Testable testable) throws Exception {
- enableBuildMode(skylarkOptions);
- testable.run();
- }
- }
-
- /**
- * A class that runs all tests in Skylark mode
- */
- protected class SkylarkTest extends ModalTestCase {
- private final String[] skylarkOptions;
- private final Map<String, Object> builtins;
-
- public SkylarkTest(String... skylarkOptions) {
- this(ImmutableMap.of(), skylarkOptions);
- }
-
- public SkylarkTest(Map<String, Object> builtins, String... skylarkOptions) {
- this.builtins = builtins;
- this.skylarkOptions = skylarkOptions;
- }
-
- @Override
- protected void run(Testable testable) throws Exception {
- enableSkylarkMode(builtins, skylarkOptions);
- testable.run();
- }
- }
}
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TestMode.java b/src/test/java/com/google/devtools/build/lib/testutil/TestMode.java
deleted file mode 100644
index 16f4a59..0000000
--- a/src/test/java/com/google/devtools/build/lib/testutil/TestMode.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2015 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.build.lib.testutil;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.analysis.skylark.SkylarkModules;
-import com.google.devtools.build.lib.packages.StarlarkSemanticsOptions;
-import com.google.devtools.build.lib.syntax.Module;
-import com.google.devtools.build.lib.syntax.Mutability;
-import com.google.devtools.build.lib.syntax.StarlarkSemantics;
-import com.google.devtools.build.lib.syntax.StarlarkThread;
-import com.google.devtools.common.options.Options;
-import com.google.devtools.common.options.OptionsParsingException;
-import java.util.Map;
-
-/**
- * Describes a particular testing mode by determining how the appropriate {@code StarlarkThread} has
- * to be created
- */
-public abstract class TestMode {
-
- private static StarlarkSemantics parseSkylarkSemantics(String... options)
- throws OptionsParsingException {
- return Options.parse(StarlarkSemanticsOptions.class, options).getOptions().toSkylarkSemantics();
- }
-
- public static final TestMode BUILD =
- new TestMode() {
- @Override
- public StarlarkThread createStarlarkThread(
- StarlarkThread.PrintHandler printHandler,
- Map<String, Object> builtins,
- String... skylarkOptions)
- throws Exception {
- StarlarkThread thread =
- StarlarkThread.builder(Mutability.create("build test"))
- .setGlobals(createModule(builtins))
- .setSemantics(TestMode.parseSkylarkSemantics(skylarkOptions))
- .build();
- thread.setPrintHandler(printHandler);
- return thread;
- }
- };
-
- public static final TestMode SKYLARK =
- new TestMode() {
- @Override
- public StarlarkThread createStarlarkThread(
- StarlarkThread.PrintHandler printHandler,
- Map<String, Object> builtins,
- String... skylarkOptions)
- throws Exception {
- StarlarkThread thread =
- StarlarkThread.builder(Mutability.create("skylark test"))
- .setGlobals(createModule(builtins))
- .setSemantics(TestMode.parseSkylarkSemantics(skylarkOptions))
- .build();
- thread.setPrintHandler(printHandler);
- return thread;
- }
- };
-
- private static Module createModule(Map<String, Object> builtins) {
- ImmutableMap.Builder<String, Object> envBuilder = ImmutableMap.builder();
-
- SkylarkModules.addSkylarkGlobalsToBuilder(envBuilder);
- envBuilder.putAll(builtins);
- return Module.createForBuiltins(envBuilder.build());
- }
-
- public abstract StarlarkThread createStarlarkThread(
- StarlarkThread.PrintHandler printHandler,
- Map<String, Object> builtins,
- String... skylarkOptions)
- throws Exception;
-}