Skip to content

Commit

Permalink
java,runfiles: fix bugs in runfiles library
Browse files Browse the repository at this point in the history
Bazel 0.11.0 releases a new Java runfiles library
in @bazel_tools. This commit fixes some bugs in
0.11.0rc1:

- The library no longer respects TEST_SRCDIR, so
  now it's possible to run Bazel inside of a test
  and build and run a mock java_binary, and that
  java_binary will *not* pick up the test's
  TEST_SRCDIR.

- The library now allows calling rlocation for
  absolute paths, and just returns the path
  itself. This is in accordance with how our Bash
  rlocation() implementation works.

Change-Id: I471247d7538a76ea8162d2192add3f9733f844a8
PiperOrigin-RevId: 184990272
  • Loading branch information
laszlocsomor authored and Copybara-Service committed Feb 8, 2018
1 parent 3d45d25 commit d855d81
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ public static Runfiles create() throws IOException {
* key's value in {@code env}.
*
* <p>Otherwise this method returns a directory-based implementation. The directory's path is
* defined by the "RUNFILES_DIR" or "TEST_SRCDIR" key's value in {@code env}, in this priority
* order.
* defined by the value in {@code env} under the "RUNFILES_DIR" key, or if absent, then under the
* "JAVA_RUNFILES" key.
*
* <p>Note about performance: the manifest-based implementation eagerly reads and caches the whole
* manifest file upon instantiation.
*
* @throws IOException if RUNFILES_MANIFEST_ONLY=1 is in {@code env} but there's no
* "RUNFILES_MANIFEST_FILE", or if neither "RUNFILES_DIR" nor "TEST_SRCDIR" is in {@code env},
* or if some IO error occurs
* "RUNFILES_MANIFEST_FILE", "RUNFILES_DIR", or "JAVA_RUNFILES" key in {@code env} or their
* values are empty, or some IO error occurs
*/
public static Runfiles create(Map<String, String> env) throws IOException {
if (isManifestOnly(env)) {
Expand All @@ -89,16 +89,15 @@ public static Runfiles create(Map<String, String> env) throws IOException {
*
* @param path runfiles-root-relative path of the runfile
* @throws IllegalArgumentException if {@code path} fails validation, for example if it's null or
* empty, it's absolute or contains uplevel references
* empty, or contains uplevel references
*/
public final String rlocation(String path) {
Util.checkArgument(path != null);
Util.checkArgument(!path.isEmpty());
Util.checkArgument(!path.contains(".."), "path contains uplevel references: \"%s\"", path);
Util.checkArgument(
!new File(path).isAbsolute() && path.charAt(0) != File.separatorChar,
"path is absolute: \"%s\"",
path);
if (new File(path).isAbsolute() || path.charAt(0) == File.separatorChar) {
return path;
}
return rlocationChecked(path);
}

Expand All @@ -118,15 +117,13 @@ private static String getManifestPath(Map<String, String> env) throws IOExceptio
}

private static String getRunfilesDir(Map<String, String> env) throws IOException {
// On Linux and macOS, Bazel sets RUNFILES_DIR and TEST_SRCDIR.
// Google-internal Blaze sets only TEST_SRCDIR.
String value = env.get("RUNFILES_DIR");
if (Util.isNullOrEmpty(value)) {
value = env.get("TEST_SRCDIR");
value = env.get("JAVA_RUNFILES");
}
if (Util.isNullOrEmpty(value)) {
throw new IOException(
"Cannot find runfiles: $RUNFILES_DIR and $TEST_SRCDIR are both unset or empty");
"Cannot find runfiles: $RUNFILES_DIR and $JAVA_RUNFILES are both unset or empty");
}
return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
@RunWith(JUnit4.class)
public final class RunfilesTest {

private static boolean isWindows() {
return File.separatorChar == '\\';
}

private void assertRlocationArg(Runfiles runfiles, String path, @Nullable String error)
throws Exception {
try {
Expand All @@ -48,13 +52,6 @@ public void testRlocationArgumentValidation() throws Exception {
assertRlocationArg(r, null, null);
assertRlocationArg(r, "", null);
assertRlocationArg(r, "foo/..", "contains uplevel");
if (File.separatorChar == '/') {
assertRlocationArg(r, "/foo", "is absolute");
} else {
assertRlocationArg(r, "\\foo", "is absolute");
assertRlocationArg(r, "c:/foo", "is absolute");
assertRlocationArg(r, "c:\\foo", "is absolute");
}
}

@Test
Expand All @@ -66,9 +63,18 @@ public void testCreatesManifestBasedRunfiles() throws Exception {
"RUNFILES_MANIFEST_ONLY", "1",
"RUNFILES_MANIFEST_FILE", mf.path.toString(),
"RUNFILES_DIR", "ignored when RUNFILES_MANIFEST_ONLY=1",
"TEST_SRCDIR", "ignored when RUNFILES_MANIFEST_ONLY=1"));
"JAVA_RUNFILES", "ignored when RUNFILES_DIR has a value",
"TEST_SRCDIR", "should always be ignored"));
assertThat(r.rlocation("a/b")).isEqualTo("c/d");
assertThat(r.rlocation("foo")).isNull();

if (isWindows()) {
assertThat(r.rlocation("\\foo")).isEqualTo("\\foo");
assertThat(r.rlocation("c:/foo")).isEqualTo("c:/foo");
assertThat(r.rlocation("c:\\foo")).isEqualTo("c:\\foo");
} else {
assertThat(r.rlocation("/foo")).isEqualTo("/foo");
}
}
}

Expand All @@ -79,17 +85,50 @@ public void testCreatesDirectoryBasedRunfiles() throws Exception {
ImmutableMap.of(
"RUNFILES_MANIFEST_FILE", "ignored when RUNFILES_MANIFEST_ONLY is not set to 1",
"RUNFILES_DIR", "runfiles/dir",
"TEST_SRCDIR", "ignored when RUNFILES_DIR is set"));
"JAVA_RUNFILES", "ignored when RUNFILES_DIR has a value",
"TEST_SRCDIR", "should always be ignored"));
assertThat(r.rlocation("a/b")).isEqualTo("runfiles/dir/a/b");
assertThat(r.rlocation("foo")).isEqualTo("runfiles/dir/foo");

