diff options
author | Vinh Tran <vinhdaitran@google.com> | 2023-07-21 19:38:23 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-07-21 19:38:23 +0000 |
commit | f0df148dbeb9b9ed3816aad328ebe7c65efaaa24 (patch) | |
tree | c75dabb560288e11786211bdc61ba40dde4b8674 /tools/migration/ctoolchain_comparator_lib_test.py | |
parent | 3544b5a539d9e51161befd2ac3fdc04525bced91 (diff) | |
parent | 9a4853f0327e0266818c8d6b4967e2e8f36b1a88 (diff) | |
download | bazelbuild-rules_cc-f0df148dbeb9b9ed3816aad328ebe7c65efaaa24.tar.gz |
Merge remote-tracking branch 'aosp/upstream-main' into main am: 755aefef35 am: d7bf0d569f am: 59148a708a am: 13ca54997b am: 9a4853f032android-14.0.0_r51android-14.0.0_r50android-14.0.0_r37android-14.0.0_r36android-14.0.0_r35android-14.0.0_r34android-14.0.0_r33android-14.0.0_r32android-14.0.0_r31android-14.0.0_r30android-14.0.0_r29android-14.0.0_r28android14-qpr3-releaseandroid14-qpr2-s5-releaseandroid14-qpr2-s4-releaseandroid14-qpr2-s3-releaseandroid14-qpr2-s2-releaseandroid14-qpr2-s1-releaseandroid14-qpr2-release
Original change: https://android-review.googlesource.com/c/platform/external/bazelbuild-rules_cc/+/2663436
Change-Id: I450b9f32024fa1b0844cc21a825c26589feb3977
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'tools/migration/ctoolchain_comparator_lib_test.py')
-rw-r--r-- | tools/migration/ctoolchain_comparator_lib_test.py | 1709 |
1 files changed, 1709 insertions, 0 deletions
diff --git a/tools/migration/ctoolchain_comparator_lib_test.py b/tools/migration/ctoolchain_comparator_lib_test.py new file mode 100644 index 0000000..c81ff47 --- /dev/null +++ b/tools/migration/ctoolchain_comparator_lib_test.py @@ -0,0 +1,1709 @@ +# 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. + +import unittest +from google.protobuf import text_format +from third_party.com.github.bazelbuild.bazel.src.main.protobuf import crosstool_config_pb2 +from tools.migration.ctoolchain_comparator_lib import compare_ctoolchains + +from py import mock +try: + # Python 2 + from cStringIO import StringIO +except ImportError: + # Python 3 + from io import StringIO + + +def make_toolchain(toolchain_proto): + toolchain = crosstool_config_pb2.CToolchain() + text_format.Merge(toolchain_proto, toolchain) + return toolchain + + +class CtoolchainComparatorLibTest(unittest.TestCase): + + def test_string_fields(self): + first = make_toolchain(""" + toolchain_identifier: "first-id" + host_system_name: "first-host" + target_system_name: "first-target" + target_cpu: "first-cpu" + target_libc: "first-libc" + compiler: "first-compiler" + abi_version: "first-abi" + abi_libc_version: "first-abi-libc" + builtin_sysroot: "sysroot" + """) + second = make_toolchain(""" + toolchain_identifier: "second-id" + host_system_name: "second-host" + target_system_name: "second-target" + target_cpu: "second-cpu" + target_libc: "second-libc" + compiler: "second-compiler" + abi_version: "second-abi" + abi_libc_version: "second-abi-libc" + cc_target_os: "os" + """) + error_toolchain_identifier = ( + "Difference in 'toolchain_identifier' field:\n" + "Value before change:\t'first-id'\n" + "Value after change:\t'second-id'\n") + error_host_system_name = ("Difference in 'host_system_name' field:\n" + "Value before change:\t'first-host'\n" + "Value after change:\t'second-host'\n") + error_target_system_name = ("Difference in 'target_system_name' field:\n" + "Value before change:\t'first-target'\n" + "Value after change:\t'second-target'\n") + error_target_cpu = ("Difference in 'target_cpu' field:\n" + "Value before change:\t'first-cpu'\n" + "Value after change:\t'second-cpu'\n") + error_target_libc = ("Difference in 'target_libc' field:\n" + "Value before change:\t'first-libc'\n" + "Value after change:\t'second-libc'\n") + error_compiler = ("Difference in 'compiler' field:\n" + "Value before change:\t'first-compiler'\n" + "Value after change:\t'second-compiler'\n") + error_abi_version = ("Difference in 'abi_version' field:\n" + "Value before change:\t'first-abi'\n" + "Value after change:\t'second-abi'\n") + error_abi_libc_version = ("Difference in 'abi_libc_version' field:\n" + "Value before change:\t'first-abi-libc'\n" + "Value after change:\t'second-abi-libc'\n") + error_builtin_sysroot = ("Difference in 'builtin_sysroot' field:\n" + "Value before change is set to 'sysroot'\n" + "Value after change is not set\n") + error_cc_target_os = ("Difference in 'cc_target_os' field:\n" + "Value before change is not set\n" + "Value after change is set to 'os'\n") + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn(error_toolchain_identifier, mock_stdout.getvalue()) + self.assertIn(error_host_system_name, mock_stdout.getvalue()) + self.assertIn(error_target_system_name, mock_stdout.getvalue()) + self.assertIn(error_target_cpu, mock_stdout.getvalue()) + self.assertIn(error_target_libc, mock_stdout.getvalue()) + self.assertIn(error_compiler, mock_stdout.getvalue()) + self.assertIn(error_abi_version, mock_stdout.getvalue()) + self.assertIn(error_abi_libc_version, mock_stdout.getvalue()) + self.assertIn(error_builtin_sysroot, mock_stdout.getvalue()) + self.assertIn(error_cc_target_os, mock_stdout.getvalue()) + + def test_tool_path(self): + first = make_toolchain(""" + tool_path { + name: "only_first" + path: "/a/b/c" + } + tool_path { + name: "paths_differ" + path: "/path/first" + } + """) + second = make_toolchain(""" + tool_path { + name: "paths_differ" + path: "/path/second" + } + tool_path { + name: "only_second_1" + path: "/a/b/c" + } + tool_path { + name: "only_second_2" + path: "/a/b/c" + } + """) + error_only_first = ("* List before change contains entries for the " + "following tools that the list after the change " + "doesn't:\n[only_first]\n") + error_only_second = ("* List after change contains entries for the " + "following tools that the list before the change " + "doesn't:\n" + "[\n" + "\tonly_second_1\n" + "\tonly_second_2\n" + "]\n") + error_paths_differ = ("* Path for tool 'paths_differ' differs before and " + "after the change:\n" + "Value before change:\t'/path/first'\n" + "Value after change:\t'/path/second'\n") + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn(error_only_first, mock_stdout.getvalue()) + self.assertIn(error_only_second, mock_stdout.getvalue()) + self.assertIn(error_paths_differ, mock_stdout.getvalue()) + + def test_make_variable(self): + first = make_toolchain(""" + make_variable { + name: "only_first" + value: "val" + } + make_variable { + name: "value_differs" + value: "first_value" + } + """) + second = make_toolchain(""" + make_variable { + name: "value_differs" + value: "second_value" + } + make_variable { + name: "only_second_1" + value: "val" + } + make_variable { + name: "only_second_2" + value: "val" + } + """) + error_only_first = ("* List before change contains entries for the " + "following variables that the list after the " + "change doesn't:\n[only_first]\n") + error_only_second = ("* List after change contains entries for the " + "following variables that the list before the " + "change doesn't:\n" + "[\n" + "\tonly_second_1\n" + "\tonly_second_2\n" + "]\n") + error_value_differs = ("* Value for variable 'value_differs' differs before" + " and after the change:\n" + "Value before change:\t'first_value'\n" + "Value after change:\t'second_value'\n") + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn(error_only_first, mock_stdout.getvalue()) + self.assertIn(error_only_second, mock_stdout.getvalue()) + self.assertIn(error_value_differs, mock_stdout.getvalue()) + + def test_cxx_builtin_include_directories(self): + first = make_toolchain(""" + cxx_builtin_include_directory: "a/b/c" + cxx_builtin_include_directory: "d/e/f" + """) + second = make_toolchain(""" + cxx_builtin_include_directory: "d/e/f" + cxx_builtin_include_directory: "a/b/c" + """) + expect_error = ("Difference in 'cxx_builtin_include_directory' field:\n" + "List of elements before change:\n" + "[\n" + "\ta/b/c\n" + "\td/e/f\n" + "]\n" + "List of elements after change:\n" + "[\n" + "\td/e/f\n" + "\ta/b/c\n" + "]\n") + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn(expect_error, mock_stdout.getvalue()) + + def test_artifact_name_pattern(self): + first = make_toolchain(""" + artifact_name_pattern { + category_name: 'object_file' + prefix: '' + extension: '.obj1' + } + artifact_name_pattern { + category_name: 'executable' + prefix: 'first' + extension: '.exe' + } + artifact_name_pattern { + category_name: 'dynamic_library' + prefix: '' + extension: '.dll' + } + """) + second = make_toolchain(""" + artifact_name_pattern { + category_name: 'object_file' + prefix: '' + extension: '.obj2' + } + artifact_name_pattern { + category_name: 'static_library' + prefix: '' + extension: '.lib' + } + artifact_name_pattern { + category_name: 'executable' + prefix: 'second' + extension: '.exe' + } + artifact_name_pattern { + category_name: 'interface_library' + prefix: '' + extension: '.if.lib' + } + """) + error_only_first = ("* List before change contains entries for the " + "following categories that the list after the " + "change doesn't:\n[dynamic_library]\n") + error_only_second = ("* List after change contains entries for the " + "following categories that the list before the " + "change doesn't:\n" + "[\n" + "\tinterface_library\n" + "\tstatic_library\n" + "]\n") + error_extension_differs = ("* Value for category 'object_file' differs " + "before and after the change:\n" + "Value before change:" + "\tprefix:''" + "\textension:'.obj1'\n" + "Value after change:" + "\tprefix:''" + "\textension:'.obj2'\n") + error_prefix_differs = ("* Value for category 'executable' differs " + "before and after the change:\n" + "Value before change:" + "\tprefix:'first'" + "\textension:'.exe'\n" + "Value after change:" + "\tprefix:'second'" + "\textension:'.exe'\n") + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn(error_only_first, mock_stdout.getvalue()) + self.assertIn(error_only_second, mock_stdout.getvalue()) + self.assertIn(error_extension_differs, mock_stdout.getvalue()) + self.assertIn(error_prefix_differs, mock_stdout.getvalue()) + + def test_features_not_ordered(self): + first = make_toolchain(""" + feature { + name: 'feature1' + } + feature { + name: 'feature2' + } + """) + second = make_toolchain(""" + feature { + name: 'feature2' + } + feature { + name: 'feature1' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("Features not in right order", mock_stdout.getvalue()) + + def test_features_missing(self): + first = make_toolchain(""" + feature { + name: 'feature1' + } + """) + second = make_toolchain(""" + feature { + name: 'feature2' + } + """) + error_only_first = ("* List before change contains entries for the " + "following features that the list after the " + "change doesn't:\n[feature1]\n") + error_only_second = ("* List after change contains entries for the " + "following features that the list before the " + "change doesn't:\n[feature2]\n") + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn(error_only_first, mock_stdout.getvalue()) + self.assertIn(error_only_second, mock_stdout.getvalue()) + + def test_feature_enabled(self): + first = make_toolchain(""" + feature { + name: 'feature' + enabled: true + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + enabled: false + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + + def test_feature_provides(self): + first = make_toolchain(""" + feature { + name: 'feature' + provides: 'a' + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + provides: 'b' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_feature_provides_preserves_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + provides: 'a' + provides: 'b' + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + provides: 'b' + provides: 'a' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_feature_implies(self): + first = make_toolchain(""" + feature { + name: 'feature' + implies: 'a' + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_feature_implies_preserves_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + implies: 'a' + implies: 'b' + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + implies: 'b' + implies: 'a' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_feature_requires_preserves_list_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + requires: { + feature: 'feature1' + } + requires: { + feature: 'feature2' + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + requires: { + feature: 'feature2' + } + requires: { + feature: 'feature1' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_feature_requires_ignores_required_features_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + requires: { + feature: 'feature1' + feature: 'feature2' + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + requires: { + feature: 'feature2' + feature: 'feature1' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_feature_requires_differs(self): + first = make_toolchain(""" + feature { + name: 'feature' + requires: { + feature: 'feature1' + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + requires: { + feature: 'feature2' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_action_config_ignores_requires(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + requires: { + feature: 'feature1' + } + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + requires: { + feature: 'feature2' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_env_set_actions_differ(self): + first = make_toolchain(""" + feature { + name: 'feature' + env_set { + action: 'a1' + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + env_set: { + action: 'a1' + action: 'a2' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_env_set_ignores_actions_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + env_set { + action: 'a2' + action: 'a1' + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + env_set: { + action: 'a1' + action: 'a2' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_env_set_env_entries_not_ordered(self): + first = make_toolchain(""" + feature { + name: 'feature' + env_set { + env_entry { + key: 'k1' + value: 'v1' + } + env_entry { + key: 'k2' + value: 'v2' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + env_set { + env_entry { + key: 'k2' + value: 'v2' + } + env_entry { + key: 'k1' + value: 'v1' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_env_set_env_entries_differ(self): + first = make_toolchain(""" + feature { + name: 'feature' + env_set { + env_entry { + key: 'k1' + value: 'value_first' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + env_set { + env_entry { + key: 'k1' + value: 'value_second' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_feature_preserves_env_set_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + env_set { + env_entry { + key: 'first' + value: 'first' + } + } + env_set { + env_entry { + key: 'second' + value: 'second' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + env_set { + env_entry { + key: 'second' + value: 'second' + } + } + env_set { + env_entry { + key: 'first' + value: 'first' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after the change:", + mock_stdout.getvalue()) + + def test_action_config_ignores_env_set(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + env_set { + env_entry { + key: 'k1' + value: 'value_first' + } + } + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + env_set { + env_entry { + key: 'k1' + value: 'value_second' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_env_set_ignores_with_feature_set_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + env_set{ + with_feature { + feature: 'feature1' + } + with_feature { + not_feature: 'feature2' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + env_set { + with_feature { + not_feature: 'feature2' + } + with_feature { + feature: 'feature1' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_env_set_ignores_with_feature_set_lists_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + env_set{ + with_feature { + feature: 'feature1' + feature: 'feature2' + not_feature: 'not_feature1' + not_feature: 'not_feature2' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + env_set{ + with_feature { + feature: 'feature2' + feature: 'feature1' + not_feature: 'not_feature2' + not_feature: 'not_feature1' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_flag_set_ignores_actions_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set { + action: 'a1' + action: 'a2' + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set { + action: 'a2' + action: 'a1' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_action_config_flag_set_actions_ignored(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + flag_set { + action: 'a1' + } + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + flag_set { + action: 'a2' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_flag_set_ignores_with_feature_set_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set { + with_feature { + feature: 'feature1' + } + with_feature { + not_feature: 'feature2' + } + } + } + action_config { + config_name: 'config' + flag_set { + with_feature { + feature: 'feature1' + } + with_feature { + not_feature: 'feature2' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set { + with_feature { + not_feature: 'feature2' + } + with_feature { + feature: 'feature1' + } + } + } + action_config { + config_name: 'config' + flag_set { + with_feature { + not_feature: 'feature2' + } + with_feature { + feature: 'feature1' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_flag_set_ignores_with_feature_set_lists_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + with_feature { + feature: 'feature1' + feature: 'feature2' + not_feature: 'not_feature1' + not_feature: 'not_feature2' + } + } + } + action_config { + config_name: 'config' + flag_set{ + with_feature { + feature: 'feature1' + feature: 'feature2' + not_feature: 'not_feature1' + not_feature: 'not_feature2' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + with_feature { + feature: 'feature2' + feature: 'feature1' + not_feature: 'not_feature2' + not_feature: 'not_feature1' + } + } + } + action_config { + config_name: 'config' + flag_set{ + with_feature { + feature: 'feature2' + feature: 'feature1' + not_feature: 'not_feature2' + not_feature: 'not_feature1' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_flag_set_preserves_flag_group_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set { + flag_group { + flag: 'a' + } + flag_group { + flag: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set { + flag_group { + flag: 'a' + } + flag_group { + flag: 'b' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set { + flag_group { + flag: 'b' + } + flag_group { + flag: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set { + flag_group { + flag: 'b' + } + flag_group { + flag: 'a' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_preserves_flags_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + flag: 'flag1' + flag: 'flag2' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + flag: 'flag1' + flag: 'flag2' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + flag: 'flag2' + flag: 'flag1' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + flag: 'flag2' + flag: 'flag1' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_iterate_over_differs(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + iterate_over: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + iterate_over: 'a' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + iterate_over: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + iterate_over: 'b' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_expand_if_true_differs(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_true: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_true: 'a' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_true: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_true: 'b' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_expand_if_false_differs(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_false: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_false: 'a' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_false: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_false: 'b' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_expand_if_all_available_differs(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_all_available: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_all_available: 'a' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_all_available: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_all_available: 'b' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_expand_if_none_available_differs(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_none_available: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_none_available: 'a' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_none_available: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_none_available: 'b' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_expand_if_all_available_ignores_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_all_available: 'a' + expand_if_all_available: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_all_available: 'a' + expand_if_all_available: 'b' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_all_available: 'b' + expand_if_all_available: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_all_available: 'b' + expand_if_all_available: 'a' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_flag_group_expand_if_none_available_ignores_order(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_none_available: 'a' + expand_if_none_available: 'b' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_none_available: 'a' + expand_if_none_available: 'b' + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_none_available: 'b' + expand_if_none_available: 'a' + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_none_available: 'b' + expand_if_none_available: 'a' + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_flag_group_expand_if_equal_differs(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_equal { + variable: 'first' + value: 'val' + } + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_equal { + variable: 'first' + value: 'val' + } + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + expand_if_equal { + variable: 'second' + value: 'val' + } + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + expand_if_equal { + variable: 'second' + value: 'val' + } + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_flag_group_flag_groups_differ(self): + first = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + flag_group { + flag: 'a' + flag: 'b' + } + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + flag_group { + flag: 'a' + flag: 'b' + } + } + } + } + """) + second = make_toolchain(""" + feature { + name: 'feature' + flag_set{ + flag_group { + flag_group { + flag: 'b' + flag: 'a' + } + } + } + } + action_config { + config_name: 'config' + flag_set{ + flag_group { + flag_group { + flag: 'b' + flag: 'a' + } + } + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Feature 'feature' differs before and after", + mock_stdout.getvalue()) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_action_configs_not_ordered(self): + first = make_toolchain(""" + action_config { + config_name: 'action1' + } + action_config { + config_name: 'action2' + } + """) + second = make_toolchain(""" + action_config { + config_name: 'action2' + } + action_config { + config_name: 'action1' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("Action configs not in right order", mock_stdout.getvalue()) + + def test_action_configs_missing(self): + first = make_toolchain(""" + action_config { + config_name: 'action1' + } + """) + second = make_toolchain(""" + action_config { + config_name: 'action2' + } + """) + error_only_first = ("* List before change contains entries for the " + "following action_configs that the list after the " + "change doesn't:\n[action1]\n") + error_only_second = ("* List after change contains entries for the " + "following action_configs that the list before the " + "change doesn't:\n[action2]\n") + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn(error_only_first, mock_stdout.getvalue()) + self.assertIn(error_only_second, mock_stdout.getvalue()) + + def test_action_config_enabled(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + enabled: true + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + enabled: false + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_action_config_action_name(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + action_name: 'config1' + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + action_name: 'config2' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_action_config_tool_tool_path_differs(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + tool { + tool_path: 'path1' + } + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + tool { + tool_path: 'path2' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_action_config_tool_execution_requirements_differ(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + tool { + execution_requirement: 'a' + } + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + tool { + execution_requirement: 'b' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_action_config_tool_execution_requirements_ignores_order(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + tool { + execution_requirement: 'a' + execution_requirement: 'b' + } + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + tool { + execution_requirement: 'b' + execution_requirement: 'a' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_action_config_implies_differs(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + implies: 'a' + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + implies: 'b' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_action_config_implies_preserves_order(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + implies: 'a' + implies: 'b' + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + implies: 'b' + implies: 'a' + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("* Action config 'config' differs before and after", + mock_stdout.getvalue()) + + def test_unused_tool_path(self): + first = make_toolchain(""" + tool_path { + name: "empty" + path: "" + } + """) + second = make_toolchain(""" + tool_path { + name: "empty" + path: "NOT_USED" + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + + def test_unused_tool_path_in_tool(self): + first = make_toolchain(""" + action_config { + config_name: 'config' + tool { + tool_path: '' + } + } + """) + second = make_toolchain(""" + action_config { + config_name: 'config' + tool { + tool_path: 'NOT_USED' + } + } + """) + mock_stdout = StringIO() + with mock.patch("sys.stdout", mock_stdout): + compare_ctoolchains(first, second) + self.assertIn("No difference", mock_stdout.getvalue()) + +if __name__ == "__main__": + unittest.main() |