Add depot, attendant, jetfire, optimus, ota services with kustomize overlays

This commit is contained in:
Chris Rai
2026-01-31 15:35:07 -05:00
parent a0ec642ca1
commit 9a5cb2f547
404 changed files with 38817 additions and 16 deletions

View File

@@ -0,0 +1,962 @@
package handlers_test
import (
"fmt"
"strings"
"testing"
"time"
"github.com/fiskerinc/cloud-services/services/attendant/handlers"
"github.com/fiskerinc/cloud-services/services/attendant/services"
"os"
"github.com/fiskerinc/cloud-services/pkg/common"
"github.com/fiskerinc/cloud-services/pkg/common/dbbasemodel"
"github.com/fiskerinc/cloud-services/pkg/common/manifestfingerprintparams"
dbm "github.com/fiskerinc/cloud-services/pkg/db/queries/mocks"
"github.com/fiskerinc/cloud-services/pkg/grpc/sms"
"github.com/fiskerinc/cloud-services/pkg/kafka"
kafkaMock "github.com/fiskerinc/cloud-services/pkg/kafka/mock"
"github.com/fiskerinc/cloud-services/pkg/redis"
rm "github.com/fiskerinc/cloud-services/pkg/redis/tester"
th "github.com/fiskerinc/cloud-services/pkg/testhelper"
"github.com/fiskerinc/cloud-services/pkg/testrunner"
"github.com/fiskerinc/cloud-services/pkg/utils/elptr"
vconfig "github.com/fiskerinc/cloud-services/pkg/vehicleconfig"
"github.com/jinzhu/copier"
)
func TestSendManifest(t *testing.T) {
os.Setenv("APP_SERVICE_NAME", "ATTENDANT")
handlers.PrivateSeed = 123456789
ka := services.NewKeepAwakeService()
ka.SetService(&services.MockKeepAwakeImplementation{})
now := time.Now()
testVIN := "JH4KA7680RC01"
tboxKey := common.TRex.Key(testVIN)
hmiKey := common.HMI.Key(testVIN)
smsKey := "manifest_tbox_send_cache:100"
var bhex common.BinaryHex = []byte("test")
redis.MockRedisConnection()
falsePtrValue := elptr.ElPtr(false)
truePtrValue := elptr.ElPtr(true)
ecuaRollback := []*common.UpdateManifestECU{
{
ID: 100,
UpdateManifestID: 200,
ECU: "ECUA",
Version: "VERSIONOLD",
Mode: "A",
DBModelBase: th.Timestamp,
Files: []*common.UpdateManifestFile{
{
FileID: "FILEIDOLD",
UpdateManifestECUID: 1001,
Filename: "FILENAMEOLD",
URL: "URLOLD",
FileType: common.Software,
WriteRegionID: 700,
WriteRegion: common.MemoryRegion{
Offset: 701,
Length: 702,
},
FileSize: 240,
DBModelBase: th.Timestamp,
},
},
},
}
ecus := []*common.UpdateManifestECU{
{
ECU: "ICC",
Version: "SWVERSION",
HWVersions: []string{"HWVERSION"},
Mode: "D",
SelfDownload: true,
InstallPriority: 13,
Files: []*common.UpdateManifestFile{
{
FileID: "AAAAAAA",
URL: "http://download.com/file1.bin",
FileSize: 1000,
Checksum: "AAAAAAA",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Calibration,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
DBModelBase: th.Timestamp,
},
{
FileID: "SHOULD_NOT_BE_IN_UPDATE",
URL: "http://download.com/SHOULD_NOT_BE_IN_UPDATE.bin",
FileSize: 1000,
Checksum: "AAAAAAA",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Calibration,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: falsePtrValue,
DBModelBase: th.Timestamp,
},
{
FileID: "MUST_BE_IN_UPDATE",
URL: "http://download.com/MUST_BE_IN_UPDATE.bin",
FileSize: 1000,
Checksum: "AAAAAAA",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Calibration,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: truePtrValue,
DBModelBase: th.Timestamp,
},
},
},
{
ECU: "ECUD",
Version: "SWVERSION",
HWVersions: []string{"HWVERSION"},
Mode: "D",
InstallPriority: 4,
Files: []*common.UpdateManifestFile{
{
FileID: "SHOULD_NOT_BE_IN_UPDATE",
URL: "http://download.com/SHOULD_NOT_BE_IN_UPDATE.bin",
FileSize: 1000,
Checksum: "AAAAAAA",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Calibration,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: falsePtrValue,
DBModelBase: th.Timestamp,
},
{
FileID: "MUST_BE_IN_UPDATE",
URL: "http://download.com/MUST_BE_IN_UPDATE.bin",
FileSize: 1000,
Checksum: "AAAAAAA",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Calibration,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: truePtrValue,
DBModelBase: th.Timestamp,
},
{
FileID: "BBBBBBB",
URL: "http://download.com/file2.bin",
FileSize: 2000,
Checksum: "BBBBBBB",
FileType: common.Calibration,
WriteRegionID: 300,
WriteRegion: common.MemoryRegion{
Offset: 301,
Length: 302,
},
EraseRegionID: 400,
EraseRegion: &common.MemoryRegion{
Offset: 401,
Length: 402,
},
DBModelBase: th.Timestamp,
},
},
DBModelBase: th.Timestamp,
},
{
ID: 100,
UpdateManifestID: 200,
ECU: "PDU",
Version: "PDU-VERS",
HWVersions: []string{"PDU-VERS"},
Mode: "PDU",
ConfigurationMask: "AAAAAAAA",
InstallPriority: 7,
Files: []*common.UpdateManifestFile{
{
FileID: "NOT_BE_IN_UPDATE",
URL: "http://download.com/NOT_BE_IN_UPDATE.bin",
FileSize: 1000,
Checksum: "AAAAAAA",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Calibration,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: falsePtrValue,
DBModelBase: th.Timestamp,
},
{
FileID: "MUST_BE_IN_UPDATE",
URL: "http://download.com/MUST_BE_IN_UPDATE.bin",
FileSize: 1000,
Checksum: "AAAAAAA",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Calibration,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: truePtrValue,
DBModelBase: th.Timestamp,
},
{
FileID: "AAAAAAAA",
URL: "http://download.com/filea.bin",
FileSize: 2000,
Checksum: "AAAAAAAA",
WriteRegionID: 500,
FileType: common.Calibration,
WriteRegion: common.MemoryRegion{
Offset: 501,
Length: 502,
},
DBModelBase: th.Timestamp,
},
},
DBModelBase: th.Timestamp,
},
{
ID: 100,
UpdateManifestID: 200,
ECU: "ECUA",
Version: "A-VERS",
HWVersions: []string{"A-VERS"},
Mode: "A",
ConfigurationMask: "AAAAAAAA",
InstallPriority: 1,
Files: []*common.UpdateManifestFile{
{
FileID: "FILEID",
UpdateManifestECUID: 100,
Filename: "FILENAME",
URL: "URL",
FileType: common.Calibration,
WriteRegionID: 600,
WriteRegion: common.MemoryRegion{
Offset: 601,
Length: 602,
},
FileSize: 240,
DBModelBase: th.Timestamp,
},
},
DBModelBase: th.Timestamp,
},
}
fingerprint := getTodaysFingerprint()
standardManifest := common.UpdateManifest{
ID: 100,
CarUpdateID: 297,
Name: "TEST",
Version: "MANIFEST_VERSION",
SUMS: "2023.10.01.00",
Description: "TESTDESC",
ReleaseNotes: "http://fiskerinc.com/release_notes",
Type: common.ManifestTypeForced,
Active: truePtrValue,
Country: "US",
PowerTrain: "MD23",
Restraint: "None",
Model: "Ocean",
Trim: "Sport",
Year: 2022,
BodyType: "truck",
RollbackEnabled: true,
ECUs: ecus,
UpdateDuration: 30,
}
rollbackDisabledManifest := common.UpdateManifest{
ID: 100,
CarUpdateID: 297,
Name: "TEST",
Version: "MANIFEST_VERSION",
SUMS: "2023.10.01.00.E",
Description: "TESTDESC",
ReleaseNotes: "http://fiskerinc.com/release_notes",
Type: "standard",
Active: truePtrValue,
Country: "US",
PowerTrain: "MD23",
Restraint: "None",
Model: "Ocean",
Trim: "Sport",
Year: 2022,
BodyType: "truck",
ECUs: ecus,
UpdateDuration: 30,
}
standardManifestNoICC := common.UpdateManifest{
ID: 100,
CarUpdateID: 297,
Name: "TEST",
Version: "MANIFEST_VERSION",
SUMS: "2023.10.01.00.E",
Description: "TESTDESC",
ReleaseNotes: "http://fiskerinc.com/release_notes",
Type: "standard",
Country: "US",
PowerTrain: "MD23",
Restraint: "None",
Model: "Ocean",
Trim: "Sport",
Year: 2022,
RollbackEnabled: true,
BodyType: "truck",
ECUs: []*common.UpdateManifestECU{
{
ECU: "ECUD",
HWVersions: []string{"HWVERSION"},
Version: "SWVERSION",
Mode: "D",
InstallPriority: 7,
Files: []*common.UpdateManifestFile{
{
FileID: "BBBBBBB",
URL: "http://download.com/file2.bin",
FileSize: 2000,
Checksum: "BBBBBBB",
FileType: common.Calibration,
WriteRegionID: 700,
WriteRegion: common.MemoryRegion{
Offset: 701,
Length: 702,
},
DBModelBase: th.Timestamp,
},
},
DBModelBase: th.Timestamp,
},
{
ID: 100,
UpdateManifestID: 200,
ECU: "PDU",
Version: "PDU-VERS",
HWVersions: []string{"PDU-VERS"},
Mode: "PDU",
ConfigurationMask: "AAAAAAAA",
InstallPriority: 10,
Files: []*common.UpdateManifestFile{
{
FileID: "AAAAAAAA",
URL: "http://download.com/filea.bin",
FileSize: 2000,
FileType: common.Calibration,
Checksum: "AAAAAAAA",
WriteRegionID: 800,
WriteRegion: common.MemoryRegion{
Offset: 801,
Length: 802,
},
EraseRegionID: 900,
EraseRegion: &common.MemoryRegion{
Offset: 901,
Length: 902,
},
DBModelBase: th.Timestamp,
},
},
DBModelBase: th.Timestamp,
},
{
ID: 100,
UpdateManifestID: 200,
ECU: "ECUA",
Version: "A-VERS",
HWVersions: []string{"A-VERS"},
Mode: "A",
ConfigurationMask: "AAAAAAAA",
InstallPriority: 4,
Files: []*common.UpdateManifestFile{
{
FileID: "FILEID",
UpdateManifestECUID: 100,
Filename: "FILENAME",
URL: "URL",
FileType: common.Calibration,
WriteRegionID: 600,
WriteRegion: common.MemoryRegion{
Offset: 601,
Length: 602,
},
FileSize: 240,
DBModelBase: th.Timestamp,
},
},
DBModelBase: th.Timestamp,
},
},
UpdateDuration: 30,
}
mockCarUpdate := &common.CarUpdate{
ID: 297,
VIN: testVIN,
UpdateManifestID: 100,
}
mockCarECUs := []common.CarECU{
{ECU: "ECUD", HWVersion: "HWVERSION"},
{ECU: "ECUA", HWVersion: "A-VERS", Version: "TEST122"},
{ECU: "OBC", HWVersion: "PDU-VERS", Version: "TEST121"},
{ECU: "BCM", HWVersion: ";#A;#"},
{ECU: "ICC", HWVersion: "HWVERSION", Version: "TEST123"},
}
mockRedis := rm.MockRedis{}
mockCUDB := dbm.MockCarUpdates{}
mockManDB := dbm.MockUpdateManifests{}
mockKeys := dbm.MockEccKeys{
MockListResponse: []common.ECCKeys{
{
ECU: "PDU",
PrivKey1: &bhex,
PrivKey2: &bhex,
PrivKey3: &bhex,
PubKey1: &bhex,
PubKey2: &bhex,
PubKey3: &bhex,
Env: "current",
DBModelBase: dbbasemodel.DBModelBase{
CreatedAt: &now,
UpdatedAt: &now,
},
},
{
ECU: "ECUA",
PrivKey1: &bhex,
PrivKey2: &bhex,
PrivKey3: &bhex,
PubKey1: &bhex,
PubKey2: &bhex,
PubKey3: &bhex,
Env: "current",
DBModelBase: dbbasemodel.DBModelBase{
CreatedAt: &now,
UpdatedAt: &now,
},
},
{
ECU: "ECUD",
PrivKey1: &bhex,
PrivKey2: &bhex,
PrivKey3: &bhex,
PubKey1: &bhex,
PubKey2: &bhex,
PubKey3: &bhex,
Env: "current",
DBModelBase: dbbasemodel.DBModelBase{
CreatedAt: &now,
UpdatedAt: &now,
},
},
},
}
services.GetDB().SetCarUpdates(&mockCUDB)
services.GetDB().SetCars(&dbm.MockCars{SelectCarECUs: mockCarECUs, SelectResponse: &common.Car{ICCID: "8000000000000000000"}})
services.GetDB().SetManifests(&mockManDB)
services.GetDB().SetECCKeys(&mockKeys)
services.SetRedisClientPool(rm.NewMockClientPool(&mockRedis))
mockSap := vconfig.SAPServiceMock{GetConfigurationMock: func(vin string) (common.SAPResponse, error) {
return common.SAPResponse{
ModelYear: 2023,
ModelType: "Ocean",
VersionDuringModelYear: "1",
Features: []common.SAPFeature{
{
FamilyCode: "FamilyCode1",
FeatureCode: "FeatureCode1",
},
{
FamilyCode: "FamilyCode2",
FeatureCode: "FeatureCode2",
},
},
}, nil
}}
mockConf := vconfig.ConfigMock{GetVODCDSCodingDataMock: func(request common.VODCDSRequest) (map[string]string, error) {
return map[string]string{
"EPS": "000147303031313632011D",
"ESP": "000F47303031313632000001012301027600000101000002B0",
"ECUA": "config",
"VOD": "",
"ADAS": "000147303031313632011D",
}, nil
}}
mockSMS := &sms.SMSMock{}
mockSMS.SetHandleSMSQueueResponse(&sms.SMSQueueResponse{
SmsMsgID: "100",
SentSuccessful: true,
}, nil)
services.SetSapService(mockSap)
services.SetVehicleConfig(mockConf)
services.SetSmsClient(mockSMS)
mockKafkaProducer := kafkaMock.GetKafkaMock(nil)
services.SetKafkaProducer(mockKafkaProducer)
clonedStandardManifest := common.UpdateManifest{}
clonedStandardManifestNoICC := common.UpdateManifest{}
err := copier.CopyWithOption(&clonedStandardManifest, &standardManifest, copier.Option{DeepCopy: true})
if err != nil {
t.Fatal(err)
}
err = copier.CopyWithOption(&clonedStandardManifestNoICC, &standardManifestNoICC, copier.Option{DeepCopy: true})
if err != nil {
t.Fatal(err)
}
tests := []testrunner.TestCase{
{
Name: "Send manifest w Self Download",
DBTestCase: &dbm.DBTestCase{
MockLoadResponse: mockCarUpdate,
SetupMockResponse: func() {
mockCUDB.LoadManifest = &clonedStandardManifest
mockManDB.ECUUpdatesMock = func(man *common.UpdateManifestECU, vin string) ([]*common.UpdateManifestECU, error) {
if man.ECU == "ECUA" {
return ecuaRollback, nil
}
return nil, nil
}
},
},
RedisTestCase: &rm.RedisTestCase{
Device: common.Service,
DeviceKey: kafka.OTAUpdateService,
PayloadData: `{"car_update_id":297}`,
ExpectedMessages: map[string]string{
hmiKey: `{"handler":"update_manifest","data":{"name":"TEST","version":"MANIFEST_VERSION","description":"TESTDESC","release_notes":"http://fiskerinc.com/release_notes","ecu_updates":[{"name":"ECUA","version":"A-VERS","current_version":"TEST122","hw_version":"A-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"FILEID","url":"URL","file_size":240,"type":"calibration","write_region":{"offset":601,"length":602}}]},{"name":"ECUD","version":"SWVERSION","hw_version":"HWVERSION","files":[{"file_id":"MUST_BE_IN_UPDATE","url":"http://download.com/MUST_BE_IN_UPDATE.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"BBBBBBB","url":"http://download.com/file2.bin","file_size":2000,"checksum":"BBBBBBB","type":"calibration","write_region":{"offset":301,"length":302},"erase_region":{"offset":401,"length":402}}]},{"name":"OBC","version":"PDU-VERS","current_version":"TEST121","hw_version":"PDU-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"MUST_BE_IN_UPDATE","url":"http://download.com/MUST_BE_IN_UPDATE.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"AAAAAAAA","url":"http://download.com/filea.bin","file_size":2000,"checksum":"AAAAAAAA","type":"calibration","write_region":{"offset":501,"length":502}}]},{"name":"ICC","version":"SWVERSION","current_version":"TEST123","hw_version":"HWVERSION","self_download":true,"files":[{"file_id":"AAAAAAA","url":"http://download.com/file1.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"MUST_BE_IN_UPDATE","url":"http://download.com/MUST_BE_IN_UPDATE.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}}]}],"fingerprint":"` + fingerprint + `","car_update_id":297,"rollback":true,"type":"forced","vod":"01011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110100202310010011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100001e","update_duration":30}}`,
},
ExpectedCaches: map[string]rm.ExpiringCacheResult{
// carupdateKey: {
// Value: `{"current_size":0,"ecu":"","errorcode":0,"file_size":0,"file_total":0,"id":297,"info":"ICC","installed":0,"status":"sent","total_files":0,"total_size":0}`,
// Expires: expectedExpire,
// },
smsKey: {
Value: `{"VIN":"JH4KA7680RC01","ManifestID":100,"Destination":"ICC"}`,
},
},
},
},
{
Name: "Send manifest w Self Download rollback disabled",
DBTestCase: &dbm.DBTestCase{
MockLoadResponse: mockCarUpdate,
SetupMockResponse: func() {
mockCUDB.LoadManifest = &rollbackDisabledManifest
mockManDB.ECUUpdatesMock = func(man *common.UpdateManifestECU, vin string) ([]*common.UpdateManifestECU, error) {
if man.ECU == "ECUA" {
return ecuaRollback, nil
}
return nil, nil
}
},
},
RedisTestCase: &rm.RedisTestCase{
Device: common.Service,
DeviceKey: kafka.OTAUpdateService,
PayloadData: `{"car_update_id":297}`,
ExpectedMessages: map[string]string{
hmiKey: `{"handler":"update_manifest","data":{"name":"TEST","version":"MANIFEST_VERSION","description":"TESTDESC","release_notes":"http://fiskerinc.com/release_notes","ecu_updates":[{"name":"ECUA","version":"A-VERS","current_version":"TEST122","hw_version":"A-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"FILEID","url":"URL","file_size":240,"type":"calibration","write_region":{"offset":601,"length":602}}]},{"name":"ECUD","version":"SWVERSION","hw_version":"HWVERSION","files":[{"file_id":"MUST_BE_IN_UPDATE","url":"http://download.com/MUST_BE_IN_UPDATE.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"BBBBBBB","url":"http://download.com/file2.bin","file_size":2000,"checksum":"BBBBBBB","type":"calibration","write_region":{"offset":301,"length":302},"erase_region":{"offset":401,"length":402}}]},{"name":"OBC","version":"PDU-VERS","current_version":"TEST121","hw_version":"PDU-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"MUST_BE_IN_UPDATE","url":"http://download.com/MUST_BE_IN_UPDATE.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"AAAAAAAA","url":"http://download.com/filea.bin","file_size":2000,"checksum":"AAAAAAAA","type":"calibration","write_region":{"offset":501,"length":502}}]},{"name":"ICC","version":"SWVERSION","current_version":"TEST123","hw_version":"HWVERSION","self_download":true,"files":[{"file_id":"AAAAAAA","url":"http://download.com/file1.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"MUST_BE_IN_UPDATE","url":"http://download.com/MUST_BE_IN_UPDATE.bin","file_size":1000,"checksum":"AAAAAAA","type":"calibration","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}}]}],"fingerprint":"` + fingerprint + `","car_update_id":297,"rollback":false,"type":"standard","vod":"0101111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111010020231001000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000ba","update_duration":30}}`,
},
ExpectedCaches: map[string]rm.ExpiringCacheResult{
smsKey: {
Value: `{"VIN":"JH4KA7680RC01","ManifestID":100,"Destination":"ICC"}`,
},
},
},
},
{
Name: "Bad message",
RedisTestCase: &rm.RedisTestCase{
Device: common.HMI,
DeviceKey: testVIN,
PayloadData: `{"car_update_id":`,
ExpectedError: "unexpected end of JSON input",
},
},
{
Name: "Send manifest w No Self Download",
DBTestCase: &dbm.DBTestCase{
MockLoadResponse: mockCarUpdate,
SetupMockResponse: func() {
mockCUDB.LoadManifest = &clonedStandardManifestNoICC
},
},
RedisTestCase: &rm.RedisTestCase{
Device: common.Service,
DeviceKey: kafka.OTAUpdateService,
PayloadData: `{"car_update_id":297}`,
ExpectedMessages: map[string]string{
hmiKey: `{"handler":"update_manifest","data":{"name":"TEST","version":"MANIFEST_VERSION","description":"TESTDESC","release_notes":"http://fiskerinc.com/release_notes","ecu_updates":[{"name":"ECUA","version":"A-VERS","current_version":"TEST122","hw_version":"A-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"FILEID","url":"URL","file_size":240,"type":"calibration","write_region":{"offset":601,"length":602}}]},{"name":"ECUD","version":"SWVERSION","hw_version":"HWVERSION","files":[{"file_id":"BBBBBBB","url":"http://download.com/file2.bin","file_size":2000,"checksum":"BBBBBBB","type":"calibration","write_region":{"offset":701,"length":702}}]},{"name":"OBC","version":"PDU-VERS","current_version":"TEST121","hw_version":"PDU-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"AAAAAAAA","url":"http://download.com/filea.bin","file_size":2000,"checksum":"AAAAAAAA","type":"calibration","write_region":{"offset":801,"length":802},"erase_region":{"offset":901,"length":902}}]}],"fingerprint":"` + fingerprint + `","car_update_id":297,"rollback":true,"type":"standard","vod":"0101111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111010020231001000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000ba","update_duration":30}}`,
tboxKey: `{"handler":"update_manifest","data":{"ecu_updates":[{"name":"ECUA","version":"A-VERS","current_version":"TEST122","hw_version":"A-VERS","configuration_mask":"AAAAAAAA","configuration":"config","files":[{"file_id":"FILEID","url":"URL","file_size":240,"type":"calibration","write_region":{"offset":601,"length":602}}],"rollback":[{"version":"VERSIONOLD","files":[{"file_id":"FILEIDOLD","url":"URLOLD","file_size":240,"type":"software","write_region":{"offset":701,"length":702}}]}],"ecc_keys":{"level_1":"74657374","level_2":"74657374","level_3":"74657374"}},{"name":"ECUD","version":"SWVERSION","hw_version":"HWVERSION","files":[{"file_id":"BBBBBBB","url":"http://download.com/file2.bin","file_size":2000,"checksum":"BBBBBBB","type":"calibration","write_region":{"offset":701,"length":702}}],"ecc_keys":{"level_1":"74657374","level_2":"74657374","level_3":"74657374"}},{"name":"OBC","version":"PDU-VERS","current_version":"TEST121","hw_version":"PDU-VERS","configuration_mask":"AAAAAAAA","files":[{"file_id":"AAAAAAAA","url":"http://download.com/filea.bin","file_size":2000,"checksum":"AAAAAAAA","type":"calibration","write_region":{"offset":801,"length":802},"erase_region":{"offset":901,"length":902}}],"ecc_keys":{"level_1":"74657374","level_2":"74657374","level_3":"74657374"}}],"fingerprint":"` + fingerprint + `","car_update_id":297,"rollback":true,"type":"standard","vod":"0101111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111010020231001000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000ba","update_duration":30}}`,
},
ExpectedCaches: map[string]rm.ExpiringCacheResult{
"manifest_tbox_send_cache:UQIDEPFQUH": {
Value: `{"VIN":"JH4KA7680RC01","ManifestID":0,"Destination":"ICC/TBOX"}`,
},
},
},
},
}
schemaTesterHMI := th.NewSchemaTestHelper(t, schemaToHMI)
schemaTesterTRex := th.NewSchemaTestHelper(t, schemaToTRex)
for _, test := range tests {
mockRedis.Reset()
for _, ecu := range ecus {
ecu.Rollback = nil
}
if test.DBTestCase != nil {
test.DBTestCase.SetupDB(&mockCUDB)
}
if test.RedisTestCase != nil {
test.RedisTestCase.SetupRedis(&mockRedis)
err := handlers.SendManifest(services.GetDB(), ka, test.RedisTestCase.Device, test.RedisTestCase.DeviceKey, []byte(test.RedisTestCase.PayloadData))
test.RedisTestCase.CheckHandlerError(t, test.Name, err)
test.RedisTestCase.Validate(t, test.Name, &mockRedis)
}
if test.DBTestCase != nil {
test.DBTestCase.Validate(t, test.Name, &mockCUDB)
}
for key, m := range test.RedisTestCase.ExpectedMessages {
name := fmt.Sprintf("%s %s", test.Name, key)
if strings.Contains(key, "2:") {
schemaTesterHMI.ValidateSchemaObject(name, []byte(m))
continue
}
schemaTesterTRex.ValidateSchemaObject(name, []byte(m))
}
}
}
func TestSendManifestMultiFile(t *testing.T) {
os.Setenv("APP_SERVICE_NAME", "ATTENDANT")
testVIN := "JH4KA7680RC01"
now := time.Now()
hmiKey := common.HMI.Key(testVIN)
falsePtrValue := elptr.ElPtr(false)
truePtrValue := elptr.ElPtr(true)
var bhex common.BinaryHex = []byte("test")
redis.MockRedisConnection()
ka := services.NewKeepAwakeService()
ka.SetService(&services.MockKeepAwakeImplementation{})
ecus := []*common.UpdateManifestECU{
{
ECU: "BCM",
Version: "DB22121A",
HWVersions: []string{";#A;#"},
Mode: "D",
SelfDownload: true,
Files: []*common.UpdateManifestFile{
{
FileID: "ShouldNotSee",
Filename: "notparsed.s19",
URL: "fakeurl.com",
Checksum: "shouldnotsee",
Parsed: falsePtrValue,
},
{
FileID: "3ee5fd6bc9402d67",
Filename: "MAGNA_BCM_FBL_driver.s19_0.bin",
URL: "https://upload-dev.fiskerdps.com/4466d78a-50e1-4f1d-a4b8-5f78076758ed/MAGNA_BCM_FBL_driver.s19_0.bin",
FileSize: 1000,
Checksum: "shouldsee",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Bootloader,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
DBModelBase: th.Timestamp,
Parsed: truePtrValue,
},
{
FileID: "7878ede9c9407779",
Filename: "FM29_Application_FR40_220111.s19_0.bin",
URL: "ttps://upload-dev.fiskerdps.com/b5c3c8c8-86cd-422e-aa11-a248697edfa3/FM29_Application_FR40_220111.s19_0.bin",
FileSize: 1000,
Checksum: "SHOULD NOT SEE",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Software,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: truePtrValue,
Signature: "ShouldNOtSee",
DBModelBase: th.Timestamp,
},
{
FileID: "7bb5083dc9407ae9",
Filename: "FM29_Application_FR40_220111.s19_1.bin",
URL: "https://upload-dev.fiskerdps.com/2cdeb566-cb00-42cd-93a8-69769b19269a/FM29_Application_FR40_220111.s19_1.bin",
FileSize: 1000,
Checksum: "shantsee",
WriteRegionID: 100,
WriteRegion: common.MemoryRegion{
Offset: 101,
Length: 102,
},
FileType: common.Software,
EraseRegionID: 200,
EraseRegion: &common.MemoryRegion{
Offset: 201,
Length: 202,
},
Parsed: truePtrValue,
DBModelBase: th.Timestamp,
Signature: "SHOULD NOT SEE",
},
{
FileID: "7ebb4fadc9409b91",
Filename: "FM29_Application_FR40_220111.s19_2.bin",
URL: "https://upload-dev.fiskerdps.com/ec9f8a84-61fb-4a9b-9735-ac6f91b07a83/FM29_Application_FR40_220111.s19_2.bin",
FileType: common.Software,
Parsed: truePtrValue,
Signature: "SomeSignatureYouShouldSee",
},
},
},
}
fingerprint := getTodaysFingerprint()
standardManifest := common.UpdateManifest{
ID: 100,
CarUpdateID: 297,
Name: "TEST",
Version: "MANIFEST_VERSION",
SUMS: "2023.10.01.00",
Description: "TESTDESC",
ReleaseNotes: "http://fiskerinc.com/release_notes",
Type: "standard",
Active: truePtrValue,
Country: "US",
PowerTrain: "MD23",
Restraint: "None",
Model: "Ocean",
Trim: "Sport",
Year: 2022,
BodyType: "truck",
RollbackEnabled: false,
ECUs: ecus,
UpdateDuration: 30,
}
mockCarUpdate := &common.CarUpdate{
ID: 297,
VIN: testVIN,
UpdateManifestID: 100,
}
mockCarECUs := []common.CarECU{
{ECU: "ECUD", HWVersion: "HWVERSION"},
{ECU: "ECUA", HWVersion: "A-VERS"},
{ECU: "OBC", HWVersion: "PDU-VERS"},
{ECU: "BCM", HWVersion: ";#A;#"},
{ECU: "ICC", HWVersion: "HWVERSION"},
}
mockRedis := rm.MockRedis{}
mockCUDB := dbm.MockCarUpdates{}
mockManDB := dbm.MockUpdateManifests{}
mockKeys := dbm.MockEccKeys{
MockListResponse: []common.ECCKeys{
{
ECU: "BCM",
PrivKey1: &bhex,
PrivKey2: &bhex,
PrivKey3: &bhex,
PubKey1: &bhex,
PubKey2: &bhex,
PubKey3: &bhex,
Env: "current",
DBModelBase: dbbasemodel.DBModelBase{
CreatedAt: &now,
UpdatedAt: &now,
},
},
},
}
services.GetDB().SetCarUpdates(&mockCUDB)
services.GetDB().SetCars(&dbm.MockCars{SelectCarECUs: mockCarECUs, SelectResponse: &common.Car{ICCID: ""}})
services.GetDB().SetManifests(&mockManDB)
services.GetDB().SetECCKeys(&mockKeys)
services.SetRedisClientPool(rm.NewMockClientPool(&mockRedis))
mockSap := vconfig.SAPServiceMock{GetConfigurationMock: func(vin string) (common.SAPResponse, error) {
return common.SAPResponse{
ModelYear: 2023,
ModelType: "Ocean",
VersionDuringModelYear: "1",
Features: []common.SAPFeature{
{
FamilyCode: "FamilyCode1",
FeatureCode: "FeatureCode1",
},
{
FamilyCode: "FamilyCode2",
FeatureCode: "FeatureCode2",
},
},
}, nil
}}
mockConf := vconfig.ConfigMock{GetVODCDSCodingDataMock: func(request common.VODCDSRequest) (map[string]string, error) {
return map[string]string{
"ECUA": "config",
"VOD": "",
}, nil
}}
mockSMS := &sms.SMSMock{}
mockSMS.SetHandleSMSQueueResponse(&sms.SMSQueueResponse{
SmsMsgID: "100",
SentSuccessful: true,
}, nil)
services.SetSmsClient(mockSMS)
services.SetSapService(mockSap)
services.SetVehicleConfig(mockConf)
smsKey := "manifest_tbox_send_cache:100"
tests := []testrunner.TestCase{
{
Name: "MultiFile right order",
DBTestCase: &dbm.DBTestCase{
MockLoadResponse: mockCarUpdate,
SetupMockResponse: func() {
mockCUDB.LoadManifest = &standardManifest
mockManDB.ECUUpdatesMock = func(man *common.UpdateManifestECU, vin string) ([]*common.UpdateManifestECU, error) {
if man.ECU == "ECUA" {
return nil, nil
}
return nil, nil
}
},
},
RedisTestCase: &rm.RedisTestCase{
Device: common.Service,
DeviceKey: kafka.OTAUpdateService,
PayloadData: `{"car_update_id":297}`,
ExpectedMessages: map[string]string{
hmiKey: `{"handler":"update_manifest","data":{"name":"TEST","version":"MANIFEST_VERSION","description":"TESTDESC","release_notes":"http://fiskerinc.com/release_notes","ecu_updates":[{"name":"BCM","version":"DB22121A","hw_version":";#A;#","self_download":true,"files":[{"file_id":"3ee5fd6bc9402d67","url":"https://upload-dev.fiskerdps.com/4466d78a-50e1-4f1d-a4b8-5f78076758ed/MAGNA_BCM_FBL_driver.s19_0.bin","file_size":1000,"checksum":"shouldsee","type":"bootloader","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"7878ede9c9407779","url":"ttps://upload-dev.fiskerdps.com/b5c3c8c8-86cd-422e-aa11-a248697edfa3/FM29_Application_FR40_220111.s19_0.bin","file_size":1000,"type":"software","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"7bb5083dc9407ae9","url":"https://upload-dev.fiskerdps.com/2cdeb566-cb00-42cd-93a8-69769b19269a/FM29_Application_FR40_220111.s19_1.bin","file_size":1000,"type":"software","write_region":{"offset":101,"length":102},"erase_region":{"offset":201,"length":202}},{"file_id":"7ebb4fadc9409b91","url":"https://upload-dev.fiskerdps.com/ec9f8a84-61fb-4a9b-9735-ac6f91b07a83/FM29_Application_FR40_220111.s19_2.bin","type":"software","write_region":{"offset":0,"length":0},"signature":"SomeSignatureYouShouldSee"}]}],"fingerprint":"` + fingerprint + `","car_update_id":297,"rollback":false,"type":"standard","vod":"01011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110100202310010011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100001e","update_duration":30}}`,
},
ExpectedCaches: map[string]rm.ExpiringCacheResult{smsKey: {
Value: `{"VIN":"JH4KA7680RC01","ManifestID":100,"Destination":"ICC"}`,
}},
},
},
}
for _, test := range tests {
mockRedis.Reset()
for _, ecu := range ecus {
ecu.Rollback = nil
}
if test.DBTestCase != nil {
test.DBTestCase.SetupDB(&mockCUDB)
}
if test.RedisTestCase != nil {
test.RedisTestCase.SetupRedis(&mockRedis)
err := handlers.SendManifest(services.GetDB(), ka, test.RedisTestCase.Device, test.RedisTestCase.DeviceKey, []byte(test.RedisTestCase.PayloadData))
test.RedisTestCase.CheckHandlerError(t, test.Name, err)
test.RedisTestCase.Validate(t, test.Name, &mockRedis)
}
if test.DBTestCase != nil {
test.DBTestCase.Validate(t, test.Name, &mockCUDB)
}
}
}
func TestSendManifestIntegration(t *testing.T) {
os.Setenv("APP_SERVICE_NAME", "ATTENDANT")
ka := services.NewKeepAwakeService()
ka.SetService(&services.MockKeepAwakeImplementation{})
err := handlers.SendManifest(services.GetDB(), ka, common.Service, "", []byte(`{"car_update_id":297}`))
if err != nil {
t.Error(err)
}
}
func getTodaysFingerprint() string {
// generate today's fingerprint
fpparams := manifestfingerprintparams.GetFPParams()
var fm = common.UpdateManifest{}
fm.GenerateFingerprint(fpparams.CurTime(), fpparams.ManifestSerial())
return fm.Fingerprint
}