diff --git a/HOWTO.md b/HOWTO.md index f205c6f4af..aeeeccdf41 100644 --- a/HOWTO.md +++ b/HOWTO.md @@ -87,7 +87,9 @@ python missing.py --host [HOST] --port [PORT] ### New Messages The `json2test` script can be used to automatically generate tests for newly -defined messages. +defined messages. The json2test script uses [uv](https://docs.astral.sh/uv/) to +manage its dependencies, which can be installed following the instructions on that +website To use `json2test` a JSON file should be hand written with example contents of a message. For example, to generate tests for the `MSG_HEARTBEAT` message (which @@ -105,13 +107,19 @@ form: And then generate a test for using `json2test` with: ```shell -PYTHONPATH="python/" python generator/json2test.py --input heartbeat.json --output spec/tests/yaml/swiftnav/sbp/system/test_MsgHeartbeat.yaml +uv -n run json2test.py --input heartbeat.json --output ../spec/tests/yaml/swiftnav/sbp/system/test_MsgHeartbeat.yaml ``` +*NOTE* because the json2test file imports the local version of sbp & the build +system of it all is a little slapdash, this command will ONLY work if called from +inside of `libsbp/generator/` directory because the `${PROJECT_ROOT}` in the script +declartion of json2test.py is whatever the PWD is when the command is called, and +caching is turned off. + Usage for `json2test` ```shell -python json2test --input [PATH_TO_JSON_IN] --output [PATH_TO_YAML_OUT] +uv -n run json2test --input [PATH_TO_JSON_IN] --output [PATH_TO_YAML_OUT] ``` * The `msg_type` can also be provided through a CLI parameter, with `--msg-id diff --git a/generator/json2test.py b/generator/json2test.py index 83d01c61bc..1e81f69c04 100644 --- a/generator/json2test.py +++ b/generator/json2test.py @@ -1,4 +1,4 @@ -# Copyright (C) 2022 Swift Navigation Inc. +# Copyright (C) 2024 Swift Navigation Inc. # Contact: https://support.swiftnav.com # # This source is subject to the license found in the file 'LICENSE' which must @@ -7,6 +7,17 @@ # THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, # EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "jinja2 ~= 3.1", +# "pytest ~= 8.3", +# "pyyaml ~= 6.0", +# "sbp @ file:///${PROJECT_ROOT}/../python", +# ] +# /// + """ Generate test case from json input """ @@ -42,7 +53,7 @@ def write_test(msg, output, test_set_name="swiftnav"): module = msg.__class__.__module__ name = msg.__class__.__name__ test_msg_data = msg_reducer(msg) - test_data = TestSpecification.from_msg(msg, test_msg_data) + test_data = TestSpecification.from_msg(msg, test_msg_data, test_msg_data['name']) now_str = datetime.datetime.now().isoformat(" ") test_package = PackageTestSpecification( package=module, diff --git a/generator/missing.py b/generator/missing.py index 2d4a1fc8af..b79ad4461e 100644 --- a/generator/missing.py +++ b/generator/missing.py @@ -62,7 +62,7 @@ def write_test(msg, test_set_name="swiftnav"): ) filename = os.path.join(*path_parts) test_msg_data = msg_reducer(msg) - test_data = TestSpecification.from_msg(msg, test_msg_data) + test_data = TestSpecification.from_msg(msg, test_msg_data, test_msg_data['name']) now_str = datetime.datetime.now().isoformat(" ") test_package = PackageTestSpecification( package=module, diff --git a/generator/sbpg/test_structs.py b/generator/sbpg/test_structs.py index 4a280518dc..6726197ce3 100644 --- a/generator/sbpg/test_structs.py +++ b/generator/sbpg/test_structs.py @@ -86,7 +86,7 @@ class TestSpecification(object): """A message description to generate tests for. """ - def __init__(self, raw_packet, msg_type, raw_json, msg, sbp, test_msg_data=None): + def __init__(self, raw_packet, msg_type, raw_json, msg, sbp, test_msg_data=None, msg_name=None): self.raw_packet = raw_packet self.raw_json = raw_json self.raw_json_obj = json.loads(raw_json) @@ -99,7 +99,8 @@ def __init__(self, raw_packet, msg_type, raw_json, msg, sbp, test_msg_data=None) self.payload = base64.standard_b64decode(self.sbp['payload']) self.payload_as_byte_array = list(bytearray(self.payload)) self.payload_len_for_encoding_buf = len(self.payload) if len(self.payload) > 0 else 1 - msg_name = msg['name'] + if msg_name is None: + msg_name = msg['name'] for i in range(0, len(ACRONYMS)): msg_name = re.sub(ACRONYMS[i], LOWER_ACRONYMS[i], msg_name) self.enum_value = "Sbp" + msg_name @@ -110,7 +111,7 @@ def __init__(self, raw_packet, msg_type, raw_json, msg, sbp, test_msg_data=None) self.fn_prefix = self.struct_name[:-2] @classmethod - def from_msg(cls, msg_instance, test_msg_data): + def from_msg(cls, msg_instance, test_msg_data, name): msg = msg_instance sbp = { "crc": "0x{:X}".format(msg.crc), @@ -127,6 +128,7 @@ def from_msg(cls, msg_instance, test_msg_data): msg, sbp, test_msg_data=test_msg_data, + msg_name=name, ) def __repr__(self):