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

258 lines
9.5 KiB
Go

// -*- Mode: Go; indent-tabs-mode: t -*-
//
// # Copyright (C) 2023 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
package provision
import (
"context"
goErrors "errors"
"github.com/edgexfoundry/device-sdk-go/v4/internal/cache"
"github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/interfaces"
"github.com/edgexfoundry/go-mod-core-contracts/v4/clients/logger"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/requests"
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/responses"
"github.com/edgexfoundry/go-mod-core-contracts/v4/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net/url"
"path"
"testing"
)
var simpleProfile = responses.DeviceProfileResponse{
Profile: dtos.DeviceProfile{
DeviceProfileBasicInfo: dtos.DeviceProfileBasicInfo{
Name: "Simple-Device",
Manufacturer: "Simple Corp.",
Description: "Example of Simple Device",
Model: "SP-01",
Labels: []string{"modbus"},
},
DeviceResources: []dtos.DeviceResource{
{
Description: "Switch On/Off.",
Name: "SwitchButton",
IsHidden: false,
Properties: dtos.ResourceProperties{
ValueType: "Bool",
ReadWrite: "RW",
DefaultValue: "true",
},
},
{
Description: "Visual representation of Switch state.",
Name: "Image",
IsHidden: false,
Properties: dtos.ResourceProperties{
ValueType: "Binary",
ReadWrite: "R",
MediaType: "image/jpeg",
},
},
{
Description: "X axis rotation rate",
Name: "Xrotation",
IsHidden: true,
Properties: dtos.ResourceProperties{
ValueType: "Int32",
ReadWrite: "RW",
Units: "rpm",
},
},
{
Description: "y axis rotation rate",
Name: "yrotation",
IsHidden: true,
Properties: dtos.ResourceProperties{
ValueType: "Int32",
ReadWrite: "RW",
Units: "rpm",
},
},
{
Description: "z axis rotation rate",
Name: "zrotation",
IsHidden: true,
Properties: dtos.ResourceProperties{
ValueType: "Int32",
ReadWrite: "RW",
Units: "rpm",
},
},
{
Description: "String array",
Name: "StringArray",
IsHidden: false,
Properties: dtos.ResourceProperties{
ValueType: "StringArray",
ReadWrite: "RW",
},
},
{
Description: "Unsigned 8bit array",
Name: "Uint8Array",
IsHidden: false,
Properties: dtos.ResourceProperties{
ValueType: "Uint8Array",
ReadWrite: "RW",
},
},
{
Description: "Counter data",
Name: "Counter",
IsHidden: false,
Properties: dtos.ResourceProperties{
ValueType: "Object",
ReadWrite: "RW",
},
},
},
DeviceCommands: []dtos.DeviceCommand{
{
Name: "Switch",
IsHidden: false,
ReadWrite: "RW",
ResourceOperations: []dtos.ResourceOperation{
{
DeviceResource: "SwitchButton",
DefaultValue: "false",
},
},
},
{
Name: "Image",
IsHidden: false,
ReadWrite: "R",
ResourceOperations: []dtos.ResourceOperation{
{
DeviceResource: "Image",
},
},
},
{
Name: "Rotation",
IsHidden: false,
ReadWrite: "RW",
ResourceOperations: []dtos.ResourceOperation{
{
DeviceResource: "XRotation",
DefaultValue: "0",
},
{
DeviceResource: "YRotation",
DefaultValue: "0",
},
{
DeviceResource: "ZRotation",
DefaultValue: "0",
},
},
},
},
},
}
func Test_processProfiles(t *testing.T) {
tests := []struct {
name string
path string
secretProvider interfaces.SecretProvider
profileName string
dpcMockRes responses.DeviceProfileResponse
dpcMockErr errors.EdgeX
expectedNumProfiles int
expectedEdgexErrMsg string
}{
{"valid load profile from file, profile exists", path.Join("..", "..", "example", "cmd", "device-gps", "res", "profiles", "Simple-Driver.yaml"), nil, "Simple-Device", simpleProfile, nil, 0, ""},
{"valid load profile from file, profile does not exist in metadata", path.Join("..", "..", "example", "cmd", "device-gps", "res", "profiles", "Simple-Driver.yaml"), nil, "Simple-Device", responses.DeviceProfileResponse{}, errors.NewCommonEdgeXWrapper(goErrors.New("could not find profile")), 1, ""},
{"valid load profile from uri, profile exists", "https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/example/cmd/device-simple/res/profiles/Simple-Driver.yaml", nil, "Simple-Device", simpleProfile, nil, 0, ""},
{"valid load profile from uri, profile does not exist in metadata", "https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/example/cmd/device-simple/res/profiles/Simple-Driver.yaml", nil, "Simple-Device", responses.DeviceProfileResponse{}, errors.NewCommonEdgeXWrapper(goErrors.New("could not find profile")), 1, ""},
{"invalid load empty profile from file", "", nil, "Simple-Device", responses.DeviceProfileResponse{}, errors.NewCommonEdgeXWrapper(goErrors.New("could not find profile")), 0, ""},
{"invalid load profile from bogus file", path.Join("..", "..", "example", "cmd", "device-gps", "res", "profiles", "bogus.yaml"), nil, "Simple-Device", responses.DeviceProfileResponse{}, nil, 0, ""},
{"invalid load profile from bogus uri", "https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/example/cmd/device-simple/res/profiles/bogus.yaml", nil, "Simple-Device", responses.DeviceProfileResponse{}, nil, 0, ""},
{"invalid load profile from file, duplicate profile", path.Join("..", "..", "example", "cmd", "device-gps", "res", "profiles", "Simple-Driver.yaml"), nil, "Simple-Device", profile, nil, 0, "Profile testProfile has already existed in cache"},
{"invalid load profile from uri, duplicate profile", "https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/example/cmd/device-simple/res/profiles/Simple-Driver.yaml", nil, "Simple-Device", profile, nil, 0, "Profile testProfile has already existed in cache"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var addProfilesReq []requests.DeviceProfileRequest
var edgexErr errors.EdgeX
lc := logger.MockLogger{}
dic, dpcMock := NewMockDIC()
dpcMock.On("DeviceProfileByName", context.Background(), tt.profileName).Return(tt.dpcMockRes, tt.dpcMockErr)
err := cache.InitCache(TestDeviceService, TestDeviceService, dic)
require.NoError(t, err)
addProfilesReq, edgexErr = processProfiles(tt.path, tt.path, tt.secretProvider, lc, dpcMock)
assert.Equal(t, len(addProfilesReq), tt.expectedNumProfiles)
if edgexErr != nil {
assert.Contains(t, edgexErr.Error(), tt.expectedEdgexErrMsg)
}
})
}
}
func Test_loadProfilesFromURI(t *testing.T) {
tests := []struct {
name string
path string
secretProvider interfaces.SecretProvider
profileNames []string
dpcMockRes []responses.DeviceProfileResponse
dpcMockErr []errors.EdgeX
expectedNumProfiles int
expectedEdgexErrMsg string
}{
{"valid load from uri, profile exists",
"https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/internal/provision/uri-test-files/profiles/index.json",
nil,
[]string{"Simple-Device", "Simple-Device2"},
[]responses.DeviceProfileResponse{simpleProfile, simpleProfile},
[]errors.EdgeX{nil, nil},
0, ""},
{"valid load from uri, profile does not exist in metadata",
"https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/internal/provision/uri-test-files/profiles/index.json",
nil,
[]string{"Simple-Device", "Simple-Device2"},
[]responses.DeviceProfileResponse{responses.DeviceProfileResponse{}, responses.DeviceProfileResponse{}},
[]errors.EdgeX{errors.NewCommonEdgeXWrapper(goErrors.New("could not find profile")), errors.NewCommonEdgeXWrapper(goErrors.New("could not find profile"))},
2, ""},
{"valid load where one profile exists and one profile does not exist in metadata",
"https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/internal/provision/uri-test-files/profiles/index.json",
nil,
[]string{"Simple-Device", "Simple-Device2"},
[]responses.DeviceProfileResponse{simpleProfile, responses.DeviceProfileResponse{}},
[]errors.EdgeX{nil, errors.NewCommonEdgeXWrapper(goErrors.New("could not find profile"))},
1, ""},
{"invalid load profile path join breaks",
"https://raw.githubusercontent.com/edgexfoundry/device-sdk-go/main/internal/provision/uri-test-files/profiles/bogus.json",
nil,
[]string{},
[]responses.DeviceProfileResponse{},
[]errors.EdgeX{},
0, "failed to load Device Profile list from URI"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var addProfilesReq []requests.DeviceProfileRequest
var edgexErr errors.EdgeX
lc := logger.MockLogger{}
dic, dpcMock := NewMockDIC()
for index := range tt.profileNames {
dpcMock.On("DeviceProfileByName", context.Background(), tt.profileNames[index]).Return(tt.dpcMockRes[index], tt.dpcMockErr[index])
}
edgexErr = cache.InitCache(TestDeviceService, TestDeviceService, dic)
require.NoError(t, edgexErr)
parsedURI, err := url.Parse(tt.path)
require.NoError(t, err)
addProfilesReq, edgexErr = loadProfilesFromURI(tt.path, parsedURI, dpcMock, tt.secretProvider, lc)
assert.Equal(t, len(addProfilesReq), tt.expectedNumProfiles)
if edgexErr != nil {
assert.Contains(t, edgexErr.Error(), tt.expectedEdgexErrMsg)
}
})
}
}