blob: 2b040ba1dd6d241d4216b5483a4419e9322b4fa1 [file] [log] [blame]
#!/usr/bin/env python3.8
# Copyright 2021 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.
"""
Compares previous output of all kazoo generation with current output.
The current golden state (vs. real syscalls) is saved in golden.txt.
A `cp` command will be printed to update golden.txt if the current
pipeline generates different output than previously checked in.
"""
import argparse
import datetime
import os
import shutil
import subprocess
import sys
SCRIPT_DIR = os.path.dirname(__file__)
GOLDEN = os.path.join(os.path.dirname(__file__), 'golden.txt')
def parse_args():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
'--fidlc', help='rspfile containing fidlc binary', required=True)
parser.add_argument(
'--kazoo', help='rspfile containing kazoo binary', required=True)
parser.add_argument(
'--syscalls',
help='path to syscalls',
default=os.path.normpath(
os.path.join(SCRIPT_DIR, os.pardir, os.pardir, 'vdso')))
parser.add_argument(
'--p4merge',
action='store_true',
help='open diffs in p4merge if changes')
parser.add_argument(
'--output-touch', help='file to touch on success', required=True)
parser.add_argument(
'--tmp-base', help='location to use for temporary files', required=True)
parser.add_argument(
'--new-golden',
help='path to output the new golden file',
required=True)
parser.add_argument(
'--depfile',
help='The path to write a depfile, see depfile from GN.',
required=True)
return parser.parse_args()
def generate_fidlc_json(fidlc_binary, syscall_dir, output_fidlc_json_path):
fidl_files = []
with os.scandir(syscall_dir) as it:
for entry in it:
if (not entry.name.startswith('.') and entry.is_file() and
entry.name.endswith('.fidl')):
fidl_files.append(os.path.join(syscall_dir, entry.name))
subprocess.check_call(
[
fidlc_binary, '--experimental', 'new_syntax_only', '--json',
output_fidlc_json_path, '--files'
] + sorted(fidl_files))
def build_golden(input_files, output_combined):
with open(output_combined, 'wb') as outf:
for filename in input_files:
outf.write(
('----- %s START -----\n' %
os.path.basename(filename)).encode('utf-8'))
outf.write(open(filename, 'rb').read())
outf.write(
('----- %s END -----\n\n\n' %
os.path.basename(filename)).encode('utf-8'))
def generate_kazoo_outputs(
kazoo_binary, fidlc_json_path, all_output_styles, output_dir):
def guess_ext(style):
if style in ('go-vdso-arm64-calls', 'go-vdso-x86-calls'):
return 's'
if style.startswith('go'):
return 'go'
if style == 'rust':
return 'rs'
if style == 'json':
return 'json'
return 'h'
style_args = []
files = []
for style in all_output_styles:
filename = '%s.%s' % (os.path.join(output_dir, style), guess_ext(style))
files.append(filename)
style_args.append('--%s=%s' % (style, filename))
subprocess.check_call([kazoo_binary] + style_args + [fidlc_json_path])
return files
def read_rsp(path):
with open(path, 'r') as f:
return f.read().strip()
def main():
args = parse_args()
tmp_json = os.path.join(args.tmp_base, 'syscalls.json')
fidlc = read_rsp(args.fidlc)
generate_fidlc_json(fidlc, args.syscalls, tmp_json)
tmp_kazoo_dir = os.path.join(args.tmp_base, 'kazoo-outputs')
try:
shutil.rmtree(tmp_kazoo_dir)
except:
pass
os.makedirs(tmp_kazoo_dir)
all_styles = (
'c-ulib-header',
'category',
'next-public-header',
'go-syscall-arm64-asm',
'go-syscall-stubs',
'go-syscall-x86-asm',
'go-vdso-arm64-calls',
'go-vdso-keys',
'go-vdso-x86-calls',
'json',
'kernel-header',
'kernel-wrappers',
'private-header',
'public-header',
'rust',
'syscall-numbers',
'testonly-public-header',
)
kazoo = read_rsp(args.kazoo)
files = generate_kazoo_outputs(kazoo, tmp_json, all_styles, tmp_kazoo_dir)
build_golden(files, args.new_golden)
result = subprocess.run(['diff', '-u', GOLDEN, args.new_golden], stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
if result.returncode != 0:
print('CHANGES DETECTED IN SYSCALL OUTPUT')
print()
print('Please run:')
print(
' cp "$(fx get-build-dir)/%s" "$(fx get-build-dir)/%s"' %
(args.new_golden, GOLDEN))
print('to acknowledge these changes.')
print()
print(
'Files can be found locally in %s for inspection.' % tmp_kazoo_dir)
if args.p4merge:
subprocess.call(['p4merge', GOLDEN, args.new_golden])
# Print the diff after the instructions so the instructions are not truncated by the
# buildbot if the output is long.
print('Diff:')
# Need to decode the stdout binary data to a string to write newlines properly.
print(result.stdout.decode('ascii'));
else:
with open(args.output_touch, 'w') as f:
f.write(str(datetime.datetime.utcnow()))
with open(args.depfile, 'w') as f:
f.write(f'{args.output_touch} {args.new_golden}: {fidlc} {kazoo}\n')
shutil.rmtree(tmp_kazoo_dir)
return result.returncode
if __name__ == '__main__':
sys.exit(main())