blob: 3d156bb7a561df55c3ee062102d5ddc56fa0c18a [file] [log] [blame]
laszlocsomora6545052019-11-05 05:18:32 -08001# pylint: disable=g-direct-third-party-import
rosica0ec99e72019-01-03 01:06:47 -08002# Copyright 2018 The Bazel Authors. All rights reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Tony Aiuto9a2d3672022-08-24 00:46:17 -070016import io
leba36c5d3d2020-12-14 07:09:37 -080017import os
rosica0ec99e72019-01-03 01:06:47 -080018import unittest
Tony Aiuto9a2d3672022-08-24 00:46:17 -070019
laszlocsomora6545052019-11-05 05:18:32 -080020# Do not edit this line. Copybara replaces it with PY2 migration helper.
21from third_party.py import mock
Tony Aiuto9a2d3672022-08-24 00:46:17 -070022
leba36c5d3d2020-12-14 07:09:37 -080023from src.main.protobuf import analysis_v2_pb2
24from tools.aquery_differ import aquery_differ
25
rosica0ec99e72019-01-03 01:06:47 -080026
leba36c5d3d2020-12-14 07:09:37 -080027def make_aquery_output(action_objs, artifact_objs, path_fragment_objs):
28 action_graph = analysis_v2_pb2.ActionGraphContainer()
leba35757972019-02-08 02:03:12 -080029
leba36c5d3d2020-12-14 07:09:37 -080030 for path_fragment_obj in path_fragment_objs:
31 path_fragment = action_graph.path_fragments.add()
32 path_fragment.id = path_fragment_obj["id"]
33 path_fragment.label = path_fragment_obj["label"]
34 if "parent_id" in path_fragment_obj:
35 path_fragment.parent_id = path_fragment_obj["parent_id"]
36
37 for artifact_obj in artifact_objs:
rosica0ec99e72019-01-03 01:06:47 -080038 artifact = action_graph.artifacts.add()
leba36c5d3d2020-12-14 07:09:37 -080039 artifact.id = artifact_obj["id"]
40 artifact.path_fragment_id = artifact_obj["path_fragment_id"]
leba35757972019-02-08 02:03:12 -080041
leba36c5d3d2020-12-14 07:09:37 -080042 for action_obj in action_objs:
rosica0ec99e72019-01-03 01:06:47 -080043 action = action_graph.actions.add()
leba36c5d3d2020-12-14 07:09:37 -080044 action.output_ids.extend(action_obj["output_ids"])
45 action.arguments.extend(action_obj["arguments"])
leba35757972019-02-08 02:03:12 -080046
leba36c5d3d2020-12-14 07:09:37 -080047 if "input_dep_set_ids" in action_obj:
48 action.input_dep_set_ids.extend(action_obj["input_dep_set_ids"])
leba35757972019-02-08 02:03:12 -080049
50 return action_graph
51
52
leba36c5d3d2020-12-14 07:09:37 -080053def make_aquery_output_with_dep_set(action_objs, artifact_objs,
54 path_fragment_objs, dep_set_objs):
55 action_graph = make_aquery_output(action_objs, artifact_objs,
56 path_fragment_objs)
leba35757972019-02-08 02:03:12 -080057
leba36c5d3d2020-12-14 07:09:37 -080058 for ds in dep_set_objs:
leba35757972019-02-08 02:03:12 -080059 dep_set = action_graph.dep_set_of_files.add()
leba36c5d3d2020-12-14 07:09:37 -080060 dep_set.id = ds["id"]
leba35757972019-02-08 02:03:12 -080061 dep_set.direct_artifact_ids.extend(ds["direct_artifact_ids"])
62 dep_set.transitive_dep_set_ids.extend(ds["transitive_dep_set_ids"])
63
rosica0ec99e72019-01-03 01:06:47 -080064 return action_graph
65
66
67class CmdLineDifferTest(unittest.TestCase):
68
69 def test_no_difference(self):
70 action_graph = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -080071 action_objs=[
72 {
73 "arguments": ["-a", "-b"],
74 "output_ids": [1, 2]
75 },
76 {
77 "arguments": ["-c"],
78 "output_ids": [3]
79 },
80 ],
81 artifact_objs=[{
82 "id": 1,
83 "path_fragment_id": 2
rosica0ec99e72019-01-03 01:06:47 -080084 }, {
leba36c5d3d2020-12-14 07:09:37 -080085 "id": 2,
86 "path_fragment_id": 3
87 }, {
88 "id": 3,
89 "path_fragment_id": 4
rosica0ec99e72019-01-03 01:06:47 -080090 }],
leba36c5d3d2020-12-14 07:09:37 -080091 path_fragment_objs=[
92 {
93 "id": 1,
94 "label": "root"
95 },
96 {
97 "id": 2,
98 "label": "foo",
99 "parent_id": 1
100 },
101 {
102 "id": 3,
103 "label": "bar",
104 "parent_id": 1
105 },
106 {
107 "id": 4,
108 "label": "baz",
109 "parent_id": 1
110 },
111 ])
Tony Aiuto9a2d3672022-08-24 00:46:17 -0700112 mock_stdout = io.StringIO()
leba35757972019-02-08 02:03:12 -0800113 attrs = ["cmdline"]
rosica0ec99e72019-01-03 01:06:47 -0800114 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800115 aquery_differ._aquery_diff(action_graph, action_graph, attrs, "before",
116 "after")
rosica0ec99e72019-01-03 01:06:47 -0800117 self.assertEqual(mock_stdout.getvalue(), "No difference\n")
118
119 def test_no_difference_different_output_files_order(self):
120 first = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800121 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800122 {
123 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800124 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800125 },
126 ],
leba36c5d3d2020-12-14 07:09:37 -0800127 artifact_objs=[{
128 "id": 1,
129 "path_fragment_id": 2
130 }, {
131 "id": 2,
132 "path_fragment_id": 3
133 }],
134 path_fragment_objs=[
135 {
136 "id": 1,
137 "label": "root"
138 },
139 {
140 "id": 2,
141 "label": "foo",
142 "parent_id": 1
143 },
144 {
145 "id": 3,
146 "label": "bar",
147 "parent_id": 1
148 },
149 ])
150
rosica0ec99e72019-01-03 01:06:47 -0800151 second = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800152 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800153 {
154 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800155 "output_ids": [2, 1]
rosica0ec99e72019-01-03 01:06:47 -0800156 },
157 ],
leba36c5d3d2020-12-14 07:09:37 -0800158 artifact_objs=[{
159 "id": 1,
160 "path_fragment_id": 2
161 }, {
162 "id": 2,
163 "path_fragment_id": 3
164 }],
165 path_fragment_objs=[
166 {
167 "id": 1,
168 "label": "root"
169 },
170 {
171 "id": 2,
172 "label": "foo",
173 "parent_id": 1
174 },
175 {
176 "id": 3,
177 "label": "bar",
178 "parent_id": 1
179 },
180 ])
rosica0ec99e72019-01-03 01:06:47 -0800181
Tony Aiuto9a2d3672022-08-24 00:46:17 -0700182 mock_stdout = io.StringIO()
leba35757972019-02-08 02:03:12 -0800183 attrs = ["cmdline"]
rosica0ec99e72019-01-03 01:06:47 -0800184 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800185 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
rosica0ec99e72019-01-03 01:06:47 -0800186 self.assertEqual(mock_stdout.getvalue(), "No difference\n")
187
188 def test_first_has_extra_output_files(self):
189 first = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800190 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800191 {
192 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800193 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800194 },
195 {
196 "arguments": ["-c"],
leba36c5d3d2020-12-14 07:09:37 -0800197 "output_ids": [3]
rosica0ec99e72019-01-03 01:06:47 -0800198 },
199 ],
leba36c5d3d2020-12-14 07:09:37 -0800200 artifact_objs=[{
201 "id": 1,
202 "path_fragment_id": 2
203 }, {
204 "id": 2,
205 "path_fragment_id": 3
206 }, {
207 "id": 3,
208 "path_fragment_id": 4
209 }],
210 path_fragment_objs=[
211 {
212 "id": 1,
213 "label": "root"
214 },
215 {
216 "id": 2,
217 "label": "foo",
218 "parent_id": 1
219 },
220 {
221 "id": 3,
222 "label": "bar",
223 "parent_id": 1
224 },
225 {
226 "id": 4,
227 "label": "baz",
228 "parent_id": 1
229 },
230 ])
rosica0ec99e72019-01-03 01:06:47 -0800231 second = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800232 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800233 {
234 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800235 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800236 },
237 ],
leba36c5d3d2020-12-14 07:09:37 -0800238 artifact_objs=[{
239 "id": 1,
240 "path_fragment_id": 2
241 }, {
242 "id": 2,
243 "path_fragment_id": 3
244 }],
245 path_fragment_objs=[{
246 "id": 1,
247 "label": "root"
248 }, {
249 "id": 2,
250 "label": "foo",
251 "parent_id": 1
252 }, {
253 "id": 3,
254 "label": "bar",
255 "parent_id": 1
256 }])
rosica0ec99e72019-01-03 01:06:47 -0800257
leba36c5d3d2020-12-14 07:09:37 -0800258 baz_path = os.path.join("root", "baz")
leba35757972019-02-08 02:03:12 -0800259 expected_error = ("Aquery output 'before' change contains an action "
rosica0ec99e72019-01-03 01:06:47 -0800260 "that generates the following outputs that aquery "
leba36c5d3d2020-12-14 07:09:37 -0800261 "output 'after' change doesn't:\n{}\n\n".format(baz_path))
Tony Aiuto9a2d3672022-08-24 00:46:17 -0700262 mock_stdout = io.StringIO()
leba35757972019-02-08 02:03:12 -0800263 attrs = ["cmdline"]
rosica0ec99e72019-01-03 01:06:47 -0800264 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800265 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
rosica0ec99e72019-01-03 01:06:47 -0800266 self.assertEqual(mock_stdout.getvalue(), expected_error)
267
268 def test_different_command_lines(self):
269 first = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800270 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800271 {
272 "arguments": ["-a", "-d"],
leba36c5d3d2020-12-14 07:09:37 -0800273 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800274 },
275 {
276 "arguments": ["-c"],
leba36c5d3d2020-12-14 07:09:37 -0800277 "output_ids": [3]
rosica0ec99e72019-01-03 01:06:47 -0800278 },
279 ],
leba36c5d3d2020-12-14 07:09:37 -0800280 artifact_objs=[{
281 "id": 1,
282 "path_fragment_id": 2
283 }, {
284 "id": 2,
285 "path_fragment_id": 3
286 }, {
287 "id": 3,
288 "path_fragment_id": 4
289 }],
290 path_fragment_objs=[
291 {
292 "id": 1,
293 "label": "root"
294 },
295 {
296 "id": 2,
297 "label": "foo",
298 "parent_id": 1
299 },
300 {
301 "id": 3,
302 "label": "bar",
303 "parent_id": 1
304 },
305 {
306 "id": 4,
307 "label": "baz",
308 "parent_id": 1
309 },
310 ])
rosica0ec99e72019-01-03 01:06:47 -0800311 second = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800312 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800313 {
314 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800315 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800316 },
317 {
318 "arguments": ["-c", "-d"],
leba36c5d3d2020-12-14 07:09:37 -0800319 "output_ids": [3]
rosica0ec99e72019-01-03 01:06:47 -0800320 },
321 ],
leba36c5d3d2020-12-14 07:09:37 -0800322 artifact_objs=[{
323 "id": 1,
324 "path_fragment_id": 2
325 }, {
326 "id": 2,
327 "path_fragment_id": 3
328 }, {
329 "id": 3,
330 "path_fragment_id": 4
331 }],
332 path_fragment_objs=[
333 {
334 "id": 1,
335 "label": "root"
336 },
337 {
338 "id": 2,
339 "label": "foo",
340 "parent_id": 1
341 },
342 {
343 "id": 3,
344 "label": "bar",
345 "parent_id": 1
346 },
347 {
348 "id": 4,
349 "label": "baz",
350 "parent_id": 1
351 },
352 ])
353
354 foo_path = os.path.join("root", "foo")
355 bar_path = os.path.join("root", "bar")
356 baz_path = os.path.join("root", "baz")
rosica0ec99e72019-01-03 01:06:47 -0800357
358 expected_error_one = "\n".join([
leba35757972019-02-08 02:03:12 -0800359 "Difference in the action that generates the following output(s):",
leba36c5d3d2020-12-14 07:09:37 -0800360 "\t{}".format(baz_path), "--- before", "+++ after", "@@ -1 +1,2 @@",
361 " -c", "+-d", "\n"
rosica0ec99e72019-01-03 01:06:47 -0800362 ])
363 expected_error_two = "\n".join([
leba35757972019-02-08 02:03:12 -0800364 "Difference in the action that generates the following output(s):",
leba36c5d3d2020-12-14 07:09:37 -0800365 "\t{}".format(bar_path), "\t{}".format(foo_path), "--- before",
366 "+++ after", "@@ -1,2 +1,2 @@", " -a", "--d", "+-b", "\n"
rosica0ec99e72019-01-03 01:06:47 -0800367 ])
leba35757972019-02-08 02:03:12 -0800368 attrs = ["cmdline"]
369
Tony Aiuto9a2d3672022-08-24 00:46:17 -0700370 mock_stdout = io.StringIO()
rosica0ec99e72019-01-03 01:06:47 -0800371 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800372 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
rosica0ec99e72019-01-03 01:06:47 -0800373 self.assertIn(expected_error_one, mock_stdout.getvalue())
374 self.assertIn(expected_error_two, mock_stdout.getvalue())
375
leba35757972019-02-08 02:03:12 -0800376 def test_different_inputs(self):
377 first = make_aquery_output_with_dep_set(
leba36c5d3d2020-12-14 07:09:37 -0800378 action_objs=[{
leba35757972019-02-08 02:03:12 -0800379 "arguments": [],
leba36c5d3d2020-12-14 07:09:37 -0800380 "output_ids": [1, 2],
381 "input_dep_set_ids": [2]
leba35757972019-02-08 02:03:12 -0800382 }],
leba36c5d3d2020-12-14 07:09:37 -0800383 artifact_objs=[{
384 "id": 1,
385 "path_fragment_id": 2
leba35757972019-02-08 02:03:12 -0800386 }, {
leba36c5d3d2020-12-14 07:09:37 -0800387 "id": 2,
388 "path_fragment_id": 3
389 }],
390 path_fragment_objs=[
leba35757972019-02-08 02:03:12 -0800391 {
leba36c5d3d2020-12-14 07:09:37 -0800392 "id": 1,
393 "label": "root"
394 },
395 {
396 "id": 2,
397 "label": "foo",
398 "parent_id": 1
399 },
400 {
401 "id": 3,
402 "label": "bar",
403 "parent_id": 1
leba35757972019-02-08 02:03:12 -0800404 },
405 ],
leba36c5d3d2020-12-14 07:09:37 -0800406 dep_set_objs=[{
407 "id": 1,
leba35757972019-02-08 02:03:12 -0800408 "transitive_dep_set_ids": [],
leba36c5d3d2020-12-14 07:09:37 -0800409 "direct_artifact_ids": [1]
410 }, {
411 "id": 2,
412 "transitive_dep_set_ids": [1],
413 "direct_artifact_ids": [2]
414 }])
415 second = make_aquery_output_with_dep_set(
416 action_objs=[
417 {
418 "arguments": [],
419 "output_ids": [1, 2],
420 "input_dep_set_ids": [1]
421 },
422 ],
423 artifact_objs=[{
424 "id": 1,
425 "path_fragment_id": 2
426 }, {
427 "id": 2,
428 "path_fragment_id": 3
429 }],
430 path_fragment_objs=[
431 {
432 "id": 1,
433 "label": "root"
434 },
435 {
436 "id": 2,
437 "label": "foo",
438 "parent_id": 1
439 },
440 {
441 "id": 3,
442 "label": "bar",
443 "parent_id": 1
444 },
445 ],
446 dep_set_objs=[{
447 "id": 1,
448 "transitive_dep_set_ids": [],
449 "direct_artifact_ids": [1]
leba35757972019-02-08 02:03:12 -0800450 }])
451
leba36c5d3d2020-12-14 07:09:37 -0800452 foo_path = os.path.join("root", "foo")
453 bar_path = os.path.join("root", "bar")
leba35757972019-02-08 02:03:12 -0800454 expected_error_one = "\n".join([
455 "Difference in the action that generates the following output(s):",
leba36c5d3d2020-12-14 07:09:37 -0800456 "\t{}".format(bar_path), "\t{}".format(foo_path), "--- before",
457 "+++ after", "@@ -1,2 +1 @@", "-{}".format(bar_path),
458 " {}".format(foo_path), "\n"
leba35757972019-02-08 02:03:12 -0800459 ])
460 attrs = ["inputs"]
461
Tony Aiuto9a2d3672022-08-24 00:46:17 -0700462 mock_stdout = io.StringIO()
leba35757972019-02-08 02:03:12 -0800463 with mock.patch("sys.stdout", mock_stdout):
464 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
465 self.assertIn(expected_error_one, mock_stdout.getvalue())
466
rosica0ec99e72019-01-03 01:06:47 -0800467
468if __name__ == "__main__":
469 unittest.main()