Skip to content

Commit 5ede4af

Browse files
authored
Merge pull request #26 from vwhitteron/add-unit-tests
Add unit tests
2 parents 9d510b9 + 31656a0 commit 5ede4af

File tree

12 files changed

+1533
-11
lines changed

12 files changed

+1533
-11
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ test:
6262
.PHONY: test/cover
6363
test/cover:
6464
go test -v -race -buildvcs -coverprofile=coverage.out ./...
65+
@sed -i '/gran_turismo_telemetry.go/d' coverage.out
6566

6667
## test/cover/show: run all tests and display coverage in a browser
6768
.PHONY: test/cover/show

cmd/capture_replay/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ func main() {
100100
gt.Telemetry.VehicleManufacturer(),
101101
gt.Telemetry.VehicleModel(),
102102
)
103+
104+
// add extra data to the gzip header
103105
if b, ok := buffer.(*gzip.Writer); ok {
104106
b.Extra = []byte(extraData)
105107
}
@@ -109,7 +111,7 @@ func main() {
109111
time.Sleep(4 * time.Millisecond)
110112
}
111113

112-
// Write the frame to the gzip buffer
114+
// write the frame to the file buffer
113115
if framesCaptured >= 0 {
114116
if diff > 1 {
115117
fmt.Printf("Dropped %d frames\n", diff-1)
@@ -132,6 +134,7 @@ func main() {
132134
}
133135
}
134136

137+
// flush and close the gzip file fuffer
135138
if b, ok := buffer.(*gzip.Writer); ok {
136139
b.Flush()
137140
b.Close()

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ go 1.22.5
55
require (
66
github.com/kaitai-io/kaitai_struct_go_runtime v0.10.0
77
github.com/rs/zerolog v1.33.0
8+
github.com/stretchr/testify v1.9.0
89
golang.org/x/crypto v0.29.0
910
)
1011

1112
require (
13+
github.com/davecgh/go-spew v1.1.1 // indirect
1214
github.com/mattn/go-colorable v0.1.13 // indirect
1315
github.com/mattn/go-isatty v0.0.20 // indirect
16+
github.com/pmezard/go-difflib v1.0.0 // indirect
1417
golang.org/x/sys v0.27.0 // indirect
1518
golang.org/x/text v0.20.0 // indirect
19+
gopkg.in/yaml.v3 v3.0.1 // indirect
1620
)

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
2+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
24
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
35
github.com/kaitai-io/kaitai_struct_go_runtime v0.10.0 h1:bxazq0XLMSVMm/DIVFLl9BqIWehrqcLsyVWSacEjIKE=
46
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
911
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
1012
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
1113
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
14+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
15+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1216
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
1317
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
1418
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
19+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
20+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
1521
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
1622
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
1723
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=
2329
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
2430
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
2531
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
32+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
33+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
34+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
35+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/telemetrysrc/network.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ func (r *UDPReader) Read() (int, []byte, error) {
6262
return 0, buffer, fmt.Errorf("no data received")
6363
}
6464

65-
decipheredPacket := utils.Salsa20Decode(buffer[:bufLen])
65+
decipheredPacket, err := utils.Salsa20Decode(buffer[:bufLen])
66+
if err != nil {
67+
return 0, buffer, fmt.Errorf("failed to decipher telemetry: %s", err.Error())
68+
}
6669

6770
return bufLen, decipheredPacket, nil
6871
}

internal/utils/salsa20.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ package utils
22

33
import (
44
"encoding/binary"
5+
"fmt"
56

67
"golang.org/x/crypto/salsa20"
78
)
89

910
const cipherKey string = "Simulator Interface Packet GT7 ver 0.0"
1011

11-
func Salsa20Decode(dat []byte) []byte {
12+
func Salsa20Decode(dat []byte) ([]byte, error) {
13+
datLen := len(dat)
14+
if datLen < 32 {
15+
return nil, fmt.Errorf("salsa20 data is too short: %d < 32", datLen)
16+
}
17+
1218
key := [32]byte{}
1319
copy(key[:], cipherKey)
1420

@@ -21,7 +27,8 @@ func Salsa20Decode(dat []byte) []byte {
2127
salsa20.XORKeyStream(ddata, dat, nonce, &key)
2228
magic := binary.LittleEndian.Uint32(ddata[:4])
2329
if magic != 0x47375330 {
24-
return nil
30+
return nil, fmt.Errorf("invalid magic value: %x", magic)
2531
}
26-
return ddata
32+
33+
return ddata, nil
2734
}

internal/utils/salsa20_test.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package utils
2+
3+
import (
4+
"bytes"
5+
"strconv"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
"github.com/stretchr/testify/suite"
11+
)
12+
13+
var validSalsa20Content = []byte{
14+
0xf6, 0x37, 0x4a, 0x12, 0x43, 0x32, 0x23, 0xcf,
15+
0x4e, 0x53, 0x1f, 0xeb, 0x64, 0x6d, 0xff, 0xae,
16+
0xc8, 0xf0, 0xc8, 0xb9, 0x6e, 0xdc, 0xaf, 0x52,
17+
0x91, 0xb4, 0x40, 0xf2, 0xab, 0x48, 0x01, 0xf1,
18+
0xfc, 0x5a, 0x34, 0x2c, 0x25, 0x75, 0x74, 0x09,
19+
0xf4, 0x97, 0xe1, 0x38, 0x75, 0x46, 0x58, 0x49,
20+
0x5e, 0xc3, 0xbc, 0xdd, 0x6b, 0xc5, 0x48, 0xcd,
21+
0xc3, 0x1a, 0x8f, 0xbc, 0x41, 0x63, 0x1f, 0x1b,
22+
0xfb, 0x59, 0x9f, 0x0c, 0x0b, 0x8d, 0xd6, 0x58,
23+
0x70, 0x06, 0x55, 0xdd, 0xc6, 0xec, 0xa7, 0x4c,
24+
0xc9, 0x91, 0xba, 0x7a, 0x1c, 0x14, 0xab, 0x1a,
25+
0x39, 0x90, 0x75, 0xad, 0xce, 0x55, 0x5a, 0x9d,
26+
0x20, 0x30, 0x41, 0x2e, 0x8a, 0xe3, 0x04, 0x33,
27+
0xa1, 0x20, 0xbc, 0x77, 0x61, 0x34, 0xee, 0xb3,
28+
0x18, 0x8a, 0xdc, 0x80, 0x39, 0x4b, 0xb8, 0xbe,
29+
0x75, 0xaa, 0xef, 0x6f, 0x67, 0x03, 0x95, 0x01,
30+
0x74, 0x5f, 0x85, 0x13, 0x35, 0xa2, 0xbc, 0x9c,
31+
0xe1, 0xc6, 0x55, 0xb5, 0x07, 0x09, 0x23, 0x67,
32+
0x27, 0xf5, 0x6f, 0xd8, 0x89, 0x4d, 0xff, 0x66,
33+
0x10, 0x65, 0x5c, 0x1b, 0x12, 0x32, 0xcd, 0x5c,
34+
0xad, 0x28, 0xef, 0xad, 0x03, 0x73, 0x03, 0xde,
35+
0x47, 0xd7, 0x20, 0xf2, 0x41, 0x1a, 0xe2, 0x0d,
36+
0x54, 0xd6, 0x42, 0x04, 0xfd, 0xaf, 0x19, 0x81,
37+
0x23, 0x21, 0x5b, 0x60, 0x89, 0x62, 0x3e, 0xc2,
38+
0x3d, 0xcb, 0xac, 0x96, 0x5b, 0xf6, 0xd2, 0x2a,
39+
0x29, 0x32, 0x59, 0xb2, 0x7e, 0xdd, 0xfe, 0x4c,
40+
0xa6, 0x06, 0x8c, 0xbe, 0xc6, 0x2e, 0xeb, 0x6a,
41+
0x58, 0xef, 0x98, 0x2d, 0xf9, 0x6a, 0x13, 0x00,
42+
0x4f, 0xd1, 0xc2, 0xc8, 0x8d, 0x58, 0xda, 0xcb,
43+
0xea, 0x28, 0x04, 0x57, 0x1b, 0x48, 0xeb, 0xf9,
44+
0x57, 0x95, 0x39, 0xbf, 0xb8, 0x9d, 0x49, 0xf0,
45+
0x27, 0x1c, 0x11, 0xeb, 0x6f, 0x27, 0x3b, 0x0e,
46+
0x6a, 0x81, 0x86, 0x9c, 0x88, 0x44, 0x48, 0x31,
47+
0x16, 0x88, 0x52, 0x6e, 0x31, 0xf0, 0xf6, 0x4a,
48+
0xa8, 0x20, 0xa9, 0xf8, 0xa2, 0x55, 0xd6, 0x49,
49+
0x36, 0x98, 0x9a, 0x9e, 0xb4, 0x5e, 0x8e, 0x1d,
50+
0x2b, 0xd7, 0x46, 0x02, 0xfd, 0x30, 0x41, 0x8a,
51+
}
52+
53+
var magicPacketHeader = []byte{0x30, 0x53, 0x37, 0x47}
54+
55+
const standardPacketSize = 296
56+
57+
type Salsa20TestSuite struct {
58+
suite.Suite
59+
}
60+
61+
func TestSalsa20TestSuite(t *testing.T) {
62+
suite.Run(t, new(Salsa20TestSuite))
63+
}
64+
65+
func (suite *Salsa20TestSuite) TestEmptySalsa20ContentReturnsNilWithError() {
66+
// Arrange
67+
encodedValue := []byte{}
68+
69+
// Act
70+
gotValue, err := Salsa20Decode(encodedValue)
71+
72+
// Assert
73+
suite.Nil(gotValue)
74+
suite.ErrorContains(err, "salsa20 data is too short: 0 < 32")
75+
}
76+
77+
func (suite *Salsa20TestSuite) TestTruncatedSalsa20ContentReturnsNilWithError() {
78+
// Arrange
79+
wantLen := 31
80+
encodedValue := bytes.Repeat([]byte{0x00}, wantLen)
81+
82+
// Act
83+
gotValue, err := Salsa20Decode(encodedValue)
84+
85+
// Assert
86+
suite.Nil(gotValue)
87+
suite.ErrorContains(err, "salsa20 data is too short: "+strconv.Itoa(wantLen)+" < 32")
88+
}
89+
90+
func (suite *Salsa20TestSuite) TestInvalidSalsa20MagicValueReturnsNilWithError() {
91+
// Arrange
92+
encodedValue := bytes.Repeat([]byte{0x00}, standardPacketSize)
93+
copy(encodedValue[:4], validSalsa20Content[4:])
94+
95+
// Act
96+
gotValue, err := Salsa20Decode(encodedValue)
97+
98+
// Assert
99+
suite.Nil(gotValue)
100+
suite.ErrorContains(err, "invalid magic value: 90f8359c")
101+
}
102+
103+
func TestValidSalsa20ContentReturnsDecodedData(t *testing.T) {
104+
// Arrange
105+
wantValue := magicPacketHeader
106+
107+
// Act
108+
gotValue, err := Salsa20Decode(validSalsa20Content)
109+
require.NoError(t, err)
110+
111+
// Assert
112+
assert.Equal(t, wantValue, gotValue[0:4])
113+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package utils
2+
3+
import (
4+
"reflect"
5+
"runtime"
6+
"strings"
7+
"testing"
8+
9+
"github.com/stretchr/testify/suite"
10+
)
11+
12+
type UnitConversionTestSuite struct {
13+
suite.Suite
14+
}
15+
16+
func TestUnitConversionTestSuite(t *testing.T) {
17+
suite.Run(t, new(UnitConversionTestSuite))
18+
}
19+
20+
func (suite *UnitConversionTestSuite) TestUnitConversionFunctionsReturnCorrectValues() {
21+
type testCase struct {
22+
function func(float32) float32
23+
withValue float32
24+
wantValue float32
25+
}
26+
27+
// Arrange
28+
testCases := []testCase{
29+
{BarToPSI, 1, 14.50377},
30+
{BarToInHg, 1, 29.52998},
31+
{BarToKPA, 1, 100},
32+
{CelsiusToFahrenheit, 1, 33.8},
33+
{MetersToFeet, 1, 3.28084},
34+
{MetersToInches, 1, 39.3701},
35+
{MetersToMillimeters, 1, 1000},
36+
{MetersPerSecondToKilometersPerHour, 1, 3.6},
37+
{MetersPerSecondToMilesPerHour, 1, 2.2369363},
38+
{RadiansPerSecondToRevolutionsPerMinute, 1, 9.549296},
39+
}
40+
41+
for _, tc := range testCases {
42+
fnNameSegments := strings.Split(runtime.FuncForPC(reflect.ValueOf(tc.function).Pointer()).Name(), ".")
43+
fnName := fnNameSegments[len(fnNameSegments)-1]
44+
45+
suite.Run(fnName, func() {
46+
// Act
47+
gotValue := tc.function(tc.withValue)
48+
49+
// Assert
50+
suite.Equal(tc.wantValue, gotValue)
51+
})
52+
}
53+
}

transformer.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"time"
66

77
"github.com/vwhitteron/gt-telemetry/internal/gttelemetry"
8+
"github.com/vwhitteron/gt-telemetry/internal/utils"
89
"github.com/vwhitteron/gt-telemetry/internal/vehicles"
910
)
1011

@@ -386,8 +387,8 @@ func (t *transformer) TyreRadiusMeters() CornerSet {
386387
}
387388

388389
func (t *transformer) TyreSlipRatio() CornerSet {
389-
groundSpeed := t.GroundSpeedKPH()
390-
wheelSpeed := t.WheelSpeedKPH()
390+
groundSpeed := utils.MetersPerSecondToKilometersPerHour(t.GroundSpeedMetersPerSecond())
391+
wheelSpeed := t.WheelSpeedMetersPerSecond()
391392
if groundSpeed == 0 {
392393
return CornerSet{
393394
FrontLeft: 1,
@@ -398,10 +399,10 @@ func (t *transformer) TyreSlipRatio() CornerSet {
398399
}
399400

400401
return CornerSet{
401-
FrontLeft: wheelSpeed.FrontLeft / groundSpeed,
402-
FrontRight: wheelSpeed.FrontRight / groundSpeed,
403-
RearLeft: wheelSpeed.RearLeft / groundSpeed,
404-
RearRight: wheelSpeed.RearRight / groundSpeed,
402+
FrontLeft: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.FrontLeft) / groundSpeed,
403+
FrontRight: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.FrontRight) / groundSpeed,
404+
RearLeft: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.RearLeft) / groundSpeed,
405+
RearRight: utils.MetersPerSecondToKilometersPerHour(wheelSpeed.RearRight) / groundSpeed,
405406
}
406407
}
407408

0 commit comments

Comments
 (0)