Skip to content

Commit

Permalink
Add a script for diffing command lines based on bazel aquery outputs
Browse files Browse the repository at this point in the history
Progress towards #5380 and #5883

RELNOTES: None.
PiperOrigin-RevId: 227646729
  • Loading branch information
scentini authored and Copybara-Service committed Jan 3, 2019
1 parent 1e9fc8e commit 0ec99e7
Show file tree
Hide file tree
Showing 8 changed files with 392 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .bazelci/postsubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ platforms:
- "//src/tools/singlejar/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
ubuntu1604:
shell_commands:
- sed -i.bak -e 's/^# android_sdk_repository/android_sdk_repository/' -e 's/^#
Expand All @@ -34,6 +35,7 @@ platforms:
- "//src/tools/singlejar/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
ubuntu1804:
shell_commands:
- sed -i.bak -e 's/^# android_sdk_repository/android_sdk_repository/' -e 's/^#
Expand All @@ -51,6 +53,7 @@ platforms:
- "//src/tools/singlejar/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
ubuntu1804_nojava:
build_flags:
- "--javabase=@openjdk_linux_archive//:runtime"
Expand All @@ -66,6 +69,7 @@ platforms:
- "//src/test/..."
- "//src/tools/singlejar/..."
- "//third_party/ijar/..."
- "//tools/cmd_line_differ/..."
# We can't run Android tests without an installed Android SDK / NDK.
- "-//src/test/java/com/google/devtools/build/android/..."
- "-//src/test/shell/bazel/android/..."
Expand Down Expand Up @@ -123,6 +127,7 @@ platforms:
- "//src/tools/singlejar/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
ubuntu1804_java10:
shell_commands:
- sed -i.bak -e 's/^# android_sdk_repository/android_sdk_repository/' -e 's/^#
Expand All @@ -140,6 +145,7 @@ platforms:
- "//src/tools/singlejar/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
macos:
shell_commands:
- sed -i.bak -e 's/^# android_sdk_repository/android_sdk_repository/' -e 's/^#
Expand All @@ -163,6 +169,7 @@ platforms:
- "//src/tools/singlejar/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
- "-//src/test/shell/integration:minimal_jdk_test"
windows:
batch_commands:
Expand Down
7 changes: 7 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ platforms:
- "//src/tools/workspacelog/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
# Disable Slow Tests
- "-//src/test/shell/bazel:bazel_determinism_test"
# Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/4663
Expand All @@ -42,6 +43,7 @@ platforms:
- "//src/tools/workspacelog/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
# Disable Slow Tests
- "-//src/test/shell/bazel:bazel_determinism_test"
# Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/4663
Expand All @@ -65,6 +67,7 @@ platforms:
- "//src/tools/workspacelog/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
# Disable Slow Tests
- "-//src/test/shell/bazel:bazel_determinism_test"
# Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/4663
Expand All @@ -86,6 +89,7 @@ platforms:
- "//src/tools/singlejar/..."
- "//src/tools/workspacelog/..."
- "//third_party/ijar/..."
- "//tools/cmd_line_differ/..."
# Disable Slow Tests
- "-//src/test/shell/bazel:bazel_determinism_test"
# We can't run Android tests without an installed Android SDK / NDK.
Expand Down Expand Up @@ -147,6 +151,7 @@ platforms:
- "//src/tools/workspacelog/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
# Disable Slow Tests
- "-//src/test/shell/bazel:bazel_determinism_test"
# Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/4663
Expand All @@ -170,6 +175,7 @@ platforms:
- "//src/tools/workspacelog/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
# Disable Slow Tests
- "-//src/test/shell/bazel:bazel_determinism_test"
# Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/4663
Expand Down Expand Up @@ -199,6 +205,7 @@ platforms:
- "//src/tools/workspacelog/..."
- "//third_party/ijar/..."
- "//tools/android/..."
- "//tools/cmd_line_differ/..."
# Re-enable once fixed: https://github.com/bazelbuild/bazel/issues/4663
- "-//src/test/shell/bazel/android:android_ndk_integration_test"
# The below tests have been disabled because they are too slow on macOS.
Expand Down
8 changes: 8 additions & 0 deletions src/main/protobuf/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ proto_library(
deps = [":build_proto"],
)

py_proto_library(
name = "analysis_py_proto",
srcs = ["analysis.proto"],
default_runtime = "//third_party/protobuf:protobuf_python",
protoc = "//third_party/protobuf:protoc",
deps = [":build_pb_py"],
)

