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

     1  //
     2  // Copyright (C) 2021-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  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  
    16  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/dtos"
    17  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/dtos/common"
    18  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/models"
    19  )
    20  
    21  var testProvisionWatcherName = "TestWatcher"
    22  var testProvisionWatcherLabels = []string{"TEST", "TEMP"}
    23  var testIdentifiers = map[string]string{
    24  	"address": "localhost",
    25  	"port":    "3[0-9]{2}",
    26  }
    27  var testBlockingIdentifiers = map[string][]string{
    28  	"port": {"397", "398", "399"},
    29  }
    30  var testAddProvisionWatcher = AddProvisionWatcherRequest{
    31  	BaseRequest: common.BaseRequest{
    32  		RequestId:   ExampleUUID,
    33  		Versionable: common.NewVersionable(),
    34  	},
    35  	ProvisionWatcher: dtos.ProvisionWatcher{
    36  		Name:                testProvisionWatcherName,
    37  		ServiceName:         TestDeviceServiceName,
    38  		Labels:              testProvisionWatcherLabels,
    39  		Identifiers:         testIdentifiers,
    40  		BlockingIdentifiers: testBlockingIdentifiers,
    41  		AdminState:          models.Locked,
    42  		DiscoveredDevice: dtos.DiscoveredDevice{
    43  			ProfileName: TestDeviceProfileName,
    44  			AdminState:  models.Locked,
    45  			AutoEvents:  testAutoEvents,
    46  		},
    47  	},
    48  }
    49  
    50  var testUpdateProvisionWatcher = UpdateProvisionWatcherRequest{
    51  	BaseRequest: common.BaseRequest{
    52  		RequestId:   ExampleUUID,
    53  		Versionable: common.NewVersionable(),
    54  	},
    55  	ProvisionWatcher: mockUpdateProvisionWatcher(),
    56  }
    57  
    58  func mockUpdateProvisionWatcher() dtos.UpdateProvisionWatcher {
    59  	testId := ExampleUUID
    60  	testName := testProvisionWatcherName
    61  	testAdminState := models.Locked
    62  	testDeviceServiceName := TestDeviceServiceName
    63  	testProfileName := TestDeviceProfileName
    64  	d := dtos.UpdateProvisionWatcher{}
    65  	d.Id = &testId
    66  	d.Name = &testName
    67  	d.ServiceName = &testDeviceServiceName
    68  	d.Labels = testProvisionWatcherLabels
    69  	d.Identifiers = testIdentifiers
    70  	d.BlockingIdentifiers = testBlockingIdentifiers
    71  	d.AdminState = &testAdminState
    72  	d.DiscoveredDevice.ProfileName = &testProfileName
    73  	d.DiscoveredDevice.AdminState = &testAdminState
    74  	d.DiscoveredDevice.AutoEvents = testAutoEvents
    75  	return d
    76  }
    77  
    78  func TestAddProvisionWatcherRequest_Validate(t *testing.T) {
    79  	whiteSpace := " "
    80  	emptyMap := make(map[string]string)
    81  	valid := testAddProvisionWatcher
    82  	noReqId := testAddProvisionWatcher
    83  	noReqId.RequestId = ""
    84  	invalidReqId := testAddProvisionWatcher
    85  	invalidReqId.RequestId = "abc"
    86  	noProvisionWatcherName := testAddProvisionWatcher
    87  	noProvisionWatcherName.ProvisionWatcher.Name = whiteSpace
    88  	provisionWatcherNameWithReservedChar := testAddProvisionWatcher
    89  	provisionWatcherNameWithReservedChar.ProvisionWatcher.Name = namesWithReservedChar[0]
    90  	noIdentifiers := testAddProvisionWatcher
    91  	noIdentifiers.ProvisionWatcher.Identifiers = emptyMap
    92  	missingIdentifiersKey := testAddProvisionWatcher
    93  	missingIdentifiersKey.ProvisionWatcher.Identifiers = map[string]string{
    94  		"": "value",
    95  	}
    96  	missingIdentifiersValue := testAddProvisionWatcher
    97  	missingIdentifiersValue.ProvisionWatcher.Identifiers = map[string]string{
    98  		"key": "",
    99  	}
   100  	noServiceName := testAddProvisionWatcher
   101  	noServiceName.ProvisionWatcher.ServiceName = whiteSpace
   102  	noProfileName := testAddProvisionWatcher
   103  	noProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = whiteSpace
   104  	emptyStringProfileName := testAddProvisionWatcher
   105  	emptyStringProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = ""
   106  	invalidFrequency := testAddProvisionWatcher
   107  	invalidFrequency.ProvisionWatcher.DiscoveredDevice.AutoEvents = []dtos.AutoEvent{
   108  		{SourceName: "TestDevice", Interval: "-1", OnChange: true},
   109  	}
   110  	noAutoEventFrequency := testAddProvisionWatcher
   111  	noAutoEventFrequency.ProvisionWatcher.DiscoveredDevice.AutoEvents = []dtos.AutoEvent{
   112  		{SourceName: "TestDevice", OnChange: true},
   113  	}
   114  	noAutoEventResource := testAddProvisionWatcher
   115  	noAutoEventResource.ProvisionWatcher.DiscoveredDevice.AutoEvents = []dtos.AutoEvent{
   116  		{Interval: "300ms", OnChange: true},
   117  	}
   118  
   119  	tests := []struct {
   120  		name             string
   121  		ProvisionWatcher AddProvisionWatcherRequest
   122  		expectError      bool
   123  	}{
   124  		{"valid AddProvisionWatcherRequest", valid, false},
   125  		{"valid AddProvisionWatcherRequest, no Request Id", noReqId, false},
   126  		{"invalid AddProvisionWatcherRequest, Request Id is not an uuid", invalidReqId, true},
   127  		{"invalid AddProvisionWatcherRequest, no ProvisionWatcherName", noProvisionWatcherName, true},
   128  		{"valid AddProvisionWatcherRequest, ProvisionWatcherName with reserved chars", provisionWatcherNameWithReservedChar, false},
   129  		{"invalid AddProvisionWatcherRequest, no Identifiers", noIdentifiers, true},
   130  		{"invalid AddProvisionWatcherRequest, missing Identifiers key", missingIdentifiersKey, true},
   131  		{"invalid AddProvisionWatcherRequest, missing Identifiers value", missingIdentifiersValue, true},
   132  		{"invalid AddProvisionWatcherRequest, no ServiceName", noServiceName, true},
   133  		{"invalid AddProvisionWatcherRequest, no ProfileName", noProfileName, true},
   134  		{"invalid AddProvisionWatcherRequest, empty string ProfileName", emptyStringProfileName, false},
   135  		{"invalid AddProvisionWatcherRequest, invalid autoEvent frequency", invalidFrequency, true},
   136  		{"invalid AddProvisionWatcherRequest, no AutoEvent frequency", noAutoEventFrequency, true},
   137  		{"invalid AddProvisionWatcherRequest, no AutoEvent resource", noAutoEventResource, true},
   138  	}
   139  	for _, tt := range tests {
   140  		t.Run(tt.name, func(t *testing.T) {
   141  			err := tt.ProvisionWatcher.Validate()
   142  			assert.Equal(t, tt.expectError, err != nil, "Unexpected addDeviceRequest validation result.", err)
   143  		})
   144  	}
   145  }
   146  
   147  func TestAddProvisionWatcherRequest_UnmarshalJSON(t *testing.T) {
   148  	valid := testAddProvisionWatcher
   149  	resultTestBytes, _ := json.Marshal(testAddProvisionWatcher)
   150  	type args struct {
   151  		data []byte
   152  	}
   153  	tests := []struct {
   154  		name                string
   155  		addProvisionWatcher AddProvisionWatcherRequest
   156  		args                args
   157  		wantErr             bool
   158  	}{
   159  		{"unmarshal AddProvisionWatcherRequest with success", valid, args{resultTestBytes}, false},
   160  		{"unmarshal invalid AddProvisionWatcherRequest, empty data", AddProvisionWatcherRequest{}, args{[]byte{}}, true},
   161  		{"unmarshal invalid AddProvisionWatcherRequest, string data", AddProvisionWatcherRequest{}, args{[]byte("Invalid AddDeviceRequest")}, true},
   162  	}
   163  	fmt.Println(string(resultTestBytes))
   164  	for _, tt := range tests {
   165  		t.Run(tt.name, func(t *testing.T) {
   166  			var expected = tt.addProvisionWatcher
   167  			err := tt.addProvisionWatcher.UnmarshalJSON(tt.args.data)
   168  			if tt.wantErr {
   169  				require.Error(t, err)
   170  			} else {
   171  				require.NoError(t, err)
   172  				assert.Equal(t, expected, tt.addProvisionWatcher, "Unmarshal did not result in expected AddProvisionWatcherRequest.")
   173  			}
   174  		})
   175  	}
   176  }
   177  
   178  func TestAddProvisionWatcherReqToProvisionWatcherModels(t *testing.T) {
   179  	requests := []AddProvisionWatcherRequest{testAddProvisionWatcher}
   180  	expectedProvisionWatcherModel := []models.ProvisionWatcher{
   181  		{
   182  			Name:        testProvisionWatcherName,
   183  			ServiceName: TestDeviceServiceName,
   184  			Labels:      testProvisionWatcherLabels,
   185  			Identifiers: map[string]string{
   186  				"address": "localhost",
   187  				"port":    "3[0-9]{2}",
   188  			},
   189  			BlockingIdentifiers: map[string][]string{
   190  				"port": {"397", "398", "399"},
   191  			},
   192  			AdminState: models.Locked,
   193  			DiscoveredDevice: models.DiscoveredDevice{
   194  				ProfileName: TestDeviceProfileName,
   195  				AdminState:  models.Locked,
   196  				AutoEvents: []models.AutoEvent{
   197  					{SourceName: "TestDevice", Interval: "300ms", OnChange: true},
   198  				},
   199  			},
   200  		},
   201  	}
   202  	resultModels := AddProvisionWatcherReqToProvisionWatcherModels(requests)
   203  	assert.Equal(t, expectedProvisionWatcherModel, resultModels, "AddProvisionWatcherReqToProvisionWatcherModels did not result in expected ProvisionWatcher model.")
   204  }
   205  
   206  func TestUpdateProvisionWatcherRequest_Validate(t *testing.T) {
   207  	whiteSpace := " "
   208  	emptyMap := make(map[string]string)
   209  	invalidUUID := "invalidUUID"
   210  
   211  	valid := testUpdateProvisionWatcher
   212  	noReqId := valid
   213  	noReqId.RequestId = ""
   214  	invalidReqId := valid
   215  	invalidReqId.RequestId = invalidUUID
   216  
   217  	// id
   218  	validOnlyId := valid
   219  	validOnlyId.ProvisionWatcher.Name = nil
   220  	invalidId := valid
   221  	invalidId.ProvisionWatcher.Id = &invalidUUID
   222  	// name
   223  	validOnlyName := valid
   224  	validOnlyName.ProvisionWatcher.Id = nil
   225  	nameAndEmptyId := valid
   226  	nameAndEmptyId.ProvisionWatcher.Id = &whiteSpace
   227  	invalidEmptyName := valid
   228  	invalidEmptyName.ProvisionWatcher.Name = &whiteSpace
   229  	reservedName := valid
   230  	reservedName.ProvisionWatcher.Name = &namesWithReservedChar[0]
   231  	// no id and name
   232  	noIdAndName := valid
   233  	noIdAndName.ProvisionWatcher.Id = nil
   234  	noIdAndName.ProvisionWatcher.Name = nil
   235  
   236  	validNilIdentifiers := valid
   237  	validNilIdentifiers.ProvisionWatcher.Identifiers = nil
   238  	invalidEmptyIdentifiers := valid
   239  	invalidEmptyIdentifiers.ProvisionWatcher.Identifiers = emptyMap
   240  	// ServiceName
   241  	validNilServiceName := valid
   242  	validNilServiceName.ProvisionWatcher.ServiceName = nil
   243  	invalidEmptyServiceName := valid
   244  	invalidEmptyServiceName.ProvisionWatcher.ServiceName = &whiteSpace
   245  	// ProfileName
   246  	validNilProfileName := valid
   247  	validNilProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = nil
   248  	invalidEmptyProfileName := valid
   249  	invalidEmptyProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = &whiteSpace
   250  	emptyStringProfileName := valid
   251  	emptyString := ""
   252  	emptyStringProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = &emptyString
   253  
   254  	invalidState := "invalid state"
   255  	invalidAdminState := valid
   256  	invalidAdminState.ProvisionWatcher.AdminState = &invalidState
   257  	invalidFrequency := valid
   258  	invalidFrequency.ProvisionWatcher.DiscoveredDevice.AutoEvents = testAutoEventsWithInvalidFrequency
   259  
   260  	tests := []struct {
   261  		name        string
   262  		req         UpdateProvisionWatcherRequest
   263  		expectError bool
   264  	}{
   265  		{"valid", valid, false},
   266  		{"valid, no Request Id", noReqId, false},
   267  		{"invalid, Request Id is not an uuid", invalidReqId, true},
   268  
   269  		{"valid, only id", validOnlyId, false},
   270  		{"invalid, invalid Id", invalidId, true},
   271  		{"valid, only name", validOnlyName, false},
   272  		{"valid, name and empty Id", nameAndEmptyId, false},
   273  		{"invalid, empty name", invalidEmptyName, true},
   274  		{"valid, name with reserved chars", reservedName, false},
   275  
   276  		{"invalid, no Id and name", noIdAndName, true},
   277  
   278  		{"valid, nil identifiers", validNilIdentifiers, false},
   279  		{"invalid, empty identifiers", invalidEmptyIdentifiers, true},
   280  
   281  		{"valid, nil service name", validNilServiceName, false},
   282  		{"invalid, empty service name", invalidEmptyServiceName, true},
   283  
   284  		{"valid, nil profile name", validNilProfileName, false},
   285  		{"invalid, empty profile name", invalidEmptyProfileName, true},
   286  		{"valid, empty string profile name", emptyStringProfileName, false},
   287  
   288  		{"invalid, invalid admin state", invalidAdminState, true},
   289  		{"invalid, invalid autoEvent frequency", invalidFrequency, true},
   290  	}
   291  	for _, tt := range tests {
   292  		t.Run(tt.name, func(t *testing.T) {
   293  			err := tt.req.Validate()
   294  			assert.Equal(t, tt.expectError, err != nil, "Unexpected updateProvisionWatcherRequest validation result.", err)
   295  		})
   296  	}
   297  }
   298  
   299  func TestUpdateProvisionWatcherRequest_UnmarshalJSON_NilField(t *testing.T) {
   300  	reqJson := `{
   301  		"apiVersion" : "v3",
   302          "requestId":"7a1707f0-166f-4c4b-bc9d-1d54c74e0137",
   303  		"provisionWatcher":{"apiVersion" : "v3","name":"test-watcher"}
   304  	}`
   305  	var req UpdateProvisionWatcherRequest
   306  
   307  	err := req.UnmarshalJSON([]byte(reqJson))
   308  
   309  	require.NoError(t, err)
   310  	// Nil field checking is used to update with patch
   311  	assert.Nil(t, req.ProvisionWatcher.ServiceName)
   312  	assert.Nil(t, req.ProvisionWatcher.Labels)
   313  	assert.Nil(t, req.ProvisionWatcher.Identifiers)
   314  	assert.Nil(t, req.ProvisionWatcher.BlockingIdentifiers)
   315  	assert.Nil(t, req.ProvisionWatcher.DiscoveredDevice.ProfileName)
   316  	assert.Nil(t, req.ProvisionWatcher.AdminState)
   317  	assert.Nil(t, req.ProvisionWatcher.DiscoveredDevice.AutoEvents)
   318  	assert.Nil(t, req.ProvisionWatcher.DiscoveredDevice.Properties)
   319  }
   320  
   321  func TestUpdateProvisionWatcherRequest_UnmarshalJSON_EmptySlice(t *testing.T) {
   322  	reqJson := `{
   323  		"apiVersion" : "v3",
   324          "requestId":"7a1707f0-166f-4c4b-bc9d-1d54c74e0137",
   325  		"provisionWatcher":{
   326  			"apiVersion" : "v3",
   327  			"name":"test-watcher",
   328  			"labels":[],
   329  			"discoveredDevice":{
   330  				"autoEvents":[]
   331  			}
   332  		}
   333  	}`
   334  	var req UpdateProvisionWatcherRequest
   335  
   336  	err := req.UnmarshalJSON([]byte(reqJson))
   337  
   338  	require.NoError(t, err)
   339  	// Empty slice is used to remove the data
   340  	assert.NotNil(t, req.ProvisionWatcher.Labels)
   341  	assert.NotNil(t, req.ProvisionWatcher.DiscoveredDevice.AutoEvents)
   342  }
   343  
   344  func TestReplaceProvisionWatcherModelFieldsWithDTO(t *testing.T) {
   345  	provisionWatcher := models.ProvisionWatcher{
   346  		Id:   "7a1707f0-166f-4c4b-bc9d-1d54c74e0137",
   347  		Name: "test watcher",
   348  	}
   349  	patch := mockUpdateProvisionWatcher()
   350  
   351  	ReplaceProvisionWatcherModelFieldsWithDTO(&provisionWatcher, patch)
   352  
   353  	assert.Equal(t, TestDeviceServiceName, provisionWatcher.ServiceName)
   354  	assert.Equal(t, testProvisionWatcherLabels, provisionWatcher.Labels)
   355  	assert.Equal(t, testIdentifiers, provisionWatcher.Identifiers)
   356  	assert.Equal(t, testBlockingIdentifiers, provisionWatcher.BlockingIdentifiers)
   357  	assert.Equal(t, TestDeviceProfileName, provisionWatcher.DiscoveredDevice.ProfileName)
   358  	assert.Equal(t, models.AdminState(models.Locked), provisionWatcher.AdminState)
   359  	assert.Equal(t, dtos.ToAutoEventModels(testAutoEvents), provisionWatcher.DiscoveredDevice.AutoEvents)
   360  }