diff --git a/go/private/repositories.bzl b/go/private/repositories.bzl index d2d75097e2..c9d767add2 100644 --- a/go/private/repositories.bzl +++ b/go/private/repositories.bzl @@ -16,6 +16,7 @@ load("@io_bazel_rules_go//go/private:common.bzl", "MINIMUM_BAZEL_VERSION") load("@io_bazel_rules_go//go/private:compat/compat_repo.bzl", "go_rules_compat") +load("@io_bazel_rules_go//go/private:skylib/lib/unittest.bzl", "register_unittest_toolchains") load("@io_bazel_rules_go//go/private:skylib/lib/versions.bzl", "versions") load("@io_bazel_rules_go//go/private:nogo.bzl", "DEFAULT_NOGO", "go_register_nogo") load("@io_bazel_rules_go//go/platform:list.bzl", "GOOS_GOARCH") @@ -28,6 +29,8 @@ def go_rules_dependencies(): if getattr(native, "bazel_version", None): versions.check(MINIMUM_BAZEL_VERSION, bazel_version = native.bazel_version) + register_unittest_toolchains() + # Compatibility layer, needed to support older versions of Bazel. _maybe( go_rules_compat, diff --git a/go/private/skylib/README.rst b/go/private/skylib/README.rst index 2a2db0c70f..950667c756 100644 --- a/go/private/skylib/README.rst +++ b/go/private/skylib/README.rst @@ -1,5 +1,8 @@ This directory is a copy of github.com/bazelbuild/bazel-skylib/lib. -Version 0.5.0, retrieved on 2018-11-26. +Version 0.5.0 (retrieved on 2018-11-26) + some changes: +- cherry-picked Skylib's daf513702286fe211f291675443235e35e79f34f, except for + the files in "tests" +- updated labels in load() statements and toolchain references This is needed only until nested workspaces works. It has to be copied in because we use the functionality inside code that diff --git a/go/private/skylib/lib/unittest.bzl b/go/private/skylib/lib/unittest.bzl index 0862130f5d..0b0b8ca32b 100644 --- a/go/private/skylib/lib/unittest.bzl +++ b/go/private/skylib/lib/unittest.bzl @@ -19,8 +19,45 @@ functions to declare and define unit tests, and `asserts` which contains the assertions used to within tests. """ -load(":skylib/lib/sets.bzl", "sets") -load(":skylib/lib/new_sets.bzl", new_sets = "sets") +load("@io_bazel_rules_go//go/private:skylib/lib/new_sets.bzl", new_sets = "sets") +load("@io_bazel_rules_go//go/private:skylib/lib/sets.bzl", "sets") + +# The following function should only be called from WORKSPACE files and workspace macros. +def register_unittest_toolchains(): + """Registers the toolchains for unittest users.""" + native.register_toolchains( + "@io_bazel_rules_go//go/private/skylib/toolchains/unittest:cmd_toolchain", + "@io_bazel_rules_go//go/private/skylib/toolchains/unittest:bash_toolchain", + ) + +TOOLCHAIN_TYPE = "@io_bazel_rules_go//go/private/skylib/toolchains/unittest:toolchain_type" + +_UnittestToolchain = provider( + doc = "Execution platform information for rules in the bazel_skylib repository.", + fields = ["file_ext", "success_templ", "failure_templ", "join_on"], +) + +def _unittest_toolchain_impl(ctx): + return [ + platform_common.ToolchainInfo( + unittest_toolchain_info = _UnittestToolchain( + file_ext = ctx.attr.file_ext, + success_templ = ctx.attr.success_templ, + failure_templ = ctx.attr.failure_templ, + join_on = ctx.attr.join_on, + ), + ), + ] + +unittest_toolchain = rule( + implementation = _unittest_toolchain_impl, + attrs = { + "file_ext": attr.string(mandatory = True), + "success_templ": attr.string(mandatory = True), + "failure_templ": attr.string(mandatory = True), + "join_on": attr.string(mandatory = True), + }, +) def _make(impl, attrs = None): """Creates a unit test rule from its implementation function. @@ -41,7 +78,7 @@ def _make(impl, attrs = None): # Assert statements go here - unittest.end(env) + return unittest.end(env) your_test = unittest.make(_your_test) ``` @@ -59,7 +96,7 @@ def _make(impl, attrs = None): """ # Derive the name of the implementation function for better test feedback. - # Skylark currently stringifies a function as "", so we use + # Starlark currently stringifies a function as "", so we use # that knowledge to parse the "NAME" portion out. If this behavior ever # changes, we'll need to update this. # TODO(bazel-team): Expose a ._name field on functions to avoid this. @@ -75,6 +112,7 @@ def _make(impl, attrs = None): attrs = attrs, _skylark_testable = True, test = True, + toolchains = [TOOLCHAIN_TYPE], ) def _suite(name, *test_rules): @@ -160,17 +198,20 @@ def _end(env): Args: env: The test environment returned by `unittest.begin`. """ - cmd = "\n".join([ - "cat << EOF", - "\n".join(env.failures), - "EOF", - "exit %d" % len(env.failures), - ]) + + tc = env.ctx.toolchains[TOOLCHAIN_TYPE].unittest_toolchain_info + testbin = env.ctx.actions.declare_file(env.ctx.label.name + tc.file_ext) + if env.failures: + cmd = tc.failure_templ % tc.join_on.join(env.failures) + else: + cmd = tc.success_templ + env.ctx.actions.write( - output = env.ctx.outputs.executable, + output = testbin, content = cmd, is_executable = True, ) + return [DefaultInfo(executable = testbin)] def _fail(env, msg): """Unconditionally causes the current test to fail. diff --git a/go/private/skylib/toolchains/unittest/BUILD b/go/private/skylib/toolchains/unittest/BUILD new file mode 100644 index 0000000000..c8743416a7 --- /dev/null +++ b/go/private/skylib/toolchains/unittest/BUILD @@ -0,0 +1,47 @@ +load("@io_bazel_rules_go//go/private:skylib/lib/unittest.bzl", "TOOLCHAIN_TYPE", "unittest_toolchain") + +toolchain_type( + name = "toolchain_type", + visibility = ["//visibility:public"], +) + +unittest_toolchain( + name = "cmd", + failure_templ = """@echo off +echo %s +exit /b 1 +""", + file_ext = ".bat", + join_on = "\necho ", + success_templ = "@exit /b 0", + visibility = ["//visibility:public"], +) + +unittest_toolchain( + name = "bash", + failure_templ = """#!/bin/sh +cat <<'EOF' +%s +EOF +exit 1 +""", + file_ext = ".sh", + join_on = "\n", + success_templ = "#!/bin/sh\nexit 0", + visibility = ["//visibility:public"], +) + +toolchain( + name = "cmd_toolchain", + exec_compatible_with = [ + "@bazel_tools//platforms:windows", + ], + toolchain = ":cmd", + toolchain_type = TOOLCHAIN_TYPE, +) + +toolchain( + name = "bash_toolchain", + toolchain = ":bash", + toolchain_type = TOOLCHAIN_TYPE, +)