java_proto_library(
name = "analysis_java_proto",
deps = [":analysis_proto"],
Expand Down
1 change: 1 addition & 0 deletions src/test/shell/bazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ filegroup(
"//src/test/shell/bazel/apple:srcs",
"//src/test/shell/bazel/remote:srcs",
"//src/test/shell/bazel/testdata:srcs",
"//tools/cmd_line_differ:srcs",
],
visibility = ["//src/test/shell:__pkg__"],
)
Expand Down
1 change: 1 addition & 0 deletions tools/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ test_suite(
"//tools/android:all_windows_tests",
"//tools/bash:all_windows_tests",
"//tools/build_defs:all_windows_tests",
"//tools/cmd_line_differ:cmd_line_differ_test",
"//tools/cpp/runfiles:all_windows_tests",
"//tools/java:all_windows_tests",
"//tools/jdk:all_windows_tests",
Expand Down
41 changes: 41 additions & 0 deletions tools/cmd_line_differ/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 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.

package(default_visibility = ["//visibility:public"])

licenses(["notice"]) # Apache 2.0

filegroup(
name = "srcs",
srcs = glob(["**"]),
)

py_binary(
name = "cmd_line_differ",
srcs = ["cmd_line_differ.py"],
deps = [
"//src/main/protobuf:analysis_py_proto",
"//third_party/py/abseil",
],
)

py_test(
name = "cmd_line_differ_test",
srcs = ["cmd_line_differ_test.py"],
deps = [
":cmd_line_differ",
"//src/main/protobuf:analysis_py_proto",
"//third_party/py/mock",
],
)
132 changes: 132 additions & 0 deletions tools/cmd_line_differ/cmd_line_differ.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# 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.
r"""Command line diffing tool that compares two bazel aquery invocations.
This script compares the proto output of two bazel aquery invocations. For
each set of output files of an action, it compares the command lines that
generated the files.
Example usage:
bazel aquery //path/to:target_one --output=textproto > \
/path/to/output_one.textproto
bazel aquery //path/to:target_two --output=textproto > \
/path/to/output_two.textproto
From a bazel repo:
bazel run //tools/cmd_line_differ:cmd_line_differ -- \
--before=/path/to/output_one.textproto \
--after=/path/to/output_two.textproto
--input_type=textproto
"""

from absl import app
from absl import flags
from google.protobuf import text_format
from src.main.protobuf import analysis_pb2

flags.DEFINE_string("before", None, "Aquery output before the change")
flags.DEFINE_string("after", None, "Aquery output after the change")
flags.DEFINE_enum(
"input_type", "proto", ["proto", "textproto"],
"The format of the aquery proto input. One of 'proto' and 'textproto.")
flags.mark_flag_as_required("before")
flags.mark_flag_as_required("after")


def _map_artifact_id_to_path(artifacts):
return {artifact.id: artifact.exec_path for artifact in artifacts}


def _map_output_files_to_command_line(actions, artifacts):
output_files_to_command_line = {}
for action in actions:
output_files = " ".join(
sorted([artifacts[output_id] for output_id in action.output_ids]))
output_files_to_command_line[output_files] = action.arguments
return output_files_to_command_line


def _aquery_diff(before, after):
"""Returns differences between command lines that generate same outputs."""
# TODO(bazel-team): Currently we compare only command lines of actions that
# generate the same output files. Expand the differ to compare other values as
# well (e.g. mnemonic, inputs, execution tags...).

found_difference = False
artifacts_before = _map_artifact_id_to_path(before.artifacts)
artifacts_after = _map_artifact_id_to_path(after.artifacts)

output_to_command_line_before = _map_output_files_to_command_line(
before.actions, artifacts_before)
output_to_command_line_after = _map_output_files_to_command_line(
after.actions, artifacts_after)

output_files_before = set(output_to_command_line_before.keys())
output_files_after = set(output_to_command_line_after.keys())

before_after_diff = output_files_before - output_files_after
after_before_diff = output_files_after - output_files_before

if before_after_diff:
print(("Aquery output before change contains an action that generates "
"the following outputs that aquery output after change doesn't:"
"\n%s\n") % "\n".join(before_after_diff))
found_difference = True
if after_before_diff:
print(("Aquery output after change contains an action that generates "
"the following outputs that aquery output before change doesn't:"
"\n%s\n") % "\n".join(after_before_diff))
found_difference = True

for output_files in output_to_command_line_before:
arguments = output_to_command_line_before[output_files]
after_arguments = output_to_command_line_after.get(output_files, None)
if after_arguments and arguments != after_arguments:
print(("Difference in action that generates the following outputs:\n%s\n"
"Aquery output before change has the following command line:\n%s\n"
"Aquery output after change has the following command line:\n%s\n")
% ("\n".join(output_files.split()), "\n".join(arguments),
"\n".join(after_arguments)))
found_difference = True

if not found_difference:
print("No difference")


def main(unused_argv):

before_file = flags.FLAGS.before
after_file = flags.FLAGS.after
input_type = flags.FLAGS.input_type

before_proto = analysis_pb2.ActionGraphContainer()
after_proto = analysis_pb2.ActionGraphContainer()
if input_type == "proto":
with open(before_file, "rb") as f:
before_proto.ParseFromString(f.read())
with open(after_file, "rb") as f:
after_proto.ParseFromString(f.read())
else:
with open(before_file, "r") as f:
before_text = f.read()
text_format.Merge(before_text, before_proto)
with open(after_file, "r") as f:
after_text = f.read()
text_format.Merge(after_text, after_proto)

_aquery_diff(before_proto, after_proto)


if __name__ == "__main__":
app.run(main)
Loading

0 comments on commit 0ec99e7

Please sign in to comment.