diff --git a/go/private/tools/files_equal_test.bzl b/go/private/tools/files_equal_test.bzl index 1c5efeceb3..80d77f99f5 100644 --- a/go/private/tools/files_equal_test.bzl +++ b/go/private/tools/files_equal_test.bzl @@ -15,62 +15,107 @@ """Tests that two files contain the same data.""" -def _impl(ctx): - if ctx.file.golden == ctx.file.actual: - fail("GOLDEN and ACTUAL should be different files") - ctx.actions.write( - output = ctx.outputs.executable, - content = "\n".join([ - "#!/bin/bash", - "function checksum() {", - " if command -v openssl >/dev/null; then", - " openssl sha1 $1 | cut -f 2 -d ' '", - " elif command -v sha256sum >/dev/null; then", - " sha256sum $1 | cut -f 1 -d ' '", - " elif command -v shasum >/dev/null; then", - " cat $1 | shasum -a 256 | cut -f 1 -d ' '", - " else", - " echo please install openssl >&2", - " exit 1", - " fi", - "}", - "SUM1=$(checksum %s)" % _runpath(ctx.file.golden), - "SUM2=$(checksum %s)" % _runpath(ctx.file.actual), - "if [[ ${SUM1} != ${SUM2} ]]; then", - " echo ERROR: %s >&2" % ctx.attr.error_message, - " echo %s ${SUM1} >&2" % _runpath(ctx.file.golden), - " echo %s ${SUM2} >&2" % _runpath(ctx.file.actual), - " exit 1", - "fi", - ]), - is_executable = True, - ) - return [DefaultInfo(runfiles = ctx.runfiles([ - ctx.file.golden, - ctx.file.actual, - ]))] +def files_equal_test(name, golden, actual, error_message = None, **kwargs): + # This genrule creates a Bash script: the source of the actual test. + # The script: + # 1. Initializes the Bash runfiles library (see + # @bazel_tools//tools/bash/runfiles/runfiles.bash). + # 2. Stores command line arguments into variables. + # 3. Computes runfile paths for the GOLDEN and ACTUAL files. + # 4. Calls "rlocation" from runfiles.bash to locates the runfiles. + # 5. Computes and compares checksums. + native.genrule( + name = name + "_src", + outs = [name + "-src.sh"], + executable = True, + visibility = ["//visibility:private"], + cmd = r"""cat >$@ <<'eof' +#!/bin/bash +# sh_test() source, generated by @io_bazel_rules_go//go/private/tools/files_equal_test.bzl + +### 1. initialize the Bash runfiles library + +# --- begin runfiles.bash initialization --- +# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). +set -euo pipefail +if [[ ! -d "$${RUNFILES_DIR:-/dev/null}" && ! -f "$${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + if [[ -f "$$0.runfiles_manifest" ]]; then + export RUNFILES_MANIFEST_FILE="$$0.runfiles_manifest" + elif [[ -f "$$0.runfiles/MANIFEST" ]]; then + export RUNFILES_MANIFEST_FILE="$$0.runfiles/MANIFEST" + elif [[ -f "$$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + export RUNFILES_DIR="$$0.runfiles" + fi +fi +if [[ -f "$${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + source "$${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" +elif [[ -f "$${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + source "$$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ + "$$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" +else + echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" + exit 1 +fi +# --- end runfiles.bash initialization --- + +### 2. Store command line arguments into variables. + +declare -r GOLDEN="$${1}" +declare -r ACTUAL="$${2}" +declare -r ERROR_MSG="$${3:-FILES DO NOT HAVE EQUAL CONTENTS}" + +### 3. Compute runfile paths. + +# Strip "external/" prefix OR prepend workspace name and strip "./" prefix. +[[ "$$GOLDEN" =~ external/* ]] && F1="$${GOLDEN#external/}" || F1="$$TEST_WORKSPACE/$${GOLDEN#./}" +[[ "$$ACTUAL" =~ external/* ]] && F2="$${ACTUAL#external/}" || F2="$$TEST_WORKSPACE/$${ACTUAL#./}" -def _runpath(f): - """Figures out the proper runfiles path for a file, using voodoo""" - if f.path.startswith("bazel-out/"): - return f.short_path - else: - return f.path +### 4. Locate the runfiles. -files_equal_test = rule( - attrs = { - "golden": attr.label( - mandatory = True, - allow_single_file = True, - ), - "actual": attr.label( - mandatory = True, - allow_single_file = True, - ), - "error_message": attr.string( - default = "FILES DO NOT HAVE EQUAL CONTENTS", - ), - }, - test = True, - implementation = _impl, -) +F1="$$(rlocation "$$F1")" +F2="$$(rlocation "$$F2")" + +if [[ "$$F1" == "$$F2" ]]; then + echo >&2 "GOLDEN and ACTUAL should be different files" + exit 1 +fi + +### 5. Compute and compare checksums. + +function checksum() { + if command -v openssl >/dev/null; then + openssl sha1 $$1 | cut -f 2 -d ' ' + elif command -v sha256sum >/dev/null; then + sha256sum $$1 | cut -f 1 -d ' ' + elif command -v shasum >/dev/null; then + cat $$1 | shasum -a 256 | cut -f 1 -d ' ' + else + echo please install openssl >&2 + exit 1 + fi +} +SUM1=$$(checksum "$$F1") +SUM2=$$(checksum "$$F2") +if [[ $${SUM1} != $${SUM2} ]]; then + echo "ERROR: $$ERROR_MSG" >&2 + echo "$$GOLDEN $${SUM1}" >&2 + echo "$$ACTUAL $${SUM2}" >&2 + exit 1 +fi +eof""", + ) + + native.sh_test( + name = name, + srcs = [name + "-src.sh"], + data = [ + "@bazel_tools//tools/bash/runfiles", + actual, + golden, + ], + args = [ + "$(location %s)" % golden, + "$(location %s)" % actual, + error_message, + ], + )