• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2023 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"Define a rule for running bazel test under Bazel"
16
17load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS", "bazel_version_to_binary_label")
18load("//python:defs.bzl", "py_test")
19
20BAZEL_BINARY = bazel_version_to_binary_label(SUPPORTED_BAZEL_VERSIONS[0])
21
22_ATTRS = {
23    "bazel_binary": attr.label(
24        default = BAZEL_BINARY,
25        doc = """The bazel binary files to test against.
26
27It is assumed by the test runner that the bazel binary is found at label_workspace/bazel (wksp/bazel.exe on Windows)""",
28    ),
29    "bazel_commands": attr.string_list(
30        default = ["info", "test --test_output=errors ..."],
31        doc = """The list of bazel commands to run.
32
33Note that if a command contains a bare `--` argument, the --test_arg passed to Bazel will appear before it.
34""",
35    ),
36    "bzlmod": attr.bool(
37        default = False,
38        doc = """Whether the test uses bzlmod.""",
39    ),
40    "workspace_files": attr.label(
41        doc = """A filegroup of all files in the workspace-under-test necessary to run the test.""",
42    ),
43}
44
45def _config_impl(ctx):
46    if len(SUPPORTED_BAZEL_VERSIONS) > 1:
47        fail("""
48        bazel_integration_test doesn't support multiple Bazel versions to test against yet.
49        """)
50    if len(ctx.files.workspace_files) == 0:
51        fail("""
52No files were found to run under integration testing. See comment in /.bazelrc.
53You probably need to run
54    tools/bazel_integration_test/update_deleted_packages.sh
55""")
56
57    # Serialize configuration file for test runner
58    config = ctx.actions.declare_file("%s.json" % ctx.attr.name)
59    ctx.actions.write(
60        output = config,
61        content = """
62{{
63    "workspaceRoot": "{TMPL_workspace_root}",
64    "bazelBinaryWorkspace": "{TMPL_bazel_binary_workspace}",
65    "bazelCommands": [ {TMPL_bazel_commands} ],
66    "bzlmod": {TMPL_bzlmod}
67}}
68""".format(
69            TMPL_workspace_root = ctx.files.workspace_files[0].dirname,
70            TMPL_bazel_binary_workspace = ctx.attr.bazel_binary.label.workspace_name,
71            TMPL_bazel_commands = ", ".join(["\"%s\"" % s for s in ctx.attr.bazel_commands]),
72            TMPL_bzlmod = str(ctx.attr.bzlmod).lower(),
73        ),
74    )
75
76    return [DefaultInfo(
77        files = depset([config]),
78        runfiles = ctx.runfiles(files = [config]),
79    )]
80
81_config = rule(
82    implementation = _config_impl,
83    doc = "Configures an integration test that runs a specified version of bazel against an external workspace.",
84    attrs = _ATTRS,
85)
86
87def bazel_integration_test(name, override_bazel_version = None, bzlmod = False, dirname = None, **kwargs):
88    """Wrapper macro to set default srcs and run a py_test with config
89
90    Args:
91        name: name of the resulting py_test
92        override_bazel_version: bazel version to use in test
93        bzlmod: whether the test uses bzlmod
94        dirname: the directory name of the test. Defaults to value of `name` after trimming the `_example` suffix.
95        **kwargs: additional attributes like timeout and visibility
96    """
97
98    # By default, we assume sources for "pip_example" are in examples/pip/**/*
99    dirname = dirname or name[:-len("_example")]
100    native.filegroup(
101        name = "_%s_sources" % name,
102        srcs = native.glob(
103            ["%s/**/*" % dirname],
104            exclude = ["%s/bazel-*/**" % dirname],
105        ),
106    )
107    workspace_files = kwargs.pop("workspace_files", "_%s_sources" % name)
108
109    bazel_binary = BAZEL_BINARY if not override_bazel_version else bazel_version_to_binary_label(override_bazel_version)
110    _config(
111        name = "_%s_config" % name,
112        workspace_files = workspace_files,
113        bazel_binary = bazel_binary,
114        bzlmod = bzlmod,
115    )
116
117    tags = kwargs.pop("tags", [])
118    tags.append("integration-test")
119
120    py_test(
121        name = name,
122        srcs = [Label("//tools/bazel_integration_test:test_runner.py")],
123        main = "test_runner.py",
124        args = [native.package_name() + "/_%s_config.json" % name],
125        deps = [Label("//python/runfiles")],
126        data = [
127            bazel_binary,
128            "//:distribution",
129            "_%s_config" % name,
130            workspace_files,
131        ],
132        tags = tags,
133        **kwargs
134    )
135