java.starlark.net tests: port Python test harness to Java

The test now runs in 2.5 seconds instead of 20s.
(The previous time was essentially all remote build + JVM overhead.)

Failed assertions (e.g. assert_eq) report errors out of band, not by
causing Starlark execution to fail, so so multiple failures can be
reported in a single run, and failed assertions cannot be suppressed
by a '###' expectation.

PiperOrigin-RevId: 323581105
diff --git a/src/BUILD b/src/BUILD
index 204dc18..b9351dc 100644
--- a/src/BUILD
+++ b/src/BUILD
@@ -456,7 +456,6 @@
         "//src/test/gen:srcs",
         "//src/test/res:srcs",
         "//src/test/native/windows:srcs",
-        "//src/test/starlark:srcs",
         "//src/test/java/com/google/devtools/build/android:srcs",
         "//src/test/java/com/google/devtools/build/docgen:srcs",
         "//src/test/java/com/google/devtools/build/lib:srcs",
@@ -464,6 +463,7 @@
         "//src/test/java/com/google/devtools/build/skydoc:srcs",
         "//src/test/java/com/google/devtools/build/skyframe:srcs",
         "//src/test/java/com/google/devtools/common/options:srcs",
+        "//src/test/java/net/starlark/java/eval:srcs",
         "//src/test/java/net/starlark/java/spelling:srcs",
         "//src/test/py/bazel:srcs",
         "//src/test/shell:srcs",
