blob: 1a3a27018f725ebc7d03dc24208ef6990f6e0c7a [file] [log] [blame]
# 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 py import mock
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
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()