| # Copyright 2018 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. |
| |
| """Unit tests for maprule.bzl.""" |
| |
| load("//lib:unittest.bzl", "asserts", "unittest") |
| load("//rules:maprule_testing.bzl", "maprule_testing") |
| |
| def _dummy_generating_action(ctx, path): |
| ctx.actions.write(path, "hello") |
| |
| def _mock_file(ctx, path): |
| f = ctx.actions.declare_file(path) |
| _dummy_generating_action(ctx, f) |
| return f |
| |
| def _lstrip_until(s, until): |
| return s[s.find(until):] |
| |
| def _assert_dict_keys(env, expected, actual, msg): |
| asserts.equals(env, {k: None for k in expected}, {k: None for k in actual}, msg) |
| |
| def _assert_ends_with(env, expected_ending, s, msg): |
| if not s.endswith(expected_ending): |
| unittest.fail(env, msg + ": expected \"%s\" to end with \"%s\"" % (s, expected_ending)) |
| |
| def _assert_no_error(env, errors, msg): |
| if errors: |
| unittest.fail(env, msg + ": expected no errors, got: [%s]" % "\n".join(errors)) |
| |
| def _assert_error(env, errors, expected_fragment, msg): |
| for e in errors: |
| if expected_fragment in e: |
| return |
| unittest.fail(env, msg + ": did not find \"%s\" in: [%s]" % (expected_fragment, "\n".join(errors))) |
| |
| def _contains_substrings_in_order(s, substrings): |
| index = 0 |
| for ss in substrings: |
| index = s.find(ss, index) |
| if index < 0: |
| return False |
| index += len(ss) |
| return True |
| |
| def _assert_error_fragments(env, errors, expected_fragments, msg): |
| for e in errors: |
| if _contains_substrings_in_order(e, expected_fragments): |
| return |
| unittest.fail(env, msg + ": did not find expected fragments in \"%s\" in order" % "\n".join(errors)) |
| |
| def _src_placeholders_test(ctx): |
| env = unittest.begin(ctx) |
| |
| for language, strategy in [ |
| ("cmd", maprule_testing.cmd_strategy), |
| ("bash", maprule_testing.bash_strategy), |
| ]: |
| for basename, basename_noext in [("bar.txt", "bar"), ("bar.pb.h", "bar.pb")]: |
| actual = maprule_testing.src_placeholders( |
| _mock_file(ctx, language + "/foo/" + basename), |
| strategy, |
| ) |
| _assert_dict_keys( |
| env, |
| ["src", "src_dir", "src_name", "src_name_noext"], |
| actual, |
| "assertion #1 (language: %s, basename: %s)" % (language, basename), |
| ) |
| _assert_ends_with( |
| env, |
| strategy.as_path(language + "/foo/" + basename), |
| actual["src"], |
| "assertion #2 (language: %s, basename: %s)" % (language, basename), |
| ) |
| _assert_ends_with( |
| env, |
| strategy.as_path(language + "/foo/"), |
| actual["src_dir"], |
| "assertion #3 (language: %s, basename: %s)" % (language, basename), |
| ) |
| asserts.equals( |
| env, |
| basename, |
| actual["src_name"], |
| "assertion #4 (language: %s, basename: %s)" % (language, basename), |
| ) |
| asserts.equals( |
| env, |
| basename_noext, |
| actual["src_name_noext"], |
| "assertion #5 (language: %s, basename: %s)" % (language, basename), |
| ) |
| |
| return unittest.end(env) |
| |
| src_placeholders_test = unittest.make(_src_placeholders_test) |
| |
| def _validate_attributes_test(ctx): |
| """Unit tests for maprule_testing.validate_attributes.""" |
| env = unittest.begin(ctx) |
| _assert_no_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "bar"}, {"BAR": "value1"}), |
| "assertion #1", |
| ) |
| _assert_no_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "bar"}, {}), |
| "assertion #2", |
| ) |
| |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({}, {}), |
| "\"outs_templates\" must not be empty", |
| "assertion #3", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"": "foo"}, {}), |
| "name should not be empty", |
| "assertion #4", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"foo": "bar"}, {}), |
| "name should be all upper-case", |
| "assertion #5", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"SRC": "bar"}, {}), |
| "conflicting with the environment variable of the source file", |
| "assertion #6", |
| ) |
| |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": ""}, {}), |
| "output path should not be empty", |
| "assertion #7", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "/usr/bin"}, {}), |
| "output path should be relative", |
| "assertion #8", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "c:/usr/bin"}, {}), |
| "output path should be relative", |
| "assertion #9", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "../foo"}, {}), |
| "output path should not contain uplevel references", |
| "assertion #10", |
| ) |
| _assert_no_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "./foo"}, {}), |
| "assertion #11", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"BAR": "foo", "FOO": "foo"}, {}), |
| "output path is already used for \"BAR\"", |
| "assertion #12", |
| ) |
| |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "bar"}, {"": "baz"}), |
| "name should not be empty", |
| "assertion #13", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "bar"}, {"Bar": "baz"}), |
| "name should be all upper-case", |
| "assertion #14", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "bar"}, {"FOO": "baz"}), |
| "conflicting with the environment variable of the \"FOO\" output file", |
| "assertion #15", |
| ) |
| |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "bar"}, {"BAR": "$(location x) $(location y)"}), |
| "use only one $(location)", |
| "assertion #16", |
| ) |
| _assert_error( |
| env, |
| maprule_testing.validate_attributes({"FOO": "bar"}, {"BAR": "a $(location b"}), |
| "missing closing parenthesis", |
| "assertion #17", |
| ) |
| |
| return unittest.end(env) |
| |
| validate_attributes_test = unittest.make(_validate_attributes_test) |
| |
| def _as_path_test(ctx): |
| """Unit tests for maprule_testing.as_path.""" |
| env = unittest.begin(ctx) |
| asserts.equals( |
| env, |
| "Foo\\Bar\\Baz\\Qux", |
| maprule_testing.cmd_strategy.as_path("Foo/Bar/Baz\\Qux"), |
| msg = "assertion #1", |
| ) |
| asserts.equals( |
| env, |
| "Foo/Bar/Baz\\Qux", |
| maprule_testing.bash_strategy.as_path("Foo/Bar/Baz\\Qux"), |
| msg = "assertion #2", |
| ) |
| return unittest.end(env) |
| |
| as_path_test = unittest.make(_as_path_test) |
| |
| def _assert_relative_path(env, path, index): |
| asserts.true( |
| env, |
| maprule_testing.is_relative_path(path), |
| msg = "assertion #%d" % index, |
| ) |
| |
| def _assert_not_relative_path(env, path, index): |
| asserts.false( |
| env, |
| maprule_testing.is_relative_path(path), |
| msg = "assertion #%d" % index, |
| ) |
| |
| def _is_relative_path_test(ctx): |
| """Unit tests for maprule_testing.is_relative_path.""" |
| env = unittest.begin(ctx) |
| _assert_relative_path(env, "Foo/Bar/Baz", 1) |
| _assert_relative_path(env, "Foo\\Bar\\Baz", 2) |
| _assert_relative_path(env, "Foo/Bar\\Baz", 3) |
| _assert_not_relative_path(env, "d:/Foo/Bar", 4) |
| _assert_not_relative_path(env, "D:/Foo/Bar", 5) |
| _assert_not_relative_path(env, "/Foo/Bar", 6) |
| _assert_not_relative_path(env, "\\Foo\\Bar", 7) |
| return unittest.end(env) |
| |
| is_relative_path_test = unittest.make(_is_relative_path_test) |
| |
| def _custom_envmap_test(ctx): |
| """Unit tests for maprule_testing.custom_envmap.""" |
| env = unittest.begin(ctx) |
| |
| actual = {} |
| |
| for language, strategy in [ |
| ("cmd", maprule_testing.cmd_strategy), |
| ("bash", maprule_testing.bash_strategy), |
| ]: |
| actual[language] = maprule_testing.custom_envmap( |
| ctx, |
| strategy, |
| src_placeholders = {"src_ph1": "Src/Ph1-value", "src_ph2": "Src/Ph2-value"}, |
| outs_dict = { |
| "out1": _mock_file(ctx, language + "/Foo/Out1"), |
| "out2": _mock_file(ctx, language + "/Foo/Out2"), |
| }, |
| add_env = {"ENV1": "Env1"}, |
| ) |
| _assert_dict_keys( |
| env, |
| ["MAPRULE_SRC_PH1", "MAPRULE_SRC_PH2", "MAPRULE_OUT1", "MAPRULE_OUT2", "MAPRULE_ENV1"], |
| actual[language], |
| msg = "assertion #1 (language: %s)" % language, |
| ) |
| actual[language]["MAPRULE_OUT1"] = _lstrip_until(actual[language]["MAPRULE_OUT1"], "Foo") |
| actual[language]["MAPRULE_OUT2"] = _lstrip_until(actual[language]["MAPRULE_OUT2"], "Foo") |
| |
| asserts.equals( |
| env, |
| { |
| "MAPRULE_ENV1": "Env1", |
| "MAPRULE_OUT1": "Foo\\Out1", |
| "MAPRULE_OUT2": "Foo\\Out2", |
| "MAPRULE_SRC_PH1": "Src\\Ph1-value", |
| "MAPRULE_SRC_PH2": "Src\\Ph2-value", |
| }, |
| actual["cmd"], |
| msg = "assertion #2", |
| ) |
| |
| asserts.equals( |
| env, |
| { |
| "MAPRULE_ENV1": "Env1", |
| "MAPRULE_OUT1": "Foo/Out1", |
| "MAPRULE_OUT2": "Foo/Out2", |
| "MAPRULE_SRC_PH1": "Src/Ph1-value", |
| "MAPRULE_SRC_PH2": "Src/Ph2-value", |
| }, |
| actual["bash"], |
| msg = "assertion #3", |
| ) |
| |
| return unittest.end(env) |
| |
| custom_envmap_test = unittest.make(_custom_envmap_test) |
| |
| def _create_outputs_test(ctx): |
| """Unit tests for maprule_testing.create_outputs.""" |
| env = unittest.begin(ctx) |
| |
| for language, strategy in [ |
| ("cmd", maprule_testing.cmd_strategy), |
| ("bash", maprule_testing.bash_strategy), |
| ]: |
| src1 = _mock_file(ctx, language + "/foo/src1.txt") |
| src2 = _mock_file(ctx, language + "/foo/src2.pb.h") |
| src3 = _mock_file(ctx, language + "/bar/src1.txt") |
| foreach_srcs = [src1, src2, src3] |
| |
| outs_dicts, all_output_files, _, errors = ( |
| maprule_testing.create_outputs( |
| ctx, |
| "my_maprule", |
| { |
| "OUT1": "{src}.out1", |
| "OUT2": "{src_dir}/out2/{src_name_noext}.out2", |
| }, |
| strategy, |
| foreach_srcs, |
| ) |
| ) |
| |
| _assert_no_error(env, errors, "assertion #1 (language: %s)" % language) |
| |
| for output in all_output_files: |
| _dummy_generating_action(ctx, output) |
| |
| _assert_dict_keys( |
| env, |
| foreach_srcs, |
| outs_dicts, |
| "assertion #2 (language: %s)" % language, |
| ) |
| for src in foreach_srcs: |
| _assert_dict_keys( |
| env, |
| ["OUT1", "OUT2"], |
| outs_dicts[src], |
| "assertion #3 (language: %s, src: %s)" % (language, src), |
| ) |
| |
| _assert_ends_with( |
| env, |
| "my_maprule_out/tests/%s/foo/src1.txt.out1" % language, |
| outs_dicts[src1]["OUT1"].path, |
| "assertion #4 (language: %s)" % language, |
| ) |
| _assert_ends_with( |
| env, |
| "my_maprule_out/tests/%s/foo/out2/src1.out2" % language, |
| outs_dicts[src1]["OUT2"].path, |
| "assertion #5 (language: %s)" % language, |
| ) |
| |
| _assert_ends_with( |
| env, |
| "my_maprule_out/tests/%s/foo/src2.pb.h.out1" % language, |
| outs_dicts[src2]["OUT1"].path, |
| "assertion #6 (language: %s)" % language, |
| ) |
| _assert_ends_with( |
| env, |
| "my_maprule_out/tests/%s/foo/out2/src2.pb.out2" % language, |
| outs_dicts[src2]["OUT2"].path, |
| "assertion #7 (language: %s)" % language, |
| ) |
| |
| _assert_ends_with( |
| env, |
| "my_maprule_out/tests/%s/bar/src1.txt.out1" % language, |
| outs_dicts[src3]["OUT1"].path, |
| "assertion #8 (language: %s)" % language, |
| ) |
| _assert_ends_with( |
| env, |
| "my_maprule_out/tests/%s/bar/out2/src1.out2" % language, |
| outs_dicts[src3]["OUT2"].path, |
| "assertion #9 (language: %s)" % language, |
| ) |
| |
| expected = [ |
| "my_maprule_out/tests/%s/foo/src1.txt.out1" % language, |
| "my_maprule_out/tests/%s/foo/out2/src1.out2" % language, |
| "my_maprule_out/tests/%s/foo/src2.pb.h.out1" % language, |
| "my_maprule_out/tests/%s/foo/out2/src2.pb.out2" % language, |
| "my_maprule_out/tests/%s/bar/src1.txt.out1" % language, |
| "my_maprule_out/tests/%s/bar/out2/src1.out2" % language, |
| ] |
| for i in range(0, len(all_output_files)): |
| actual = _lstrip_until(all_output_files[i].path, "my_maprule_out") |
| asserts.equals( |
| env, |
| expected[i], |
| actual, |
| "assertion #10 (language: %s, index: %d)" % (language, i), |
| ) |
| |
| return unittest.end(env) |
| |
| create_outputs_test = unittest.make(_create_outputs_test) |
| |
| def _conflicting_outputs_test(ctx): |
| """Unit tests for maprule_testing.create_outputs catching conflicting outputs.""" |
| env = unittest.begin(ctx) |
| |
| for language, strategy in [ |
| ("cmd", maprule_testing.cmd_strategy), |
| ("bash", maprule_testing.bash_strategy), |
| ]: |
| src1 = _mock_file(ctx, language + "/foo/src1.txt") |
| src2 = _mock_file(ctx, language + "/foo/src2.pb.h") |
| src3 = _mock_file(ctx, language + "/bar/src1.txt") |
| foreach_srcs = [src1, src2, src3] |
| |
| _, all_output_files, _, errors = ( |
| maprule_testing.create_outputs( |
| ctx, |
| "my_maprule", |
| { |
| "OUT1": "out1", # 3 conflicts |
| "OUT2": "{src_dir}/out2", # 2 conflicts |
| "OUT3": "out3/{src_name}", # 2 conflicts |
| }, |
| strategy, |
| foreach_srcs, |
| ) |
| ) |
| |
| for output in all_output_files: |
| _dummy_generating_action(ctx, output) |
| |
| _assert_error_fragments( |
| env, |
| errors, |
| ["out1", language + "/foo/src1.txt", "OUT1", language + "/foo/src2.pb.h", "OUT1"], |
| msg = "assertion #1 (language: %s)" % language, |
| ) |
| |
| _assert_error_fragments( |
| env, |
| errors, |
| ["out2", language + "/foo/src1.txt", "OUT2", language + "/foo/src2.pb.h", "OUT2"], |
| msg = "assertion #2 (language: %s)" % language, |
| ) |
| |
| _assert_error_fragments( |
| env, |
| errors, |
| ["out3/src1.txt", language + "/foo/src1.txt", "OUT3", language + "/bar/src1.txt", "OUT3"], |
| msg = "assertion #5 (language: %s)" % language, |
| ) |
| |
| return unittest.end(env) |
| |
| conflicting_outputs_test = unittest.make(_conflicting_outputs_test) |
| |
| def maprule_test_suite(): |
| """Creates the test targets and test suite for maprule.bzl tests.""" |
| |
| unittest.suite( |
| "maprule_tests", |
| src_placeholders_test, |
| validate_attributes_test, |
| as_path_test, |
| is_relative_path_test, |
| custom_envmap_test, |
| conflicting_outputs_test, |
| ) |