diff --git a/src/test/java/net/starlark/java/eval/BUILD b/src/test/java/net/starlark/java/eval/BUILD
new file mode 100644
index 0000000..3126cca
--- /dev/null
+++ b/src/test/java/net/starlark/java/eval/BUILD
@@ -0,0 +1,45 @@
+load("@rules_java//java:defs.bzl", "java_test")
+
+filegroup(
+    name = "srcs",
+    srcs = glob(["**"]),
+    visibility = ["//src:__subpackages__"],
+)
+
+# Script-based tests of the Starlark interpreter.
+java_test(
+    name = "EvalTest",
+    srcs = ["EvalTest.java"],
+    data = [
+        "testdata/all_any.sky",
+        "testdata/and_or_not.sky",
+        "testdata/dict.sky",
+        "testdata/equality.sky",
+        "testdata/function.sky",
+        "testdata/int.sky",
+        "testdata/int_constructor.sky",
+        "testdata/int_function.sky",
+        "testdata/list_mutation.sky",
+        "testdata/list_slices.sky",
+        "testdata/min_max.sky",
+        "testdata/range.sky",
+        "testdata/reversed.sky",
+        "testdata/sorted.sky",
+        "testdata/string_elems.sky",
+        "testdata/string_find.sky",
+        "testdata/string_format.sky",
+        "testdata/string_misc.sky",
+        "testdata/string_partition.sky",
+        "testdata/string_slice_index.sky",
+        "testdata/string_split.sky",
+        "testdata/string_splitlines.sky",
+        "testdata/string_test_characters.sky",
+    ],
+    use_testrunner = False,
+    deps = [
+        "//src/main/java/com/google/devtools/build/lib:syntax",
+        "//src/main/java/net/starlark/java/annot",
+        "//third_party:guava",
+        "//third_party:junit4",
+    ],
+)
diff --git a/src/test/java/net/starlark/java/eval/EvalTest.java b/src/test/java/net/starlark/java/eval/EvalTest.java
new file mode 100644
index 0000000..d177f8b
--- /dev/null
+++ b/src/test/java/net/starlark/java/eval/EvalTest.java
@@ -0,0 +1,241 @@
+// Copyright 2020 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 net.starlark.java.eval;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.Files;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.EvalUtils;
+import com.google.devtools.build.lib.syntax.FileOptions;
+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.Starlark;
+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 java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import net.starlark.java.annot.Param;
+import net.starlark.java.annot.StarlarkGlobalLibrary;
+import net.starlark.java.annot.StarlarkMethod;
+
+/** Tests of Starlark evaluator. */
+@StarlarkGlobalLibrary
+public final class EvalTest {
+
+  // Tests for Starlark.
+  //
+  // In each test file, chunks are separated by "\n---\n".
+  // Each chunk is evaluated separately.
+  // Use "###" to specify the expected error.
+  // If there is no "###", the test will succeed iff there is no error.
+  //
+  // Within the file, the assert_ and assert_eq functions may be used to
+  // report errors without stopping the program. (They are not evaluation
+  // errors that can be caught with a '###' expectation.)
+
+  // TODO(adonovan): improve this test driver (following go.starlark.net):
+  //
+  // - use a proper quotation syntax (Starlark string literals) in '### "foo"' expectations.
+  // - extract support for "chunked files" into a library
+  //   and reuse it for tests of lexer, parser, resolver.
+  // - separate static tests entirely. They can use the same
+  //   notation, but we shouldn't be mixing static and dynamic tests.
+  // - don't interpret the pattern as "either a substring or a regexp".
+  //   Be consistent: always use regexp.
+  // - require that some frame of each EvalError match the file/line of the expectation.
+
+  interface Reporter {
+    void reportError(StarlarkThread thread, String message);
+  }
+
+  @StarlarkMethod(
+      name = "assert_",
+      documented = false,
+      parameters = {
+        @Param(name = "cond", noneable = true),
+        @Param(name = "msg", defaultValue = "'assertion failed'"),
+      },
+      useStarlarkThread = true)
+  public Object assertStarlark(Object cond, String msg, StarlarkThread thread)
+      throws EvalException {
+    if (!Starlark.truth(cond)) {
+      thread.getThreadLocal(Reporter.class).reportError(thread, "assert_: " + msg);
+    }
+    return Starlark.NONE;
+  }
+
+  @StarlarkMethod(
+      name = "assert_eq",
+      documented = false,
+      parameters = {
+        @Param(name = "x", noneable = true),
+        @Param(name = "y", noneable = true),
+      },
+      useStarlarkThread = true)
+  public Object assertEq(Object x, Object y, StarlarkThread thread) throws EvalException {
+    // TODO(adonovan): use Starlark.equals.
+    if (!x.equals(y)) {
+      String msg = String.format("assert_eq: %s != %s", Starlark.repr(x), Starlark.repr(y));
+      thread.getThreadLocal(Reporter.class).reportError(thread, msg);
+    }
+    return Starlark.NONE;
+  }
+
+  private static boolean ok = true;
+
+  public static void main(String[] args) throws Exception {
+    File root = new File("third_party/bazel"); // blaze
+    if (!root.exists()) {
+      root = new File("."); // bazel
+    }
+    File testdata = new File(root, "src/test/java/net/starlark/java/eval/testdata");
+    for (String name : testdata.list()) {
+      File file = new File(testdata, name);
+      String content = Files.asCharSource(file, UTF_8).read();
+      int linenum = 1;
+      for (String chunk : Splitter.on("\n---\n").split(content)) {
+        // prepare chunk
+        StringBuilder buf = new StringBuilder();
+        for (int i = 1; i < linenum; i++) {
+          buf.append('\n');
+        }
+        buf.append(chunk);
+        if (false) {
+          System.err.printf("%s:%d: <<%s>>\n", file, linenum, buf);
+        }
+
+        // extract "### string" expectations
+        Map<String, Integer> expectations = new HashMap<>();
+        for (int i = 0; true; i += "###".length()) {
+          i = chunk.indexOf("###", i);
+          if (i < 0) {
+            break;
+          }
+          int j = chunk.indexOf("\n", i);
+          if (j < 0) {
+            j = chunk.length();
+          }
+          String pattern = chunk.substring(i + 3, j).trim();
+          int line = linenum + newlines(chunk.substring(0, i));
+          if (false) {
+            System.err.printf("%s:%d: expectation '%s'\n", file, line, pattern);
+          }
+          expectations.put(pattern, line);
+        }
+
+        // parse & execute
+        ParserInput input = ParserInput.fromString(buf.toString(), file.toString());
+        ImmutableMap.Builder<String, Object> predeclared = ImmutableMap.builder();
+        Starlark.addMethods(predeclared, new EvalTest()); // e.g. assert_eq
+        StarlarkSemantics semantics = StarlarkSemantics.DEFAULT;
+        Module module = Module.withPredeclared(semantics, predeclared.build());
+        try (Mutability mu = Mutability.create("test")) {
+          StarlarkThread thread = new StarlarkThread(mu, semantics);
+          thread.setThreadLocal(Reporter.class, EvalTest::reportError);
+          EvalUtils.exec(input, FileOptions.DEFAULT, module, thread);
+
+        } catch (SyntaxError.Exception ex) {
+          // parser/resolver errors
+          for (SyntaxError err : ex.errors()) {
+            if (!expected(expectations, err.message())) {
+              System.err.println(err); // includes location
+              ok = false;
+            }
+          }
+
+        } catch (EvalException ex) {
+          // evaluation error
+          //
+          // TODO(adonovan): the old logic checks only that each error is matched
+          // by at least one expectation. Instead, ensure that errors
+          // and expections match exactly. Furthermore, look only at errors
+          // whose stack has a frame with a file/line that matches the expectation.
+          // This requires (planned) changes to EvalExceptionWithStackTrace.
+          if (!expected(expectations, ex.getMessage())) {
+            String backtrace = ex.print();
+            if (!backtrace.contains(name)) {
+              // TODO(adonovan): for errors at top level, there's no stack at all.
+              // Fix EvalExceptionWithStackTrace so that it uses a proper CallStack.
+              System.err.printf("%s:%d: eval error in this chunk: %s\n", file, linenum, backtrace);
+            } else {
+              System.err.println(backtrace);
+            }
+            ok = false;
+          }
+
+        } catch (Throwable ex) {
+          // unhandled exception (incl. InterruptedException)
+          System.err.printf(
+              "%s:%d: unhandled %s in this chunk: %s\n",
+              file, linenum, ex.getClass().getSimpleName(), ex.getMessage());
+          ex.printStackTrace();
+          ok = false;
+        }
+
+        // unmatched expectations
+        for (Map.Entry<String, Integer> e : expectations.entrySet()) {
+          System.err.printf("%s:%d: unmatched expectation: %s\n", file, e.getValue(), e.getKey());
+          ok = false;
+        }
+
+        // advance line number
+        linenum += newlines(chunk) + 2; // for "\n---\n"
+      }
+    }
+    if (!ok) {
+      System.exit(1);
+    }
+  }
+
+  // Called by assert_ and assert_eq when the test encounters an error.
+  // Does not stop the program; multiple failures may be reported in a single run.
+  private static void reportError(StarlarkThread thread, String message) {
+    System.err.printf("Traceback (most recent call last):\n");
+    List<StarlarkThread.CallStackEntry> stack = thread.getCallStack();
+    stack = stack.subList(0, stack.size() - 1); // pop the built-in function
+    for (StarlarkThread.CallStackEntry fr : stack) {
+      System.err.printf("%s: called from %s\n", fr.location, fr.name);
+    }
+    System.err.println("Error: " + message);
+    ok = false;
+  }
+
+  private static boolean expected(Map<String, Integer> expectations, String message) {
+    for (String pattern : expectations.keySet()) {
+      if (message.contains(pattern) || message.matches(".*" + pattern + ".*")) {
+        expectations.remove(pattern);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private static int newlines(String s) {
+    int n = 0;
+    for (int i = 0; i < s.length(); i++) {
+      if (s.charAt(i) == '\n') {
+        n++;
+      }
+    }
+    return n;
+  }
+}
diff --git a/src/test/starlark/testdata/all_any.sky b/src/test/java/net/starlark/java/eval/testdata/all_any.sky
similarity index 100%
rename from src/test/starlark/testdata/all_any.sky
rename to src/test/java/net/starlark/java/eval/testdata/all_any.sky
diff --git a/src/test/starlark/testdata/and_or_not.sky b/src/test/java/net/starlark/java/eval/testdata/and_or_not.sky
similarity index 100%
rename from src/test/starlark/testdata/and_or_not.sky
rename to src/test/java/net/starlark/java/eval/testdata/and_or_not.sky
diff --git a/src/test/starlark/testdata/dict.sky b/src/test/java/net/starlark/java/eval/testdata/dict.sky
similarity index 100%
rename from src/test/starlark/testdata/dict.sky
rename to src/test/java/net/starlark/java/eval/testdata/dict.sky
diff --git a/src/test/starlark/testdata/equality.sky b/src/test/java/net/starlark/java/eval/testdata/equality.sky
similarity index 100%
rename from src/test/starlark/testdata/equality.sky
rename to src/test/java/net/starlark/java/eval/testdata/equality.sky
diff --git a/src/test/starlark/testdata/function.sky b/src/test/java/net/starlark/java/eval/testdata/function.sky
similarity index 100%
rename from src/test/starlark/testdata/function.sky
rename to src/test/java/net/starlark/java/eval/testdata/function.sky
diff --git a/src/test/starlark/testdata/int.sky b/src/test/java/net/starlark/java/eval/testdata/int.sky
similarity index 100%
rename from src/test/starlark/testdata/int.sky
rename to src/test/java/net/starlark/java/eval/testdata/int.sky
diff --git a/src/test/starlark/testdata/int_constructor.sky b/src/test/java/net/starlark/java/eval/testdata/int_constructor.sky
similarity index 100%
rename from src/test/starlark/testdata/int_constructor.sky
rename to src/test/java/net/starlark/java/eval/testdata/int_constructor.sky
diff --git a/src/test/starlark/testdata/int_function.sky b/src/test/java/net/starlark/java/eval/testdata/int_function.sky
similarity index 100%
rename from src/test/starlark/testdata/int_function.sky
rename to src/test/java/net/starlark/java/eval/testdata/int_function.sky
diff --git a/src/test/starlark/testdata/list_mutation.sky b/src/test/java/net/starlark/java/eval/testdata/list_mutation.sky
similarity index 100%
rename from src/test/starlark/testdata/list_mutation.sky
rename to src/test/java/net/starlark/java/eval/testdata/list_mutation.sky
diff --git a/src/test/starlark/testdata/list_slices.sky b/src/test/java/net/starlark/java/eval/testdata/list_slices.sky
similarity index 100%
rename from src/test/starlark/testdata/list_slices.sky
rename to src/test/java/net/starlark/java/eval/testdata/list_slices.sky
diff --git a/src/test/starlark/testdata/min_max.sky b/src/test/java/net/starlark/java/eval/testdata/min_max.sky
similarity index 100%
rename from src/test/starlark/testdata/min_max.sky
rename to src/test/java/net/starlark/java/eval/testdata/min_max.sky
diff --git a/src/test/starlark/testdata/range.sky b/src/test/java/net/starlark/java/eval/testdata/range.sky
similarity index 100%
rename from src/test/starlark/testdata/range.sky
rename to src/test/java/net/starlark/java/eval/testdata/range.sky
diff --git a/src/test/starlark/testdata/reversed.sky b/src/test/java/net/starlark/java/eval/testdata/reversed.sky
similarity index 100%
rename from src/test/starlark/testdata/reversed.sky
rename to src/test/java/net/starlark/java/eval/testdata/reversed.sky
diff --git a/src/test/starlark/testdata/sorted.sky b/src/test/java/net/starlark/java/eval/testdata/sorted.sky
similarity index 100%
rename from src/test/starlark/testdata/sorted.sky
rename to src/test/java/net/starlark/java/eval/testdata/sorted.sky
diff --git a/src/test/starlark/testdata/string_elems.sky b/src/test/java/net/starlark/java/eval/testdata/string_elems.sky
similarity index 100%
rename from src/test/starlark/testdata/string_elems.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_elems.sky
diff --git a/src/test/starlark/testdata/string_find.sky b/src/test/java/net/starlark/java/eval/testdata/string_find.sky
similarity index 100%
rename from src/test/starlark/testdata/string_find.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_find.sky
diff --git a/src/test/starlark/testdata/string_format.sky b/src/test/java/net/starlark/java/eval/testdata/string_format.sky
similarity index 100%
rename from src/test/starlark/testdata/string_format.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_format.sky
diff --git a/src/test/starlark/testdata/string_misc.sky b/src/test/java/net/starlark/java/eval/testdata/string_misc.sky
similarity index 99%
rename from src/test/starlark/testdata/string_misc.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_misc.sky
index d3286ab..514c216 100644
--- a/src/test/starlark/testdata/string_misc.sky
+++ b/src/test/java/net/starlark/java/eval/testdata/string_misc.sky
@@ -164,6 +164,7 @@
 "\777" ### octal escape sequence out of range (maximum is \377)
 ---
 "\" ### unterminated string literal at eol
+
 ---
 """ ### unterminated string literal at eof
 ---
diff --git a/src/test/starlark/testdata/string_partition.sky b/src/test/java/net/starlark/java/eval/testdata/string_partition.sky
similarity index 100%
rename from src/test/starlark/testdata/string_partition.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_partition.sky
diff --git a/src/test/starlark/testdata/string_slice_index.sky b/src/test/java/net/starlark/java/eval/testdata/string_slice_index.sky
similarity index 100%
rename from src/test/starlark/testdata/string_slice_index.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_slice_index.sky
diff --git a/src/test/starlark/testdata/string_split.sky b/src/test/java/net/starlark/java/eval/testdata/string_split.sky
similarity index 100%
rename from src/test/starlark/testdata/string_split.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_split.sky
diff --git a/src/test/starlark/testdata/string_splitlines.sky b/src/test/java/net/starlark/java/eval/testdata/string_splitlines.sky
similarity index 100%
rename from src/test/starlark/testdata/string_splitlines.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_splitlines.sky
diff --git a/src/test/starlark/testdata/string_test_characters.sky b/src/test/java/net/starlark/java/eval/testdata/string_test_characters.sky
similarity index 100%
rename from src/test/starlark/testdata/string_test_characters.sky
rename to src/test/java/net/starlark/java/eval/testdata/string_test_characters.sky
diff --git a/src/test/starlark/BUILD b/src/test/starlark/BUILD
deleted file mode 100644
index f1555b6..0000000
--- a/src/test/starlark/BUILD
+++ /dev/null
@@ -1,71 +0,0 @@
-load(
-    "//tools/build_rules:test_rules.bzl",
-    "file_test",
-    "rule_test",
-)
-
-package(default_visibility = ["//src:__subpackages__"])
-
-filegroup(
-    name = "srcs",
-    srcs = glob(["**"]),
-    visibility = ["//src:__subpackages__"],
-)
-
-[
-    py_test(
-        name = "starlark_test_" + test_file.replace(".", "_"),
-        srcs = [
-            "starlark_test.py",
-            "testenv.py",
-        ],
-        args = [test_file],
-        data = [
-            "//src/main/java/net/starlark/java/cmd:Starlark",
-            test_file,
-        ],
-        main = "starlark_test.py",
-        python_version = "PY3",
-    )
-    for test_file in glob(["testdata/*"])
-]
-
-## Rest of the file should be moved somewhere else (under bazel/tools/).
-
-genrule(
-    name = "tone_below",
-    outs = [
-        "g1",
-        "g2",
-    ],
-    cmd = "echo 48.9994 > $(location :g1) ; echo 97.9989 > $(location :g2)",
-)
-
-rule_test(
-    name = "assert_tone_below_1",
-    generates = [
-        "g1",
-        "g2",
-    ],
-    rule = "tone_below",
-)
-
-file_test(
-    name = "question_content",
-    content = ("If you could ask a unique question to a computer during a Turing test, " +
-               "what would you ask?\n"),
-    file = "question.text",
-)
-
-file_test(
-    name = "question_regexp",
-    file = "question.text",
-    regexp = "[eu]n[uchs questi]\\+on",
-)
-
-file_test(
-    name = "question_regexp_1",
-    file = "question.text",
-    matches = 1,
-    regexp = "what would you ask",
-)
diff --git a/src/test/starlark/question.text b/src/test/starlark/question.text
deleted file mode 100644
index 238bebb8..0000000
--- a/src/test/starlark/question.text
+++ /dev/null
@@ -1 +0,0 @@
-If you could ask a unique question to a computer during a Turing test, what would you ask?
diff --git a/src/test/starlark/starlark_test.py b/src/test/starlark/starlark_test.py
deleted file mode 100644
index 15893dc..0000000
--- a/src/test/starlark/starlark_test.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright 2017 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.
-
-from __future__ import print_function
-
-import os.path
-import re
-import subprocess
-import sys
-import tempfile
-import unittest
-
-from src.test.starlark import testenv
-
-
-class StarlarkTest(unittest.TestCase):
-  """Tests for Starlark.
-
-  In a test file, chunks are separated by "---". Each chunk is evaluated
-  separately. Use "###" to specify the expected error. If there is no "###",
-  the test will succeed iff there is no error.
-  """
-
-  CHUNK_SEP = "---"
-  ERR_SEP = "###"
-  seen_error = False
-
-  def chunks(self, path):
-    code = []
-    expected_errors = []
-    with open(path, mode="rb") as f:
-      for line in f:
-        line = line.decode("utf-8")
-        if line.strip() == self.CHUNK_SEP:
-          yield code, expected_errors
-          expected_errors = []
-          code = []
-        else:
-          code.append(line)
-          i = line.find(self.ERR_SEP)
-          if i >= 0:
-            expected_errors.append(line[i + len(self.ERR_SEP):].strip())
-    yield code, expected_errors
-
-  def evaluate(self, f):
-    """Execute Starlark file, return stderr."""
-    proc = subprocess.Popen(
-        [testenv.STARLARK_BINARY_PATH, f], stderr=subprocess.PIPE)
-    _, stderr = proc.communicate()
-    return stderr
-
-  def check_output(self, output, expected):
-    if expected and not output:
-      self.seen_error = True
-      print("Expected error:", expected)
-
-    if output and not expected:
-      self.seen_error = True
-      print("Unexpected error:", output)
-
-    for exp in expected:
-      # Try both substring and regex matching.
-      if exp not in output and not re.search(exp, output):
-        self.seen_error = True
-        print("Error `{}` not found, got: `{}`".format(exp, output))
-
-  PRELUDE = """
-def assert_eq(x, y):
-  if x != y:
-    fail("%r != %r" % (x, y))
-
-def assert_(cond, msg="assertion failed"):
-  if not cond:
-    fail(msg)
-"""
-
-  def testFile(self):
-    t = test_file
-    print("===", t, "===")
-    f = os.path.join(testenv.STARLARK_TESTDATA_PATH, t)
-    for chunk, expected in self.chunks(f):
-      with tempfile.NamedTemporaryFile(
-          mode="wb", suffix=".sky", delete=False) as tmp:
-        lines = [line.encode("utf-8") for line in
-                 [self.PRELUDE] + chunk]
-        tmp.writelines(lines)
-      output = self.evaluate(tmp.name).decode("utf-8")
-      os.unlink(tmp.name)
-      self.check_output(output, expected)
-    if self.seen_error:
-      raise Exception("Test failed")
-
-
-if __name__ == "__main__":
-  # Test filename is the last argument on the command-line.
-  test_file = sys.argv[-1]
-  unittest.main(argv=sys.argv[1:])
diff --git a/src/test/starlark/testenv.py b/src/test/starlark/testenv.py
deleted file mode 100644
index defff7e..0000000
--- a/src/test/starlark/testenv.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2017 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.
-"""Test constants for src/test/starlark."""
-
-STARLARK_BINARY_PATH = "src/main/java/net/starlark/java/cmd/Starlark"
-STARLARK_TESTDATA_PATH = "src/test/starlark/"