blob: 101e5eae17bae977aa32ef17c6ba5715bbfb1ffe [file] [log] [blame]
#!/usr/bin/env python3
# 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
from pathlib import Path
import pprint
import os
from typing import Dict, List
import sys
import errors
from gen import generate_test
import scaffolding
from transitions import transitions, Binding, Transition, Type, FIDL_ASSISTED
from serialize import read_transitions, write_transitions, to_flags
from util import print_err, white, print_warning
EXAMPLES = """
This tool will create the source compatibility test structure and walk you
through the implementation step by step, as if you were implementing the
transition.
Examples:
Generate a test by specifying the types of transitions for each binding with the
gen command:
main.py gen protocol-method-add \\
--rust mixed \\
--go fidl-assisted
The test will only include the specified bindings. When you are ready to add
more bindings, rerun the tool with any new bindings:
main.py gen protocol-method-add \\
--rust mixed \\
--go fidl-assisted \\
--hlcpp fidl-assisted
You can get the flags that were invoked for a particular test by running
main.py describe protocol-method-add
If you ever exit the tool while working an test, you can pick up where you left
off without respecifying all of the flags, by using --continue:
main.py gen protocol-method-add --continue
"""
def gen(args):
test_dir = Path(os.path.join(args.root, args.name))
os.makedirs(test_dir, exist_ok=True)
if args.continue_:
transitions_by_binding = read_transitions(test_dir)
else:
transitions_by_binding = transitions_from_args(args)
try:
existing = read_transitions(test_dir)
except FileNotFoundError:
write_transitions(test_dir, transitions_by_binding)
else:
if transitions_by_binding != existing:
print_warning(
f'specified transitions do not match previously existing ones for {args.name}:'
)
print('your parameters:')
print(f' {to_flags(transitions_by_binding)}')
print('existing parameters:')
print(f' {to_flags(existing)}')
if input('\ncontinue? (Y/n) ') == 'n':
return
write_transitions(test_dir, transitions_by_binding)
generate_test(args.fidl, test_dir, transitions_by_binding)
def describe(args):
root = Path(os.path.join(args.root, args.name))
transitions_by_binding = read_transitions(root)
print(white(f'Parameters for test {args.name}:'))
print(to_flags(transitions_by_binding))
def transitions_from_args(args) -> Dict[Binding, Transition]:
transitions_by_binding = {}
for binding in Binding:
transition = getattr(args, binding.value)
if transition is None:
continue
if transition not in transitions:
print_err(
f'error: undefined transition {transition} for binding {binding.value}'
)
return
transitions_by_binding[binding] = transitions[transition]
return transitions_by_binding
parser = argparse.ArgumentParser(
description="Generate FIDL source compatibility test scaffolding",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=EXAMPLES)
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_parser = subparsers.add_parser("gen", help="Generate or modify a test")
gen_parser.set_defaults(func=gen)
gen_parser.add_argument(
'fidl',
help=
'The FIDL library name. Must be a valid library name component, e.g. addmethod'
)
gen_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'
)
gen_parser.add_argument(
'--continue',
dest='continue_',
help='Resume running the tool from an existing test.',
action='store_true')
valid_transitions = set(transitions)
for binding in Binding:
name = binding.value
gen_parser.add_argument(
f'--{name}',
help=
f'The type of transition for {name}. Refer to source_compatibility/README.md for a description of the transitions',
choices=valid_transitions
)
describe_parser = subparsers.add_parser(
'describe',
help='Get the command line arguments used to generate an existing test')
describe_parser.set_defaults(func=describe)
describe_parser.add_argument('name', help='the name of the test/directory')
if __name__ == '__main__':
args = parser.parse_args()
try:
func = args.func
except AttributeError:
parser.print_help(sys.stderr)
sys.exit(1)
func(args)