blob: e98901d6801ca4e0d08bd220c4f9a48c91aff35f [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
leba36c5d3d2020-12-14 07:09:37 -080016import os
rosica0ec99e72019-01-03 01:06:47 -080017import unittest
laszlocsomora6545052019-11-05 05:18:32 -080018# Do not edit this line. Copybara replaces it with PY2 migration helper.
19from third_party.py import mock
20import six
leba36c5d3d2020-12-14 07:09:37 -080021from src.main.protobuf import analysis_v2_pb2
22from tools.aquery_differ import aquery_differ
23
24# pylint: disable=g-import-not-at-top
laszlocsomora6545052019-11-05 05:18:32 -080025if six.PY2:
26 from cStringIO import StringIO
27else:
28 from io import StringIO
leba36c5d3d2020-12-14 07:09:37 -080029# pylint: enable=g-import-not-at-top
rosica0ec99e72019-01-03 01:06:47 -080030
31
leba36c5d3d2020-12-14 07:09:37 -080032def make_aquery_output(action_objs, artifact_objs, path_fragment_objs):
33 action_graph = analysis_v2_pb2.ActionGraphContainer()
leba35757972019-02-08 02:03:12 -080034
leba36c5d3d2020-12-14 07:09:37 -080035 for path_fragment_obj in path_fragment_objs:
36 path_fragment = action_graph.path_fragments.add()
37 path_fragment.id = path_fragment_obj["id"]
38 path_fragment.label = path_fragment_obj["label"]
39 if "parent_id" in path_fragment_obj:
40 path_fragment.parent_id = path_fragment_obj["parent_id"]
41
42 for artifact_obj in artifact_objs:
rosica0ec99e72019-01-03 01:06:47 -080043 artifact = action_graph.artifacts.add()
leba36c5d3d2020-12-14 07:09:37 -080044 artifact.id = artifact_obj["id"]
45 artifact.path_fragment_id = artifact_obj["path_fragment_id"]
leba35757972019-02-08 02:03:12 -080046
leba36c5d3d2020-12-14 07:09:37 -080047 for action_obj in action_objs:
rosica0ec99e72019-01-03 01:06:47 -080048 action = action_graph.actions.add()
leba36c5d3d2020-12-14 07:09:37 -080049 action.output_ids.extend(action_obj["output_ids"])
50 action.arguments.extend(action_obj["arguments"])
leba35757972019-02-08 02:03:12 -080051
leba36c5d3d2020-12-14 07:09:37 -080052 if "input_dep_set_ids" in action_obj:
53 action.input_dep_set_ids.extend(action_obj["input_dep_set_ids"])
leba35757972019-02-08 02:03:12 -080054
55 return action_graph
56
57
leba36c5d3d2020-12-14 07:09:37 -080058def make_aquery_output_with_dep_set(action_objs, artifact_objs,
59 path_fragment_objs, dep_set_objs):
60 action_graph = make_aquery_output(action_objs, artifact_objs,
61 path_fragment_objs)
leba35757972019-02-08 02:03:12 -080062
leba36c5d3d2020-12-14 07:09:37 -080063 for ds in dep_set_objs:
leba35757972019-02-08 02:03:12 -080064 dep_set = action_graph.dep_set_of_files.add()
leba36c5d3d2020-12-14 07:09:37 -080065 dep_set.id = ds["id"]
leba35757972019-02-08 02:03:12 -080066 dep_set.direct_artifact_ids.extend(ds["direct_artifact_ids"])
67 dep_set.transitive_dep_set_ids.extend(ds["transitive_dep_set_ids"])
68
rosica0ec99e72019-01-03 01:06:47 -080069 return action_graph
70
71
72class CmdLineDifferTest(unittest.TestCase):
73
74 def test_no_difference(self):
75 action_graph = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -080076 action_objs=[
77 {
78 "arguments": ["-a", "-b"],
79 "output_ids": [1, 2]
80 },
81 {
82 "arguments": ["-c"],
83 "output_ids": [3]
84 },
85 ],
86 artifact_objs=[{
87 "id": 1,
88 "path_fragment_id": 2
rosica0ec99e72019-01-03 01:06:47 -080089 }, {
leba36c5d3d2020-12-14 07:09:37 -080090 "id": 2,
91 "path_fragment_id": 3
92 }, {
93 "id": 3,
94 "path_fragment_id": 4
rosica0ec99e72019-01-03 01:06:47 -080095 }],
leba36c5d3d2020-12-14 07:09:37 -080096 path_fragment_objs=[
97 {
98 "id": 1,
99 "label": "root"
100 },
101 {
102 "id": 2,
103 "label": "foo",
104 "parent_id": 1
105 },
106 {
107 "id": 3,
108 "label": "bar",
109 "parent_id": 1
110 },
111 {
112 "id": 4,
113 "label": "baz",
114 "parent_id": 1
115 },
116 ])
rosica0ec99e72019-01-03 01:06:47 -0800117 mock_stdout = StringIO()
leba35757972019-02-08 02:03:12 -0800118 attrs = ["cmdline"]
rosica0ec99e72019-01-03 01:06:47 -0800119 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800120 aquery_differ._aquery_diff(action_graph, action_graph, attrs, "before",
121 "after")
rosica0ec99e72019-01-03 01:06:47 -0800122 self.assertEqual(mock_stdout.getvalue(), "No difference\n")
123
124 def test_no_difference_different_output_files_order(self):
125 first = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800126 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800127 {
128 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800129 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800130 },
131 ],
leba36c5d3d2020-12-14 07:09:37 -0800132 artifact_objs=[{
133 "id": 1,
134 "path_fragment_id": 2
135 }, {
136 "id": 2,
137 "path_fragment_id": 3
138 }],
139 path_fragment_objs=[
140 {
141 "id": 1,
142 "label": "root"
143 },
144 {
145 "id": 2,
146 "label": "foo",
147 "parent_id": 1
148 },
149 {
150 "id": 3,
151 "label": "bar",
152 "parent_id": 1
153 },
154 ])
155
rosica0ec99e72019-01-03 01:06:47 -0800156 second = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800157 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800158 {
159 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800160 "output_ids": [2, 1]
rosica0ec99e72019-01-03 01:06:47 -0800161 },
162 ],
leba36c5d3d2020-12-14 07:09:37 -0800163 artifact_objs=[{
164 "id": 1,
165 "path_fragment_id": 2
166 }, {
167 "id": 2,
168 "path_fragment_id": 3
169 }],
170 path_fragment_objs=[
171 {
172 "id": 1,
173 "label": "root"
174 },
175 {
176 "id": 2,
177 "label": "foo",
178 "parent_id": 1
179 },
180 {
181 "id": 3,
182 "label": "bar",
183 "parent_id": 1
184 },
185 ])
rosica0ec99e72019-01-03 01:06:47 -0800186
187 mock_stdout = StringIO()
leba35757972019-02-08 02:03:12 -0800188 attrs = ["cmdline"]
rosica0ec99e72019-01-03 01:06:47 -0800189 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800190 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
rosica0ec99e72019-01-03 01:06:47 -0800191 self.assertEqual(mock_stdout.getvalue(), "No difference\n")
192
193 def test_first_has_extra_output_files(self):
194 first = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800195 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800196 {
197 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800198 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800199 },
200 {
201 "arguments": ["-c"],
leba36c5d3d2020-12-14 07:09:37 -0800202 "output_ids": [3]
rosica0ec99e72019-01-03 01:06:47 -0800203 },
204 ],
leba36c5d3d2020-12-14 07:09:37 -0800205 artifact_objs=[{
206 "id": 1,
207 "path_fragment_id": 2
208 }, {
209 "id": 2,
210 "path_fragment_id": 3
211 }, {
212 "id": 3,
213 "path_fragment_id": 4
214 }],
215 path_fragment_objs=[
216 {
217 "id": 1,
218 "label": "root"
219 },
220 {
221 "id": 2,
222 "label": "foo",
223 "parent_id": 1
224 },
225 {
226 "id": 3,
227 "label": "bar",
228 "parent_id": 1
229 },
230 {
231 "id": 4,
232 "label": "baz",
233 "parent_id": 1
234 },
235 ])
rosica0ec99e72019-01-03 01:06:47 -0800236 second = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800237 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800238 {
239 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800240 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800241 },
242 ],
leba36c5d3d2020-12-14 07:09:37 -0800243 artifact_objs=[{
244 "id": 1,
245 "path_fragment_id": 2
246 }, {
247 "id": 2,
248 "path_fragment_id": 3
249 }],
250 path_fragment_objs=[{
251 "id": 1,
252 "label": "root"
253 }, {
254 "id": 2,
255 "label": "foo",
256 "parent_id": 1
257 }, {
258 "id": 3,
259 "label": "bar",
260 "parent_id": 1
261 }])
rosica0ec99e72019-01-03 01:06:47 -0800262
leba36c5d3d2020-12-14 07:09:37 -0800263 baz_path = os.path.join("root", "baz")
leba35757972019-02-08 02:03:12 -0800264 expected_error = ("Aquery output 'before' change contains an action "
rosica0ec99e72019-01-03 01:06:47 -0800265 "that generates the following outputs that aquery "
leba36c5d3d2020-12-14 07:09:37 -0800266 "output 'after' change doesn't:\n{}\n\n".format(baz_path))
rosica0ec99e72019-01-03 01:06:47 -0800267 mock_stdout = StringIO()
leba35757972019-02-08 02:03:12 -0800268 attrs = ["cmdline"]
rosica0ec99e72019-01-03 01:06:47 -0800269 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800270 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
rosica0ec99e72019-01-03 01:06:47 -0800271 self.assertEqual(mock_stdout.getvalue(), expected_error)
272
273 def test_different_command_lines(self):
274 first = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800275 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800276 {
277 "arguments": ["-a", "-d"],
leba36c5d3d2020-12-14 07:09:37 -0800278 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800279 },
280 {
281 "arguments": ["-c"],
leba36c5d3d2020-12-14 07:09:37 -0800282 "output_ids": [3]
rosica0ec99e72019-01-03 01:06:47 -0800283 },
284 ],
leba36c5d3d2020-12-14 07:09:37 -0800285 artifact_objs=[{
286 "id": 1,
287 "path_fragment_id": 2
288 }, {
289 "id": 2,
290 "path_fragment_id": 3
291 }, {
292 "id": 3,
293 "path_fragment_id": 4
294 }],
295 path_fragment_objs=[
296 {
297 "id": 1,
298 "label": "root"
299 },
300 {
301 "id": 2,
302 "label": "foo",
303 "parent_id": 1
304 },
305 {
306 "id": 3,
307 "label": "bar",
308 "parent_id": 1
309 },
310 {
311 "id": 4,
312 "label": "baz",
313 "parent_id": 1
314 },
315 ])
rosica0ec99e72019-01-03 01:06:47 -0800316 second = make_aquery_output(
leba36c5d3d2020-12-14 07:09:37 -0800317 action_objs=[
rosica0ec99e72019-01-03 01:06:47 -0800318 {
319 "arguments": ["-a", "-b"],
leba36c5d3d2020-12-14 07:09:37 -0800320 "output_ids": [1, 2]
rosica0ec99e72019-01-03 01:06:47 -0800321 },
322 {
323 "arguments": ["-c", "-d"],
leba36c5d3d2020-12-14 07:09:37 -0800324 "output_ids": [3]
rosica0ec99e72019-01-03 01:06:47 -0800325 },
326 ],
leba36c5d3d2020-12-14 07:09:37 -0800327 artifact_objs=[{
328 "id": 1,
329 "path_fragment_id": 2
330 }, {
331 "id": 2,
332 "path_fragment_id": 3
333 }, {
334 "id": 3,
335 "path_fragment_id": 4
336 }],
337 path_fragment_objs=[
338 {
339 "id": 1,
340 "label": "root"
341 },
342 {
343 "id": 2,
344 "label": "foo",
345 "parent_id": 1
346 },
347 {
348 "id": 3,
349 "label": "bar",
350 "parent_id": 1
351 },
352 {
353 "id": 4,
354 "label": "baz",
355 "parent_id": 1
356 },
357 ])
358
359 foo_path = os.path.join("root", "foo")
360 bar_path = os.path.join("root", "bar")
361 baz_path = os.path.join("root", "baz")
rosica0ec99e72019-01-03 01:06:47 -0800362
363 expected_error_one = "\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(baz_path), "--- before", "+++ after", "@@ -1 +1,2 @@",
366 " -c", "+-d", "\n"
rosica0ec99e72019-01-03 01:06:47 -0800367 ])
368 expected_error_two = "\n".join([
leba35757972019-02-08 02:03:12 -0800369 "Difference in the action that generates the following output(s):",
leba36c5d3d2020-12-14 07:09:37 -0800370 "\t{}".format(bar_path), "\t{}".format(foo_path), "--- before",
371 "+++ after", "@@ -1,2 +1,2 @@", " -a", "--d", "+-b", "\n"
rosica0ec99e72019-01-03 01:06:47 -0800372 ])
leba35757972019-02-08 02:03:12 -0800373 attrs = ["cmdline"]
374
rosica0ec99e72019-01-03 01:06:47 -0800375 mock_stdout = StringIO()
376 with mock.patch("sys.stdout", mock_stdout):
leba35757972019-02-08 02:03:12 -0800377 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
rosica0ec99e72019-01-03 01:06:47 -0800378 self.assertIn(expected_error_one, mock_stdout.getvalue())
379 self.assertIn(expected_error_two, mock_stdout.getvalue())
380
leba35757972019-02-08 02:03:12 -0800381 def test_different_inputs(self):
382 first = make_aquery_output_with_dep_set(
leba36c5d3d2020-12-14 07:09:37 -0800383 action_objs=[{
leba35757972019-02-08 02:03:12 -0800384 "arguments": [],
leba36c5d3d2020-12-14 07:09:37 -0800385 "output_ids": [1, 2],
386 "input_dep_set_ids": [2]
leba35757972019-02-08 02:03:12 -0800387 }],
leba36c5d3d2020-12-14 07:09:37 -0800388 artifact_objs=[{
389 "id": 1,
390 "path_fragment_id": 2
leba35757972019-02-08 02:03:12 -0800391 }, {
leba36c5d3d2020-12-14 07:09:37 -0800392 "id": 2,
393 "path_fragment_id": 3
394 }],
395 path_fragment_objs=[
leba35757972019-02-08 02:03:12 -0800396 {
leba36c5d3d2020-12-14 07:09:37 -0800397 "id": 1,
398 "label": "root"
399 },
400 {
401 "id": 2,
402 "label": "foo",
403 "parent_id": 1
404 },
405 {
406 "id": 3,
407 "label": "bar",
408 "parent_id": 1
leba35757972019-02-08 02:03:12 -0800409 },
410 ],
leba36c5d3d2020-12-14 07:09:37 -0800411 dep_set_objs=[{
412 "id": 1,
leba35757972019-02-08 02:03:12 -0800413 "transitive_dep_set_ids": [],
leba36c5d3d2020-12-14 07:09:37 -0800414 "direct_artifact_ids": [1]
415 }, {
416 "id": 2,
417 "transitive_dep_set_ids": [1],
418 "direct_artifact_ids": [2]
419 }])
420 second = make_aquery_output_with_dep_set(
421 action_objs=[
422 {
423 "arguments": [],
424 "output_ids": [1, 2],
425 "input_dep_set_ids": [1]
426 },
427 ],
428 artifact_objs=[{
429 "id": 1,
430 "path_fragment_id": 2
431 }, {
432 "id": 2,
433 "path_fragment_id": 3
434 }],
435 path_fragment_objs=[
436 {
437 "id": 1,
438 "label": "root"
439 },
440 {
441 "id": 2,
442 "label": "foo",
443 "parent_id": 1
444 },
445 {
446 "id": 3,
447 "label": "bar",
448 "parent_id": 1
449 },
450 ],
451 dep_set_objs=[{
452 "id": 1,
453 "transitive_dep_set_ids": [],
454 "direct_artifact_ids": [1]
leba35757972019-02-08 02:03:12 -0800455 }])
456
leba36c5d3d2020-12-14 07:09:37 -0800457 foo_path = os.path.join("root", "foo")
458 bar_path = os.path.join("root", "bar")
leba35757972019-02-08 02:03:12 -0800459 expected_error_one = "\n".join([
460 "Difference in the action that generates the following output(s):",
leba36c5d3d2020-12-14 07:09:37 -0800461 "\t{}".format(bar_path), "\t{}".format(foo_path), "--- before",
462 "+++ after", "@@ -1,2 +1 @@", "-{}".format(bar_path),
463 " {}".format(foo_path), "\n"
leba35757972019-02-08 02:03:12 -0800464 ])
465 attrs = ["inputs"]
466
467 mock_stdout = StringIO()
468 with mock.patch("sys.stdout", mock_stdout):
469 aquery_differ._aquery_diff(first, second, attrs, "before", "after")
470 self.assertIn(expected_error_one, mock_stdout.getvalue())
471
rosica0ec99e72019-01-03 01:06:47 -0800472
473if __name__ == "__main__":
474 unittest.main()