diff --git a/dtos/event_test.go b/dtos/event_test.go index 3d76317f..db1ca781 100644 --- a/dtos/event_test.go +++ b/dtos/event_test.go @@ -151,7 +151,7 @@ func TestEvent_AddSimpleReading(t *testing.T) { assert.Equal(t, expectedDeviceName, actual.DeviceName) assert.Equal(t, expectedReadingDetails[index].resourceName, actual.ResourceName) assert.Equal(t, expectedReadingDetails[index].valueType, actual.ValueType) - assert.Equal(t, expectedReadingDetails[index].value, actual.Value) + assert.Equal(t, expectedReadingDetails[index].value, *actual.Value) assert.NotZero(t, actual.Origin) } } diff --git a/dtos/reading.go b/dtos/reading.go index 1755cec0..07d3bd30 100644 --- a/dtos/reading.go +++ b/dtos/reading.go @@ -35,7 +35,7 @@ type BaseReading struct { } type SimpleReading struct { - Value string `json:"value"` + Value *string `json:"value"` } type BinaryReading struct { @@ -60,14 +60,20 @@ func newBaseReading(profileName string, deviceName string, resourceName string, // NewSimpleReading creates and returns a new initialized BaseReading with its SimpleReading initialized func NewSimpleReading(profileName string, deviceName string, resourceName string, valueType string, value any) (BaseReading, error) { - stringValue, err := convertInterfaceValue(valueType, value) - if err != nil { - return BaseReading{}, err + var val *string + if value == nil { + val = nil + } else { + stringValue, err := convertInterfaceValue(valueType, value) + if err != nil { + return BaseReading{}, err + } + val = &stringValue } reading := newBaseReading(profileName, deviceName, resourceName, valueType) reading.SimpleReading = SimpleReading{ - Value: stringValue, + Value: val, } return reading, nil } @@ -286,7 +292,7 @@ func (b BaseReading) Validate() error { if err := common.Validate(simpleReading); err != nil { return err } - if err := ValidateValue(b.ValueType, simpleReading.Value); err != nil { + if err := ValidateValue(b.ValueType, *simpleReading.Value); err != nil { return edgexErrors.NewCommonEdgeX(edgexErrors.KindContractInvalid, fmt.Sprintf("The value does not match the %v valueType", b.ValueType), nil) } } @@ -321,7 +327,7 @@ func ToReadingModel(r BaseReading) models.Reading { } else { readingModel = models.SimpleReading{ BaseReading: br, - Value: r.Value, + Value: *r.Value, } } return readingModel @@ -364,7 +370,7 @@ func FromReadingModelToDTO(reading models.Reading) BaseReading { ValueType: r.ValueType, Units: r.Units, Tags: r.Tags, - SimpleReading: SimpleReading{Value: r.Value}, + SimpleReading: SimpleReading{Value: &r.Value}, } } diff --git a/dtos/reading_test.go b/dtos/reading_test.go index cc4879de..81e92b8a 100644 --- a/dtos/reading_test.go +++ b/dtos/reading_test.go @@ -16,6 +16,8 @@ import ( "github.com/stretchr/testify/assert" ) +var TestSimpleValue = "500" + var testSimpleReading = BaseReading{ Id: TestUUID, DeviceName: TestDeviceName, @@ -26,7 +28,7 @@ var testSimpleReading = BaseReading{ Units: TestUnit, Tags: testTags, SimpleReading: SimpleReading{ - Value: TestValue, + Value: &TestSimpleValue, }, } @@ -83,7 +85,7 @@ func TestFromReadingModelToDTO(t *testing.T) { Units: TestUnit, Tags: testTags, SimpleReading: SimpleReading{ - Value: TestValue, + Value: &TestSimpleValue, }, } @@ -148,7 +150,7 @@ func TestNewSimpleReading(t *testing.T) { assert.Equal(t, expectedDeviceName, actual.DeviceName) assert.Equal(t, expectedResourceName, actual.ResourceName) assert.Equal(t, tt.expectedValueType, actual.ValueType) - assert.Equal(t, tt.expectedValue, actual.Value) + assert.Equal(t, tt.expectedValue, *actual.Value) assert.NotZero(t, actual.Origin) }) } @@ -194,6 +196,60 @@ func TestNewSimpleReadingError(t *testing.T) { } } +func TestNewSimpleReadingWithNilValue(t *testing.T) { + expectedDeviceName := TestDeviceName + expectedProfileName := TestDeviceProfileName + expectedResourceName := TestDeviceResourceName + + var nilValue *string = nil + + tests := []struct { + name string + expectedValueType string + value any + expectedValue any + }{ + {"Simple Boolean", common.ValueTypeBool, nil, nilValue}, + {"Simple String", common.ValueTypeString, nil, nilValue}, + {"Simple Uint8", common.ValueTypeUint8, nil, nilValue}, + {"Simple Uint16", common.ValueTypeUint16, nil, nilValue}, + {"Simple Uint32", common.ValueTypeUint32, nil, nilValue}, + {"Simple uint64", common.ValueTypeUint64, nil, nilValue}, + {"Simple int8", common.ValueTypeInt8, nil, nilValue}, + {"Simple int16", common.ValueTypeInt16, nil, nilValue}, + {"Simple int32", common.ValueTypeInt32, nil, nilValue}, + {"Simple int64", common.ValueTypeInt64, nil, nilValue}, + {"Simple Float32", common.ValueTypeFloat32, nil, nilValue}, + {"Simple Float64", common.ValueTypeFloat64, nil, nilValue}, + {"Simple Boolean Array", common.ValueTypeBoolArray, nil, nilValue}, + {"Simple String Array", common.ValueTypeStringArray, nil, nilValue}, + {"Simple Uint8 Array", common.ValueTypeUint8Array, nil, nilValue}, + {"Simple Uint16 Array", common.ValueTypeUint16Array, nil, nilValue}, + {"Simple Uint32 Array", common.ValueTypeUint32Array, nil, nilValue}, + {"Simple Uint64 Array", common.ValueTypeUint64Array, nil, nilValue}, + {"Simple Int8 Array", common.ValueTypeInt8Array, nil, nilValue}, + {"Simple Int16 Array", common.ValueTypeInt16Array, nil, nilValue}, + {"Simple Int32 Array", common.ValueTypeInt32Array, nil, nilValue}, + {"Simple Int64 Array", common.ValueTypeInt64Array, nil, nilValue}, + {"Simple Float32 Array", common.ValueTypeFloat32Array, nil, nilValue}, + {"Simple Float64 Array", common.ValueTypeFloat64Array, nil, nilValue}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual, err := NewSimpleReading(expectedProfileName, expectedDeviceName, expectedResourceName, tt.expectedValueType, tt.value) + require.NoError(t, err) + assert.NotEmpty(t, actual.Id) + assert.Equal(t, expectedProfileName, actual.ProfileName) + assert.Equal(t, expectedDeviceName, actual.DeviceName) + assert.Equal(t, expectedResourceName, actual.ResourceName) + assert.Equal(t, tt.expectedValueType, actual.ValueType) + assert.Equal(t, tt.expectedValue, actual.Value) + assert.NotZero(t, actual.Origin) + }) + } +} + func TestNewBinaryReading(t *testing.T) { expectedDeviceName := TestDeviceName expectedProfileName := TestDeviceProfileName @@ -214,6 +270,26 @@ func TestNewBinaryReading(t *testing.T) { assert.NotZero(t, actual.Origin) } +func TestNewBinaryReadingWithNilValue(t *testing.T) { + expectedDeviceName := TestDeviceName + expectedProfileName := TestDeviceProfileName + expectedResourceName := TestDeviceResourceName + + expectedValueType := common.ValueTypeBinary + var expectedBinaryValue []byte = nil + expectedMediaType := "application/text" + + actual := NewBinaryReading(expectedProfileName, expectedDeviceName, expectedResourceName, expectedBinaryValue, expectedMediaType) + + assert.NotEmpty(t, actual.Id) + assert.Equal(t, expectedProfileName, actual.ProfileName) + assert.Equal(t, expectedDeviceName, actual.DeviceName) + assert.Equal(t, expectedResourceName, actual.ResourceName) + assert.Equal(t, expectedValueType, actual.ValueType) + assert.Equal(t, expectedBinaryValue, actual.BinaryValue) + assert.NotZero(t, actual.Origin) +} + func TestNewObjectReading(t *testing.T) { expectedDeviceName := TestDeviceName expectedProfileName := TestDeviceProfileName @@ -262,6 +338,24 @@ func TestNewObjectReadingWithArray(t *testing.T) { assert.NotZero(t, actual.Origin) } +func TestNewObjectReadingWithNilValue(t *testing.T) { + expectedDeviceName := TestDeviceName + expectedProfileName := TestDeviceProfileName + expectedResourceName := TestDeviceResourceName + expectedValueType := common.ValueTypeObject + var expectedValue any = nil + + actual := NewObjectReading(expectedProfileName, expectedDeviceName, expectedResourceName, expectedValue) + + assert.NotEmpty(t, actual.Id) + assert.Equal(t, expectedProfileName, actual.ProfileName) + assert.Equal(t, expectedDeviceName, actual.DeviceName) + assert.Equal(t, expectedResourceName, actual.ResourceName) + assert.Equal(t, expectedValueType, actual.ValueType) + assert.Equal(t, expectedValue, actual.ObjectValue) + assert.NotZero(t, actual.Origin) +} + func TestValidateValue(t *testing.T) { tests := []struct { name string diff --git a/dtos/requests/event.go b/dtos/requests/event.go index 8711b785..948e0c4f 100644 --- a/dtos/requests/event.go +++ b/dtos/requests/event.go @@ -42,6 +42,9 @@ func (a AddEventRequest) Validate() error { // Otherwise error will occur as only one of them exists // Therefore, need to validate the nested BinaryReading and SimpleReading struct here for _, r := range a.Event.Readings { + if r.Value == nil { + continue // since we support nil value, skip checking + } if err := r.Validate(); err != nil { return err } diff --git a/dtos/requests/event_test.go b/dtos/requests/event_test.go index 1c197ff8..ebabeb27 100644 --- a/dtos/requests/event_test.go +++ b/dtos/requests/event_test.go @@ -77,7 +77,7 @@ func TestAddEventRequest_Validate(t *testing.T) { invalidReadingInvalidValueType.Event.Readings[0].ValueType = "BadType" invalidSimpleReadingNoValue := eventRequestData() - invalidSimpleReadingNoValue.Event.Readings[0].SimpleReading.Value = "" + invalidSimpleReadingNoValue.Event.Readings[0].SimpleReading.Value = &emptyString invalidBinaryReadingNoValue := eventRequestData() invalidBinaryReadingNoValue.Event.Readings[0].ValueType = common.ValueTypeBinary