Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Executable and runfiles "teleportation" #64

Open
hchauvin opened this issue Apr 23, 2018 · 1 comment
Open

Executable and runfiles "teleportation" #64

hchauvin opened this issue Apr 23, 2018 · 1 comment

Comments

@hchauvin
Copy link
Contributor

hchauvin commented Apr 23, 2018

Sorry in advance for the cheesy name :)

Imagine you want to write an integration test for a rule that depends on an executable with runfiles that is somewhat expensive to make (let's say, a rule for a language and you want to test some side effects of its compiler). One way to do that with speed while retaining a certain level of isolation and generality would be to:

  1. Build the executable in the invoking bazel environment.
  2. Gather all the runfiles in a runfile manifest.
  3. Add the manifest, the executable and the executable's runfiles as runfiles to, e.g., bazel_java_integration_test.
  4. Reproduce the runfile tree in the integration environment by symlinking with the information provided in 3.

Pseudo-code:

BUILD file:

java_binary(
    name = "bin",
    ...
)

teleportation_manifest(
    name = "bin_with_manifest",
    binary = ":bin",
)

bazel_java_integration_test(
    name = "test",
    data = [":bin_with_manifest"],
)

Test suite:

public class Test {
  ...

  @Before
  public void setUp() {
    driver.setUp();

    driver.teleportExecutable(
        WorkspaceDriver.getRunfile(".../bin_with_manifest.txt"),
        "to/some/package",
        "target");

    driver.scratchFile(
        "foo/BUILD",
        "sh_test(",
        "    ...,",
        "    data = [\"//to/some/package:target\"]",
        ")");
  }
}
@hchauvin
Copy link
Contributor Author

hchauvin commented Apr 23, 2018

Oops I just saw #32 and #45 which are definitely relevant, sorry for the duplicate, I don't know how I could have missed that. I also saw bazelbuild/rules_scala#364.

I actually did a proof of concept with bazelbuild/rules_kotlin#52 (about code coverage). Relevant files are here: https://github.com/bazelbuild/rules_kotlin/tree/4c2b07476a9fe41334ed1e1f9dc96cfe9cdf4b23/tests/integrationtests/jvm/coverage
With this in place and a shared download cache (see #63), I am able to run those tests in under two minutes.

@ittaiz What do you have in mind when you allude to buildifier rules in #32?

======

Concerning a question that arose in bazelbuild/rules_scala#364, one way I found to import the current workspace to the integration environment is to pass the workspace as data:

bazel_java_integration_test(
      ...,
      data = ["//:WORKSPACE"],
)

From that, you can unwrap the symlink and have an integration WORKSPACE as such:

local_repository(
      name = "rule_to_test",
      path = "%realpath%",
)

But that is horrible because now only changes in the WORKSPACE file triggers an integration test and you rebuild your rule's dependency every single time.

One way to avoid that would be to both have a dependency on the WORKSPACE and some form of stamping that is done every single time, but I am not aware of anything in Bazel to do that and it would anyway defeat the purpose of Bazel, especially in the context of a monorepo. I think it is better to be explicit.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant