dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts@v1.0.2/dtos/requests/deviceprofile_test.go (about)

     1  //
     2  // Copyright (C) 2020-2023 IOTech Ltd
     3  //
     4  // SPDX-License-Identifier: Apache-2.0
     5  
     6  package requests
     7  
     8  import (
     9  	"encoding/json"
    10  	"fmt"
    11  	"testing"
    12  
    13  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/common"
    14  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/dtos"
    15  	dtoCommon "dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/dtos/common"
    16  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/models"
    17  
    18  	"github.com/stretchr/testify/assert"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  var testLabels = []string{"MODBUS", "TEMP"}
    23  var testAttributes = map[string]interface{}{
    24  	"TestAttribute": "TestAttributeValue",
    25  }
    26  var testTags = map[string]any{
    27  	"TestTagsKey": "TestTagsValue",
    28  }
    29  
    30  func profileData() DeviceProfileRequest {
    31  	var testDeviceResources = []dtos.DeviceResource{{
    32  		Name:        TestDeviceResourceName,
    33  		Description: TestDescription,
    34  		Attributes:  testAttributes,
    35  		Properties: dtos.ResourceProperties{
    36  			ValueType: common.ValueTypeInt16,
    37  			ReadWrite: common.ReadWrite_RW,
    38  		},
    39  		Tags: testTags,
    40  	}}
    41  	var testDeviceCommands = []dtos.DeviceCommand{{
    42  		Name:      TestDeviceCommandName,
    43  		ReadWrite: common.ReadWrite_RW,
    44  		ResourceOperations: []dtos.ResourceOperation{{
    45  			DeviceResource: TestDeviceResourceName,
    46  		}},
    47  		Tags: testTags,
    48  	}}
    49  	return DeviceProfileRequest{
    50  		BaseRequest: dtoCommon.BaseRequest{
    51  			RequestId:   ExampleUUID,
    52  			Versionable: dtoCommon.NewVersionable(),
    53  		},
    54  		Profile: dtos.DeviceProfile{
    55  			DeviceProfileBasicInfo: dtos.DeviceProfileBasicInfo{
    56  				Name:         TestDeviceProfileName,
    57  				Manufacturer: TestManufacturer,
    58  				Description:  TestDescription,
    59  				Model:        TestModel,
    60  				Labels:       testLabels,
    61  			},
    62  			DeviceResources: testDeviceResources,
    63  			DeviceCommands:  testDeviceCommands,
    64  		},
    65  	}
    66  }
    67  
    68  var expectedDeviceProfile = models.DeviceProfile{
    69  	Name:         TestDeviceProfileName,
    70  	Manufacturer: TestManufacturer,
    71  	Description:  TestDescription,
    72  	Model:        TestModel,
    73  	Labels:       testLabels,
    74  	DeviceResources: []models.DeviceResource{{
    75  		Name:        TestDeviceResourceName,
    76  		Description: TestDescription,
    77  		Attributes:  testAttributes,
    78  		Properties: models.ResourceProperties{
    79  			ValueType: common.ValueTypeInt16,
    80  			ReadWrite: common.ReadWrite_RW,
    81  		},
    82  		Tags: testTags,
    83  	}},
    84  	DeviceCommands: []models.DeviceCommand{{
    85  		Name:      TestDeviceCommandName,
    86  		ReadWrite: common.ReadWrite_RW,
    87  		ResourceOperations: []models.ResourceOperation{{
    88  			DeviceResource: TestDeviceResourceName,
    89  		}},
    90  		Tags: testTags,
    91  	}},
    92  }
    93  
    94  func TestDeviceProfileRequest_Validate(t *testing.T) {
    95  	emptyString := " "
    96  	valid := profileData()
    97  	noName := profileData()
    98  	noName.Profile.Name = emptyString
    99  	noDeviceResourceAndDeviceCommand := profileData()
   100  	noDeviceResourceAndDeviceCommand.Profile.DeviceResources = []dtos.DeviceResource{}
   101  	noDeviceResourceAndDeviceCommand.Profile.DeviceCommands = []dtos.DeviceCommand{}
   102  	noDeviceResourceName := profileData()
   103  	noDeviceResourceName.Profile.DeviceResources[0].Name = emptyString
   104  	noDeviceResourcePropertyType := profileData()
   105  	noDeviceResourcePropertyType.Profile.DeviceResources[0].Properties.ValueType = emptyString
   106  	invalidDeviceResourcePropertyType := profileData()
   107  	invalidDeviceResourcePropertyType.Profile.DeviceResources[0].Properties.ValueType = "BadType"
   108  	noDeviceResourceReadWrite := profileData()
   109  	noDeviceResourceReadWrite.Profile.DeviceResources[0].Properties.ReadWrite = emptyString
   110  	invalidDeviceResourceReadWrite := profileData()
   111  	invalidDeviceResourceReadWrite.Profile.DeviceResources[0].Properties.ReadWrite = "invalid"
   112  	validDeviceResourceReadWrite := profileData()
   113  	validDeviceResourceReadWrite.Profile.DeviceResources[0].Properties.ReadWrite = common.ReadWrite_WR
   114  	dismatchDeviceCommand := profileData()
   115  	dismatchDeviceCommand.Profile.DeviceResources = []dtos.DeviceResource{}
   116  
   117  	tests := []struct {
   118  		name          string
   119  		DeviceProfile DeviceProfileRequest
   120  		expectError   bool
   121  	}{
   122  		{"valid DeviceProfileRequest", valid, false},
   123  		{"invalid DeviceProfileRequest, no name", noName, true},
   124  		{"valid DeviceProfileRequest, no deviceResource and no deviceCommand", noDeviceResourceAndDeviceCommand, false},
   125  		{"invalid DeviceProfileRequest, no deviceResource name", noDeviceResourceName, true},
   126  		{"invalid DeviceProfileRequest, no deviceResource property type", noDeviceResourcePropertyType, true},
   127  		{"invalid DeviceProfileRequest, invalid deviceResource property type", invalidDeviceResourcePropertyType, true},
   128  		{"invalid DeviceProfileRequest, no deviceResource property readWrite", noDeviceResourceReadWrite, true},
   129  		{"invalid DeviceProfileRequest, invalid deviceResource property readWrite", invalidDeviceResourcePropertyType, true},
   130  		{"valid DeviceProfileRequest, valid deviceResource property readWrite with value WR", validDeviceResourceReadWrite, false},
   131  		{"invalid DeviceProfileRequest, dismatch deviceCommand", dismatchDeviceCommand, true},
   132  	}
   133  	for _, tt := range tests {
   134  		t.Run(tt.name, func(t *testing.T) {
   135  			err := tt.DeviceProfile.Validate()
   136  			if tt.expectError {
   137  				require.Error(t, err)
   138  			} else {
   139  				require.NoError(t, err)
   140  			}
   141  		})
   142  	}
   143  
   144  	profileNameWithUnreservedChars := profileData()
   145  	profileNameWithUnreservedChars.Profile.Name = nameWithUnreservedChars
   146  
   147  	err := profileNameWithUnreservedChars.Validate()
   148  	assert.NoError(t, err, fmt.Sprintf("DeviceProfileRequest with profile name containing unreserved chars %s should pass validation", nameWithUnreservedChars))
   149  
   150  	// Following tests verify if profile name containing reserved characters should not be detected with an error
   151  	for _, n := range namesWithReservedChar {
   152  		profileNameWithReservedChar := profileData()
   153  		profileNameWithReservedChar.Profile.Name = n
   154  
   155  		err := profileNameWithReservedChar.Validate()
   156  		assert.NoError(t, err, fmt.Sprintf("DeviceProfileRequest with profile name containing reserved char %s should not return error during validation", n))
   157  	}
   158  }
   159  
   160  func TestAddDeviceProfile_UnmarshalJSON(t *testing.T) {
   161  	expected := profileData()
   162  	validData, err := json.Marshal(profileData())
   163  	require.NoError(t, err)
   164  	validValueTypeLowerCase := profileData()
   165  	validValueTypeLowerCase.Profile.DeviceResources[0].Properties.ValueType = "int16"
   166  	validValueTypeLowerCaseData, err := json.Marshal(validValueTypeLowerCase)
   167  	require.NoError(t, err)
   168  	validValueTypeUpperCase := profileData()
   169  	validValueTypeUpperCase.Profile.DeviceResources[0].Properties.ValueType = "INT16"
   170  	validValueTypeUpperCaseData, err := json.Marshal(validValueTypeUpperCase)
   171  	require.NoError(t, err)
   172  
   173  	tests := []struct {
   174  		name    string
   175  		data    []byte
   176  		wantErr bool
   177  	}{
   178  		{"unmarshal DeviceProfileRequest with success", validData, false},
   179  		{"unmarshal DeviceProfileRequest with success, valid value type int16", validValueTypeLowerCaseData, false},
   180  		{"unmarshal DeviceProfileRequest with success, valid value type INT16", validValueTypeUpperCaseData, false},
   181  		{"unmarshal invalid DeviceProfileRequest, empty data", []byte{}, true},
   182  		{"unmarshal invalid DeviceProfileRequest, string data", []byte("Invalid DeviceProfileRequest"), true},
   183  	}
   184  	for _, tt := range tests {
   185  		t.Run(tt.name, func(t *testing.T) {
   186  			var dp DeviceProfileRequest
   187  			err := dp.UnmarshalJSON(tt.data)
   188  			if tt.wantErr {
   189  				require.Error(t, err)
   190  			} else {
   191  				require.NoError(t, err)
   192  				assert.Equal(t, expected, dp, "Unmarshal did not result in expected DeviceProfileRequest.")
   193  			}
   194  		})
   195  	}
   196  }
   197  
   198  func TestAddDeviceProfileReqToDeviceProfileModels(t *testing.T) {
   199  	requests := []DeviceProfileRequest{profileData()}
   200  	expectedDeviceProfileModels := []models.DeviceProfile{expectedDeviceProfile}
   201  	resultModels := DeviceProfileReqToDeviceProfileModels(requests)
   202  	assert.Equal(t, expectedDeviceProfileModels, resultModels, "DeviceProfileReqToDeviceProfileModels did not result in expected DeviceProfile model.")
   203  }
   204  
   205  func TestNewDeviceProfileRequest(t *testing.T) {
   206  	expectedApiVersion := common.ApiVersion
   207  
   208  	actual := NewDeviceProfileRequest(dtos.DeviceProfile{})
   209  
   210  	assert.Equal(t, expectedApiVersion, actual.ApiVersion)
   211  }