Files
revng-revng/scripts/compare-json.py
T
Alessandro Di Federico 7fe00c08dd Rewrite the stack and introduce the ABI analyses
This is a very large commit importing the reviewed (and heavily
simplified) stack analysis and the new ABI analysis, which provides
information on the calling convention of each function and so on.

For an overview of the new analyses please consult OVERVIEW.md.
2018-09-18 15:58:20 +02:00

131 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python
# This script compares two JSON files. In general, the reference JSON file is
# supposed to be included in the other one. For instance, {"a": 1, "b": 2}
# contains {"b": 2}. This is useful for enforcing the content of certain parts
# of a JSON file, in particular during testing.
#
# This script works and should keep working on Python 2.7 and Python 3.
import argparse
import json
import sys
def do_log(indent, message, *args):
message = message.replace("\n", "\n" + " " * indent)
sys.stderr.write((" " * indent) + message.format(*args) + "\n")
def to_json(obj):
return json.dumps(obj)
def compare(reference, input, order, exact, verbose, quiet, indent):
def log(message, *args):
if not quiet or verbose:
do_log(indent, message, *args)
def vlog(message, *args):
if verbose:
log(message, *args)
recurse = lambda new_reference, new_input, force_quiet: compare(new_reference,
new_input,
order,
exact,
verbose,
force_quiet,
indent + 1)
vlog("Comparing:\n {}\n {}", to_json(reference), to_json(input))
if type(reference) is not type(input):
log("Different types met:\n {}\n {}",
to_json(type(reference)),
to_json(type(input)))
return False
elif not exact and type(reference) is dict:
for key, value in reference.items():
if key not in input:
log("Couldn't find the following key in a dictionary: {}",
to_json(key))
return False
else:
if not recurse(value, input[key], quiet):
return False
vlog("Found!")
return True
elif not exact and type(reference) is list:
if order:
start = 0
for reference_index, reference_item in enumerate(reference):
found = False
for input_index, input_item in enumerate(input[start:]):
if recurse(reference_item, input_item, True):
found = True
start = start + input_index + 1
break
if not found:
log("Couldn't find element {} of a list in order:\n {}",
reference_index,
to_json(reference_item))
return False
vlog("Found!")
return True
else:
for reference_index, reference_item in enumerate(reference):
found = False
for input_item in input:
if recurse(reference_item, input_item, True):
found = True
break
if not found:
log("Couldn't find element {} of a list:\n {}",
reference_index,
to_json(reference_item))
return False
vlog("Found!")
return True
else:
if reference != input:
log("Difference:\n {}\n {}", to_json(reference), to_json(input))
return False
vlog("Found!")
return True
def main():
parser = argparse.ArgumentParser(description='Compare a JSON file against a \
reference.')
parser.add_argument('reference',
metavar='REFERENCE',
help='The reference file.')
parser.add_argument('input', metavar='INPUT',
default="/dev/stdin",
help='The input file.')
parser.add_argument('--exact',
action='store_true',
help=("Match exactly, containing the reference is not "
+ "enough."))
parser.add_argument('--order',
action='store_true',
help="The order of elements of a list matters.")
parser.add_argument('--verbose',
action='store_true',
help="Print each element being compared.")
args = parser.parse_args()
with open(args.reference) as reference_file, open(args.input) as input_file:
reference = json.load(reference_file)
input = json.load(input_file)
result = compare(reference,
input,
args.order,
args.exact,
args.verbose,
False,
0)
return 0 if result else 1
if __name__ == "__main__":
sys.exit(main())