blob: b5b8becb574defca1364f95967f04c88a711c188 [file] [log] [blame]
# Lint as: python2, python3
# pylint: disable=g-direct-third-party-import
# 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
# Do not edit this line. Copybara replaces it with PY2 migration helper.
from third_party.py import mock
import six
if six.PY2:
from cStringIO import StringIO
else:
from io import StringIO
from src.main.protobuf import analysis_pb2
from tools.aquery_differ import aquery_differ
def make_aquery_output(actions, artifact_paths):
action_graph = analysis_pb2.ActionGraphContainer()
for artifact_path in artifact_paths:
next_id = len(action_graph.artifacts)
artifact = action_graph.artifacts.add()
artifact.id = str(next_id)
artifact.exec_path = artifact_path
for next_action in actions:
action = action_graph.actions.add()
action.output_ids.extend(next_action["output_ids"])
action.arguments.extend(next_action["arguments"])
if "input_dep_set_ids" in next_action:
action.input_dep_set_ids.extend(next_action["input_dep_set_ids"])
return action_graph
def make_aquery_output_with_dep_set(actions, artifact_paths, dep_sets):
action_graph = make_aquery_output(actions, artifact_paths)
for ds in dep_sets:
next_id = len(action_graph.dep_set_of_files)
dep_set = action_graph.dep_set_of_files.add()
dep_set.id = str(next_id)
dep_set.direct_artifact_ids.extend(ds["direct_artifact_ids"])
dep_set.transitive_dep_set_ids.extend(ds["transitive_dep_set_ids"])
return action_graph
class CmdLineDifferTest(unittest.TestCase):
def test_no_difference(self):
action_graph = make_aquery_output(
actions=[{
"arguments": ["-a", "-b"],
"output_ids": ["0", "1"]
}, {
"arguments": ["-c"],
"output_ids": ["2"]
}],
artifact_paths=["exec/path/zero", "exec/path/one", "exec/path/two"])
mock_stdout = StringIO()
attrs = ["cmdline"]
with mock.patch("sys.stdout", mock_stdout):
aquery_differ._aquery_diff(action_graph, action_graph, attrs, "before",
"after")
self.assertEqual(mock_stdout.getvalue(), "No difference\n")
def test_no_difference_different_output_files_order(self):
first = make_aquery_output(
actions=[
{
"arguments": ["-a", "-b"],
"output_ids": ["0", "1"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one"])
second = make_aquery_output(
actions=[
{
"arguments": ["-a", "-b"],
"output_ids": ["1", "0"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one"])
mock_stdout = StringIO()
attrs = ["cmdline"]
with mock.patch("sys.stdout", mock_stdout):
aquery_differ._aquery_diff(first, second, attrs, "before", "after")
self.assertEqual(mock_stdout.getvalue(), "No difference\n")
def test_first_has_extra_output_files(self):
first = make_aquery_output(
actions=[
{
"arguments": ["-a", "-b"],
"output_ids": ["0", "1"]
},
{
"arguments": ["-c"],
"output_ids": ["2"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one", "exec/path/two"],
)
second = make_aquery_output(
actions=[
{
"arguments": ["-a", "-b"],
"output_ids": ["1", "0"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one", "exec/path/two"],
)
expected_error = ("Aquery output 'before' change contains an action "
"that generates the following outputs that aquery "
"output 'after' change doesn't:\nexec/path/two\n\n")
mock_stdout = StringIO()
attrs = ["cmdline"]
with mock.patch("sys.stdout", mock_stdout):
aquery_differ._aquery_diff(first, second, attrs, "before", "after")
self.assertEqual(mock_stdout.getvalue(), expected_error)
def test_second_has_extra_output_files(self):
first = make_aquery_output(
actions=[
{
"arguments": ["-a", "-b"],
"output_ids": ["0", "1"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one", "exec/path/two"],
)
second = make_aquery_output(
actions=[
{
"arguments": ["-a", "-b"],
"output_ids": ["0", "1"]
},
{
"arguments": ["-c"],
"output_ids": ["2"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one", "exec/path/two"],
)
expected_error = ("Aquery output 'after' change contains an action that"
" generates the following outputs that aquery"
" output 'before' change doesn't:\nexec/path/two\n\n")
mock_stdout = StringIO()
attrs = ["cmdline"]
with mock.patch("sys.stdout", mock_stdout):
aquery_differ._aquery_diff(first, second, attrs, "before", "after")
self.assertEqual(mock_stdout.getvalue(), expected_error)
def test_different_command_lines(self):
first = make_aquery_output(
actions=[
{
"arguments": ["-a", "-d"],
"output_ids": ["0", "1"]
},
{
"arguments": ["-c"],
"output_ids": ["2"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one", "exec/path/two"],
)
second = make_aquery_output(
actions=[
{
"arguments": ["-a", "-b"],
"output_ids": ["0", "1"]
},
{
"arguments": ["-c", "-d"],
"output_ids": ["2"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one", "exec/path/two"],
)
expected_error_one = "\n".join([
"Difference in the action that generates the following output(s):",
"\texec/path/two", "--- before", "+++ after", "@@ -1 +1,2 @@", " -c",
"+-d", "\n"
])
expected_error_two = "\n".join([
"Difference in the action that generates the following output(s):",
"\texec/path/one", "\texec/path/zero", "--- before", "+++ after",
"@@ -1,2 +1,2 @@", " -a", "--d", "+-b", "\n"
])
attrs = ["cmdline"]
mock_stdout = StringIO()
with mock.patch("sys.stdout", mock_stdout):
aquery_differ._aquery_diff(first, second, attrs, "before", "after")
self.assertIn(expected_error_one, mock_stdout.getvalue())
self.assertIn(expected_error_two, mock_stdout.getvalue())
def test_different_inputs(self):
first = make_aquery_output_with_dep_set(
actions=[{
"arguments": [],
"output_ids": ["0", "1"],
"input_dep_set_ids": ["1"]
}],
artifact_paths=["exec/path/zero", "exec/path/one"],
dep_sets=[{
"transitive_dep_set_ids": [],
"direct_artifact_ids": ["0"]
}, {
"transitive_dep_set_ids": ["0"],
"direct_artifact_ids": ["1"]
}])
second = make_aquery_output_with_dep_set(
actions=[
{
"arguments": [],
"output_ids": ["0", "1"],
"input_dep_set_ids": ["0"]
},
],
artifact_paths=["exec/path/zero", "exec/path/one"],
dep_sets=[{
"transitive_dep_set_ids": [],
"direct_artifact_ids": ["0"]
}])
expected_error_one = "\n".join([
"Difference in the action that generates the following output(s):",
"\texec/path/one", "\texec/path/zero", "--- before", "+++ after",
"@@ -1,2 +1 @@", "-exec/path/one", " exec/path/zero", "\n"
])
attrs = ["inputs"]
mock_stdout = StringIO()
with mock.patch("sys.stdout", mock_stdout):
aquery_differ._aquery_diff(first, second, attrs, "before", "after")
self.assertIn(expected_error_one, mock_stdout.getvalue())
if __name__ == "__main__":
unittest.main()