2021-12-21 22:18:34 +00:00
|
|
|
# Copyright 2019 The Bazel Authors. All rights reserved.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
|
|
|
|
"""A test rule that compares two binary files or two directories.
|
|
|
|
|
2022-12-03 07:23:57 +00:00
|
|
|
Similar to `bazel-skylib`'s [`diff_test`](https://github.com/bazelbuild/bazel-skylib/blob/main/rules/diff_test.bzl)
|
|
|
|
but also supports comparing directories.
|
|
|
|
|
2021-12-21 22:18:34 +00:00
|
|
|
The rule uses a Bash command (diff) on Linux/macOS/non-Windows, and a cmd.exe
|
|
|
|
command (fc.exe) on Windows (no Bash is required).
|
|
|
|
"""
|
|
|
|
|
2023-09-29 21:42:33 +00:00
|
|
|
load(":directory_path.bzl", "DirectoryPathInfo")
|
2022-03-15 00:33:52 +00:00
|
|
|
|
2021-12-21 22:18:34 +00:00
|
|
|
def _runfiles_path(f):
|
|
|
|
if f.root.path:
|
|
|
|
return f.path[len(f.root.path) + 1:] # generated file
|
|
|
|
else:
|
|
|
|
return f.path # source file
|
|
|
|
|
|
|
|
def _diff_test_impl(ctx):
|
2022-04-29 07:36:51 +00:00
|
|
|
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
|
|
|
|
|
2022-03-15 00:33:52 +00:00
|
|
|
if DirectoryPathInfo in ctx.attr.file1:
|
|
|
|
file1 = ctx.attr.file1[DirectoryPathInfo].directory
|
|
|
|
file1_path = "/".join([_runfiles_path(file1), ctx.attr.file1[DirectoryPathInfo].path])
|
|
|
|
else:
|
|
|
|
if len(ctx.files.file1) != 1:
|
|
|
|
fail("file1 must be a single file or a target that provides a DirectoryPathInfo")
|
|
|
|
file1 = ctx.files.file1[0]
|
|
|
|
file1_path = _runfiles_path(file1)
|
|
|
|
|
|
|
|
if DirectoryPathInfo in ctx.attr.file2:
|
|
|
|
file2 = ctx.attr.file2[DirectoryPathInfo].directory
|
|
|
|
file2_path = "/".join([_runfiles_path(file2), ctx.attr.file2[DirectoryPathInfo].path])
|
|
|
|
else:
|
|
|
|
if len(ctx.files.file2) != 1:
|
|
|
|
fail("file2 must be a single file or a target that provides a DirectoryPathInfo")
|
|
|
|
file2 = ctx.files.file2[0]
|
|
|
|
file2_path = _runfiles_path(file2)
|
|
|
|
|
2022-04-12 23:31:04 +00:00
|
|
|
if file1 == file2:
|
|
|
|
msg = "diff_test comparing the same file %s" % file1
|
|
|
|
fail(msg)
|
|
|
|
|
2022-04-29 07:36:51 +00:00
|
|
|
if is_windows:
|
2022-08-30 04:02:11 +00:00
|
|
|
test_suffix = "-test.bat"
|
|
|
|
template = ctx.file._diff_test_tmpl_bat
|
|
|
|
else:
|
|
|
|
test_suffix = "-test.sh"
|
|
|
|
template = ctx.file._diff_test_tmpl_sh
|
|
|
|
|
|
|
|
test_bin = ctx.actions.declare_file(ctx.label.name + test_suffix)
|
|
|
|
ctx.actions.expand_template(
|
|
|
|
template = template,
|
|
|
|
output = test_bin,
|
|
|
|
substitutions = {
|
2022-08-26 17:11:10 +00:00
|
|
|
"{name}": ctx.attr.name,
|
2022-08-30 04:02:11 +00:00
|
|
|
"{fail_msg}": ctx.attr.failure_message,
|
|
|
|
"{file1}": file1_path,
|
|
|
|
"{file2}": file2_path,
|
2023-09-21 20:27:08 +00:00
|
|
|
"{build_file_path}": ctx.build_file_path,
|
2022-08-30 04:02:11 +00:00
|
|
|
},
|
|
|
|
is_executable = True,
|
2021-12-21 22:18:34 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
return DefaultInfo(
|
|
|
|
executable = test_bin,
|
|
|
|
files = depset(direct = [test_bin]),
|
2022-03-15 00:33:52 +00:00
|
|
|
runfiles = ctx.runfiles(files = [test_bin, file1, file2]),
|
2021-12-21 22:18:34 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
_diff_test = rule(
|
|
|
|
attrs = {
|
|
|
|
"failure_message": attr.string(),
|
|
|
|
"file1": attr.label(
|
2022-03-15 00:33:52 +00:00
|
|
|
allow_files = True,
|
2021-12-21 22:18:34 +00:00
|
|
|
mandatory = True,
|
|
|
|
),
|
|
|
|
"file2": attr.label(
|
2022-03-15 00:33:52 +00:00
|
|
|
allow_files = True,
|
2021-12-21 22:18:34 +00:00
|
|
|
mandatory = True,
|
|
|
|
),
|
2022-04-29 07:36:51 +00:00
|
|
|
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
|
2022-08-30 04:02:11 +00:00
|
|
|
"_diff_test_tmpl_sh": attr.label(
|
|
|
|
default = ":diff_test_tmpl.sh",
|
|
|
|
allow_single_file = True,
|
|
|
|
),
|
|
|
|
"_diff_test_tmpl_bat": attr.label(
|
|
|
|
default = ":diff_test_tmpl.bat",
|
|
|
|
allow_single_file = True,
|
|
|
|
),
|
2021-12-21 22:18:34 +00:00
|
|
|
},
|
|
|
|
test = True,
|
|
|
|
implementation = _diff_test_impl,
|
|
|
|
)
|
|
|
|
|
2024-07-19 19:50:50 +00:00
|
|
|
def diff_test(name, file1, file2, size = "small", **kwargs):
|
2021-12-21 22:18:34 +00:00
|
|
|
"""A test that compares two files.
|
|
|
|
|
|
|
|
The test succeeds if the files' contents match.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
name: The name of the test rule.
|
|
|
|
file1: Label of the file to compare to <code>file2</code>.
|
|
|
|
file2: Label of the file to compare to <code>file1</code>.
|
2022-08-20 19:53:12 +00:00
|
|
|
size: standard attribute for tests
|
2021-12-21 22:18:34 +00:00
|
|
|
**kwargs: The <a href="https://docs.bazel.build/versions/main/be/common-definitions.html#common-attributes-tests">common attributes for tests</a>.
|
|
|
|
"""
|
|
|
|
_diff_test(
|
|
|
|
name = name,
|
|
|
|
file1 = file1,
|
|
|
|
file2 = file2,
|
2022-08-20 19:53:12 +00:00
|
|
|
size = size,
|
2021-12-21 22:18:34 +00:00
|
|
|
**kwargs
|
|
|
|
)
|