diff options
author | nickreid <nickreid@google.com> | 2023-02-18 11:03:54 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-02-18 11:04:28 -0800 |
commit | c04423eb627441bfbdfb57db339440f2609b9dd5 (patch) | |
tree | 30a66ab0bab901dbe07ffca75ee5bd71480c377f | |
parent | 85f1316233777c96da04a5b166a9032e964531e9 (diff) | |
download | bazelbuild-kotlin-rules-c04423eb627441bfbdfb57db339440f2609b9dd5.tar.gz |
Rework the implementation of FileFactory and add tests.
PiperOrigin-RevId: 510678619
Change-Id: I04dbe628417439db19c6d695ebe9a8686e848d0a
6 files changed, 197 insertions, 9 deletions
diff --git a/kotlin/common.bzl b/kotlin/common.bzl index f487f0f..a4431a7 100644 --- a/kotlin/common.bzl +++ b/kotlin/common.bzl @@ -994,7 +994,7 @@ def _kt_jvm_import( if not jars: fail("Must import at least one JAR") - file_factory = FileFactory(ctx, jars[0]) + file_factory = FileFactory(ctx, ctx.label.name) deps = java_common.merge(deps + kt_toolchain.kotlin_libs) # Check that any needed deps are declared unless neverlink, in which case Jars won't be used diff --git a/kotlin/jvm/internal_do_not_use/util/file_factory.bzl b/kotlin/jvm/internal_do_not_use/util/file_factory.bzl index 51e18f9..2e076c3 100644 --- a/kotlin/jvm/internal_do_not_use/util/file_factory.bzl +++ b/kotlin/jvm/internal_do_not_use/util/file_factory.bzl @@ -16,8 +16,8 @@ load("//:visibility.bzl", "RULES_KOTLIN") -def FileFactory(ctx, base, suffix = None): - """Creates files with names derived from some base file +def FileFactory(ctx, base): + """Creates files with names derived from some base file or prefix Including the name of a rule is not always enough to guarantee unique filenames. For example, helper functions that declare their own output files may be called multiple times in the same @@ -25,26 +25,35 @@ def FileFactory(ctx, base, suffix = None): Args: ctx: ctx - base: [File] The file to derive other filenames from - suffix: [Optional[string]] An additional suffix to differentiate declared files + base: [File|string] The file to derive other filenames from, or an exact base prefix Returns: FileFactory """ - base_name = base.basename.rsplit(".", 1)[0] + (suffix or "") + if type(base) == "File": + base = _scrub_base_file(ctx, base) def declare_directory(suffix): - return ctx.actions.declare_directory(base_name + suffix, sibling = base) + return ctx.actions.declare_directory(base + suffix) def declare_file(suffix): - return ctx.actions.declare_file(base_name + suffix, sibling = base) + return ctx.actions.declare_file(base + suffix) def derive(suffix): - return FileFactory(ctx, base, suffix) + return FileFactory(ctx, base + suffix) return struct( + base_as_path = ctx.bin_dir.path + "/" + ctx.label.package + "/" + base, declare_directory = declare_directory, declare_file = declare_file, derive = derive, ) + +def _scrub_base_file(ctx, file): + if not file.extension: + fail("Base file must have an extension: was %s" % (file.path)) + if file.owner.package != ctx.label.package: + fail("Base file must be from ctx package: was %s expected %s" % (file.owner.package, ctx.label.package)) + + return file.short_path.removeprefix(ctx.label.package + "/").rsplit(".", 1)[0] diff --git a/tests/analysis/internal_do_not_use/util/file_factory/BUILD b/tests/analysis/internal_do_not_use/util/file_factory/BUILD new file mode 100644 index 0000000..d92e379 --- /dev/null +++ b/tests/analysis/internal_do_not_use/util/file_factory/BUILD @@ -0,0 +1,41 @@ +# Copyright 2022 Google LLC. 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. + +load(":happy_test.bzl", "file_factory_happy_test") +load(":check_base_file_valid.bzl", "check_base_file_valid") +load("//tests/analysis:assert_failure_test.bzl", "assert_failure_test") + +licenses(["notice"]) + +file_factory_happy_test( + name = "happy_test", +) + +assert_failure_test( + name = "base_without_extension_test", + msg_contains = "file must have an extension", + target_under_test = check_base_file_valid( + name = "base_without_extension", + base_file = "BUILD", + ), +) + +assert_failure_test( + name = "base_from_other_package_test", + msg_contains = "file must be from ctx package", + target_under_test = check_base_file_valid( + name = "base_from_other_package", + base_file = "//tests/analysis/internal_do_not_use/util/file_factory/sub", + ), +) diff --git a/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl b/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl new file mode 100644 index 0000000..9ca1f05 --- /dev/null +++ b/tests/analysis/internal_do_not_use/util/file_factory/check_base_file_valid.bzl @@ -0,0 +1,38 @@ +# Copyright 2022 Google LLC. 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. + +"""Happy tests for FileFactory.""" + +load("//kotlin/jvm/internal_do_not_use/util:file_factory.bzl", "FileFactory") +load("//tests/analysis:util.bzl", "ONLY_FOR_ANALYSIS_TEST_TAGS") +load("//:visibility.bzl", "RULES_KOTLIN") + +def _check_base_file_valid_impl(ctx): + FileFactory(ctx, ctx.file.base_file) + return [] + +_check_base_file_valid = rule( + implementation = _check_base_file_valid_impl, + attrs = dict( + base_file = attr.label(allow_single_file = True, mandatory = True), + ), +) + +def check_base_file_valid(name, tags = [], **kwargs): + _check_base_file_valid( + name = name, + tags = tags + ONLY_FOR_ANALYSIS_TEST_TAGS, + **kwargs + ) + return name diff --git a/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl b/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl new file mode 100644 index 0000000..1a2a655 --- /dev/null +++ b/tests/analysis/internal_do_not_use/util/file_factory/happy_test.bzl @@ -0,0 +1,78 @@ +# Copyright 2022 Google LLC. 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. + +"""file_factory_happy_test""" + +load("//kotlin/jvm/internal_do_not_use/util:file_factory.bzl", "FileFactory") +load("//:visibility.bzl", "RULES_KOTLIN") + +def _test_base_from_file(ctx, pkg_path): + base_file = ctx.actions.declare_file("file/base.txt") + factory = FileFactory(ctx, base_file) + + _assert_equals(pkg_path + "/file/base", factory.base_as_path) + + return [base_file] + +def _test_declare(ctx, pkg_path): + factory = FileFactory(ctx, "string/base") + + _assert_equals(pkg_path + "/string/base", factory.base_as_path) + + a_file = factory.declare_file("a.txt") + _assert_equals(pkg_path + "/string/basea.txt", a_file.path) + + b_dir = factory.declare_directory("b_dir") + _assert_equals(pkg_path + "/string/baseb_dir", b_dir.path) + + return [a_file, b_dir] + +def _test_derive(ctx, pkg_path): + factory = FileFactory(ctx, "") + + # Once + factory_once = factory.derive("once") + _assert_equals(pkg_path + "/once", factory_once.base_as_path) + + # Twice + factory_twice = factory_once.derive("/twice") + _assert_equals(pkg_path + "/once/twice", factory_twice.base_as_path) + +def _assert_equals(expected, actual): + if expected != actual: + fail("Expected '%s' but was '%s'" % (expected, actual)) + +def _file_factory_happy_test_impl(ctx): + pkg_path = ctx.bin_dir.path + "/" + ctx.label.package + all_files = [] + + all_files.extend(_test_base_from_file(ctx, pkg_path)) + all_files.extend(_test_declare(ctx, pkg_path)) + _test_derive(ctx, pkg_path) + + ctx.actions.run_shell( + outputs = all_files, + command = "exit 1", + ) + + test_script = ctx.actions.declare_file(ctx.label.name + "_test.sh") + ctx.actions.write(test_script, "#!/bin/bash", True) + return [ + DefaultInfo(executable = test_script), + ] + +file_factory_happy_test = rule( + implementation = _file_factory_happy_test_impl, + test = True, +) diff --git a/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD b/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD new file mode 100644 index 0000000..db873cf --- /dev/null +++ b/tests/analysis/internal_do_not_use/util/file_factory/sub/BUILD @@ -0,0 +1,22 @@ +# Copyright 2022 Google LLC. 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. + +licenses(["notice"]) + +genrule( + name = "sub", + outs = ["sub.txt"], + cmd = "touch $(OUTS)", + visibility = ["//tests/analysis/internal_do_not_use/util/file_factory:__pkg__"], +) |