From 802dd264538d0b2e113924599e3d4fb5cb1fd498 Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Tue, 13 Oct 2026 22:16:35 +1000 Subject: [PATCH] fixtures: add golden payloads for NavigationGpsRequest (VehicleAction 53) Pin lat/lon as doubles at tags 1 and 2 with order left at its default, asserted identically by the TypeScript and Python encoders and decoders. --- fixtures/golden/navigation_gps_request.json | 71 +++++++++++++++++++ .../tests/test_navigation_gps_request.py | 44 ++++++++++++ .../test/navigation-gps-request.test.ts | 43 +++++++++++ 3 files changed, 158 insertions(+) create mode 100644 fixtures/golden/navigation_gps_request.json create mode 100644 packages/python/tests/test_navigation_gps_request.py create mode 100644 packages/typescript/test/navigation-gps-request.test.ts diff --git a/fixtures/golden/navigation_gps_request.json b/fixtures/golden/navigation_gps_request.json new file mode 100644 index 0000000..666f070 --- /dev/null +++ b/fixtures/golden/navigation_gps_request.json @@ -0,0 +1,71 @@ +{ + "description": "Golden wire-format fixtures for CarServer.Action.vehicleAction (navigation GPS request, latitude/longitude pair). Pins NavigationGpsRequest.lat and .lon as little-endian IEEE-754 doubles at tags 1 and 2. Coordinates below are synthetic, and every case leaves order (tag 3) at its default so it is absent from the wire. Consumed identically by the TypeScript and Python test suites: both encoders must produce these exact bytes, and both decoders must round-trip them back to the same field values.", + "outer_message": "CarServer.Action", + "outer_field": { + "name": "vehicleAction", + "tag": 2, + "type": "CarServer.VehicleAction" + }, + "cases": [ + { + "name": "navigation_gps_northern_western", + "vehicle_action_field": { + "name": "navigationGpsRequest", + "tag": 53, + "type": "CarServer.NavigationGpsRequest" + }, + "payload": { + "lat": 37.5, + "lon": -122.25, + "order": "REMOTE_NAV_TRIP_ORDER_UNKNOWN", + "order_number": 0 + }, + "hex": "1215aa0312090000000000c04240110000000000905ec0" + }, + { + "name": "navigation_gps_origin_all_defaults", + "vehicle_action_field": { + "name": "navigationGpsRequest", + "tag": 53, + "type": "CarServer.NavigationGpsRequest" + }, + "payload": { + "lat": 0.0, + "lon": 0.0, + "order": "REMOTE_NAV_TRIP_ORDER_UNKNOWN", + "order_number": 0 + }, + "hex": "1203aa0300" + }, + { + "name": "navigation_gps_southern_eastern", + "vehicle_action_field": { + "name": "navigationGpsRequest", + "tag": 53, + "type": "CarServer.NavigationGpsRequest" + }, + "payload": { + "lat": -33.875, + "lon": 151.25, + "order": "REMOTE_NAV_TRIP_ORDER_UNKNOWN", + "order_number": 0 + }, + "hex": "1215aa0312090000000000f040c0110000000000e86240" + }, + { + "name": "navigation_gps_positive_extremes", + "vehicle_action_field": { + "name": "navigationGpsRequest", + "tag": 53, + "type": "CarServer.NavigationGpsRequest" + }, + "payload": { + "lat": 90.0, + "lon": 180.0, + "order": "REMOTE_NAV_TRIP_ORDER_UNKNOWN", + "order_number": 0 + }, + "hex": "1215aa0312090000000000805640110000000000806640" + } + ] +} diff --git a/packages/python/tests/test_navigation_gps_request.py b/packages/python/tests/test_navigation_gps_request.py new file mode 100644 index 0000000..071a694 --- /dev/null +++ b/packages/python/tests/test_navigation_gps_request.py @@ -0,0 +1,44 @@ +import json +import unittest +from pathlib import Path + +from tesla_protocol.command.car_server_pb2 import Action, NavigationGpsRequest + +FIXTURE = json.loads( + ( + Path(__file__).parents[3] / "fixtures" / "golden" / "navigation_gps_request.json" + ).read_text() +) + + +class GoldenFixtureTests(unittest.TestCase): + def test_outer_vehicle_action_wrapper_is_tag_2(self): + self.assertEqual(FIXTURE["outer_field"]["tag"], 2) + self.assertEqual(FIXTURE["outer_field"]["name"], "vehicleAction") + + def test_fixtures_round_trip_to_golden_bytes(self): + for case in FIXTURE["cases"]: + with self.subTest(case=case["name"]): + self.assertEqual(case["vehicle_action_field"]["tag"], 53) + action = Action( + vehicleAction={ + "navigationGpsRequest": NavigationGpsRequest( + lat=case["payload"]["lat"], + lon=case["payload"]["lon"], + order=case["payload"]["order_number"], + ) + } + ) + + encoded = action.SerializeToString() + self.assertEqual(encoded.hex(), case["hex"]) + + decoded = Action.FromString(encoded) + request = decoded.vehicleAction.navigationGpsRequest + self.assertEqual(request.lat, case["payload"]["lat"]) + self.assertEqual(request.lon, case["payload"]["lon"]) + self.assertEqual(request.order, case["payload"]["order_number"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/typescript/test/navigation-gps-request.test.ts b/packages/typescript/test/navigation-gps-request.test.ts new file mode 100644 index 0000000..75fbbce --- /dev/null +++ b/packages/typescript/test/navigation-gps-request.test.ts @@ -0,0 +1,43 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; + +import { Action } from "../dist/command/car_server.mjs"; + +const fixturePath = fileURLToPath( + new URL("../../../fixtures/golden/navigation_gps_request.json", import.meta.url), +); +const fixture = JSON.parse(readFileSync(fixturePath, "utf8")); + +function hex(bytes: Uint8Array): string { + return Buffer.from(bytes).toString("hex"); +} + +test("Action.vehicleAction outer wrapper is tag 2", () => { + assert.equal(fixture.outer_field.tag, 2); + assert.equal(fixture.outer_field.name, "vehicleAction"); +}); + +for (const c of fixture.cases) { + test(`golden fixture: ${c.name}`, () => { + assert.equal(c.vehicle_action_field.tag, 53); + const action = Action.fromJSON({ + vehicleAction: { + navigationGpsRequest: { + lat: c.payload.lat, + lon: c.payload.lon, + order: c.payload.order_number, + }, + }, + }); + + const encoded = Action.encode(action).finish(); + assert.equal(hex(encoded), c.hex, `encode mismatch for ${c.name}`); + + const decoded = Action.decode(encoded); + assert.equal(decoded.vehicleAction?.navigationGpsRequest?.lat ?? 0, c.payload.lat); + assert.equal(decoded.vehicleAction?.navigationGpsRequest?.lon ?? 0, c.payload.lon); + assert.equal(decoded.vehicleAction?.navigationGpsRequest?.order ?? 0, c.payload.order_number); + }); +}