bazel-lib/lib/tests/write_source_files/write_source_file_test.bzl

191 lines
5.8 KiB
Python

"""Tests for write_source_files"""
# Inspired by https://github.com/cgrindel/bazel-starlib/blob/main/updatesrc/private/updatesrc_update_test.bzl
load("//lib/private:write_source_file.bzl", _write_source_file = "write_source_file")
load("//lib/private:directory_path.bzl", "DirectoryPathInfo")
def _write_source_file_test_impl_sh(ctx, in_file_path, out_file_path):
test = ctx.actions.declare_file(
ctx.label.name + "_test.sh",
)
contents = []
contents.append("""
#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
assert_different() {
local in_file="${1}"
local out_file="${2}"
diff "${in_file}" "${out_file}" > /dev/null && (echo >&2 "Expected files to differ. in: ${in_file}, out: ${out_file}" && return -1)
return 0
}
assert_same() {
local in_file="${1}"
local out_file="${2}"
diff "${in_file}" "${out_file}" || (echo >&2 "Expected files to be same. in: ${in_file}, out: ${out_file}" && return -1)
}""")
contents.append("""
# Check that in and out files are different
assert_different {in_file} {out_file}
""".format(
in_file = in_file_path,
out_file = out_file_path,
))
contents.append("""# Write to the source files
{write_source_files}
""".format(write_source_files = ctx.file.write_source_file_target.short_path))
contents.append("""# Check that in and out files are the same
assert_same {in_file} {out_file}""".format(
in_file = in_file_path,
out_file = out_file_path,
))
ctx.actions.write(
output = test,
is_executable = True,
content = "\n".join(contents),
)
return test
def _write_source_file_test_impl_bat(ctx, in_file_path, out_file_path):
test = ctx.actions.declare_file(
ctx.label.name + "_test.bat",
)
# BUG: Windows is having trouble executing the symlink to the write_source_files executable,
# but it is able to execute the actual output script so point to that for now.
#
# What we would use if this bug didn't exist:
# write_source_files = ctx.executable.write_source_file_target.short_path.replace("/", "\\")
#
# Instead back out of the runfiles execution directory:
# write_to_source_files_test_test.bat.runfiles/aspect_bazel_lib
# And point to the output script.
write_source_files = "..\\..\\%s" % ctx.executable.write_source_file_target.basename
contents = []
contents.append("""
@rem @generated by @aspect_bazel_lib//:lib/tests/write_source_files:write_source_file_test.bzl
@echo off
@rem Check that in and out files are different
call :assert_different {in_file}, {out_file}
if %errorlevel% neq 0 exit /b 1
""".format(
in_file = in_file_path.replace("/", "\\"),
out_file = out_file_path.replace("/", "\\"),
))
contents.append("""
@rem Write to the source files
call {write_source_files}
if %errorlevel% neq 0 exit /b 1
""".format(write_source_files = write_source_files))
contents.append("""
@rem Check that in and out files are the same
call :assert_same {in_file}, {out_file}
if %errorlevel% neq 0 exit /b 1
""".format(
in_file = in_file_path.replace("/", "\\"),
out_file = out_file_path.replace("/", "\\"),
))
contents.append("""
exit /b 0
:assert_different
fc /b %~1 %~2 > nul
if %errorlevel% equ 1 exit /b 0
echo Error: %~1 and %~2 are not different
exit /b 1
:assert_same
fc /b %~1 %~2 > nul
if %errorlevel% equ 0 exit /b 0
echo Error: %~1 and %~2 are not the same
exit /b 1
""")
ctx.actions.write(
output = test,
is_executable = True,
content = "\n".join(contents).replace("\n", "\r\n"),
)
return test
def _write_source_file_test_impl(ctx):
is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
if DirectoryPathInfo in ctx.attr.in_file:
in_file = ctx.attr.in_file[DirectoryPathInfo].directory
in_file_path = "/".join([in_file.short_path, ctx.attr.in_file[DirectoryPathInfo].path])
else:
if len(ctx.files.in_file) != 1:
fail("in_file must be a single file or a target that provides a DirectoryPathInfo")
in_file = ctx.files.in_file[0]
in_file_path = in_file.short_path
if is_windows:
test = _write_source_file_test_impl_bat(ctx, in_file_path, ctx.file.out_file.short_path)
else:
test = _write_source_file_test_impl_sh(ctx, in_file_path, ctx.file.out_file.short_path)
return DefaultInfo(
executable = test,
runfiles = ctx.runfiles(
files = [ctx.executable.write_source_file_target, in_file, ctx.file.out_file],
),
)
_write_source_file_test = rule(
implementation = _write_source_file_test_impl,
attrs = {
"write_source_file_target": attr.label(
allow_single_file = True,
executable = True,
# Should be cfg = "exec" but a bazel bug causes a wrong executable symlink on windows
cfg = "target",
mandatory = True,
),
"out_file": attr.label(
allow_single_file = True,
mandatory = True,
),
"in_file": attr.label(
allow_files = True,
mandatory = True,
),
"_windows_constraint": attr.label(default = "@platforms//os:windows"),
},
test = True,
)
def write_source_file_test(name, in_file, out_file):
"""Stamp a write_source_files executable and a test to run against it"""
_write_source_file(
name = name + "_updater",
in_file = in_file,
out_file = out_file,
diff_test = False,
)
# Note that for testing we update the source files in the sandbox,
# not the actual source tree.
_write_source_file_test(
name = name,
write_source_file_target = name + "_updater",
in_file = in_file,
out_file = out_file,
timeout = "short",
)