aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com
diff options
context:
space:
mode:
authorGravatar Francois-Rene Rideau <tunes@google.com>2015-09-04 19:13:47 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-09-08 09:02:28 +0000
commit5a94e59f02833f9142bad9203acd72626b089535 (patch)
treeddfe00a54a701eff0f74af6e84e5b8cefcef1c93 /src/test/java/com
parentab1711b026f8a4915ee2ef2556b2a7dbff18fa63 (diff)
Refactor Skylark Environment-s
Make Environment-s freezable: Introduce a class Mutability as a revokable capability to mutate objects in an Environment. For now, only Environment-s carry this capability. Make sure that every Mutability is revoked in the same function that creates it, so no Environment is left open for modification after being created and exported; exceptions for tests, the shell and initialization contexts. Unify Environment, SkylarkEnvironment and EvaluationContext into Environment. Have a notion of Frame for the bindings + parent + mutability. Replace the updateAndPropagate mechanism by a dynamicFrame. Simplify ValidationEnvironment, that is now always deduced from the Environment. -- MOS_MIGRATED_REVID=102363438
Diffstat (limited to 'src/test/java/com')
-rw-r--r--src/test/java/com/google/devtools/build/lib/events/util/EventCollectionApparatus.java6
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java4
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java118
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java98
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java4
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java90
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java32
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java2
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/SkylarkListTest.java4
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/SkylarkShell.java8
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java6
-rw-r--r--src/test/java/com/google/devtools/build/lib/testutil/TestMode.java45
12 files changed, 250 insertions, 167 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/events/util/EventCollectionApparatus.java b/src/test/java/com/google/devtools/build/lib/events/util/EventCollectionApparatus.java
index aa8d8f83a6..c7f85d6fcb 100644
--- a/src/test/java/com/google/devtools/build/lib/events/util/EventCollectionApparatus.java
+++ b/src/test/java/com/google/devtools/build/lib/events/util/EventCollectionApparatus.java
@@ -18,7 +18,7 @@ import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.PrintingEventHandler;
import com.google.devtools.build.lib.events.Reporter;
-import com.google.devtools.build.lib.syntax.EvaluationContext;
+import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.testutil.MoreAsserts;
import com.google.devtools.build.lib.util.io.OutErr;
@@ -67,9 +67,9 @@ public class EventCollectionApparatus {
*/
public void setFailFast(boolean failFast) {
if (failFast) {
- reporter.addHandler(EvaluationContext.FAIL_FAST_HANDLER);
+ reporter.addHandler(Environment.FAIL_FAST_HANDLER);
} else {
- reporter.removeHandler(EvaluationContext.FAIL_FAST_HANDLER);
+ reporter.removeHandler(Environment.FAIL_FAST_HANDLER);
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
index 24ac455762..2f298518e3 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
@@ -30,9 +30,9 @@ import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.PackageFactory.LegacyGlobber;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.syntax.BuildFileAST;
+import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.ParserInputSource;
-import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.testutil.TestUtils;
@@ -134,7 +134,7 @@ public class PackageFactoryApparatus {
LegacyBuilder resultBuilder = factory.evaluateBuildFile(
externalPkg, packageId, buildFileAST, buildFile,
globber, ImmutableList.<Event>of(), ConstantRuleVisibility.PUBLIC, false, false,
- new MakeEnvironment.Builder(), ImmutableMap.<PathFragment, SkylarkEnvironment>of(),
+ new MakeEnvironment.Builder(), ImmutableMap.<PathFragment, Environment>of(),
ImmutableList.<Label>of());
Package result = resultBuilder.build();
Event.replayEventsOn(events.reporter(), result.getEvents());
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java b/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java
index eff5badfb6..00e9062d63 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/BuildFileASTTest.java
@@ -22,11 +22,7 @@ import static org.junit.Assert.assertTrue;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
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.Reporter;
-import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
import com.google.devtools.build.lib.packages.CachingPackageLocator;
-import com.google.devtools.build.lib.testutil.MoreAsserts;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.vfs.Path;
@@ -37,13 +33,14 @@ import org.junit.runners.JUnit4;
import java.io.IOException;
import java.util.Arrays;
+/**
+ * Unit tests for BuildFileAST.
+ */
@RunWith(JUnit4.class)
-public class BuildFileASTTest {
+public class BuildFileASTTest extends EvaluationTestCase {
private Scratch scratch = new Scratch();
- private EventCollectionApparatus events = new EventCollectionApparatus(EventKind.ALL_EVENTS);
-
private class ScratchPathPackageLocator implements CachingPackageLocator {
@Override
public Path getBuildFileForPackage(PackageIdentifier packageName) {
@@ -53,13 +50,18 @@ public class BuildFileASTTest {
private CachingPackageLocator locator = new ScratchPathPackageLocator();
+ @Override
+ public Environment newEnvironment() throws Exception {
+ return newBuildEnvironment();
+ }
+
/**
* Parses the contents of the specified string (using DUMMY_PATH as the fake
* filename) and returns the AST. Resets the error handler beforehand.
*/
private BuildFileAST parseBuildFile(String... lines) throws IOException {
Path file = scratch.file("/a/build/file/BUILD", lines);
- return BuildFileAST.parseBuildFile(file, events.reporter(), locator, false);
+ return BuildFileAST.parseBuildFile(file, getEventHandler(), locator, false);
}
@Test
@@ -69,11 +71,9 @@ public class BuildFileASTTest {
"",
"x = [1,2,'foo',4] + [1,2, \"%s%d\" % ('foo', 1)]");
- Environment env = new Environment();
- Reporter reporter = new Reporter();
- BuildFileAST buildfile = BuildFileAST.parseBuildFile(buildFile, reporter, null, false);
+ BuildFileAST buildfile = BuildFileAST.parseBuildFile(buildFile, getEventHandler(), null, false);
- assertTrue(buildfile.exec(env, reporter));
+ assertTrue(buildfile.exec(env, getEventHandler()));
// Test final environment is correctly modified:
//
@@ -91,15 +91,11 @@ public class BuildFileASTTest {
"",
"z = x + y");
- Environment env = new Environment();
- Reporter reporter = new Reporter();
- EventCollector collector = new EventCollector(EventKind.ALL_EVENTS);
- reporter.addHandler(collector);
- BuildFileAST buildfile = BuildFileAST.parseBuildFile(buildFile, reporter, null, false);
+ setFailFast(false);
+ BuildFileAST buildfile = BuildFileAST.parseBuildFile(buildFile, getEventHandler(), null, false);
- assertFalse(buildfile.exec(env, reporter));
- Event e = MoreAsserts.assertContainsEvent(collector,
- "unsupported operand type(s) for +: 'int' and 'List'");
+ assertFalse(buildfile.exec(env, getEventHandler()));
+ Event e = assertContainsEvent("unsupported operand type(s) for +: 'int' and 'List'");
assertEquals(4, e.getLocation().getStartLineAndColumn().getLine());
}
@@ -114,13 +110,12 @@ public class BuildFileASTTest {
@Test
public void testFailsIfNewlinesAreMissing() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
BuildFileAST buildFileAST =
parseBuildFile("foo() bar() something = baz() bar()");
- Event event = events.collector().iterator().next();
- assertEquals("syntax error at \'bar\': expected newline", event.getMessage());
+ Event event = assertContainsEvent("syntax error at \'bar\': expected newline");
assertEquals("/a/build/file/BUILD",
event.getLocation().getPath().toString());
assertEquals(1, event.getLocation().getStartLineAndColumn().getLine());
@@ -129,11 +124,10 @@ public class BuildFileASTTest {
@Test
public void testImplicitStringConcatenationFails() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
BuildFileAST buildFileAST = parseBuildFile("a = 'foo' 'bar'");
- Event event = events.collector().iterator().next();
- assertEquals("Implicit string concatenation is forbidden, use the + operator",
- event.getMessage());
+ Event event = assertContainsEvent(
+ "Implicit string concatenation is forbidden, use the + operator");
assertEquals("/a/build/file/BUILD",
event.getLocation().getPath().toString());
assertEquals(1, event.getLocation().getStartLineAndColumn().getLine());
@@ -143,11 +137,10 @@ public class BuildFileASTTest {
@Test
public void testImplicitStringConcatenationAcrossLinesIsIllegal() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
BuildFileAST buildFileAST = parseBuildFile("a = 'foo'\n 'bar'");
- Event event = events.collector().iterator().next();
- assertEquals("indentation error", event.getMessage());
+ Event event = assertContainsEvent("indentation error");
assertEquals("/a/build/file/BUILD",
event.getLocation().getPath().toString());
assertEquals(2, event.getLocation().getStartLineAndColumn().getLine());
@@ -172,7 +165,7 @@ public class BuildFileASTTest {
@Test
public void testWithSyntaxErrorsDoesNotPrintDollarError() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
BuildFileAST buildFile = parseBuildFile(
"abi = cxx_abi + '-glibc-' + glibc_version + '-' + generic_cpu + '-' + sysname",
"libs = [abi + opt_level + '/lib/libcc.a']",
@@ -182,14 +175,11 @@ public class BuildFileASTTest {
" srcs = libs,",
" includes = [ abi + opt_level + '/include' ])");
assertTrue(buildFile.containsErrors());
- Event event = events.collector().iterator().next();
- assertEquals("syntax error at '+': expected expression", event.getMessage());
- Environment env = new Environment();
- assertFalse(buildFile.exec(env, events.reporter()));
- assertNull(findEvent(events.collector(), "$error$"));
+ assertContainsEvent("syntax error at '+': expected expression");
+ assertFalse(buildFile.exec(env, getEventHandler()));
+ assertNull(findEvent(getEventCollector(), "$error$"));
// This message should not be printed anymore.
- Event event2 = findEvent(events.collector(), "contains syntax error(s)");
- assertNull(event2);
+ assertNull(findEvent(getEventCollector(), "contains syntax error(s)"));
}
@Test
@@ -202,7 +192,7 @@ public class BuildFileASTTest {
+ "include(\"//foo/bar:BUILD\")\n"
+ "b = 4\n");
- BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(buildFile, events.reporter(),
+ BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(buildFile, getEventHandler(),
locator, false);
assertFalse(buildFileAST.containsErrors());
@@ -217,15 +207,14 @@ public class BuildFileASTTest {
"include(\"//foo/bar:defs\")\n"
+ "b = a + 1\n");
- BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(buildFile, events.reporter(),
+ BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(buildFile, getEventHandler(),
locator, false);
assertFalse(buildFileAST.containsErrors());
assertThat(buildFileAST.getStatements()).hasSize(3);
- Environment env = new Environment();
- Reporter reporter = new Reporter();
- assertFalse(buildFileAST.exec(env, reporter));
+ setFailFast(false);
+ assertFalse(buildFileAST.exec(env, getEventHandler()));
assertEquals(2, env.lookup("b"));
}
@@ -247,63 +236,53 @@ public class BuildFileASTTest {
assertFalse(buildFileAST.containsErrors());
assertThat(buildFileAST.getStatements()).hasSize(8);
- Environment env = new Environment();
- Reporter reporter = new Reporter();
- assertFalse(buildFileAST.exec(env, reporter));
+ setFailFast(false);
+ assertFalse(buildFileAST.exec(env, getEventHandler()));
assertEquals(5, env.lookup("b"));
assertEquals(7, env.lookup("c"));
}
@Test
public void testFailInclude() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
BuildFileAST buildFileAST = parseBuildFile("include(\"//nonexistent\")");
assertThat(buildFileAST.getStatements()).hasSize(1);
- events.assertContainsEvent("Include of '//nonexistent' failed");
- }
-
-
- private class EmptyPackageLocator implements CachingPackageLocator {
- @Override
- public Path getBuildFileForPackage(PackageIdentifier packageName) {
- return null;
- }
+ assertContainsEvent("Include of '//nonexistent' failed");
}
- private CachingPackageLocator emptyLocator = new EmptyPackageLocator();
@Test
public void testFailInclude2() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
Path buildFile = scratch.file("/foo/bar/BUILD",
"include(\"//nonexistent:foo\")\n");
- BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(buildFile, events.reporter(),
- emptyLocator, false);
+ BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(
+ buildFile, getEventHandler(), Environment.EMPTY_PACKAGE_LOCATOR, false);
assertThat(buildFileAST.getStatements()).hasSize(1);
- events.assertContainsEvent("Package 'nonexistent' not found");
+ assertContainsEvent("Package 'nonexistent' not found");
}
@Test
public void testInvalidInclude() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
BuildFileAST buildFileAST = parseBuildFile("include(2)");
assertThat(buildFileAST.getStatements()).isEmpty();
- events.assertContainsEvent("syntax error at '2'");
+ assertContainsEvent("syntax error at '2'");
}
@Test
public void testRecursiveInclude() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
Path buildFile = scratch.file("/foo/bar/BUILD",
"include(\"//foo/bar:BUILD\")\n");
- BuildFileAST.parseBuildFile(buildFile, events.reporter(), locator, false);
- events.assertContainsEvent("Recursive inclusion");
+ BuildFileAST.parseBuildFile(buildFile, getEventHandler(), locator, false);
+ assertContainsEvent("Recursive inclusion");
}
@Test
public void testParseErrorInclude() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
scratch.file("/foo/bar/file",
"a = 2 + % 3\n"); // parse error
@@ -311,14 +290,13 @@ public class BuildFileASTTest {
parseBuildFile("include(\"//foo/bar:file\")");
// Check the location is properly reported
- Event event = events.collector().iterator().next();
+ Event event = assertContainsEvent("syntax error at '%': expected expression");
assertEquals("/foo/bar/file:1:9", event.getLocation().print());
- assertEquals("syntax error at '%': expected expression", event.getMessage());
}
@Test
public void testNonExistentIncludeReported() throws Exception {
- events.setFailFast(false);
+ setFailFast(false);
BuildFileAST buildFileAST = parseBuildFile("include('//foo:bar')");
assertThat(buildFileAST.getStatements()).hasSize(1);
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java
index a324b13ff5..02021245c6 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java
@@ -31,8 +31,8 @@ import org.junit.runners.JUnit4;
public class EnvironmentTest extends EvaluationTestCase {
@Override
- public EvaluationContext newEvaluationContext() {
- return EvaluationContext.newBuildContext(getEventHandler());
+ public Environment newEnvironment() {
+ return newBuildEnvironment();
}
// Test the API directly
@@ -104,25 +104,41 @@ public class EnvironmentTest extends EvaluationTestCase {
@Test
public void testGetVariableNames() throws Exception {
- update("foo", "bar");
- update("wiz", 3);
-
- Environment nestedEnv = new Environment(getEnvironment());
- nestedEnv.update("foo", "bat");
- nestedEnv.update("quux", 42);
+ Environment outerEnv;
+ Environment innerEnv;
+ try (Mutability mut = Mutability.create("outer")) {
+ outerEnv = Environment.builder(mut)
+ .setGlobals(Environment.BUILD).build()
+ .update("foo", "bar")
+ .update("wiz", 3);
+ }
+ try (Mutability mut = Mutability.create("inner")) {
+ innerEnv = Environment.builder(mut)
+ .setGlobals(outerEnv.getGlobals()).build()
+ .update("foo", "bat")
+ .update("quux", 42);
+ }
- assertEquals(Sets.newHashSet("True", "False", "None", "foo", "wiz"),
- getEnvironment().getVariableNames());
- assertEquals(Sets.newHashSet("True", "False", "None", "foo", "wiz", "quux"),
- nestedEnv.getVariableNames());
+ assertEquals(Sets.newHashSet("foo", "wiz",
+ "False", "None", "True",
+ "-", "bool", "dict", "enumerate", "int", "len", "list",
+ "range", "repr", "select", "sorted", "str", "zip"),
+ outerEnv.getVariableNames());
+ assertEquals(Sets.newHashSet("foo", "wiz", "quux",
+ "False", "None", "True",
+ "-", "bool", "dict", "enumerate", "int", "len", "list",
+ "range", "repr", "select", "sorted", "str", "zip"),
+ innerEnv.getVariableNames());
}
@Test
public void testToString() throws Exception {
update("subject", new StringLiteral("Hello, 'world'.", '\''));
update("from", new StringLiteral("Java", '"'));
- assertEquals("Environment{False -> false, None -> None, True -> true, from -> \"Java\", "
- + "subject -> 'Hello, \\'world\\'.', }", getEnvironment().toString());
+ assertThat(getEnvironment().toString())
+ .startsWith("Environment(lexicalFrame=null, "
+ + "globalFrame=Frame[test]{\"from\": \"Java\", \"subject\": 'Hello, \\'world\\'.'}=>"
+ + "(BUILD){");
}
@Test
@@ -134,4 +150,58 @@ public class EnvironmentTest extends EvaluationTestCase {
assertThat(e).hasMessage("update(value == null)");
}
}
+
+ @Test
+ public void testFrozen() throws Exception {
+ Environment env;
+ try (Mutability mutability = Mutability.create("testFrozen")) {
+ env = Environment.builder(mutability)
+ .setGlobals(Environment.BUILD).setEventHandler(Environment.FAIL_FAST_HANDLER).build();
+ env.update("x", 1);
+ assertEquals(env.lookup("x"), 1);
+ env.update("y", 2);
+ assertEquals(env.lookup("y"), 2);
+ assertEquals(env.lookup("x"), 1);
+ env.update("x", 3);
+ assertEquals(env.lookup("x"), 3);
+ }
+ try {
+ // This update to an existing variable should fail because the environment was frozen.
+ env.update("x", 4);
+ throw new Exception("failed to fail"); // not an AssertionError like fail()
+ } catch (AssertionError e) {
+ assertThat(e).hasMessage("Can't update x to 4 in frozen environment");
+ }
+ try {
+ // This update to a new variable should also fail because the environment was frozen.
+ env.update("newvar", 5);
+ throw new Exception("failed to fail"); // not an AssertionError like fail()
+ } catch (AssertionError e) {
+ assertThat(e).hasMessage("Can't update newvar to 5 in frozen environment");
+ }
+ }
+
+ @Test
+ public void testReadOnly() throws Exception {
+ Environment env = newSkylarkEnvironment()
+ .setup("special_var", 42)
+ .update("global_var", 666);
+
+ // We don't even get a runtime exception trying to modify these,
+ // because we get compile-time exceptions even before we reach runtime!
+ try {
+ env.eval("special_var = 41");
+ throw new AssertionError("failed to fail");
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("ERROR 1:1: Variable special_var is read only");
+ }
+
+ try {
+ env.eval("def foo(x): x += global_var; global_var = 36; return x", "foo(1)");
+ throw new AssertionError("failed to fail");
+ } catch (EvalExceptionWithStackTrace e) {
+ assertThat(e.getMessage()).contains("Variable 'global_var' is referenced before assignment. "
+ + "The variable is defined in the global scope.");
+ }
+ }
}
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 cf23858207..83a55be2d8 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
@@ -482,9 +482,9 @@ public class EvaluationTest extends EvaluationTestCase {
@Test
public void testDictComprehensions_ToString() throws Exception {
assertEquals("{x: x for x in [1, 2]}",
- evaluationContext.parseExpression("{x : x for x in [1, 2]}").toString());
+ parseExpression("{x : x for x in [1, 2]}").toString());
assertEquals("{x + 'a': x for x in [1, 2]}",
- evaluationContext.parseExpression("{x + 'a' : x for x in [1, 2]}").toString());
+ parseExpression("{x + 'a' : x for x in [1, 2]}").toString());
}
@Test
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java
index b2d661b7d4..e26234af0c 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java
@@ -35,48 +35,76 @@ import java.util.List;
* Base class for test cases that use parsing and evaluation services.
*/
public class EvaluationTestCase {
-
+
private EventCollectionApparatus eventCollectionApparatus;
private PackageFactory factory;
private TestMode testMode = TestMode.SKYLARK;
-
- protected EvaluationContext evaluationContext;
+ protected Environment env;
+ protected Mutability mutability = Mutability.create("test");
public EvaluationTestCase() {
createNewInfrastructure();
}
-
+
@Before
public void setUp() throws Exception {
createNewInfrastructure();
- evaluationContext = newEvaluationContext();
+ env = newEnvironment();
+ }
+
+ /**
+ * Creates a standard Environment for tests in the BUILD language.
+ * No PythonPreprocessing, mostly empty mutable Environment.
+ */
+ public Environment newBuildEnvironment() {
+ return Environment.builder(mutability)
+ .setGlobals(Environment.BUILD)
+ .setEventHandler(getEventHandler())
+ .setLoadingPhase()
+ .build();
}
- public EvaluationContext newEvaluationContext() throws Exception {
+ /**
+ * Creates an Environment for Skylark with a mostly empty initial environment.
+ * For internal initialization or tests.
+ */
+ public Environment newSkylarkEnvironment() {
+ return Environment.builder(mutability)
+ .setSkylark()
+ .setGlobals(Environment.SKYLARK)
+ .setEventHandler(getEventHandler())
+ .build();
+ }
+
+ /**
+ * Creates a new Environment suitable for the test case. Subclasses may override it
+ * to fit their purpose and e.g. call newBuildEnvironment or newSkylarkEnvironment;
+ * or they may play with the testMode to run tests in either or both kinds of Environment.
+ * Note that all Environment-s may share the same Mutability, so don't close it.
+ * @return a fresh Environment.
+ */
+ public Environment newEnvironment() throws Exception {
if (testMode == null) {
throw new IllegalArgumentException(
"TestMode is null. Please set a Testmode via setMode() or set the "
- + "evaluatenContext manually by overriding newEvaluationContext()");
+ + "Environment manually by overriding newEnvironment()");
}
-
- return testMode.createContext(getEventHandler(), factory.getEnvironment());
+ return testMode.createEnvironment(getEventHandler(), null);
}
protected void createNewInfrastructure() {
eventCollectionApparatus = new EventCollectionApparatus(EventKind.ALL_EVENTS);
factory = new PackageFactory(TestRuleClassProvider.getRuleClassProvider());
}
-
+
/**
- * Sets the specified {@code TestMode} and tries to create the appropriate {@code
- * EvaluationContext}
- *
+ * Sets the specified {@code TestMode} and tries to create the appropriate {@code Environment}
* @param testMode
* @throws Exception
*/
protected void setMode(TestMode testMode) throws Exception {
this.testMode = testMode;
- evaluationContext = newEvaluationContext();
+ env = newEnvironment();
}
protected void enableSkylarkMode() throws Exception {
@@ -96,32 +124,33 @@ public class EvaluationTestCase {
}
public Environment getEnvironment() {
- return evaluationContext.getEnvironment();
+ return env;
}
-
+
public boolean isSkylark() {
- return evaluationContext.isSkylark();
+ return env.isSkylark();
}
protected List<Statement> parseFile(String... input) {
- return evaluationContext.parseFile(input);
+ return env.parseFile(input);
}
+ /** Parses an Expression from string without a supporting file */
Expression parseExpression(String... input) {
- return evaluationContext.parseExpression(input);
+ return Parser.parseExpression(env.createLexer(input), getEventHandler());
}
public EvaluationTestCase update(String varname, Object value) throws Exception {
- evaluationContext.update(varname, value);
+ env.update(varname, value);
return this;
}
public Object lookup(String varname) throws Exception {
- return evaluationContext.lookup(varname);
+ return env.lookup(varname);
}
public Object eval(String... input) throws Exception {
- return evaluationContext.eval(input);
+ return env.eval(input);
}
public void checkEvalError(String msg, String... input) throws Exception {
@@ -189,15 +218,14 @@ public class EvaluationTestCase {
/**
* Base class for test cases that run in specific modes (e.g. Build and/or Skylark)
- *
- */
+ */
protected abstract class ModalTestCase {
private final SetupActions setup;
-
- protected ModalTestCase() {
+
+ protected ModalTestCase() {
setup = new SetupActions();
}
-
+
/**
* Allows the execution of several statements before each following test
* @param statements The statement(s) to be executed
@@ -218,7 +246,7 @@ public class EvaluationTestCase {
setup.registerUpdate(name, value);
return this;
}
-
+
/**
* Evaluates two parameters and compares their results.
* @param statement The statement to be evaluated
@@ -255,7 +283,7 @@ public class EvaluationTestCase {
runTest(collectionTestable(statement, false, items));
return this;
}
-
+
/**
* Evaluates the given statement and compares its result to the collection of expected objects
* while considering their order
@@ -409,7 +437,7 @@ public class EvaluationTestCase {
}
/**
- * A simple decorator that allows the execution of setup actions before running
+ * A simple decorator that allows the execution of setup actions before running
* a {@code Testable}
*/
class TestableDecorator implements Testable {
@@ -480,7 +508,7 @@ public class EvaluationTestCase {
}
}
}
-
+
/**
* A class that executes each separate test in both modes (Build and Skylark)
*/
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
index e0c074a126..5137b45c65 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
@@ -32,43 +32,45 @@ import org.junit.runners.JUnit4;
import java.util.LinkedList;
import java.util.List;
-
/**
* Tests of parser behaviour.
*/
@RunWith(JUnit4.class)
public class ParserTest extends EvaluationTestCase {
- EvaluationContext buildContext;
- EvaluationContext buildContextWithPython;
+ Environment buildEnvironment;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
- buildContext = EvaluationContext.newBuildContext(getEventHandler());
- buildContextWithPython = EvaluationContext.newBuildContext(
- getEventHandler(), new Environment(), /*parsePython*/true);
+ buildEnvironment = newBuildEnvironment();
}
private Parser.ParseResult parseFileWithComments(String... input) {
- return buildContext.parseFileWithComments(input);
+ return buildEnvironment.parseFileWithComments(input);
}
+
+ /** Parses build code (not Skylark) */
@Override
protected List<Statement> parseFile(String... input) {
- return buildContext.parseFile(input);
+ return buildEnvironment.parseFile(input);
}
+
+ /** Parses a build code (not Skylark) with PythonProcessing enabled */
private List<Statement> parseFileWithPython(String... input) {
- return buildContextWithPython.parseFile(input);
+ return Parser.parseFile(
+ buildEnvironment.createLexer(input),
+ getEventHandler(),
+ Environment.EMPTY_PACKAGE_LOCATOR,
+ /*parsePython=*/true).statements;
}
+
+ /** Parses Skylark code */
private List<Statement> parseFileForSkylark(String... input) {
- return evaluationContext.parseFile(input);
- }
- private Statement parseStatement(String... input) {
- return buildContext.parseStatement(input);
+ return env.parseFile(input);
}
-
private static String getText(String text, ASTNode node) {
return text.substring(node.getLocation().getStartOffset(),
node.getLocation().getEndOffset());
@@ -707,7 +709,7 @@ public class ParserTest extends EvaluationTestCase {
@Test
public void testParserContainsErrors() throws Exception {
setFailFast(false);
- parseStatement("+");
+ parseFile("+");
assertContainsEvent("syntax error at '+'");
}
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 16bcb8010f..a473f9525b 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
@@ -526,7 +526,7 @@ public class SkylarkEvaluationTest extends EvaluationTest {
new SkylarkTest()
.update("mock", new Mock())
.testIfExactError("Keyword arguments are not allowed when calling a java method"
- + "\nwhile calling method 'string' on object of type Mock",
+ + "\nwhile calling method 'string' for type Mock",
"mock.string(key=True)");
}
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 86ad1fb557..7558b6c4f3 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
@@ -45,8 +45,8 @@ public class SkylarkListTest extends EvaluationTestCase {
SkylarkList.lazyList(new CustomIterable(), Integer.class);
@Override
- public EvaluationContext newEvaluationContext() throws Exception {
- return super.newEvaluationContext().update("lazy", list);
+ public Environment newEnvironment() throws Exception {
+ return newSkylarkEnvironment().update("lazy", list);
}
@Test
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkShell.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkShell.java
index c4bb7d84a9..b12f51b1d0 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkShell.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkShell.java
@@ -15,7 +15,6 @@ package com.google.devtools.build.lib.syntax;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
-import com.google.devtools.build.lib.rules.SkylarkModules;
import java.io.BufferedReader;
import java.io.IOException;
@@ -42,8 +41,9 @@ class SkylarkShell {
private final BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in, Charset.defaultCharset()));
- private final EvaluationContext ev =
- SkylarkModules.newEvaluationContext(PRINT_HANDLER);
+ private final Mutability mutability = Mutability.create("shell");
+ private final Environment env = Environment.builder(mutability)
+ .setSkylark().setGlobals(Environment.SKYLARK).setEventHandler(PRINT_HANDLER).build();
public String read() {
StringBuilder input = new StringBuilder();
@@ -70,7 +70,7 @@ class SkylarkShell {
String input;
while ((input = read()) != null) {
try {
- Object result = ev.eval(input);
+ Object result = env.eval(input);
if (result != null) {
System.out.println(Printer.repr(result));
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java b/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java
index 57b341f3b9..3ebdf8dde4 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java
@@ -95,7 +95,7 @@ public class ValidationTests extends EvaluationTestCase {
@Test
public void testBuiltinSymbolsAreReadOnly() throws Exception {
- checkError("Variable rule is read only", "rule = 1");
+ checkError("Variable repr is read only", "repr = 1");
}
@Test
@@ -300,8 +300,8 @@ public class ValidationTests extends EvaluationTestCase {
@Test
public void testFunctionReturnsFunction() {
parse(
- "def impl(ctx):",
- " return None",
+ "def rule(*, implementation): return None",
+ "def impl(ctx): return None",
"",
"skylark_rule = rule(implementation = impl)",
"",
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
index 5ec7ac27b2..ea887f9d68 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/TestMode.java
+++ b/src/test/java/com/google/devtools/build/lib/testutil/TestMode.java
@@ -14,31 +14,36 @@
package com.google.devtools.build.lib.testutil;
import com.google.devtools.build.lib.events.EventHandler;
-import com.google.devtools.build.lib.rules.SkylarkModules;
import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.EvaluationContext;
+import com.google.devtools.build.lib.syntax.Mutability;
/**
* Describes a particular testing mode by determining how the
- * appropriate {@code EvaluationContext} has to be created
+ * appropriate {@code Environment} has to be created
*/
public abstract class TestMode {
- public static final TestMode BUILD = new TestMode() {
- @Override
- public EvaluationContext createContext(EventHandler eventHandler, Environment environment)
- throws Exception {
- return EvaluationContext.newBuildContext(eventHandler, environment);
- }
- };
+ public static final TestMode BUILD =
+ new TestMode() {
+ @Override
+ public Environment createEnvironment(EventHandler eventHandler, Environment environment) {
+ return Environment.builder(Mutability.create("build test"))
+ .setGlobals(environment == null ? Environment.BUILD : environment.getGlobals())
+ .setEventHandler(eventHandler)
+ .build();
+ }
+ };
- public static final TestMode SKYLARK = new TestMode() {
- @Override
- public EvaluationContext createContext(EventHandler eventHandler, Environment environment)
- throws Exception {
- return SkylarkModules.newEvaluationContext(eventHandler);
- }
- };
+ public static final TestMode SKYLARK =
+ new TestMode() {
+ @Override
+ public Environment createEnvironment(EventHandler eventHandler, Environment environment) {
+ return Environment.builder(Mutability.create("skylark test"))
+ .setSkylark()
+ .setGlobals(environment == null ? Environment.SKYLARK : environment.getGlobals())
+ .setEventHandler(eventHandler)
+ .build();
+ }
+ };
- public abstract EvaluationContext createContext(
- EventHandler eventHandler, Environment environment) throws Exception;
-} \ No newline at end of file
+ public abstract Environment createEnvironment(EventHandler eventHandler, Environment environment);
+}