r =
Runfiles.create(
ImmutableMap.of(
"RUNFILES_MANIFEST_FILE", "ignored when RUNFILES_MANIFEST_ONLY is not set to 1",
"TEST_SRCDIR", "test/srcdir"));
assertThat(r.rlocation("a/b")).isEqualTo("test/srcdir/a/b");
assertThat(r.rlocation("foo")).isEqualTo("test/srcdir/foo");
"RUNFILES_DIR", "",
"JAVA_RUNFILES", "runfiles/dir",
"TEST_SRCDIR", "should always be ignored"));
assertThat(r.rlocation("a/b")).isEqualTo("runfiles/dir/a/b");
assertThat(r.rlocation("foo")).isEqualTo("runfiles/dir/foo");
}

@Test
public void testIgnoresTestSrcdirWhenJavaRunfilesIsUndefinedAndJustFails() throws Exception {
Runfiles.create(
ImmutableMap.of(
"RUNFILES_DIR", "non-empty",
"RUNFILES_MANIFEST_FILE", "ignored when RUNFILES_MANIFEST_ONLY is not set to 1",
"TEST_SRCDIR", "should always be ignored"));

Runfiles.create(
ImmutableMap.of(
"JAVA_RUNFILES", "non-empty",
"RUNFILES_MANIFEST_FILE", "ignored when RUNFILES_MANIFEST_ONLY is not set to 1",
"TEST_SRCDIR", "should always be ignored"));

try {
// The method must ignore TEST_SRCDIR, for the scenario when Bazel runs a test which itself
// runs Bazel to build and run java_binary. The java_binary should not pick up the test's
// TEST_SRCDIR.
Runfiles.create(
ImmutableMap.of(
"RUNFILES_DIR", "",
"JAVA_RUNFILES", "",
"RUNFILES_MANIFEST_FILE", "ignored when RUNFILES_MANIFEST_ONLY is not set to 1",
"TEST_SRCDIR", "should always be ignored"));
fail();
} catch (IOException e) {
assertThat(e).hasMessageThat().contains("$RUNFILES_DIR and $JAVA_RUNFILES");
}
}

@Test
Expand Down

0 comments on commit d855d81

Please sign in to comment.