258 lines
9.5 KiB
Go
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)
|
|
}
|
|
})
|
|
}
|
|
}
|