| # 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 io | 
 | import os | 
 | import unittest | 
 |  | 
 | # Do not edit this line. Copybara replaces it with PY2 migration helper. | 
 | from third_party.py import mock | 
 |  | 
 | from src.main.protobuf import analysis_v2_pb2 | 
 | from tools.aquery_differ import aquery_differ | 
 |  | 
 |  | 
 | def make_aquery_output(action_objs, artifact_objs, path_fragment_objs): | 
 |   action_graph = analysis_v2_pb2.ActionGraphContainer() | 
 |  | 
 |   for path_fragment_obj in path_fragment_objs: | 
 |     path_fragment = action_graph.path_fragments.add() | 
 |     path_fragment.id = path_fragment_obj["id"] | 
 |     path_fragment.label = path_fragment_obj["label"] | 
 |     if "parent_id" in path_fragment_obj: | 
 |       path_fragment.parent_id = path_fragment_obj["parent_id"] | 
 |  | 
 |   for artifact_obj in artifact_objs: | 
 |     artifact = action_graph.artifacts.add() | 
 |     artifact.id = artifact_obj["id"] | 
 |     artifact.path_fragment_id = artifact_obj["path_fragment_id"] | 
 |  | 
 |   for action_obj in action_objs: | 
 |     action = action_graph.actions.add() | 
 |     action.output_ids.extend(action_obj["output_ids"]) | 
 |     action.arguments.extend(action_obj["arguments"]) | 
 |  | 
 |     if "input_dep_set_ids" in action_obj: | 
 |       action.input_dep_set_ids.extend(action_obj["input_dep_set_ids"]) | 
 |  | 
 |   return action_graph | 
 |  | 
 |  | 
 | def make_aquery_output_with_dep_set(action_objs, artifact_objs, | 
 |                                     path_fragment_objs, dep_set_objs): | 
 |   action_graph = make_aquery_output(action_objs, artifact_objs, | 
 |                                     path_fragment_objs) | 
 |  | 
 |   for ds in dep_set_objs: | 
 |     dep_set = action_graph.dep_set_of_files.add() | 
 |     dep_set.id = ds["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( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": ["-a", "-b"], | 
 |                 "output_ids": [1, 2] | 
 |             }, | 
 |             { | 
 |                 "arguments": ["-c"], | 
 |                 "output_ids": [3] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }, { | 
 |             "id": 3, | 
 |             "path_fragment_id": 4 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 4, | 
 |                 "label": "baz", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ]) | 
 |     mock_stdout = io.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( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": ["-a", "-b"], | 
 |                 "output_ids": [1, 2] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ]) | 
 |  | 
 |     second = make_aquery_output( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": ["-a", "-b"], | 
 |                 "output_ids": [2, 1] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ]) | 
 |  | 
 |     mock_stdout = io.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( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": ["-a", "-b"], | 
 |                 "output_ids": [1, 2] | 
 |             }, | 
 |             { | 
 |                 "arguments": ["-c"], | 
 |                 "output_ids": [3] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }, { | 
 |             "id": 3, | 
 |             "path_fragment_id": 4 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 4, | 
 |                 "label": "baz", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ]) | 
 |     second = make_aquery_output( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": ["-a", "-b"], | 
 |                 "output_ids": [1, 2] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }], | 
 |         path_fragment_objs=[{ | 
 |             "id": 1, | 
 |             "label": "root" | 
 |         }, { | 
 |             "id": 2, | 
 |             "label": "foo", | 
 |             "parent_id": 1 | 
 |         }, { | 
 |             "id": 3, | 
 |             "label": "bar", | 
 |             "parent_id": 1 | 
 |         }]) | 
 |  | 
 |     baz_path = os.path.join("root", "baz") | 
 |     expected_error = ("Aquery output 'before' change contains an action " | 
 |                       "that generates the following outputs that aquery " | 
 |                       "output 'after' change doesn't:\n{}\n\n".format(baz_path)) | 
 |     mock_stdout = io.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( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": ["-a", "-d"], | 
 |                 "output_ids": [1, 2] | 
 |             }, | 
 |             { | 
 |                 "arguments": ["-c"], | 
 |                 "output_ids": [3] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }, { | 
 |             "id": 3, | 
 |             "path_fragment_id": 4 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 4, | 
 |                 "label": "baz", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ]) | 
 |     second = make_aquery_output( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": ["-a", "-b"], | 
 |                 "output_ids": [1, 2] | 
 |             }, | 
 |             { | 
 |                 "arguments": ["-c", "-d"], | 
 |                 "output_ids": [3] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }, { | 
 |             "id": 3, | 
 |             "path_fragment_id": 4 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 4, | 
 |                 "label": "baz", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ]) | 
 |  | 
 |     foo_path = os.path.join("root", "foo") | 
 |     bar_path = os.path.join("root", "bar") | 
 |     baz_path = os.path.join("root", "baz") | 
 |  | 
 |     expected_error_one = "\n".join([ | 
 |         "Difference in the action that generates the following output(s):", | 
 |         "\t{}".format(baz_path), "--- before", "+++ after", "@@ -1 +1,2 @@", | 
 |         " -c", "+-d", "\n" | 
 |     ]) | 
 |     expected_error_two = "\n".join([ | 
 |         "Difference in the action that generates the following output(s):", | 
 |         "\t{}".format(bar_path), "\t{}".format(foo_path), "--- before", | 
 |         "+++ after", "@@ -1,2 +1,2 @@", " -a", "--d", "+-b", "\n" | 
 |     ]) | 
 |     attrs = ["cmdline"] | 
 |  | 
 |     mock_stdout = io.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( | 
 |         action_objs=[{ | 
 |             "arguments": [], | 
 |             "output_ids": [1, 2], | 
 |             "input_dep_set_ids": [2] | 
 |         }], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ], | 
 |         dep_set_objs=[{ | 
 |             "id": 1, | 
 |             "transitive_dep_set_ids": [], | 
 |             "direct_artifact_ids": [1] | 
 |         }, { | 
 |             "id": 2, | 
 |             "transitive_dep_set_ids": [1], | 
 |             "direct_artifact_ids": [2] | 
 |         }]) | 
 |     second = make_aquery_output_with_dep_set( | 
 |         action_objs=[ | 
 |             { | 
 |                 "arguments": [], | 
 |                 "output_ids": [1, 2], | 
 |                 "input_dep_set_ids": [1] | 
 |             }, | 
 |         ], | 
 |         artifact_objs=[{ | 
 |             "id": 1, | 
 |             "path_fragment_id": 2 | 
 |         }, { | 
 |             "id": 2, | 
 |             "path_fragment_id": 3 | 
 |         }], | 
 |         path_fragment_objs=[ | 
 |             { | 
 |                 "id": 1, | 
 |                 "label": "root" | 
 |             }, | 
 |             { | 
 |                 "id": 2, | 
 |                 "label": "foo", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |             { | 
 |                 "id": 3, | 
 |                 "label": "bar", | 
 |                 "parent_id": 1 | 
 |             }, | 
 |         ], | 
 |         dep_set_objs=[{ | 
 |             "id": 1, | 
 |             "transitive_dep_set_ids": [], | 
 |             "direct_artifact_ids": [1] | 
 |         }]) | 
 |  | 
 |     foo_path = os.path.join("root", "foo") | 
 |     bar_path = os.path.join("root", "bar") | 
 |     expected_error_one = "\n".join([ | 
 |         "Difference in the action that generates the following output(s):", | 
 |         "\t{}".format(bar_path), "\t{}".format(foo_path), "--- before", | 
 |         "+++ after", "@@ -1,2 +1 @@", "-{}".format(bar_path), | 
 |         " {}".format(foo_path), "\n" | 
 |     ]) | 
 |     attrs = ["inputs"] | 
 |  | 
 |     mock_stdout = io.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() |