blob: 415dfdef1d950b5913ef2fd40e0960a88f204e50 [file] [log] [blame]
#!/usr/bin/env python3.8
# Copyright 2020 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 json
from pathlib import Path
import os
import signal
import shutil
import sys
import generate_test
import generate_docs
from reverse_test import reverse_test
from util import print_err, TEST_FILE, white, find_tests, print_warning
from types_ import CompatTest
def signal_handler(sig, frame):
print('\nGoodbye')
sys.exit(0)
def gen_test(args):
# Users are expected to exit the tool with ^C, so print a message instead of
# dumping a stacktrace.
signal.signal(signal.SIGINT, signal_handler)
test_dir = Path(os.path.join(args.root, args.name))
os.makedirs(test_dir, exist_ok=True)
test_file = test_dir / TEST_FILE
if test_file.exists():
# This resumes from the latest point. If you'd like to edit existing
# steps, this must be done manually.
with open(test_file, 'r') as f:
test = CompatTest.fromdict(json.load(f))
state = generate_test.TransitionState.from_test(test)
generate_test.run(test_dir, state)
else:
generate_test.run(test_dir, None)
def gen_reverse(args):
src_dir = Path(os.path.join(args.root, args.source))
with open(src_dir / TEST_FILE, 'r') as f:
src_test = CompatTest.fromdict(json.load(f))
new_test, old_to_new_files = reverse_test(src_test)
target_dir = Path(os.path.join(args.root, args.target))
os.makedirs(target_dir, exist_ok=True)
for old, new in old_to_new_files.items():
old = src_dir / old
new = target_dir / new
os.makedirs(new.parent, exist_ok=True)
shutil.copyfile(old, new)
new_test.save(target_dir / TEST_FILE)
generate_test.regen_files(target_dir, new_test)
def regen(args):
tests = args.tests or find_tests(args.root)
for name in tests:
print(f'Regenerating files for {name}')
test_dir = Path(os.path.join(args.root, name))
with open(test_dir / TEST_FILE, 'r') as f:
test = CompatTest.fromdict(json.load(f))
generate_test.regen_files(test_dir, test)
if not tests:
print_warning('No tests found')
else:
print(
white('Done! Run fx-format to get rid of formatting differences.'))
def regen_toc(args):
all_tests = []
for test_root in find_tests(args.root):
with open(test_root / TEST_FILE, 'r') as f:
test = CompatTest.fromdict(json.load(f))
all_tests.append((test_root, test))
if not all_tests:
print_warning('No tests found')
generate_docs.regen_toc(all_tests)
parser = argparse.ArgumentParser(
description="Generate FIDL source compatibility test scaffolding",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='For full usage details, refer to the tool README.')
parser.add_argument(
'--root',
help=
'Directory that all other paths should be relative to. Useful for testing. Defaults to %(default)s)',
default=os.path.join(
os.environ['FUCHSIA_DIR'], 'src/tests/fidl/source_compatibility'),
)
subparsers = parser.add_subparsers()
gen_test_parser = subparsers.add_parser(
"generate_test", help="Generate a source compatibility test")
gen_test_parser.set_defaults(func=gen_test)
gen_test_parser.add_argument(
'name',
help=
'The test name. Ideally, this should match [parent]-[target]-[change] format specificied in the ABI/API compatibility guide, e.g. protocol-method-add'
)
regen_parser = subparsers.add_parser(
'regen',
help=
"Regenerates the GN sidecar, docs, and BUILD file based on the test's JSON file. Useful when making manual edits."
)
regen_parser.set_defaults(func=regen)
regen_parser.add_argument(
'tests',
nargs='*',
help=
'Tests to regen (i.e. their paths relative to the --root, like "protocol-method-add"). Tries to regen all tests in the --root directory if none are provided'
)
gen_reverse_parser = subparsers.add_parser(
"generate_reverse",
help=
"Generate a source compatibility test that runs an existing one in reverse. See tool README for details."
)
gen_reverse_parser.set_defaults(func=gen_reverse)
gen_reverse_parser.add_argument('source', help='Name of the test to reverse.')
gen_reverse_parser.add_argument(
'target', help='Name of the (new) reversed test.')
regen_toc_parser = subparsers.add_parser(
'regen_toc',
help=
'Regenerate the docs compatibility guide TOC, e.g. when you add/remove a test case.'
)
regen_toc_parser.set_defaults(func=regen_toc)
if __name__ == '__main__':
args = parser.parse_args()
try:
func = args.func
except AttributeError:
parser.print_help(sys.stderr)
sys.exit(1)
func(args)