1# Copyright 2019 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"""A test verifying other targets build as part of a `bazel test`""" 16 17load("//lib:new_sets.bzl", "sets") 18 19def build_test(name, targets, **kwargs): 20 """Test rule checking that other targets build. 21 22 This works not by an instance of this test failing, but instead by 23 the targets it depends on failing to build, and hence failing 24 the attempt to run this test. 25 26 NOTE: At the moment, this won't work on Windows; but someone adding 27 support would be welcomed. 28 29 Typical usage: 30 31 ``` 32 load("@bazel_skylib//rules:build_test.bzl", "build_test") 33 build_test( 34 name = "my_build_test", 35 targets = [ 36 "//some/package:rule", 37 ], 38 ) 39 ``` 40 41 Args: 42 name: The name of the test rule. 43 targets: A list of targets to ensure build. 44 **kwargs: The <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes-tests">common attributes for tests</a>. 45 """ 46 if len(targets) == 0: 47 fail("targets must be non-empty", "targets") 48 if kwargs.get("data", None): 49 fail("data is not supported on a build_test()", "data") 50 51 # Remove any duplicate test targets. 52 targets = sets.to_list(sets.make(targets)) 53 54 # Use a genrule to ensure the targets are built (works because it forces 55 # the outputs of the other rules on as data for the genrule) 56 57 # Split into batches to hopefully avoid things becoming so large they are 58 # too much for a remote execution set up. 59 batch_size = max(1, len(targets) // 100) 60 61 # Pull a few args over from the test to the genrule. 62 args_to_reuse = ["compatible_with", "restricted_to", "tags"] 63 genrule_args = {k: kwargs.get(k) for k in args_to_reuse if k in kwargs} 64 65 # Pass an output from the genrules as data to a shell test to bundle 66 # it all up in a test. 67 test_data = [] 68 69 for idx, batch in enumerate([targets[i:i + batch_size] for i in range(0, len(targets), batch_size)]): 70 full_name = "{name}_{idx}__deps".format(name = name, idx = idx) 71 test_data.append(full_name) 72 native.genrule( 73 name = full_name, 74 srcs = batch, 75 outs = [full_name + ".out"], 76 testonly = 1, 77 visibility = ["//visibility:private"], 78 # TODO: Does this need something else for Windows? 79 cmd = "touch $@", 80 **genrule_args 81 ) 82 83 native.sh_test( 84 name = name, 85 # TODO: Does this need something else for Windows? 86 srcs = ["@bazel_skylib//rules:empty_test.sh"], 87 data = test_data, 88 size = kwargs.pop("size", "small"), # Default to small for test size 89 **kwargs 90 ) 91