Skip to content

Commit

Permalink
get the automated generation of test cases working again (#1448)
Browse files Browse the repository at this point in the history
# Description

@swift-nav/algint-team

This pr fixes the json2test script using UV, which installs dependencies
on the fly. I tried hard to make it so that it could easily be called
from any directory & link to the local version of SBP, but throwing in
the towel under the theory that working but less than ideal is better
than not working.

---------

Co-authored-by: Ivan Smolyakov <[email protected]>
Co-authored-by: Ivan Smolyakov <[email protected]>
Co-authored-by: Ivan Smolyakov <[email protected]>
  • Loading branch information
4 people authored Oct 3, 2024
1 parent d775e3d commit 7fa009d
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 9 deletions.
14 changes: 11 additions & 3 deletions HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
15 changes: 13 additions & 2 deletions generator/json2test.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
"""
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion generator/missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 5 additions & 3 deletions generator/sbpg/test_structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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),
Expand All @@ -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):
Expand Down

0 comments on commit 7fa009d

Please sign in to comment.