blob: 3866afa2cba70ed84217091d9268eee40a0f9c00 [file] [log] [blame] [edit]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import difflib
import json
import pathlib
import sys
import subprocess
from depfile import DepFile
def clean_cml(cml_json):
for key in cml_json:
if isinstance(cml_json[key], list):
cml_json[key].sort(key=lambda x: json.dumps(x, sort_keys=True))
def diff(json1, json2, file1_name, file2_name):
file1_lines = json.dumps(json1, sort_keys=True, indent=2).splitlines()
file2_lines = json.dumps(json2, sort_keys=True, indent=2).splitlines()
return difflib.unified_diff(
file1_lines,
file2_lines,
fromfile=file1_name,
tofile=file2_name,
lineterm="",
)
def get_config_values(configc_bin, cvf, component):
command = [
configc_bin,
"dump-values",
"--cvf",
str(cvf),
"--cm",
component,
]
output = subprocess.run(command, capture_output=True)
stdout, stderr = (
output.stdout.decode("UTF-8"), output.stderr.decode("UTF-8"))
if (stderr):
raise ValueError(f"Error running configc: {command}\n{stderr}")
return stdout
def main():
parser = argparse.ArgumentParser(
description='Compare two fshost packages, one generated by GN and another'
'by Assembly, and assert they are the same')
parser.add_argument('--configc-bin', type=pathlib.Path, required=True)
parser.add_argument(
'--gn-fshost-component', type=pathlib.Path, required=True)
parser.add_argument(
'--assembly-fshost-component', type=pathlib.Path, required=True)
parser.add_argument(
'--gn-fshost-cml', type=argparse.FileType('r'), required=True)
parser.add_argument(
'--assembly-fshost-cml', type=argparse.FileType('r'), required=True)
parser.add_argument('--gn-fshost-cvf', type=pathlib.Path, required=True)
parser.add_argument(
'--assembly-fshost-cvf', type=pathlib.Path, required=True)
parser.add_argument(
"--output",
type=argparse.FileType('w'),
help="A file to write output to.")
parser.add_argument(
"--depfile",
type=argparse.FileType('w'),
help="A depfile of read files, this requires the use of --output")
output = []
def error(string: str):
"""output an error string"""
print(string, file=sys.stderr)
if args.output:
output.append(string)
args = parser.parse_args()
difflines = []
difflines += diff(
clean_cml(json.load(args.gn_fshost_cml)),
clean_cml(json.load(args.assembly_fshost_cml)), args.gn_fshost_cml.name,
args.assembly_fshost_cml.name)
gn_fshost_config_values = get_config_values(
args.configc_bin, args.gn_fshost_cvf, args.gn_fshost_component)
assembly_fshost_config_values = get_config_values(
args.configc_bin, args.assembly_fshost_cvf,
args.assembly_fshost_component)
difflines += diff(
gn_fshost_config_values, assembly_fshost_config_values,
"gn_structured_config", "assembly_structured_config")
output += difflines
diffstr = "\n".join(difflines)
if args.depfile:
if args.output:
depfile = DepFile(args.output.name)
depfile.update(
[
args.gn_fshost_cml.name, args.assembly_fshost_cml.name,
args.gn_fshost_component, args.assembly_fshost_component,
args.gn_fshost_cvf, args.assembly_fshost_cvf,
args.configc_bin
])
depfile.write_to(args.depfile)
else:
error("Cannot create a depfile without an output file")
return -2
if args.output:
for line in difflines:
print(line, file=args.output)
if len(diffstr) != 0:
print(
"Error: non-empty diff between canonical json"
f" representations:\n{diffstr}")
return 1
return 0
if __name__ == '__main__':
sys.exit(main())