1# Copyright 2024 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"""Unit tests for the directory rule.""" 16 17load("@bazel_skylib//rules/directory:directory.bzl", "directory") 18load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo") 19load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") 20load("@rules_testing//lib:truth.bzl", "matching") 21load(":utils.bzl", "directory_subject", "failure_matching", "failure_test") 22 23def _source_root_test(name): 24 analysis_test( 25 name = name, 26 impl = _source_root_test_impl, 27 targets = { 28 "root": ":root", 29 "f1": ":f1_filegroup", 30 "f2": ":f2_filegroup", 31 }, 32 ) 33 34def _source_root_test_impl(env, targets): 35 f1 = targets.f1.files.to_list()[0] 36 f2 = targets.f2.files.to_list()[0] 37 38 env.expect.that_collection(targets.root.files.to_list()).contains_exactly( 39 [f1, f2], 40 ) 41 42 human_readable = str(targets.root.label) 43 44 root = directory_subject(env, targets.root[DirectoryInfo]) 45 root.entries().keys().contains_exactly(["testdata"]) 46 root.transitive_files().contains_exactly([f1, f2]).in_order() 47 root.human_readable().equals(human_readable) 48 env.expect.that_str(root.actual.path + "/testdata/f1").equals(f1.path) 49 50 testdata = directory_subject(env, root.actual.entries["testdata"]) 51 testdata.entries().keys().contains_exactly(["f1", "subdir"]) 52 testdata.human_readable().equals(human_readable + "/testdata") 53 54 subdir = directory_subject(env, testdata.actual.entries["subdir"]) 55 subdir.entries().contains_exactly({"f2": f2}) 56 subdir.transitive_files().contains_exactly([f2]) 57 env.expect.that_str(subdir.actual.path + "/f2").equals(f2.path) 58 59def _generated_root_test(name): 60 subject_name = "_%s_subject" % name 61 directory( 62 name = subject_name, 63 srcs = [":generated_file"], 64 ) 65 66 analysis_test( 67 name = name, 68 impl = _generated_root_test_impl, 69 targets = { 70 "root": subject_name, 71 "generated": ":generated_file", 72 }, 73 ) 74 75def _generated_root_test_impl(env, targets): 76 generated = targets.generated.files.to_list()[0] 77 78 env.expect.that_collection(targets.root.files.to_list()).contains_exactly( 79 [generated], 80 ) 81 82 human_readable = str(targets.root.label) 83 84 root = directory_subject(env, targets.root[DirectoryInfo]) 85 root.entries().keys().contains_exactly(["dir"]) 86 root.transitive_files().contains_exactly([generated]).in_order() 87 root.human_readable().equals(human_readable) 88 env.expect.that_str(root.actual.path + "/dir/generated").equals(generated.path) 89 90 dir = directory_subject(env, root.actual.entries["dir"]) 91 dir.human_readable().equals(human_readable + "/dir") 92 dir.entries().contains_exactly({"generated": generated}) 93 dir.transitive_files().contains_exactly([generated]) 94 env.expect.that_str(dir.actual.path + "/generated").equals(generated.path) 95 96def _no_srcs_test(name): 97 subject_name = "_%s_subject" % name 98 directory( 99 name = subject_name, 100 ) 101 102 analysis_test( 103 name = name, 104 impl = _no_srcs_test_impl, 105 targets = { 106 "root": subject_name, 107 "f1": ":f1_filegroup", 108 }, 109 ) 110 111def _no_srcs_test_impl(env, targets): 112 f1 = targets.f1.files.to_list()[0] 113 114 env.expect.that_collection(targets.root.files.to_list()).contains_exactly([]) 115 116 d = directory_subject(env, targets.root[DirectoryInfo]) 117 d.entries().contains_exactly({}) 118 env.expect.that_str(d.actual.path + "/testdata/f1").equals(f1.path) 119 120def _directory_with_self_srcs_test(name): 121 failure_test( 122 name = name, 123 impl = failure_matching(matching.contains("tests/directory to start with")), 124 rule = directory, 125 srcs = ["."], 126 ) 127 128def _outside_testdata_test(name): 129 failure_test( 130 name = name, 131 impl = failure_matching(matching.contains("lib/paths.bzl to start with")), 132 rule = directory, 133 srcs = ["@bazel_skylib//lib:paths"], 134 ) 135 136def _source_and_generated_root_test(name): 137 failure_test( 138 name = name, 139 impl = failure_matching(matching.contains( 140 "Having both source and generated files in a single directory is unsupported", 141 )), 142 rule = directory, 143 srcs = ["f1", ":generated_file"], 144 ) 145 146# buildifier: disable=function-docstring 147def directory_test_suite(name): 148 test_suite( 149 name = name, 150 tests = [ 151 _source_root_test, 152 _generated_root_test, 153 _no_srcs_test, 154 _directory_with_self_srcs_test, 155 _outside_testdata_test, 156 _source_and_generated_root_test, 157 ], 158 ) 159