Skip to content

Commit

Permalink
chore: refactor so that clients do not require `cgrindel_bazel_starli…
Browse files Browse the repository at this point in the history
…b` (#236)

- Remove dependency on `cgrindel_bazel_starlib` in
`bazel_integration_test`.
- Convert `default_test_runner` from a macro to a rule.
- Add an e2e test that confirms that `rules_bazel_integration_test` can
be used without requiring any additional dependencies.

Closes #234.
  • Loading branch information
cgrindel authored Oct 30, 2023
1 parent 07dde2a commit 5c733e3
Show file tree
Hide file tree
Showing 22 changed files with 2,407 additions and 91 deletions.
8 changes: 6 additions & 2 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
# This lets us glob() up all the files inside the examples to make them inputs to tests
# (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
# To update these lines, run tools/update_deleted_packages.sh
build --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/params_tests/workspace
query --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/params_tests/workspace
build --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/e2e_tests/workspace,tests/e2e_tests/workspace/child_workspace,tests/params_tests/workspace
query --deleted_packages=examples/custom_test_runner,examples/custom_test_runner/Sources/CustomTestRunner,examples/custom_test_runner/Sources/CustomTestRunnerLib,examples/custom_test_runner/Tests/CustomTestRunnerTests,examples/custom_test_runner/integration_tests,examples/custom_test_runner/integration_tests/workspace,examples/env_var_with_rootpath/sample_workspace,examples/simple,examples/simple/mockascript,examples/simple/mockascript/private,examples/simple/tests,tests/e2e_tests/workspace,tests/e2e_tests/workspace/child_workspace,tests/params_tests/workspace

# Import Shared settings
import %workspace%/shared.bazelrc

# Import CI settings.
import %workspace%/ci.bazelrc

# Only enable for rules_bazel_integration_test
build --@cgrindel_bazel_starlib//bzlmod:enabled

# Try to import a local.rc file; typically, written by CI
try-import %workspace%/local.bazelrc

1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ test_suite(
"//examples:integration_tests",
"//examples/env_var_with_rootpath:integration_tests",
"//release:archive_test",
"//tests/e2e_tests:integration_tests",
"//tests/params_tests:integration_tests",
"//tests/py_tests:integration_tests",
],
Expand Down
4 changes: 0 additions & 4 deletions bazel_integration_test/private/bazel_integration_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,6 @@ def bazel_integration_test(
],
args = args,
data = data,
deps = [
"@bazel_tools//tools/bash/runfiles",
"@cgrindel_bazel_starlib//shlib/lib:messages",
],
timeout = timeout,
env = env,
env_inherit = env_inherit,
Expand Down
80 changes: 45 additions & 35 deletions bazel_integration_test/private/default_test_runner.bzl
Original file line number Diff line number Diff line change
@@ -1,44 +1,54 @@
"""Defines the default test runner for integration tests."""

load("@cgrindel_bazel_starlib//shlib/rules:execute_binary.bzl", "execute_binary")
load(
"@cgrindel_bazel_starlib//shlib/rules:execute_binary.bzl",
"execute_binary_utils",
)
load(":integration_test_utils.bzl", "integration_test_utils")

def default_test_runner(
name,
bazel_cmds = integration_test_utils.DEFAULT_BAZEL_CMDS,
**kwargs):
"""Macro that defines a test runner that executes a set of Bazel commands against a workspace.
def _default_test_runner_impl(ctx):
if len(ctx.attr.args) > 0:
fail("""\
The args attribute is not supported. Use the bazel_cmds instead.\
""")

Args:
name: The name for the integration runner instance.
bazel_cmds: A `list` of `string` values that represent arguments for
Bazel.
**kwargs: attributes that are passed to the `sh_binary` target.
"""
test_runner_args = []
for cmd in ctx.attr.bazel_cmds:
test_runner_args.extend(["--bazel_cmd", cmd])

# Prepare the Bazel commands
args = []
for cmd in bazel_cmds:
args.extend(["--bazel_cmd", cmd])

# Define the shell binary
binary_name = name + "_binary"
native.sh_binary(
name = binary_name,
srcs = [
"@rules_bazel_integration_test//bazel_integration_test/private:default_test_runner.sh",
],
deps = [
"@bazel_tools//tools/bash/runfiles",
"@cgrindel_bazel_starlib//shlib/lib:messages",
],
args = args,
**kwargs
out = ctx.actions.declare_file(ctx.label.name + ".sh")
execute_binary_utils.write_execute_binary_script(
write_file = ctx.actions.write,
out = out,
bin_path = ctx.executable._test_runner_script.short_path,
arguments = test_runner_args,
workspace_name = ctx.workspace_name,
)

# Wrap the arguments with the binary.
execute_binary(
name = name,
binary = binary_name,
arguments = args,
runfiles = ctx.runfiles(files = ctx.files._test_runner_script)
runfiles = execute_binary_utils.collect_runfiles(
runfiles,
[ctx.attr._test_runner_script],
)

return DefaultInfo(executable = out, runfiles = runfiles)

default_test_runner = rule(
implementation = _default_test_runner_impl,
attrs = {
"bazel_cmds": attr.string_list(
default = integration_test_utils.DEFAULT_BAZEL_CMDS,
doc = """\
The Bazel commands to be executed by the test runner in the test workspace.\
""",
),
"_test_runner_script": attr.label(
default = "//bazel_integration_test/private:default_test_runner.sh",
executable = True,
allow_files = True,
cfg = "target",
),
},
doc = "",
executable = True,
)
21 changes: 6 additions & 15 deletions bazel_integration_test/private/default_test_runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,12 @@
# --bazel and --workspace flags, it also expects one or more --bazel_cmd
# flag-value pairs.

# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---

messages_sh_location=cgrindel_bazel_starlib/shlib/lib/messages.sh
messages_sh="$(rlocation "${messages_sh_location}")" || \
(echo >&2 "Failed to locate ${messages_sh_location}" && exit 1)
source "${messages_sh}"
# NOTE: Do not introduce any external dependencies to this script!

exit_with_msg() {
echo >&2 "${@}"
exit 1
}

bazel_cmds=()
bazel="${BIT_BAZEL_BINARY:-}"
Expand Down
19 changes: 5 additions & 14 deletions bazel_integration_test/private/integration_test_wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,12 @@
# This script is used to call the test runner that is provided to the
# bazel_integration_test.

# --- begin runfiles.bash initialization v2 ---
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---
# NOTE: Do not introduce any external dependencies to this script!

messages_sh_location=cgrindel_bazel_starlib/shlib/lib/messages.sh
messages_sh="$(rlocation "${messages_sh_location}")" || \
(echo >&2 "Failed to locate ${messages_sh_location}" && exit 1)
source "${messages_sh}"
exit_with_msg() {
echo >&2 "${@}"
exit 1
}

args=()
while (("$#")); do
Expand Down
39 changes: 19 additions & 20 deletions doc/rules_and_macros_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,25 @@ On this page:
* [default_test_runner](#default_test_runner)


<a id="default_test_runner"></a>

## default_test_runner

<pre>
default_test_runner(<a href="#default_test_runner-name">name</a>, <a href="#default_test_runner-bazel_cmds">bazel_cmds</a>)
</pre>



**ATTRIBUTES**


| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="default_test_runner-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="default_test_runner-bazel_cmds"></a>bazel_cmds | The Bazel commands to be executed by the test runner in the test workspace. | List of strings | optional | <code>["info", "test //..."]</code> |


<a id="bazel_integration_test"></a>

## bazel_integration_test
Expand Down Expand Up @@ -83,23 +102,3 @@ Macro that defines a set Bazel integration tests each executed with a different
| <a id="bazel_integration_tests-kwargs"></a>kwargs | additional attributes like timeout and visibility | none |


<a id="default_test_runner"></a>

## default_test_runner

<pre>
default_test_runner(<a href="#default_test_runner-name">name</a>, <a href="#default_test_runner-bazel_cmds">bazel_cmds</a>, <a href="#default_test_runner-kwargs">kwargs</a>)
</pre>

Macro that defines a test runner that executes a set of Bazel commands against a workspace.

**PARAMETERS**


| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="default_test_runner-name"></a>name | The name for the integration runner instance. | none |
| <a id="default_test_runner-bazel_cmds"></a>bazel_cmds | A <code>list</code> of <code>string</code> values that represent arguments for Bazel. | <code>["info", "test //..."]</code> |
| <a id="default_test_runner-kwargs"></a>kwargs | attributes that are passed to the <code>sh_binary</code> target. | none |


1 change: 0 additions & 1 deletion shared.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ common --color=auto --curses=auto

# Enable bzlmod
common --enable_bzlmod
build --@cgrindel_bazel_starlib//bzlmod:enabled
36 changes: 36 additions & 0 deletions tests/e2e_tests/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
load("@bazel_binaries//:defs.bzl", "bazel_binaries")
load("@cgrindel_bazel_starlib//bzlformat:defs.bzl", "bzlformat_pkg")
load(
"//bazel_integration_test:defs.bzl",
"bazel_integration_tests",
"default_test_runner",
"integration_test_utils",
)

bzlformat_pkg(name = "bzlformat")

default_test_runner(name = "e2e_test_runner")

bazel_integration_tests(
name = "e2e_test",
bazel_binaries = bazel_binaries,
bazel_versions = bazel_binaries.versions.all,
tags = integration_test_utils.DEFAULT_INTEGRATION_TEST_TAGS + [
"no-sandbox",
],
test_runner = ":e2e_test_runner",
workspace_files = integration_test_utils.glob_workspace_files("workspace") + [
"//:local_repository_files",
],
workspace_path = "workspace",
)

test_suite(
name = "integration_tests",
tags = integration_test_utils.DEFAULT_INTEGRATION_TEST_TAGS,
tests = integration_test_utils.bazel_integration_test_names(
"e2e_test",
bazel_binaries.versions.all,
),
visibility = ["//:__subpackages__"],
)
8 changes: 8 additions & 0 deletions tests/e2e_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# E2E Test

The e2e tests are designed to test the use of `rules_bazel_integration_test` by a client. It
demonstrates the minimum requirements needed to use this ruleset.

This package contains integration tests that execute other integration tests defined under the
workspace in the `workspace` directory. The `workspace` directory contains its own child workspace
under the `child_workspace` directory.
13 changes: 13 additions & 0 deletions tests/e2e_tests/workspace/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# To update these lines, execute
# `bazel run @rules_bazel_integration_test//tools:update_deleted_packages`
build --deleted_packages=child_workspace
query --deleted_packages=child_workspace

# Import Shared settings
import %workspace%/../../../shared.bazelrc

# Import CI settings.
import %workspace%/../../../ci.bazelrc

# Try to import a local.rc file; typically, written by CI
try-import %workspace%/../../../local.bazelrc
1 change: 1 addition & 0 deletions tests/e2e_tests/workspace/.bazelversion
28 changes: 28 additions & 0 deletions tests/e2e_tests/workspace/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
load("@bazel_binaries//:defs.bzl", "bazel_binaries")
load(
"@rules_bazel_integration_test//bazel_integration_test:defs.bzl",
"bazel_integration_tests",
"default_test_runner",
)

filegroup(
name = "all_files",
srcs = glob(["*"]),
visibility = ["//:__subpackages__"],
)

# Declare a test runner to drive the integration tests.
default_test_runner(
name = "child_test_runner",
)

# If you want to execute an integration test using multiple versions of Bazel,
# use bazel_integration_tests. It will generate multiple integration test
# targets with names derived from the base name and the bazel version.
bazel_integration_tests(
name = "child_test",
bazel_versions = bazel_binaries.versions.all,
tags = ["exclusive-if-local"],
test_runner = ":child_test_runner",
workspace_path = "child_workspace",
)
26 changes: 26 additions & 0 deletions tests/e2e_tests/workspace/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module(
name = "e2e_parent",
version = "0.0.0",
)

bazel_dep(
name = "rules_bazel_integration_test",
version = "0.0.0",
dev_dependency = True,
)
local_path_override(
module_name = "rules_bazel_integration_test",
path = "../../..",
)

bazel_binaries = use_extension(
"@rules_bazel_integration_test//:extensions.bzl",
"bazel_binaries",
dev_dependency = True,
)
bazel_binaries.download(version_file = "//:.bazelversion")
use_repo(
bazel_binaries,
"bazel_binaries",
"build_bazel_bazel_.bazelversion",
)
Loading

0 comments on commit 5c733e3

Please sign in to comment.