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

     1  //
     2  // Copyright (C) 2020-2021 IOTech Ltd
     3  //
     4  // SPDX-License-Identifier: Apache-2.0
     5  
     6  package requests
     7  
     8  import (
     9  	"encoding/json"
    10  	"fmt"
    11  	"strconv"
    12  	"testing"
    13  
    14  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/common"
    15  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/dtos"
    16  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/models"
    17  	"github.com/fxamacker/cbor/v2"
    18  
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  func eventData() dtos.Event {
    24  	event := dtos.NewEvent(TestDeviceProfileName, TestDeviceName, TestSourceName)
    25  	event.Id = ExampleUUID
    26  	event.Origin = TestOriginTime
    27  	event.Tags = map[string]interface{}{
    28  		"GatewayId": "Houston-0001",
    29  	}
    30  	value, _ := strconv.ParseUint(TestReadingValue, 10, 8)
    31  	_ = event.AddSimpleReading(TestDeviceResourceName, common.ValueTypeUint8, uint8(value))
    32  	event.Readings[0].Id = ExampleUUID
    33  	event.Readings[0].Origin = TestOriginTime
    34  
    35  	return event
    36  }
    37  
    38  func eventRequestData() AddEventRequest {
    39  	request := NewAddEventRequest(eventData())
    40  	return request
    41  }
    42  
    43  func TestAddEventRequest_Validate(t *testing.T) {
    44  	valid := eventRequestData()
    45  	noReqId := eventRequestData()
    46  	noReqId.RequestId = ""
    47  	invalidReqId := eventRequestData()
    48  	invalidReqId.RequestId = "xxy"
    49  	noEventId := eventRequestData()
    50  	noEventId.Event.Id = ""
    51  	invalidEventId := eventRequestData()
    52  	invalidEventId.Event.Id = "gj93j2-v92hvi3h"
    53  	noDeviceName := eventRequestData()
    54  	noDeviceName.Event.DeviceName = ""
    55  	noProfileName := eventRequestData()
    56  	noProfileName.Event.ProfileName = ""
    57  	noSourceName := eventRequestData()
    58  	noSourceName.Event.SourceName = ""
    59  	noOrigin := eventRequestData()
    60  	noOrigin.Event.Origin = 0
    61  
    62  	noReading := eventRequestData()
    63  	noReading.Event.Readings = nil
    64  
    65  	invalidReadingNoDevice := eventRequestData()
    66  	invalidReadingNoDevice.Event.Readings[0].DeviceName = ""
    67  	invalidReadingNoResourceName := eventRequestData()
    68  	invalidReadingNoResourceName.Event.Readings[0].ResourceName = ""
    69  	invalidReadingNoProfileName := eventRequestData()
    70  	invalidReadingNoProfileName.Event.Readings[0].ProfileName = ""
    71  	invalidReadingNoOrigin := eventRequestData()
    72  	invalidReadingNoOrigin.Event.Readings[0].Origin = 0
    73  
    74  	invalidReadingNoValueType := eventRequestData()
    75  	invalidReadingNoValueType.Event.Readings[0].ValueType = ""
    76  	invalidReadingInvalidValueType := eventRequestData()
    77  	invalidReadingInvalidValueType.Event.Readings[0].ValueType = "BadType"
    78  
    79  	invalidSimpleReadingNoValue := eventRequestData()
    80  	invalidSimpleReadingNoValue.Event.Readings[0].SimpleReading.Value = ""
    81  
    82  	invalidBinaryReadingNoValue := eventRequestData()
    83  	invalidBinaryReadingNoValue.Event.Readings[0].ValueType = common.ValueTypeBinary
    84  	invalidBinaryReadingNoValue.Event.Readings[0].BinaryReading.MediaType = TestBinaryReadingMediaType
    85  	invalidBinaryReadingNoValue.Event.Readings[0].BinaryReading.BinaryValue = []byte{}
    86  
    87  	invalidBinaryReadingNoMedia := eventRequestData()
    88  	invalidBinaryReadingNoMedia.Event.Readings[0].ValueType = common.ValueTypeBinary
    89  	invalidBinaryReadingNoMedia.Event.Readings[0].BinaryReading.MediaType = ""
    90  	invalidBinaryReadingNoMedia.Event.Readings[0].BinaryReading.BinaryValue = []byte(TestReadingBinaryValue)
    91  
    92  	tests := []struct {
    93  		name        string
    94  		event       AddEventRequest
    95  		expectError bool
    96  	}{
    97  		{"valid AddEventRequest", valid, false},
    98  		{"valid AddEventRequest, no Request Id", noReqId, false},
    99  		{"invalid AddEventRequest, Request Id is not an uuid", invalidReqId, true},
   100  		{"invalid AddEventRequest, no Event Id", noEventId, true},
   101  		{"invalid AddEventRequest, Event Id is not an uuid", invalidEventId, true},
   102  		{"invalid AddEventRequest, no DeviceName", noDeviceName, true},
   103  		{"invalid AddEventRequest, no ProfileName", noProfileName, true},
   104  		{"invalid AddEventRequest, no SourceName", noSourceName, true},
   105  		{"invalid AddEventRequest, no Origin", noOrigin, true},
   106  		{"invalid AddEventRequest, no Reading", noReading, true},
   107  		{"invalid AddEventRequest, no Reading DeviceName", invalidReadingNoDevice, true},
   108  		{"invalid AddEventRequest, no Resource Name", invalidReadingNoResourceName, true},
   109  		{"invalid AddEventRequest, no Profile Name", invalidReadingNoProfileName, true},
   110  		{"invalid AddEventRequest, no Reading Origin", invalidReadingNoOrigin, true},
   111  		{"invalid AddEventRequest, no Reading ValueType", invalidReadingNoValueType, true},
   112  		{"invalid AddEventRequest, invalid Reading ValueType", invalidReadingInvalidValueType, true},
   113  		{"invalid AddEventRequest, no SimpleReading Value", invalidSimpleReadingNoValue, true},
   114  		{"invalid AddEventRequest, no BinaryReading BinaryValue", invalidBinaryReadingNoValue, true},
   115  		{"invalid AddEventRequest, no BinaryReading MediaType", invalidBinaryReadingNoMedia, true},
   116  	}
   117  	for _, tt := range tests {
   118  		t.Run(tt.name, func(t *testing.T) {
   119  			err := tt.event.Validate()
   120  			if tt.expectError {
   121  				require.Error(t, err)
   122  			} else {
   123  				require.NoError(t, err)
   124  			}
   125  		})
   126  	}
   127  
   128  	type testForNameField struct {
   129  		name        string
   130  		event       AddEventRequest
   131  		expectError bool
   132  	}
   133  
   134  	deviceNameWithUnreservedChar := eventRequestData()
   135  	deviceNameWithUnreservedChar.Event.DeviceName = nameWithUnreservedChars
   136  	profileNameWithUnreservedChar := eventRequestData()
   137  	profileNameWithUnreservedChar.Event.ProfileName = nameWithUnreservedChars
   138  	sourceNameWithUnreservedChar := eventRequestData()
   139  	sourceNameWithUnreservedChar.Event.SourceName = nameWithUnreservedChars
   140  	readingDeviceNameWithUnreservedChar := eventRequestData()
   141  	readingDeviceNameWithUnreservedChar.Event.Readings[0].DeviceName = nameWithUnreservedChars
   142  	readingResourceNameWithUnreservedChar := eventRequestData()
   143  	readingResourceNameWithUnreservedChar.Event.Readings[0].ResourceName = nameWithUnreservedChars
   144  	readingProfileNameWithUnreservedChar := eventRequestData()
   145  	readingProfileNameWithUnreservedChar.Event.Readings[0].ProfileName = nameWithUnreservedChars
   146  
   147  	// Following tests verify if name fields containing unreserved characters should pass edgex-dto-rfc3986-unreserved-chars check
   148  	testsForNameFields := []testForNameField{
   149  		{"Valid AddEventRequest with device name containing unreserved chars", deviceNameWithUnreservedChar, false},
   150  		{"Valid AddEventRequest with profile name containing unreserved chars", profileNameWithUnreservedChar, false},
   151  		{"Valid AddEventRequest with source name containing unreserved chars", sourceNameWithUnreservedChar, false},
   152  		{"Valid AddEventRequest with reading device name containing unreserved chars", readingDeviceNameWithUnreservedChar, false},
   153  		{"Valid AddEventRequest with reading resource name containing unreserved chars", readingResourceNameWithUnreservedChar, false},
   154  		{"Valid AddEventRequest with reading profile name containing unreserved chars", readingProfileNameWithUnreservedChar, false},
   155  	}
   156  
   157  	// Following tests verify if name fields containing reserved characters should be detected with an error
   158  	for _, n := range namesWithReservedChar {
   159  		deviceNameWithReservedChar := eventRequestData()
   160  		deviceNameWithReservedChar.Event.DeviceName = n
   161  		profileNameWithReservedChar := eventRequestData()
   162  		profileNameWithReservedChar.Event.ProfileName = n
   163  		sourceNameWithReservedChar := eventRequestData()
   164  		sourceNameWithReservedChar.Event.SourceName = n
   165  		readingDeviceNameWithReservedChar := eventRequestData()
   166  		readingDeviceNameWithReservedChar.Event.Readings[0].DeviceName = n
   167  		readingResourceNameWithReservedChar := eventRequestData()
   168  		readingResourceNameWithReservedChar.Event.Readings[0].ResourceName = n
   169  		readingProfileNameWithReservedChar := eventRequestData()
   170  		readingProfileNameWithReservedChar.Event.Readings[0].ProfileName = n
   171  
   172  		testsForNameFields = append(testsForNameFields,
   173  			testForNameField{"Valid AddEventRequest with device name containing reserved char", deviceNameWithReservedChar, false},
   174  			testForNameField{"Valid AddEventRequest with profile name containing reserved char", profileNameWithReservedChar, false},
   175  			testForNameField{"Valid AddEventRequest with source name containing reserved char", sourceNameWithReservedChar, false},
   176  			testForNameField{"Valid AddEventRequest with reading device name containing reserved char", readingDeviceNameWithReservedChar, false},
   177  			testForNameField{"Valid AddEventRequest with reading resource name containing reserved char", readingResourceNameWithReservedChar, false},
   178  			testForNameField{"Valid AddEventRequest with reading profile name containing reserved char", readingProfileNameWithReservedChar, false},
   179  		)
   180  	}
   181  
   182  	for _, tt := range testsForNameFields {
   183  		t.Run(tt.name, func(t *testing.T) {
   184  			err := tt.event.Validate()
   185  			if tt.expectError {
   186  				assert.Error(t, err, fmt.Sprintf("expect error but not : %s", tt.name))
   187  			} else {
   188  				assert.NoError(t, err, fmt.Sprintf("unexpected error occurs : %s", tt.name))
   189  			}
   190  		})
   191  	}
   192  }
   193  
   194  func TestAddEvent_UnmarshalJSON(t *testing.T) {
   195  	expected := eventRequestData()
   196  	expected.RequestId = ExampleUUID
   197  	validData, err := json.Marshal(expected)
   198  	require.NoError(t, err)
   199  
   200  	validValueTypeLowerCase := eventRequestData()
   201  	validValueTypeLowerCase.RequestId = ExampleUUID
   202  	validValueTypeLowerCase.Event.Readings[0].ValueType = "uint8"
   203  	validValueTypeLowerCaseData, err := json.Marshal(validValueTypeLowerCase)
   204  	require.NoError(t, err)
   205  
   206  	validValueTypeUpperCase := eventRequestData()
   207  	validValueTypeUpperCase.RequestId = ExampleUUID
   208  	validValueTypeUpperCase.Event.Readings[0].ValueType = "UINT8"
   209  	validValueTypeUpperCaseData, err := json.Marshal(validValueTypeUpperCase)
   210  	require.NoError(t, err)
   211  
   212  	tests := []struct {
   213  		name    string
   214  		data    []byte
   215  		wantErr bool
   216  	}{
   217  		{"unmarshal AddEventRequest with success", validData, false},
   218  		{"unmarshal AddEventRequest with success, valid value type uint8", validValueTypeLowerCaseData, false},
   219  		{"unmarshal AddEventRequest with success, valid value type UINT8", validValueTypeUpperCaseData, false},
   220  		{"unmarshal invalid AddEventRequest, empty data", []byte{}, true},
   221  		{"unmarshal invalid AddEventRequest, string data", []byte("Invalid AddEventRequest"), true},
   222  	}
   223  
   224  	for _, tt := range tests {
   225  		t.Run(tt.name, func(t *testing.T) {
   226  			var addEvent AddEventRequest
   227  			err := addEvent.UnmarshalJSON(tt.data)
   228  			if tt.wantErr {
   229  				require.Error(t, err)
   230  			} else {
   231  				require.NoError(t, err)
   232  				assert.Equal(t, expected, addEvent, "Unmarshal did not result in expected AddEventRequest.")
   233  			}
   234  		})
   235  	}
   236  }
   237  
   238  func TestAddEvent_UnmarshalCBOR(t *testing.T) {
   239  	expected := eventRequestData()
   240  	expected.RequestId = ExampleUUID
   241  	validData, err := cbor.Marshal(expected)
   242  	require.NoError(t, err)
   243  
   244  	validValueTypeLowerCase := eventRequestData()
   245  	validValueTypeLowerCase.RequestId = ExampleUUID
   246  	validValueTypeLowerCase.Event.Readings[0].ValueType = "uint8"
   247  	validValueTypeLowerCaseData, err := cbor.Marshal(validValueTypeLowerCase)
   248  	require.NoError(t, err)
   249  
   250  	validValueTypeUpperCase := eventRequestData()
   251  	validValueTypeUpperCase.RequestId = ExampleUUID
   252  	validValueTypeUpperCase.Event.Readings[0].ValueType = "UINT8"
   253  	validValueTypeUpperCaseData, err := cbor.Marshal(validValueTypeUpperCase)
   254  	require.NoError(t, err)
   255  
   256  	tests := []struct {
   257  		name    string
   258  		data    []byte
   259  		wantErr bool
   260  	}{
   261  		{"unmarshal AddEventRequest with success", validData, false},
   262  		{"unmarshal AddEventRequest with success, valid value type uint8", validValueTypeLowerCaseData, false},
   263  		{"unmarshal AddEventRequest with success, valid value type UINT8", validValueTypeUpperCaseData, false},
   264  		{"unmarshal invalid AddEventRequest, empty data", []byte{}, true},
   265  		{"unmarshal invalid AddEventRequest, string data", []byte("Invalid AddEventRequest"), true},
   266  	}
   267  
   268  	for _, tt := range tests {
   269  		t.Run(tt.name, func(t *testing.T) {
   270  			var addEvent AddEventRequest
   271  			err := addEvent.UnmarshalCBOR(tt.data)
   272  			if tt.wantErr {
   273  				require.Error(t, err)
   274  			} else {
   275  				require.NoError(t, err)
   276  				assert.Equal(t, expected, addEvent, "Unmarshal did not result in expected AddEventRequest.")
   277  			}
   278  		})
   279  	}
   280  }
   281  
   282  func Test_AddEventReqToEventModels(t *testing.T) {
   283  	valid := eventRequestData()
   284  	s := models.SimpleReading{
   285  		BaseReading: models.BaseReading{
   286  			Id:           ExampleUUID,
   287  			DeviceName:   TestDeviceName,
   288  			ResourceName: TestDeviceResourceName,
   289  			ProfileName:  TestDeviceProfileName,
   290  			Origin:       TestOriginTime,
   291  			ValueType:    common.ValueTypeUint8,
   292  		},
   293  		Value: TestReadingValue,
   294  	}
   295  	expectedEventModel := models.Event{
   296  		Id:          ExampleUUID,
   297  		DeviceName:  TestDeviceName,
   298  		ProfileName: TestDeviceProfileName,
   299  		SourceName:  TestSourceName,
   300  		Origin:      TestOriginTime,
   301  		Readings:    []models.Reading{s},
   302  		Tags: map[string]interface{}{
   303  			"GatewayId": "Houston-0001",
   304  		},
   305  	}
   306  
   307  	tests := []struct {
   308  		name        string
   309  		addEventReq AddEventRequest
   310  	}{
   311  		{"valid AddEventRequest", valid},
   312  	}
   313  	for _, tt := range tests {
   314  		t.Run(tt.name, func(t *testing.T) {
   315  			eventModel := AddEventReqToEventModel(tt.addEventReq)
   316  			assert.Equal(t, expectedEventModel, eventModel, "AddEventReqToEventModel did not result in expected Event model.")
   317  		})
   318  	}
   319  }
   320  
   321  func TestNewAddEventRequest(t *testing.T) {
   322  	expectedProfileName := TestDeviceProfileName
   323  	expectedDeviceName := TestDeviceName
   324  	expectedSourceName := TestSourceName
   325  	expectedApiVersion := common.ApiVersion
   326  
   327  	actual := NewAddEventRequest(eventData())
   328  
   329  	assert.Equal(t, expectedApiVersion, actual.ApiVersion)
   330  	assert.NotEmpty(t, actual.RequestId)
   331  	assert.Equal(t, expectedApiVersion, actual.Event.ApiVersion)
   332  	assert.NotEmpty(t, actual.Event.Id)
   333  	assert.Equal(t, expectedProfileName, actual.Event.ProfileName)
   334  	assert.Equal(t, expectedDeviceName, actual.Event.DeviceName)
   335  	assert.Equal(t, expectedSourceName, actual.Event.SourceName)
   336  	assert.NotZero(t, len(actual.Event.Readings))
   337  	assert.NotZero(t, actual.Event.Origin)
   338  }