From f30bbeb8731cf32582d63b4f39d18b18d9c78f7b Mon Sep 17 00:00:00 2001 From: "Michael A. Wekesa" Date: Mon, 27 Nov 2023 23:59:05 +0300 Subject: [PATCH] add for checker for cmd ids orders and union types --- projects/jdwp/defs/command_sets/__init__.py | 11 +++ projects/jdwp/defs/schema.py | 2 +- projects/jdwp/tools/BUCK | 19 +++++ .../jdwp/tools/check_command_ids_order.py | 34 +++++++++ projects/jdwp/tools/check_union_types.py | 73 +++++++++++++++++++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 projects/jdwp/defs/command_sets/__init__.py create mode 100644 projects/jdwp/tools/BUCK create mode 100644 projects/jdwp/tools/check_command_ids_order.py create mode 100644 projects/jdwp/tools/check_union_types.py diff --git a/projects/jdwp/defs/command_sets/__init__.py b/projects/jdwp/defs/command_sets/__init__.py new file mode 100644 index 0000000..e289170 --- /dev/null +++ b/projects/jdwp/defs/command_sets/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. + +from projects.jdwp.defs.command_sets.virtual_machine import VirtualMachine +from projects.jdwp.defs.command_sets.reference_type import ReferenceType +from projects.jdwp.defs.command_sets.event_request import EventRequest + +ALL = [ + VirtualMachine, + ReferenceType, + EventRequest, +] diff --git a/projects/jdwp/defs/schema.py b/projects/jdwp/defs/schema.py index 2a3c56a..6062fad 100644 --- a/projects/jdwp/defs/schema.py +++ b/projects/jdwp/defs/schema.py @@ -95,7 +95,7 @@ def __post_init__(self): class UnionTag(Generic[EnumT]): """Union tag class type.""" - tag: IntegralType + type: IntegralType value: TypeAlias[EnumT] diff --git a/projects/jdwp/tools/BUCK b/projects/jdwp/tools/BUCK new file mode 100644 index 0000000..108618b --- /dev/null +++ b/projects/jdwp/tools/BUCK @@ -0,0 +1,19 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. + +python_binary( + name = "check-uniontypes", + deps = [ + "//projects/jdwp/defs:defs" + ], + main_module = "projects.jdwp.tools.check_union_types", + +) + +python_binary( + name = "cmd-order-check", + deps = [ + "//projects/jdwp/defs:defs" + ], + main_module = "projects.jdwp.tools.check_command_ids_order", + +) \ No newline at end of file diff --git a/projects/jdwp/tools/check_command_ids_order.py b/projects/jdwp/tools/check_command_ids_order.py new file mode 100644 index 0000000..5c6dc78 --- /dev/null +++ b/projects/jdwp/tools/check_command_ids_order.py @@ -0,0 +1,34 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. + +from argparse import ArgumentParser +from projects.jdwp.defs.schema import CommandSet +from projects.jdwp.defs.command_sets import ALL + + +def check_command_ids(command_set: CommandSet) -> None: + try: + sorted_command_ids = [command.id for command in command_set.commands] + if sorted_command_ids != sorted(sorted_command_ids): + print(f"Command IDs in {command_set.name} are NOT in ascending order.") + exit(1) + except Exception as e: + print(f"Error checking command IDs in {command_set.name}: {e}") + exit(1) + + +def main() -> None: + parser = ArgumentParser(description="Check order of command IDs in command sets") + parser.add_argument("--command-set", type=str, help="Specific command set to check") + args = parser.parse_args() + + arg_command_set: str = args.command_set + + for command_set in ALL: + if arg_command_set: + if arg_command_set != command_set.name: + continue + check_command_ids(command_set) + + +if __name__ == "__main__": + main() diff --git a/projects/jdwp/tools/check_union_types.py b/projects/jdwp/tools/check_union_types.py new file mode 100644 index 0000000..a4874dc --- /dev/null +++ b/projects/jdwp/tools/check_union_types.py @@ -0,0 +1,73 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. + +from argparse import ArgumentParser +from projects.jdwp.defs.command_sets import ALL +from projects.jdwp.defs.schema import ( + Command, + CommandSet, + Struct, + TaggedUnion, + Type, + Array, + UnionTag, +) + + +def check_command_set(command_set: CommandSet) -> None: + for command in command_set.commands: + check_command(command) + + +def check_command(command: Command) -> None: + if command.out: + check_struct(command.out) + if command.reply: + check_struct(command.reply) + + +def check_struct(struct: Struct) -> None: + for field in struct.fields: + check_type(field.type) + + +def check_type(type: Type) -> None: + match type: + case Struct(): + check_struct(type) + case Array(): + check_struct(type.element_type) + case TaggedUnion(): + check_tagged_union(type) + + +def check_tagged_union(union: TaggedUnion) -> None: + tagged_union: UnionTag = union.tag.type + for enum_value in tagged_union.value: + try: + union.cases[enum_value] + except KeyError: + print( + f"Error in tagged union '{union.tag.type}': Missing case for enum value '{enum_value}'" + ) + exit(1) + + for value in union.cases.values(): + check_struct(value) + + +def main() -> None: + parser = ArgumentParser(description="Check tagged union mappings in command sets") + parser.add_argument("--command-set", type=str, help="Specific command set to check") + args = parser.parse_args() + + arg_command_set: str = args.command_set + + for command_set in ALL: + if arg_command_set: + if arg_command_set != command_set.name: + continue + check_command_set(command_set) + + +if __name__ == "__main__": + main()