EdgexAgent/device-gps-go/internal/transformer/transform_test.go
2025-07-10 20:30:06 +08:00

248 lines
8.9 KiB
Go

//
// Copyright (C) 2021-2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0
package transformer
import (
"context"
"fmt"
"math/rand"
"testing"
bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/container"
bootstrapMocks "github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/interfaces/mocks"
"github.com/edgexfoundry/go-mod-bootstrap/v4/di"
clientMocks "github.com/edgexfoundry/go-mod-core-contracts/v4/clients/interfaces/mocks"
"github.com/edgexfoundry/go-mod-core-contracts/v4/clients/logger"
"github.com/edgexfoundry/go-mod-core-contracts/v4/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos"
dtoCommon "github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/responses"
"github.com/edgexfoundry/go-mod-core-contracts/v4/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/edgexfoundry/device-sdk-go/v4/internal/cache"
"github.com/edgexfoundry/device-sdk-go/v4/internal/config"
"github.com/edgexfoundry/device-sdk-go/v4/internal/container"
"github.com/edgexfoundry/device-sdk-go/v4/pkg/interfaces/mocks"
sdkModels "github.com/edgexfoundry/device-sdk-go/v4/pkg/models"
)
const (
TestDevice = "testDevice"
TestDeviceService = "testDeviceService"
TestProfile = "testProfile"
TestDeviceResource = "testResource"
TestDeviceCommand = "testCommand"
TestValue = "testValue"
TestUnits = "testUnits"
)
var TestProtocols map[string]dtos.ProtocolProperties
func NewMockDIC() *di.Container {
cr := sdkModels.CommandRequest{
DeviceResourceName: TestDeviceResource,
Attributes: nil,
Type: common.ValueTypeString,
}
cv := &sdkModels.CommandValue{
DeviceResourceName: TestDeviceResource,
Type: common.ValueTypeString,
Value: TestValue,
Tags: make(map[string]string),
}
driverMock := &mocks.ProtocolDriver{}
driverMock.On("HandleReadCommands", TestDevice, TestProtocols, []sdkModels.CommandRequest{cr}).Return(nil, nil)
driverMock.On("HandleWriteCommands", TestDevice, TestProtocols, []sdkModels.CommandRequest{cr}, []*sdkModels.CommandValue{cv}).Return(nil)
devices := responses.MultiDevicesResponse{
BaseWithTotalCountResponse: dtoCommon.BaseWithTotalCountResponse{},
Devices: []dtos.Device{
{
Name: TestDevice,
AdminState: models.Unlocked,
OperatingState: models.Up,
Protocols: TestProtocols,
ServiceName: TestDeviceService,
ProfileName: TestProfile,
},
},
}
dcMock := &clientMocks.DeviceClient{}
dcMock.On("DevicesByServiceName", context.Background(), TestDeviceService, 0, -1).Return(devices, nil)
profile := responses.DeviceProfileResponse{
BaseResponse: dtoCommon.BaseResponse{},
Profile: dtos.DeviceProfile{
DeviceProfileBasicInfo: dtos.DeviceProfileBasicInfo{Name: TestProfile},
DeviceResources: []dtos.DeviceResource{
{
Name: TestDeviceResource,
Properties: dtos.ResourceProperties{
ValueType: common.ValueTypeString,
ReadWrite: common.ReadWrite_RW,
DefaultValue: TestValue,
Units: TestUnits,
},
},
},
DeviceCommands: []dtos.DeviceCommand{
{
Name: TestDeviceCommand,
IsHidden: false,
ReadWrite: common.ReadWrite_RW,
ResourceOperations: []dtos.ResourceOperation{{DeviceResource: TestDeviceResource}},
},
},
},
}
dpcMock := &clientMocks.DeviceProfileClient{}
dpcMock.On("DeviceProfileByName", context.Background(), TestProfile).Return(profile, nil)
pwcMock := &clientMocks.ProvisionWatcherClient{}
pwcMock.On("ProvisionWatchersByServiceName", context.Background(), TestDeviceService, 0, -1).Return(responses.MultiProvisionWatchersResponse{}, nil)
configuration := &config.ConfigurationStruct{
Device: config.DeviceInfo{MaxCmdOps: 1},
}
mockMetricsManager := &bootstrapMocks.MetricsManager{}
mockMetricsManager.On("Register", mock.Anything, mock.Anything, mock.Anything).Return(nil)
mockMetricsManager.On("Unregister", mock.Anything)
return di.NewContainer(di.ServiceConstructorMap{
bootstrapContainer.LoggingClientInterfaceName: func(get di.Get) interface{} {
return logger.NewMockClient()
},
container.ProtocolDriverName: func(get di.Get) interface{} {
return driverMock
},
bootstrapContainer.DeviceClientName: func(get di.Get) interface{} {
return dcMock
},
bootstrapContainer.DeviceProfileClientName: func(get di.Get) interface{} {
return dpcMock
},
bootstrapContainer.ProvisionWatcherClientName: func(get di.Get) interface{} {
return pwcMock
},
container.ConfigurationName: func(get di.Get) interface{} {
return configuration
},
bootstrapContainer.MetricsManagerInterfaceName: func(get di.Get) interface{} {
return mockMetricsManager
},
})
}
func Test_getUniqueOrigin(t *testing.T) {
// nolint: gosec
for i := 0; i < rand.Intn(1000); i++ {
t.Run(fmt.Sprintf("TestCase%d", i), func(t *testing.T) {
t.Parallel()
o1 := getUniqueOrigin()
o2 := getUniqueOrigin()
assert.NotEqual(t, o1, o2)
})
}
}
func TestCommandValuesToEventDTO_ReadingUnits(t *testing.T) {
dic := NewMockDIC()
err := cache.InitCache(TestDeviceService, TestDeviceService, dic)
require.NoError(t, err)
stringCommandValue, e := sdkModels.NewCommandValue(TestDeviceResource, common.ValueTypeString, TestValue)
require.NoError(t, e)
tests := []struct {
Name string
CommandValues []*sdkModels.CommandValue
ReadingUnits bool
}{
{"ReadingUnits is true, indicate Units in the Reading", []*sdkModels.CommandValue{stringCommandValue}, true},
{"ReadingUnits is false, not to indicate Units in the Reading", []*sdkModels.CommandValue{stringCommandValue}, false},
}
for _, testCase := range tests {
t.Run(testCase.Name, func(t *testing.T) {
configuration := container.ConfigurationFrom(dic.Get)
configuration.Writable.Reading.ReadingUnits = testCase.ReadingUnits
dic.Update(di.ServiceConstructorMap{
container.ConfigurationName: func(get di.Get) interface{} {
return configuration
},
})
event, err := CommandValuesToEventDTO(testCase.CommandValues, TestDevice, TestDeviceCommand, configuration.Device.DataTransform, dic)
require.NoError(t, err)
assert.Equal(t, TestDevice, event.DeviceName)
assert.Equal(t, TestProfile, event.ProfileName)
assert.Equal(t, TestDeviceCommand, event.SourceName)
assert.Equal(t, TestDeviceResource, event.Readings[0].ResourceName)
if testCase.ReadingUnits {
assert.NotEmpty(t, event.Readings[0].Units, "units is not presented")
assert.Equal(t, TestUnits, event.Readings[0].Units)
} else {
assert.Empty(t, event.Readings[0].Units, "units is presented")
}
})
}
}
func TestCommandValuesToEventDTO_ReadingNilValue(t *testing.T) {
dic := NewMockDIC()
err := cache.InitCache(TestDeviceService, TestDeviceService, dic)
require.NoError(t, err)
cvs := []*sdkModels.CommandValue{
testCommandNilValue(t, common.ValueTypeBool),
testCommandNilValue(t, common.ValueTypeString),
testCommandNilValue(t, common.ValueTypeUint8),
testCommandNilValue(t, common.ValueTypeUint16),
testCommandNilValue(t, common.ValueTypeUint32),
testCommandNilValue(t, common.ValueTypeUint64),
testCommandNilValue(t, common.ValueTypeInt8),
testCommandNilValue(t, common.ValueTypeInt16),
testCommandNilValue(t, common.ValueTypeInt32),
testCommandNilValue(t, common.ValueTypeInt64),
testCommandNilValue(t, common.ValueTypeFloat32),
testCommandNilValue(t, common.ValueTypeFloat64),
testCommandNilValue(t, common.ValueTypeBinary),
testCommandNilValue(t, common.ValueTypeBoolArray),
testCommandNilValue(t, common.ValueTypeStringArray),
testCommandNilValue(t, common.ValueTypeUint8Array),
testCommandNilValue(t, common.ValueTypeUint16Array),
testCommandNilValue(t, common.ValueTypeUint32Array),
testCommandNilValue(t, common.ValueTypeUint64Array),
testCommandNilValue(t, common.ValueTypeInt8Array),
testCommandNilValue(t, common.ValueTypeInt16Array),
testCommandNilValue(t, common.ValueTypeInt32Array),
testCommandNilValue(t, common.ValueTypeInt64Array),
testCommandNilValue(t, common.ValueTypeFloat32Array),
testCommandNilValue(t, common.ValueTypeFloat64Array),
testCommandNilValue(t, common.ValueTypeObject),
testCommandNilValue(t, common.ValueTypeObjectArray),
}
event, err := CommandValuesToEventDTO(cvs, TestDevice, TestDeviceCommand, true, dic)
require.NoError(t, err)
for _, r := range event.Readings {
assert.Empty(t, r.Value)
assert.Empty(t, r.BinaryValue)
assert.Empty(t, r.ObjectValue)
expectedNullReading := dtos.NewNullReading(TestProfile, TestDevice, TestDeviceResource, r.ValueType)
expectedNullReading.Id = r.Id
expectedNullReading.Origin = r.Origin
assert.Equal(t, expectedNullReading, r)
}
}
func testCommandNilValue(t *testing.T, valueType string) *sdkModels.CommandValue {
cv, e := sdkModels.NewCommandValue(TestDeviceResource, valueType, nil)
require.NoError(t, e)
return cv
}