From 00fb66c58cbc22eb849ac70b4cac675492dd5e02 Mon Sep 17 00:00:00 2001 From: Vaughan Whitteron Date: Sun, 14 Jul 2024 21:05:15 +0900 Subject: [PATCH 1/5] test: add tests for unit conversion utils --- go.mod | 4 ++ go.sum | 10 +++++ internal/utils/unit_conversion_test.go | 53 ++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 internal/utils/unit_conversion_test.go diff --git a/go.mod b/go.mod index 22fc3d8..ac8efbb 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,16 @@ go 1.22.5 require ( github.com/kaitai-io/kaitai_struct_go_runtime v0.10.0 github.com/rs/zerolog v1.33.0 + github.com/stretchr/testify v1.9.0 golang.org/x/crypto v0.25.0 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ea6f470..ecb90d9 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,6 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/kaitai-io/kaitai_struct_go_runtime v0.10.0 h1:bxazq0XLMSVMm/DIVFLl9BqIWehrqcLsyVWSacEjIKE= github.com/kaitai-io/kaitai_struct_go_runtime v0.10.0/go.mod h1:fBebEoDoc0xNbZsIcRQWqDp4jViaTKv6uxAUjmCFGgM= @@ -9,9 +11,13 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -23,3 +29,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/utils/unit_conversion_test.go b/internal/utils/unit_conversion_test.go new file mode 100644 index 0000000..c911cb8 --- /dev/null +++ b/internal/utils/unit_conversion_test.go @@ -0,0 +1,53 @@ +package utils + +import ( + "reflect" + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/suite" +) + +type UnitConversionTestSuite struct { + suite.Suite +} + +func TestUnitConversionTestSuite(t *testing.T) { + suite.Run(t, new(UnitConversionTestSuite)) +} + +func (suite *UnitConversionTestSuite) TestUnitConversionFunctionsReturnCorrectValues() { + type testCase struct { + function func(float32) float32 + withValue float32 + wantValue float32 + } + + // Arrange + testCases := []testCase{ + {BarToPSI, 1, 14.50377}, + {BarToInHg, 1, 29.52998}, + {BarToKPA, 1, 100}, + {CelsiusToFahrenheit, 1, 33.8}, + {MetersToFeet, 1, 3.28084}, + {MetersToInches, 1, 39.3701}, + {MetersToMillimeters, 1, 1000}, + {MetersPerSecondToKilometersPerHour, 1, 3.6}, + {MetersPerSecondToMilesPerHour, 1, 2.2369363}, + {RadiansPerSecondToRevolutionsPerMinute, 1, 9.549296}, + } + + for _, tc := range testCases { + fnNameSegments := strings.Split(runtime.FuncForPC(reflect.ValueOf(tc.function).Pointer()).Name(), ".") + fnName := fnNameSegments[len(fnNameSegments)-1] + + suite.Run(fnName, func() { + // Act + gotValue := tc.function(tc.withValue) + + // Assert + suite.Equal(tc.wantValue, gotValue) + }) + } +} From 91598b347e7496c67853f50a2ae14e67ad4b29e7 Mon Sep 17 00:00:00 2001 From: Vaughan Whitteron Date: Sat, 3 Aug 2024 21:11:23 +0900 Subject: [PATCH 2/5] test: add salsa20 decoder tests --- internal/telemetrysrc/network.go | 5 +- internal/utils/salsa20.go | 13 +++- internal/utils/salsa20_test.go | 113 +++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 internal/utils/salsa20_test.go diff --git a/internal/telemetrysrc/network.go b/internal/telemetrysrc/network.go index bfad7cc..46d0585 100644 --- a/internal/telemetrysrc/network.go +++ b/internal/telemetrysrc/network.go @@ -62,7 +62,10 @@ func (r *UDPReader) Read() (int, []byte, error) { return 0, buffer, fmt.Errorf("no data received") } - decipheredPacket := utils.Salsa20Decode(buffer[:bufLen]) + decipheredPacket, err := utils.Salsa20Decode(buffer[:bufLen]) + if err != nil { + return 0, buffer, fmt.Errorf("failed to decipher telemetry: %s", err.Error()) + } return bufLen, decipheredPacket, nil } diff --git a/internal/utils/salsa20.go b/internal/utils/salsa20.go index 8ed91b8..8f6d3b2 100644 --- a/internal/utils/salsa20.go +++ b/internal/utils/salsa20.go @@ -2,13 +2,19 @@ package utils import ( "encoding/binary" + "fmt" "golang.org/x/crypto/salsa20" ) const cipherKey string = "Simulator Interface Packet GT7 ver 0.0" -func Salsa20Decode(dat []byte) []byte { +func Salsa20Decode(dat []byte) ([]byte, error) { + datLen := len(dat) + if datLen < 32 { + return nil, fmt.Errorf("salsa20 data is too short: %d < 32", datLen) + } + key := [32]byte{} copy(key[:], cipherKey) @@ -21,7 +27,8 @@ func Salsa20Decode(dat []byte) []byte { salsa20.XORKeyStream(ddata, dat, nonce, &key) magic := binary.LittleEndian.Uint32(ddata[:4]) if magic != 0x47375330 { - return nil + return nil, fmt.Errorf("invalid magic value: %x", magic) } - return ddata + + return ddata, nil } diff --git a/internal/utils/salsa20_test.go b/internal/utils/salsa20_test.go new file mode 100644 index 0000000..2cea607 --- /dev/null +++ b/internal/utils/salsa20_test.go @@ -0,0 +1,113 @@ +package utils + +import ( + "bytes" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var validSalsa20Content = []byte{ + 0xf6, 0x37, 0x4a, 0x12, 0x43, 0x32, 0x23, 0xcf, + 0x4e, 0x53, 0x1f, 0xeb, 0x64, 0x6d, 0xff, 0xae, + 0xc8, 0xf0, 0xc8, 0xb9, 0x6e, 0xdc, 0xaf, 0x52, + 0x91, 0xb4, 0x40, 0xf2, 0xab, 0x48, 0x01, 0xf1, + 0xfc, 0x5a, 0x34, 0x2c, 0x25, 0x75, 0x74, 0x09, + 0xf4, 0x97, 0xe1, 0x38, 0x75, 0x46, 0x58, 0x49, + 0x5e, 0xc3, 0xbc, 0xdd, 0x6b, 0xc5, 0x48, 0xcd, + 0xc3, 0x1a, 0x8f, 0xbc, 0x41, 0x63, 0x1f, 0x1b, + 0xfb, 0x59, 0x9f, 0x0c, 0x0b, 0x8d, 0xd6, 0x58, + 0x70, 0x06, 0x55, 0xdd, 0xc6, 0xec, 0xa7, 0x4c, + 0xc9, 0x91, 0xba, 0x7a, 0x1c, 0x14, 0xab, 0x1a, + 0x39, 0x90, 0x75, 0xad, 0xce, 0x55, 0x5a, 0x9d, + 0x20, 0x30, 0x41, 0x2e, 0x8a, 0xe3, 0x04, 0x33, + 0xa1, 0x20, 0xbc, 0x77, 0x61, 0x34, 0xee, 0xb3, + 0x18, 0x8a, 0xdc, 0x80, 0x39, 0x4b, 0xb8, 0xbe, + 0x75, 0xaa, 0xef, 0x6f, 0x67, 0x03, 0x95, 0x01, + 0x74, 0x5f, 0x85, 0x13, 0x35, 0xa2, 0xbc, 0x9c, + 0xe1, 0xc6, 0x55, 0xb5, 0x07, 0x09, 0x23, 0x67, + 0x27, 0xf5, 0x6f, 0xd8, 0x89, 0x4d, 0xff, 0x66, + 0x10, 0x65, 0x5c, 0x1b, 0x12, 0x32, 0xcd, 0x5c, + 0xad, 0x28, 0xef, 0xad, 0x03, 0x73, 0x03, 0xde, + 0x47, 0xd7, 0x20, 0xf2, 0x41, 0x1a, 0xe2, 0x0d, + 0x54, 0xd6, 0x42, 0x04, 0xfd, 0xaf, 0x19, 0x81, + 0x23, 0x21, 0x5b, 0x60, 0x89, 0x62, 0x3e, 0xc2, + 0x3d, 0xcb, 0xac, 0x96, 0x5b, 0xf6, 0xd2, 0x2a, + 0x29, 0x32, 0x59, 0xb2, 0x7e, 0xdd, 0xfe, 0x4c, + 0xa6, 0x06, 0x8c, 0xbe, 0xc6, 0x2e, 0xeb, 0x6a, + 0x58, 0xef, 0x98, 0x2d, 0xf9, 0x6a, 0x13, 0x00, + 0x4f, 0xd1, 0xc2, 0xc8, 0x8d, 0x58, 0xda, 0xcb, + 0xea, 0x28, 0x04, 0x57, 0x1b, 0x48, 0xeb, 0xf9, + 0x57, 0x95, 0x39, 0xbf, 0xb8, 0x9d, 0x49, 0xf0, + 0x27, 0x1c, 0x11, 0xeb, 0x6f, 0x27, 0x3b, 0x0e, + 0x6a, 0x81, 0x86, 0x9c, 0x88, 0x44, 0x48, 0x31, + 0x16, 0x88, 0x52, 0x6e, 0x31, 0xf0, 0xf6, 0x4a, + 0xa8, 0x20, 0xa9, 0xf8, 0xa2, 0x55, 0xd6, 0x49, + 0x36, 0x98, 0x9a, 0x9e, 0xb4, 0x5e, 0x8e, 0x1d, + 0x2b, 0xd7, 0x46, 0x02, 0xfd, 0x30, 0x41, 0x8a, +} + +var magicPacketHeader = []byte{0x30, 0x53, 0x37, 0x47} + +const standardPacketSize = 296 + +type Salsa20TestSuite struct { + suite.Suite +} + +func TestSalsa20TestSuite(t *testing.T) { + suite.Run(t, new(Salsa20TestSuite)) +} + +func (suite *Salsa20TestSuite) TestEmptySalsa20ContentReturnsNilWithError() { + // Arrange + encodedValue := []byte{} + + // Act + gotValue, err := Salsa20Decode(encodedValue) + + // Assert + suite.Nil(gotValue) + suite.ErrorContains(err, "salsa20 data is too short: 0 < 32") +} + +func (suite *Salsa20TestSuite) TestTruncatedSalsa20ContentReturnsNilWithError() { + // Arrange + wantLen := 31 + encodedValue := bytes.Repeat([]byte{0x00}, wantLen) + + // Act + gotValue, err := Salsa20Decode(encodedValue) + + // Assert + suite.Nil(gotValue) + suite.ErrorContains(err, "salsa20 data is too short: "+strconv.Itoa(wantLen)+" < 32") +} + +func (suite *Salsa20TestSuite) TestInvalidSalsa20MagicValueReturnsNilWithError() { + // Arrange + encodedValue := bytes.Repeat([]byte{0x00}, standardPacketSize) + copy(encodedValue[:4], validSalsa20Content[4:]) + + // Act + gotValue, err := Salsa20Decode(encodedValue) + + // Assert + suite.Nil(gotValue) + suite.ErrorContains(err, "invalid magic value: 90f8359c") +} + +func TestValidSalsa20ContentReturnsDecodedData(t *testing.T) { + // Arrange + wantValue := magicPacketHeader + + // Act + gotValue, err := Salsa20Decode(validSalsa20Content) + require.NoError(t, err) + + // Assert + assert.Equal(t, wantValue, gotValue[0:4]) +} From 96ed0a9fc460f0dc12d97d8abb7d5f499bb003cc Mon Sep 17 00:00:00 2001 From: Vaughan Whitteron Date: Sat, 3 Aug 2024 21:30:21 +0900 Subject: [PATCH 3/5] ci: ignore generated kaitai code coverage --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 8af748f..af0bffb 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,7 @@ test: .PHONY: test/cover test/cover: go test -v -race -buildvcs -coverprofile=coverage.out ./... + @sed -i '/gran_turismo_telemetry.go/d' coverage.out ## test/cover/show: run all tests and display coverage in a browser .PHONY: test/cover/show From 03d2233b5a7cb5aedb572106775af154e964e57d Mon Sep 17 00:00:00 2001 From: Vaughan Whitteron Date: Sun, 4 Aug 2024 20:32:51 +0900 Subject: [PATCH 4/5] test: add transformer unit tests --- transformer.go | 13 +- transformer_test.go | 926 ++++++++++++++++++++++++++++++++++++++++ unit_alternates.go | 4 + unit_alternates_test.go | 397 +++++++++++++++++ 4 files changed, 1334 insertions(+), 6 deletions(-) create mode 100644 transformer_test.go create mode 100644 unit_alternates_test.go diff --git a/transformer.go b/transformer.go index 242cd40..61b87f6 100644 --- a/transformer.go +++ b/transformer.go @@ -5,6 +5,7 @@ import ( "time" "github.com/vwhitteron/gt-telemetry/internal/gttelemetry" + "github.com/vwhitteron/gt-telemetry/internal/utils" "github.com/vwhitteron/gt-telemetry/internal/vehicles" ) @@ -386,8 +387,8 @@ func (t *transformer) TyreRadiusMeters() CornerSet { } func (t *transformer) TyreSlipRatio() CornerSet { - groundSpeed := t.GroundSpeedKPH() - wheelSpeed := t.WheelSpeedKPH() + groundSpeed := utils.MetersPerSecondToKilometersPerHour(t.GroundSpeedMetersPerSecond()) + wheelSpeed := t.WheelSpeedMetersPerSecond() if groundSpeed == 0 { return CornerSet{ FrontLeft: 1, @@ -398,10 +399,10 @@ func (t *transformer) TyreSlipRatio() CornerSet { } return CornerSet{ - FrontLeft: wheelSpeed.FrontLeft / groundSpeed, - FrontRight: wheelSpeed.FrontRight / groundSpeed, - RearLeft: wheelSpeed.RearLeft / groundSpeed, - RearRight: wheelSpeed.RearRight / groundSpeed, + FrontLeft: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.FrontLeft) / groundSpeed, + FrontRight: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.FrontRight) / groundSpeed, + RearLeft: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.RearLeft) / groundSpeed, + RearRight: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.RearRight) / groundSpeed, } } diff --git a/transformer_test.go b/transformer_test.go new file mode 100644 index 0000000..cf7d2d5 --- /dev/null +++ b/transformer_test.go @@ -0,0 +1,926 @@ +package telemetry + +import ( + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/suite" + "github.com/vwhitteron/gt-telemetry/internal/gttelemetry" + "github.com/vwhitteron/gt-telemetry/internal/vehicles" +) + +type TransformerTestSuite struct { + suite.Suite + transformer *transformer +} + +func TestTransformerTestSuite(t *testing.T) { + suite.Run(t, new(TransformerTestSuite)) +} + +func (suite *TransformerTestSuite) SetupTest() { + transformer := NewTransformer(&vehicles.Inventory{}) + // db: map[uint32]vehicles.Vehicle{ + // 1: { + // Id: 1, + // Model: "Test Model", + // Manufacturer: "Test Manufacturer", + // Year: 2021, + // Category: "Test Category", + // CarType: "street", + // Drivetrain: "fr", + // Aspiration: "na", + // OpenCockpit: false, + // }, + // }, + // }) + transformer.RawTelemetry = gttelemetry.GranTurismoTelemetry{} + + suite.transformer = transformer +} + +func (suite *TransformerTestSuite) TestTransformerWithMissingAngularVelocityVectorReturnsZeroVector() { + // Arrange + suite.transformer.RawTelemetry.AngularVelocityVector = nil + + // Act + gotValue := suite.transformer.AngularVelocityVector() + + // Assert + suite.Equal(float32(0), gotValue.X) + suite.Equal(float32(0), gotValue.Y) + suite.Equal(float32(0), gotValue.Z) +} + +func (suite *TransformerTestSuite) TestTransformerWithPopulatedAngularVelocityVectorHasValidVector() { + // Arrange + wantValue := Vector{X: 0.1, Y: 0.2, Z: 0.3} + suite.transformer.RawTelemetry.AngularVelocityVector = >telemetry.GranTurismoTelemetry_Vector{ + VectorX: wantValue.X, + VectorY: wantValue.Y, + VectorZ: wantValue.Z, + } + + // Act + gotValue := suite.transformer.AngularVelocityVector() + + // Assert + suite.Equal(wantValue.X, gotValue.X) + suite.Equal(wantValue.Y, gotValue.Y) + suite.Equal(wantValue.Z, gotValue.Z) +} + +func (suite *TransformerTestSuite) TestTrasnformerBestLaptimeReportsCorrectDuration() { + // Arrange + laptime := 1234567 + wantValue := time.Duration(laptime) * time.Millisecond + suite.transformer.RawTelemetry.BestLaptime = int32(laptime) + + // Act + gotValue := suite.transformer.BestLaptime() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerBrakePercentReportsCorrectValue() { + // Arrange + wantValue := float32(56.078434) + suite.transformer.RawTelemetry.Brake = uint8(143) + + // Act + gotValue := suite.transformer.BrakePercent() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerCalculatedVmaxReportsCorrectValue() { + // Arrange + wantSpeed := uint16(322) + wantRPM := uint16(6709) + suite.transformer.RawTelemetry.CalculatedMaxSpeed = wantSpeed + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.317, + FrontRight: 0.317, + RearLeft: 0.317, + RearRight: 0.317, + } + suite.transformer.RawTelemetry.TransmissionTopSpeedRatio = 2.49 + + // Act + gotValue := suite.transformer.CalculatedVmax() + + // Assert + suite.Equal(wantSpeed, gotValue.Speed) + suite.Equal(wantRPM, gotValue.RPM) +} + +func (suite *TransformerTestSuite) TestTransformerClutchActuationPercentReportsCorrectValue() { + // Arrange + wantValue := float32(62) + suite.transformer.RawTelemetry.ClutchActuation = float32(0.62) + + // Act + gotValue := suite.transformer.ClutchActuationPercent() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerClutcEngagementPercentReportsCorrectValue() { + // Arrange + wantValue := float32(87) + suite.transformer.RawTelemetry.ClutchEngagement = float32(0.87) + + // Act + gotValue := suite.transformer.ClutchEngagementPercent() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerClutchOutputRPMReportsCorrectValue() { + // Arrange + wantValue := float32(2305) + suite.transformer.RawTelemetry.CluchOutputRpm = wantValue + + // Act + gotValue := suite.transformer.ClutchOutputRPM() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerNilCurrentGearReportsNeutral() { + // Arrange + suite.transformer.RawTelemetry.TransmissionGear = nil + + // Act + gotValue := suite.transformer.CurrentGear() + + // Assert + suite.Equal(15, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerCurrentGearReportsCorrectValue() { + minGear := 0 + maxGear := 15 + + for tc := minGear; tc <= maxGear; tc++ { + suite.Run("Gear"+strconv.Itoa(tc), func() { + // Arrange + suite.transformer.RawTelemetry.TransmissionGear = >telemetry.GranTurismoTelemetry_TransmissionGear{ + Current: uint64(tc), + } + + // Act + gotValue := suite.transformer.CurrentGear() + + // Assert + suite.Equal(tc, gotValue) + }) + } +} + +func (suite *TransformerTestSuite) TestTransformerCurrentGearRatioReportsCorrectValue() { + // Arrange + wantValues := []float32{4.32, 3.21, 2.10, 1.09, 0.87} + suite.transformer.RawTelemetry.TransmissionGearRatio = >telemetry.GranTurismoTelemetry_GearRatio{ + Gear: wantValues, + } + + for tc := 0; tc < len(wantValues); tc++ { + suite.Run("Gear"+strconv.Itoa(tc), func() { + // Arrange + suite.transformer.RawTelemetry.TransmissionGear = >telemetry.GranTurismoTelemetry_TransmissionGear{ + Current: uint64(tc + 1), + } + + // Act + gotValue := suite.transformer.CurrentGearRatio() + + // Assert + suite.Equal(wantValues[tc], gotValue) + }) + } +} + +func (suite *TransformerTestSuite) TestTransformerCurrentGearRatioOutOfBoundsReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TransmissionGearRatio = >telemetry.GranTurismoTelemetry_GearRatio{ + Gear: []float32{}, + } + + // Act + gotValue := suite.transformer.CurrentGearRatio() + + // Assert + suite.Equal(float32(-1), gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerCurrentLapReportsCorrectValue() { + // Arrange + wantValue := int16(3) + suite.transformer.RawTelemetry.CurrentLap = uint16(wantValue) + + // Act + gotValue := suite.transformer.CurrentLap() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerDifferentialRatioReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.DifferentialRatio() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerEngineRPMReportsCorrectValue() { + // Arrange + wantValue := float32(9876) + suite.transformer.RawTelemetry.EngineRpm = wantValue + + // Act + gotValue := suite.transformer.EngineRPM() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerEngineRPMLightInactiveBelowRPMMin() { + // Arrange + suite.transformer.RawTelemetry.EngineRpm = float32(1000) + suite.transformer.RawTelemetry.RevLightRpmMin = uint16(2000) + + // Act + gotValue := suite.transformer.EngineRPMLight().Active + + // Assert + suite.False(gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerEngineRPMLightActiveAboveRPMMin() { + // Arrange + suite.transformer.RawTelemetry.EngineRpm = float32(2000) + suite.transformer.RawTelemetry.RevLightRpmMin = uint16(1000) + + // Act + gotValue := suite.transformer.EngineRPMLight().Active + + // Assert + suite.True(gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerAllFlagsDisabledWhenFlagsNil() { + // Arrange + suite.transformer.RawTelemetry.Flags = nil + + // Act + gotValue := suite.transformer.Flags() + + // Assert + suite.Equal(Flags{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerFlagsReportCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.Flags = >telemetry.GranTurismoTelemetry_Flags{ + Live: true, + GamePaused: true, + Loading: true, + InGear: true, + HasTurbo: true, + RevLimiterAlert: true, + HandBrakeActive: true, + HeadlightsActive: true, + HighBeamActive: true, + LowBeamActive: true, + AsmActive: true, + TcsActive: true, + Flag13: true, + Flag14: true, + Flag15: true, + Flag16: true, + } + + // Act + suite.transformer.Flags() + + // Assert + suite.Equal(true, suite.transformer.Flags().Live) + suite.Equal(true, suite.transformer.Flags().GamePaused) + suite.Equal(true, suite.transformer.Flags().Loading) + suite.Equal(true, suite.transformer.Flags().InGear) + suite.Equal(true, suite.transformer.Flags().HasTurbo) + suite.Equal(true, suite.transformer.Flags().RevLimiterAlert) + suite.Equal(true, suite.transformer.Flags().HandbrakeActive) + suite.Equal(true, suite.transformer.Flags().HeadlightsActive) + suite.Equal(true, suite.transformer.Flags().HighBeamActive) + suite.Equal(true, suite.transformer.Flags().LowBeamActive) + suite.Equal(true, suite.transformer.Flags().ASMActive) + suite.Equal(true, suite.transformer.Flags().TCSActive) + suite.Equal(true, suite.transformer.Flags().Flag13) + suite.Equal(true, suite.transformer.Flags().Flag14) + suite.Equal(true, suite.transformer.Flags().Flag15) + suite.Equal(true, suite.transformer.Flags().Flag16) +} + +func (suite *TransformerTestSuite) TestTransformerFuelCapacityPercentReportsCorrectValue() { + // Arrange + wantValue := float32(98) + suite.transformer.RawTelemetry.FuelCapacity = wantValue + + // Act + gotValue := suite.transformer.FuelCapacityPercent() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerFuelLevelPercentReportsCorrectValue() { + // Arrange + wantValue := float32(50) + suite.transformer.RawTelemetry.FuelLevel = wantValue + + // Act + gotValue := suite.transformer.FuelLevelPercent() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerTransmissionFIXME() { + // Arrange + // FIXME + + // Act + suite.transformer.Transmission() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerGroundSpeedMetersPerSecondReportsCorrectValue() { + // Arrange + wantValue := float32(39.33952) + suite.transformer.RawTelemetry.GroundSpeed = wantValue + + // Act + gotValue := suite.transformer.GroundSpeedMetersPerSecond() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerHeadingReportsCorrectValue() { + // Arrange + wantValue := float32(0.9477) + suite.transformer.RawTelemetry.Heading = wantValue + + // Act + gotValue := suite.transformer.Heading() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerLastLaptimeReportsCorrectValue() { + // Arrange + laptime := 123456 + wantValue := time.Duration(laptime) * time.Millisecond + suite.transformer.RawTelemetry.LastLaptime = int32(laptime) + + // Act + gotValue := suite.transformer.LastLaptime() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerOilPressureKPAReportsCorrectValue() { + // Arrange + wantValue := float32(0.12345) + suite.transformer.RawTelemetry.OilPressure = wantValue + + // Act + gotValue := suite.transformer.OilPressureKPA() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerOilTemperatureCelsiusReportsCorrectValue() { + // Arrange + wantValue := float32(104.2945) + suite.transformer.RawTelemetry.OilTemperature = wantValue + + // Act + gotValue := suite.transformer.OilTemperatureCelsius() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerNilPositionalMapCoordinatesReportsEmptyVector() { + suite.transformer.RawTelemetry.RotationAxes = nil + + // Act + gotValue := suite.transformer.PositionalMapCoordinates() + + // Assert + suite.Equal(Vector{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerPositionalMapCoordinatesReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.MapPositionCoordinates = >telemetry.GranTurismoTelemetry_Coordinate{ + CoordinateX: 10.1, + CoordinateY: 20.2, + CoordinateZ: 30.3, + } + + // Act + suite.transformer.PositionalMapCoordinates() + + // Assert + suite.Equal(float32(10.1), suite.transformer.PositionalMapCoordinates().X) + suite.Equal(float32(20.2), suite.transformer.PositionalMapCoordinates().Y) + suite.Equal(float32(30.3), suite.transformer.PositionalMapCoordinates().Z) +} + +func (suite *TransformerTestSuite) TestTransformerRaceEntrantsReportsCorrectValue() { + // Arrange + wantValue := int16(16) + suite.transformer.RawTelemetry.RaceEntrants = wantValue + + // Act + gotValue := suite.transformer.RaceEntrants() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerRaceLapsReportsCorrectValue() { + // Arrange + wantValue := uint16(30) + suite.transformer.RawTelemetry.RaceLaps = wantValue + + // Act + gotValue := suite.transformer.RaceLaps() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerRideHeightMetersReportsCorrectValue() { + // Arrange + wantValue := float32(0.12345) + suite.transformer.RawTelemetry.RideHeight = wantValue + + // Act + gotValue := suite.transformer.RideHeightMeters() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerNilRotationVectorReportsEmptyVector() { + // Arrange + suite.transformer.RawTelemetry.RotationAxes = nil + + // Act + gotValue := suite.transformer.RotationVector() + + // Assert + suite.Equal(SymmetryAxes{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerRotationVectorReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.RotationAxes = >telemetry.GranTurismoTelemetry_SymmetryAxes{ + Yaw: 0.1, + Pitch: 0.2, + Roll: 0.3, + } + + // Act + gotValue := suite.transformer.RotationVector() + + // Assert + suite.Equal(float32(0.1), gotValue.Yaw) + suite.Equal(float32(0.2), gotValue.Pitch) + suite.Equal(float32(0.3), gotValue.Roll) +} + +func (suite *TransformerTestSuite) TestTransformerSequenceIDReportsCorrectValue() { + // Arrange + wantValue := uint32(123456789) + suite.transformer.RawTelemetry.SequenceId = wantValue + + // Act + gotValue := suite.transformer.SequenceID() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerStartingPositionReportsCorrectValue() { + // Arrange + wantValue := int16(5) + suite.transformer.RawTelemetry.StartingPosition = wantValue + + // Act + gotValue := suite.transformer.StartingPosition() + + // Assert + suite.Equal(wantValue, gotValue) + +} + +func (suite *TransformerTestSuite) TestTransformerNilSuggestedGearReportsNeutral() { + // Arrange + suite.transformer.RawTelemetry.TransmissionGear = nil + + // Act + gotValue := suite.transformer.SuggestedGear() + + // Assert + suite.Equal(uint64(15), gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerSuggestedGearReportsCorrectValue() { + minGear := 0 + maxGear := 15 + + for tc := minGear; tc <= maxGear; tc++ { + suite.Run("Gear"+strconv.Itoa(tc), func() { + // Arrange + suite.transformer.RawTelemetry.TransmissionGear = >telemetry.GranTurismoTelemetry_TransmissionGear{ + Suggested: uint64(tc), + } + + // Act + gotValue := suite.transformer.SuggestedGear() + + // Assert + suite.Equal(uint64(tc), gotValue) + }) + } +} + +func (suite *TransformerTestSuite) TestTransformerNilSuspensionHeightMetersReportsEmptyCornerSet() { + // Arrange + suite.transformer.RawTelemetry.SuspensionHeight = nil + + // Act + gotValue := suite.transformer.SuspensionHeightMeters() + + // Assert + suite.Equal(CornerSet{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerSuspensionHeightMetersReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.SuspensionHeight = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.101, + FrontRight: 0.102, + RearLeft: 0.103, + RearRight: 0.104, + } + + // Act + gotValue := suite.transformer.SuspensionHeightMeters() + + // Assert + suite.Equal(float32(0.101), gotValue.FrontLeft) + suite.Equal(float32(0.102), gotValue.FrontRight) + suite.Equal(float32(0.103), gotValue.RearLeft) + suite.Equal(float32(0.104), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestTransformerThrottlePercentReportsCorrectValue() { + // Arrange + wantValue := float32(79.60784) + suite.transformer.RawTelemetry.Throttle = 203 + + // Act + gotValue := suite.transformer.ThrottlePercent() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerTimeOfDayReportsCorrectValue() { + // Arrange + timeMS := 34567890 + wantValue := time.Duration(timeMS) * time.Millisecond + suite.transformer.RawTelemetry.TimeOfDay = uint32(timeMS) + + // Act + gotValue := suite.transformer.TimeOfDay() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerTransmissionTopSpeedRatioReportsCorrectValue() { + // Arrange + wantValue := float32(0.7890) + suite.transformer.RawTelemetry.TransmissionTopSpeedRatio = wantValue + + // Act + gotValue := suite.transformer.TransmissionTopSpeedRatio() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerTurboBoostBarReportsCorrectValue() { + // Arrange + wantValue := float32(0.821) + suite.transformer.RawTelemetry.ManifoldPressure = float32(1.821) + + // Act + gotValue := suite.transformer.TurboBoostBar() + + // Assert + suite.Equal(wantValue, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerNilTyreDiameterMetersReportsEmptyCornerSet() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = nil + + // Act + gotValue := suite.transformer.TyreDiameterMeters() + + // Assert + suite.Equal(CornerSet{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerTyreDiameterMetersReportsCorrectValue() { + // Arrange + // FIXME + + // Act + suite.transformer.TyreDiameterMeters() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerNilTyreRadiusMetersReportsEmptyCornerSet() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = nil + + // Act + gotValue := suite.transformer.TyreRadiusMeters() + + // Assert + suite.Equal(CornerSet{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerTyreRadiusMetersReportsCorrectValue() { + // Arrange + wantValue := float32(0.317) + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: wantValue, + FrontRight: wantValue, + RearLeft: wantValue, + RearRight: wantValue, + } + + // Act + gotValue := suite.transformer.TyreRadiusMeters() + + // Assert + suite.Equal(wantValue, gotValue.FrontLeft) + suite.Equal(wantValue, gotValue.FrontRight) + suite.Equal(wantValue, gotValue.RearLeft) + suite.Equal(wantValue, gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestTransformerTyreSlipRatioIsOneWhenGroundSpeedZero() { + // Arrange + suite.transformer.RawTelemetry.GroundSpeed = 0 + + // Act + gotValue := suite.transformer.TyreSlipRatio() + + // Assert + suite.Equal(CornerSet{FrontLeft: 1, FrontRight: 1, RearLeft: 1, RearRight: 1}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerTyreSlipRatioReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.GroundSpeed = 42 + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.317, + FrontRight: 0.317, + RearLeft: 0.317, + RearRight: 0.317, + } + suite.transformer.RawTelemetry.WheelRadiansPerSecond = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 132.50, + FrontRight: 132.51, + RearLeft: 132.45, + RearRight: 132.40, + } + + // Act + gotValue := suite.transformer.TyreSlipRatio() + + // Assert + suite.Equal(float32(1.0000595), gotValue.FrontLeft) + suite.Equal(float32(1.000135), gotValue.FrontRight) + suite.Equal(float32(0.9996821), gotValue.RearLeft) + suite.Equal(float32(0.99930465), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestTransformerNilTyreTemperatureCelsiusReportsEmptyCornerSet() { + // Arrange + suite.transformer.RawTelemetry.TyreTemperature = nil + + // Act + gotValue := suite.transformer.TyreTemperatureCelsius() + + // Assert + suite.Equal(CornerSet{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerTyreTemperatureCelsiusReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreTemperature = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 64.3, + FrontRight: 64.1, + RearLeft: 68.2, + RearRight: 67.8, + } + + // Act + gotValue := suite.transformer.TyreTemperatureCelsius() + + // Assert + suite.Equal(float32(64.3), gotValue.FrontLeft) + suite.Equal(float32(64.1), gotValue.FrontRight) + suite.Equal(float32(68.2), gotValue.RearLeft) + suite.Equal(float32(67.8), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestTransformerVehicleIDReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.VehicleID() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerVehicleCategoryReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.VehicleCategory() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerVehicleDrivetrainReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.VehicleDrivetrain() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerVehicleManufacturerReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.VehicleManufacturer() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerVehicleModelReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.VehicleModel() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerVehicleHasOpenCockpitReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.VehicleHasOpenCockpit() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerVehicleYearReportsCorrectValue() { + // Arrange + // FIXME needs vehicle inventory to be mod-able + + // Act + suite.transformer.VehicleYear() + + // Assert +} + +func (suite *TransformerTestSuite) TestTransformerNilWheelSpeedRadiansPerSecondReportsEmptyCornerSet() { + // Arrange + suite.transformer.RawTelemetry.WheelRadiansPerSecond = nil + + // Act + gotValue := suite.transformer.WheelSpeedRadiansPerSecond() + + // Assert + suite.Equal(CornerSet{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerWheelSpeedRadiansPerSecondReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.WheelRadiansPerSecond = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 132.50, + FrontRight: 132.51, + RearLeft: 132.45, + RearRight: 132.40, + } + + // Act + gotValue := suite.transformer.WheelSpeedRadiansPerSecond() + + // Assert + suite.Equal(float32(132.50), gotValue.FrontLeft) + suite.Equal(float32(132.51), gotValue.FrontRight) + suite.Equal(float32(132.45), gotValue.RearLeft) + suite.Equal(float32(132.40), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestTransformerNilVelocityVectorReportsEmptyVector() { + // Arrange + suite.transformer.RawTelemetry.VelocityVector = nil + + // Act + gotValue := suite.transformer.VelocityVector() + + // Assert + suite.Equal(Vector{}, gotValue) +} + +func (suite *TransformerTestSuite) TestTransformerVelocityVectorReportsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.VelocityVector = >telemetry.GranTurismoTelemetry_Vector{ + VectorX: 42.1, + VectorY: 1.2, + VectorZ: 0.3, + } + + // Act + gotValue := suite.transformer.VelocityVector() + + // Assert + suite.Equal(float32(42.1), gotValue.X) + suite.Equal(float32(1.2), gotValue.Y) + suite.Equal(float32(0.3), gotValue.Z) +} + +func (suite *TransformerTestSuite) TestTransformerWaterTemperatureCelsiusReportsCorrectValue() { + // Arrange + wantValue := float32(94.56) + suite.transformer.RawTelemetry.WaterTemperature = wantValue + + // Act + gotValue := suite.transformer.WaterTemperatureCelsius() + + // Assert + suite.Equal(wantValue, gotValue) +} diff --git a/unit_alternates.go b/unit_alternates.go index 6aed5d1..c92b21d 100644 --- a/unit_alternates.go +++ b/unit_alternates.go @@ -21,6 +21,10 @@ func (t *transformer) GroundSpeedKPH() float32 { return utils.MetersPerSecondToKilometersPerHour(t.GroundSpeedMetersPerSecond()) } +func (t *transformer) OilTemperatureFahrenheit() float32 { + return utils.CelsiusToFahrenheit(t.RawTelemetry.OilTemperature) +} + func (t *transformer) RideHeightMillimeters() float32 { return utils.MetersToMillimeters(t.RideHeightMeters()) } diff --git a/unit_alternates_test.go b/unit_alternates_test.go new file mode 100644 index 0000000..38a29bf --- /dev/null +++ b/unit_alternates_test.go @@ -0,0 +1,397 @@ +package telemetry + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/suite" + "github.com/vwhitteron/gt-telemetry/internal/gttelemetry" + "github.com/vwhitteron/gt-telemetry/internal/vehicles" +) + +type UnitAlternatesTestSuite struct { + suite.Suite + transformer *transformer +} + +func TestUnitAlternatesTestSuite(t *testing.T) { + suite.Run(t, new(UnitAlternatesTestSuite)) +} + +func (suite *UnitAlternatesTestSuite) SetupTest() { + transformer := NewTransformer(&vehicles.Inventory{}) + transformer.RawTelemetry = gttelemetry.GranTurismoTelemetry{} + + suite.transformer = transformer +} + +func (suite *TransformerTestSuite) TestUnitAlternatesCurrentGearStringReturnsCorrectValue() { + wantValues := map[int]string{ + 0: "R", + 1: "1", + 2: "2", + 3: "3", + 4: "4", + 5: "5", + 6: "6", + 7: "7", + 8: "8", + 9: "9", + 10: "10", + 11: "11", + 12: "12", + 13: "13", + 14: "14", + 15: "N", + } + + for testValue, wantValue := range wantValues { + suite.Run("Gear"+strconv.Itoa(testValue), func() { + // Arrange + suite.transformer.RawTelemetry.TransmissionGear = >telemetry.GranTurismoTelemetry_TransmissionGear{ + Current: uint64(testValue), + } + + // Act + gotValue := suite.transformer.CurrentGearString() + + // Assert + suite.Equal(wantValue, gotValue) + }) + } +} + +func (suite *TransformerTestSuite) TestUnitAlternatesGroundSpeedKPHReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.GroundSpeed = 82 + + // Act + gotValue := suite.transformer.GroundSpeedKPH() + + // Assert + suite.Equal(float32(295.19998), gotValue) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesOilTemperatureFahrenheitReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.OilTemperature = 104.2945 + + // Act + gotValue := suite.transformer.OilTemperatureFahrenheit() + + // Assert + suite.Equal(float32(219.7301), gotValue) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesRideHeightMillimetersReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.RideHeight = 0.10267 + + // Act + gotValue := suite.transformer.RideHeightMillimeters() + + // Assert + suite.Equal(float32(102.67), gotValue) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesSuspensionHeightFeetReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.SuspensionHeight = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.0267, + FrontRight: 0.0213, + RearLeft: 0.0312, + RearRight: 0.0298, + } + + // Act + gotValue := suite.transformer.SuspensionHeightFeet() + + // Assert + suite.Equal(float32(0.08759842), gotValue.FrontLeft) + suite.Equal(float32(0.069881886), gotValue.FrontRight) + suite.Equal(float32(0.1023622), gotValue.RearLeft) + suite.Equal(float32(0.09776903), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesSuspensionHeightInchesReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.SuspensionHeight = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.0267, + FrontRight: 0.0213, + RearLeft: 0.0312, + RearRight: 0.0298, + } + + // Act + gotValue := suite.transformer.SuspensionHeightInches() + + // Assert + suite.Equal(float32(1.0511816), gotValue.FrontLeft) + suite.Equal(float32(0.83858305), gotValue.FrontRight) + suite.Equal(float32(1.2283471), gotValue.RearLeft) + suite.Equal(float32(1.1732289), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesSuspensionHeightMillimetersReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.SuspensionHeight = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.0267, + FrontRight: 0.0213, + RearLeft: 0.0312, + RearRight: 0.0298, + } + + // Act + gotValue := suite.transformer.SuspensionHeightMillimeters() + + // Assert + suite.Equal(float32(26.699999), gotValue.FrontLeft) + suite.Equal(float32(21.3), gotValue.FrontRight) + suite.Equal(float32(31.199999), gotValue.RearLeft) + suite.Equal(float32(29.8), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTurboBoostPSIReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.ManifoldPressure = 2.13 + + // Act + gotValue := suite.transformer.TurboBoostPSI() + + // Assert + suite.Equal(float32(16.389261), gotValue) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTurboBoostInHgReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.ManifoldPressure = 2.13 + + // Act + gotValue := suite.transformer.TurboBoostInHg() + + // Assert + suite.Equal(float32(33.36888), gotValue) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTurboBoostKPAReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.ManifoldPressure = 2.13 + + // Act + gotValue := suite.transformer.TurboBoostKPA() + + // Assert + suite.Equal(float32(113.000015), gotValue) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTyreDiameterFeetReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.314, + FrontRight: 0.314, + RearLeft: 0.343, + RearRight: 0.343, + } + + // Act + gotValue := suite.transformer.TyreDiameterFeet() + + // Assert + suite.Equal(float32(2.0603676), gotValue.FrontLeft) + suite.Equal(float32(2.0603676), gotValue.FrontRight) + suite.Equal(float32(2.2506561), gotValue.RearLeft) + suite.Equal(float32(2.2506561), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTyreDiameterInchesReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.314, + FrontRight: 0.314, + RearLeft: 0.343, + RearRight: 0.343, + } + + // Act + gotValue := suite.transformer.TyreDiameterInches() + // Assert + suite.Equal(float32(24.724422), gotValue.FrontLeft) + suite.Equal(float32(24.724422), gotValue.FrontRight) + suite.Equal(float32(27.007887), gotValue.RearLeft) + suite.Equal(float32(27.007887), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTyreDiameterMillimetersReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.314, + FrontRight: 0.314, + RearLeft: 0.343, + RearRight: 0.343, + } + + // Act + gotValue := suite.transformer.TyreDiameterMillimeters() + + // Assert + suite.Equal(float32(628), gotValue.FrontLeft) + suite.Equal(float32(628), gotValue.FrontRight) + suite.Equal(float32(686), gotValue.RearLeft) + suite.Equal(float32(686), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTyreRadiusFeetReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.314, + FrontRight: 0.314, + RearLeft: 0.343, + RearRight: 0.343, + } + + // Act + gotValue := suite.transformer.TyreRadiusFeet() + + // Assert + suite.Equal(float32(1.0301838), gotValue.FrontLeft) + suite.Equal(float32(1.0301838), gotValue.FrontRight) + suite.Equal(float32(1.1253281), gotValue.RearLeft) + suite.Equal(float32(1.1253281), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTyreRadiusInchesReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.314, + FrontRight: 0.314, + RearLeft: 0.343, + RearRight: 0.343, + } + + // Act + gotValue := suite.transformer.TyreRadiusInches() + + // Assert + suite.Equal(float32(12.362211), gotValue.FrontLeft) + suite.Equal(float32(12.362211), gotValue.FrontRight) + suite.Equal(float32(13.503943), gotValue.RearLeft) + suite.Equal(float32(13.503943), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTyreRadiusMillimetersReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.314, + FrontRight: 0.314, + RearLeft: 0.343, + RearRight: 0.343, + } + + // Act + gotValue := suite.transformer.TyreRadiusMillimeters() + + // Assert + suite.Equal(float32(314), gotValue.FrontLeft) + suite.Equal(float32(314), gotValue.FrontRight) + suite.Equal(float32(343), gotValue.RearLeft) + suite.Equal(float32(343), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesTyreTemperatureFahrenheitReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreTemperature = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 64.3, + FrontRight: 64.1, + RearLeft: 68.2, + RearRight: 67.8, + } + + // Act + gotValue := suite.transformer.TyreTemperatureFahrenheit() + + // Assert + suite.Equal(float32(143.835), gotValue.FrontLeft) + suite.Equal(float32(143.38762), gotValue.FrontRight) + suite.Equal(float32(152.55905), gotValue.RearLeft) + suite.Equal(float32(151.66429), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesWheelSpeedKPHReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.317, + FrontRight: 0.317, + RearLeft: 0.317, + RearRight: 0.317, + } + suite.transformer.RawTelemetry.WheelRadiansPerSecond = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 132.50, + FrontRight: 132.51, + RearLeft: 132.45, + RearRight: 132.40, + } + + // Act + gotValue := suite.transformer.WheelSpeedKPH() + + // Assert + suite.Equal(float32(151.20898), gotValue.FrontLeft) + suite.Equal(float32(151.2204), gotValue.FrontRight) + suite.Equal(float32(151.15193), gotValue.RearLeft) + suite.Equal(float32(151.09486), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesWheelSpeedMPHReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.TyreRadius = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 0.317, + FrontRight: 0.317, + RearLeft: 0.317, + RearRight: 0.317, + } + suite.transformer.RawTelemetry.WheelRadiansPerSecond = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 132.50, + FrontRight: 132.51, + RearLeft: 132.45, + RearRight: 132.40, + } + + // Act + gotValue := suite.transformer.WheelSpeedMPH() + + // Assert + suite.Equal(float32(93.95692), gotValue.FrontLeft) + suite.Equal(float32(93.964005), gotValue.FrontRight) + suite.Equal(float32(93.92146), gotValue.RearLeft) + suite.Equal(float32(93.886), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesWheelSpeedRPMReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.WheelRadiansPerSecond = >telemetry.GranTurismoTelemetry_CornerSet{ + FrontLeft: 132.50, + FrontRight: 132.51, + RearLeft: 132.45, + RearRight: 132.40, + } + + // Act + gotValue := suite.transformer.WheelSpeedRPM() + + // Assert + suite.Equal(float32(1265.2817), gotValue.FrontLeft) + suite.Equal(float32(1265.3772), gotValue.FrontRight) + suite.Equal(float32(1264.8043), gotValue.RearLeft) + suite.Equal(float32(1264.3268), gotValue.RearRight) +} + +func (suite *TransformerTestSuite) TestUnitAlternatesWaterTemperatureFahrenheitReturnsCorrectValue() { + // Arrange + suite.transformer.RawTelemetry.WaterTemperature = 94.56 + + // Act + gotValue := suite.transformer.WaterTemperatureFahrenheit() + + // Assert + suite.Equal(float32(202.208), gotValue) +} From 728a70ac44b1b16650b6c42b6288bbef592fd7a7 Mon Sep 17 00:00:00 2001 From: Vaughan Whitteron Date: Tue, 8 Oct 2024 10:32:54 +0900 Subject: [PATCH 5/5] wip: comments --- cmd/capture_replay/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/capture_replay/main.go b/cmd/capture_replay/main.go index 6694855..48695aa 100644 --- a/cmd/capture_replay/main.go +++ b/cmd/capture_replay/main.go @@ -100,6 +100,8 @@ func main() { gt.Telemetry.VehicleManufacturer(), gt.Telemetry.VehicleModel(), ) + + // add extra data to the gzip header if b, ok := buffer.(*gzip.Writer); ok { b.Extra = []byte(extraData) } @@ -109,7 +111,7 @@ func main() { time.Sleep(4 * time.Millisecond) } - // Write the frame to the gzip buffer + // write the frame to the file buffer if framesCaptured >= 0 { if diff > 1 { fmt.Printf("Dropped %d frames\n", diff-1) @@ -132,6 +134,7 @@ func main() { } } + // flush and close the gzip file fuffer if b, ok := buffer.(*gzip.Writer); ok { b.Flush() b.Close()