package handlers_test import ( "fmt" "net/http" "testing" "otaupdate/handlers" "otaupdate/services" "github.com/fiskerinc/cloud-services/pkg/cache" m "github.com/fiskerinc/cloud-services/pkg/common" dbtc "github.com/fiskerinc/cloud-services/pkg/db/queries/mocks" htc "github.com/fiskerinc/cloud-services/pkg/httpclient/tester" "github.com/fiskerinc/cloud-services/pkg/mongo" "github.com/fiskerinc/cloud-services/pkg/redis" rtc "github.com/fiskerinc/cloud-services/pkg/redis/tester" th "github.com/fiskerinc/cloud-services/pkg/testhelper" tr "github.com/fiskerinc/cloud-services/pkg/testrunner" "github.com/fiskerinc/cloud-services/pkg/utils/elptr" ) var schemaToTRex = "file://" + th.GetSchemaDirPath() + "/trex/RXMessage.json" func TestVehicleUpdate(t *testing.T) { client, err := services.GetMongoClient() if err != nil { t.Error(err) return } mockMongo := mongo.NewVehiclesCollection(&mongo.MockCollection{}) client.SetVehicles(mockMongo) mockRedis := rtc.MockRedis{} services.SetRedisClientPool(rtc.NewMockClientPool(&mockRedis)) mockDB := dbtc.MockCars{} services.GetDB().SetCars(&mockDB) vin := "1G1FP87S3GN100062" trexKey := m.TRex.Key(vin) cacheKey := redis.CarConfigKey(vin) tests := []tr.TestCase{ { Name: "Good data", HttpTestCase: &htc.HttpTestCase{ Request: th.MakeTestRequest(http.MethodPut, "http://example.com/vehicle", m.UpdateCarRequest{ VIN: vin, Model: "Ocean", Year: 2021, Trim: "Basic", Country: "Germany", Powertrain: "test pt", Restraint: "US Spec", BodyType: "test bt", CANBus: &m.CANBus{ Enabled: true, DataLogger: false, // DTCEnabled: elptr.ElPtr(true), }, IDPSEnabled: true, }), ExpectedStatus: http.StatusOK, ExpectedResponse: `{"vin":"1G1FP87S3GN100062","year":2021,"model":"Ocean","trim":"Basic","country":"Germany","powertrain":"test pt","restraint":"US Spec","body_type":"test bt","canbus":{"enabled":true,"data_logger_enabled":false,"dtc_enabled":true},"idps_enabled":true}`, }, RedisTestCase: &rtc.RedisTestCase{ ExpectedMessages: map[string]string{ trexKey: `{"data":{"canbus":{"data_logger_enabled":false,"dtc_enabled":true,"enabled":true},"log_level":"trace"},"handler":"config"}`, }, ExpectedCaches: map[string]rtc.ExpiringCacheResult{ cacheKey: {Value: "DELETED"}, }, }, }, { Name: "Good data with debug mask", HttpTestCase: &htc.HttpTestCase{ Request: th.MakeTestRequest(http.MethodPut, "http://example.com/vehicle", m.UpdateCarRequest{ VIN: vin, Model: "Ocean", Year: 2021, Trim: "Basic", Country: "Germany", Powertrain: "test pt", Restraint: "US Spec", BodyType: "test bt", CANBus: &m.CANBus{ Enabled: true, DataLogger: false, DTCEnabled: elptr.ElPtr(false), }, DebugMask: "E", IDPSEnabled: true, }), ExpectedStatus: http.StatusOK, ExpectedResponse: `{"vin":"1G1FP87S3GN100062","year":2021,"model":"Ocean","trim":"Basic","country":"Germany","powertrain":"test pt","restraint":"US Spec","body_type":"test bt","canbus":{"enabled":true,"data_logger_enabled":false,"dtc_enabled":false},"idps_enabled":true,"debug_mask":"E"}`, }, RedisTestCase: &rtc.RedisTestCase{ ExpectedMessages: map[string]string{ trexKey: `{"data":{"canbus":{"data_logger_enabled":false,"dtc_enabled":false,"enabled":true},"debug_mask":"E","log_level":"trace"},"handler":"config"}`, }, ExpectedCaches: map[string]rtc.ExpiringCacheResult{ cacheKey: {Value: "DELETED"}, }, }, }, { Name: "No CANBus", HttpTestCase: &htc.HttpTestCase{ Request: th.MakeTestRequest(http.MethodPut, "http://example.com/vehicle", m.UpdateCarRequest{ VIN: vin, Model: "Ocean", Year: 2021, Trim: "Basic", IDPSEnabled: true, }), ExpectedStatus: http.StatusOK, ExpectedResponse: `{"vin":"1G1FP87S3GN100062","year":2021,"model":"Ocean","trim":"Basic","idps_enabled":true}`, }, RedisTestCase: &rtc.RedisTestCase{ ExpectedMessages: map[string]string{}, ExpectedCaches: map[string]rtc.ExpiringCacheResult{ cacheKey: {Value: "DELETED"}, }, }, }, { Name: "No data", HttpTestCase: &htc.HttpTestCase{ Request: th.MakeTestRequest(http.MethodPut, "http://example.com/vehicle", nil), ExpectedStatus: http.StatusBadRequest, ExpectedResponse: `{"message":"VIN required. Year required. Model required. Trim required","error":"Bad Request"}`, }, }, { Name: "No VIN", HttpTestCase: &htc.HttpTestCase{ Request: th.MakeTestRequest(http.MethodPut, "http://example.com/vehicle", m.Car{ Model: "Ocean", Year: 2021, Trim: "Basic", }), ExpectedStatus: http.StatusBadRequest, ExpectedResponse: `{"message":"VIN required","error":"Bad Request"}`, }, }, { Name: "Bad data", HttpTestCase: &htc.HttpTestCase{ Request: th.MakeTestRequest(http.MethodPut, "http://example.com/vehicle", m.Car{ VIN: "XXXXXXXXXXXXXXXXXXXXX", Model: "Ocean", Year: 2021, Trim: "Basic", }), ExpectedStatus: http.StatusBadRequest, ExpectedResponse: `{"message":"VIN 'XXXXXXXXXXXXXXXXXXXXX' invalid","error":"Bad Request"}`, }, }, { Name: "Error", HttpTestCase: &htc.HttpTestCase{ Request: th.MakeTestRequest(http.MethodPut, "http://example.com/vehicle", m.Car{ VIN: "1G1FP87S3GN100062", Model: "Ocean", Year: 2021, Trim: "Basic", }), ExpectedStatus: http.StatusServiceUnavailable, ExpectedResponse: `{"message":"something went wrong","error":"Service Unavailable"}`, }, DBTestCase: &dbtc.DBTestCase{ MockError: fmt.Errorf("something went wrong"), }, }, } schemaTesterTRex := th.NewSchemaTestHelper(t, schemaToTRex) for _, test := range tests { mockRedis.Reset() if test.DBTestCase != nil { test.DBTestCase.SetupDB(&mockDB) } if test.RedisTestCase != nil { test.RedisTestCase.SetupRedis(&mockRedis) } if test.HttpTestCase != nil { w := test.HttpTestCase.Test(handlers.HandleVehicleUpdate) test.HttpTestCase.ValidateHttp(t, test.Name, w) } if test.DBTestCase != nil { test.DBTestCase.Validate(t, test.Name, &mockDB) } if test.RedisTestCase != nil { test.RedisTestCase.Validate(t, test.Name, &mockRedis) // By default in all environments, ENABLE_DEBUG_MASK is true // so we set that, otherwise unit tests fail. t.Setenv(cache.ENABLE_DBG_MASK_EV_NAME, cache.ENABLE_DBG_MASK_VAL_TRUE) cache.ENABLE_DEBUG_MASK = cache.DbgMaskEnabled() for _, mes := range test.RedisTestCase.ExpectedMessages { schemaTesterTRex.ValidateSchemaObject(test.Name, []byte(mes)) } } } }