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

     1  //
     2  // Copyright (C) 2020-2023 IOTech Ltd
     3  //
     4  // SPDX-License-Identifier: Apache-2.0
     5  
     6  package dtos
     7  
     8  import (
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/require"
    12  
    13  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/common"
    14  	"dev.azure.com/aidainnovazione0090/DeviceManager/_git/go-mod-core-contracts/models"
    15  
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  var testSimpleReading = BaseReading{
    20  	Id:           TestUUID,
    21  	DeviceName:   TestDeviceName,
    22  	ResourceName: TestReadingName,
    23  	ProfileName:  TestDeviceProfileName,
    24  	Origin:       TestTimestamp,
    25  	ValueType:    TestValueType,
    26  	Units:        TestUnit,
    27  	Tags:         testTags,
    28  	SimpleReading: SimpleReading{
    29  		Value: TestValue,
    30  	},
    31  }
    32  
    33  func Test_ToReadingModel(t *testing.T) {
    34  	valid := testSimpleReading
    35  	expectedSimpleReading := models.SimpleReading{
    36  		BaseReading: models.BaseReading{
    37  			Id:           TestUUID,
    38  			DeviceName:   TestDeviceName,
    39  			ResourceName: TestReadingName,
    40  			ProfileName:  TestDeviceProfileName,
    41  			Origin:       TestTimestamp,
    42  			ValueType:    TestValueType,
    43  			Units:        TestUnit,
    44  			Tags:         testTags,
    45  		},
    46  		Value: TestValue,
    47  	}
    48  	tests := []struct {
    49  		name    string
    50  		reading BaseReading
    51  	}{
    52  		{"valid Reading", valid},
    53  	}
    54  	for _, tt := range tests {
    55  		t.Run(tt.name, func(t *testing.T) {
    56  			readingModel := ToReadingModel(tt.reading)
    57  			assert.Equal(t, expectedSimpleReading, readingModel, "ToReadingModel did not result in expected Reading model.")
    58  		})
    59  	}
    60  }
    61  
    62  func TestFromReadingModelToDTO(t *testing.T) {
    63  	valid := models.SimpleReading{
    64  		BaseReading: models.BaseReading{
    65  			Id:           TestUUID,
    66  			Origin:       TestTimestamp,
    67  			DeviceName:   TestDeviceName,
    68  			ResourceName: TestReadingName,
    69  			ProfileName:  TestDeviceProfileName,
    70  			ValueType:    TestValueType,
    71  			Units:        TestUnit,
    72  			Tags:         testTags,
    73  		},
    74  		Value: TestValue,
    75  	}
    76  	expectedDTO := BaseReading{
    77  		Id:           TestUUID,
    78  		Origin:       TestTimestamp,
    79  		DeviceName:   TestDeviceName,
    80  		ResourceName: TestReadingName,
    81  		ProfileName:  TestDeviceProfileName,
    82  		ValueType:    TestValueType,
    83  		Units:        TestUnit,
    84  		Tags:         testTags,
    85  		SimpleReading: SimpleReading{
    86  			Value: TestValue,
    87  		},
    88  	}
    89  
    90  	tests := []struct {
    91  		name    string
    92  		reading models.Reading
    93  	}{
    94  		{"success to convert from reading model to DTO ", valid},
    95  	}
    96  	for _, tt := range tests {
    97  		t.Run(tt.name, func(t *testing.T) {
    98  			result := FromReadingModelToDTO(tt.reading)
    99  			assert.Equal(t, expectedDTO, result, "FromReadingModelToDTO did not result in expected Reading DTO.")
   100  		})
   101  	}
   102  }
   103  
   104  func TestNewSimpleReading(t *testing.T) {
   105  	expectedDeviceName := TestDeviceName
   106  	expectedProfileName := TestDeviceProfileName
   107  	expectedResourceName := TestDeviceResourceName
   108  
   109  	tests := []struct {
   110  		name              string
   111  		expectedValueType string
   112  		value             interface{}
   113  		expectedValue     string
   114  	}{
   115  		{"Simple Boolean (true)", common.ValueTypeBool, true, "true"},
   116  		{"Simple Boolean (false)", common.ValueTypeBool, false, "false"},
   117  		{"Simple String", common.ValueTypeString, "hello world", "hello world"},
   118  		{"Simple Uint8", common.ValueTypeUint8, uint8(123), "123"},
   119  		{"Simple Uint16", common.ValueTypeUint16, uint16(12345), "12345"},
   120  		{"Simple Uint32", common.ValueTypeUint32, uint32(1234567890), "1234567890"},
   121  		{"Simple uint64", common.ValueTypeUint64, uint64(1234567890987654321), "1234567890987654321"},
   122  		{"Simple int8", common.ValueTypeInt8, int8(-123), "-123"},
   123  		{"Simple int16", common.ValueTypeInt16, int16(-12345), "-12345"},
   124  		{"Simple int32", common.ValueTypeInt32, int32(-1234567890), "-1234567890"},
   125  		{"Simple int64", common.ValueTypeInt64, int64(-1234567890987654321), "-1234567890987654321"},
   126  		{"Simple Float32", common.ValueTypeFloat32, float32(123.456), "1.234560e+02"},
   127  		{"Simple Float64", common.ValueTypeFloat64, float64(123456789.0987654321), "1.234568e+08"},
   128  		{"Simple Boolean Array", common.ValueTypeBoolArray, []bool{true, false}, "[true, false]"},
   129  		{"Simple String Array", common.ValueTypeStringArray, []string{"hello", "world"}, "[hello, world]"},
   130  		{"Simple Uint8 Array", common.ValueTypeUint8Array, []uint8{123, 21}, "[123, 21]"},
   131  		{"Simple Uint16 Array", common.ValueTypeUint16Array, []uint16{12345, 4321}, "[12345, 4321]"},
   132  		{"Simple Uint32 Array", common.ValueTypeUint32Array, []uint32{1234567890, 87654321}, "[1234567890, 87654321]"},
   133  		{"Simple Uint64 Array", common.ValueTypeUint64Array, []uint64{1234567890987654321, 10987654321}, "[1234567890987654321, 10987654321]"},
   134  		{"Simple Int8 Array", common.ValueTypeInt8Array, []int8{-123, 123}, "[-123, 123]"},
   135  		{"Simple Int16 Array", common.ValueTypeInt16Array, []int16{-12345, 12345}, "[-12345, 12345]"},
   136  		{"Simple Int32 Array", common.ValueTypeInt32Array, []int32{-1234567890, 1234567890}, "[-1234567890, 1234567890]"},
   137  		{"Simple Int64 Array", common.ValueTypeInt64Array, []int64{-1234567890987654321, 1234567890987654321}, "[-1234567890987654321, 1234567890987654321]"},
   138  		{"Simple Float32 Array", common.ValueTypeFloat32Array, []float32{123.456, -654.321}, "[1.234560e+02, -6.543210e+02]"},
   139  		{"Simple Float64 Array", common.ValueTypeFloat64Array, []float64{123456789.0987654321, -987654321.123456789}, "[1.234568e+08, -9.876543e+08]"},
   140  	}
   141  
   142  	for _, tt := range tests {
   143  		t.Run(tt.name, func(t *testing.T) {
   144  			actual, err := NewSimpleReading(expectedProfileName, expectedDeviceName, expectedResourceName, tt.expectedValueType, tt.value)
   145  			require.NoError(t, err)
   146  			assert.NotEmpty(t, actual.Id)
   147  			assert.Equal(t, expectedProfileName, actual.ProfileName)
   148  			assert.Equal(t, expectedDeviceName, actual.DeviceName)
   149  			assert.Equal(t, expectedResourceName, actual.ResourceName)
   150  			assert.Equal(t, tt.expectedValueType, actual.ValueType)
   151  			assert.Equal(t, tt.expectedValue, actual.Value)
   152  			assert.NotZero(t, actual.Origin)
   153  		})
   154  	}
   155  }
   156  
   157  func TestNewSimpleReadingError(t *testing.T) {
   158  	tests := []struct {
   159  		name              string
   160  		expectedValueType string
   161  		value             interface{}
   162  	}{
   163  		{"Invalid Simple Boolean", common.ValueTypeBool, 123},
   164  		{"Invalid Simple String", common.ValueTypeString, 234},
   165  		{"Invalid Simple Uint8", common.ValueTypeUint8, uint32(1234567890)},
   166  		{"Invalid Simple Uint16", common.ValueTypeUint16, uint32(1234567890)},
   167  		{"Invalid Simple Uint32", common.ValueTypeUint32, uint64(1234567890987654321)},
   168  		{"Invalid Simple uint64", common.ValueTypeUint64, int64(1234567890987654321)},
   169  		{"Invalid Simple int8", common.ValueTypeInt8, uint8(123)},
   170  		{"Invalid Simple int16", common.ValueTypeInt16, uint16(12345)},
   171  		{"Invalid Simple int32", common.ValueTypeInt32, uint32(1234567890)},
   172  		{"Invalid Simple int64", common.ValueTypeInt64, uint64(1234567890987654321)},
   173  		{"Invalid Simple Float32", common.ValueTypeFloat32, float64(123.456)},
   174  		{"Invalid Simple Float64", common.ValueTypeFloat64, float32(123456789.0987654321)},
   175  		{"Invalid Simple Boolean Array", common.ValueTypeBoolArray, []string{"true", "false"}},
   176  		{"Invalid Simple String Array", common.ValueTypeStringArray, []bool{false, true}},
   177  		{"Invalid Simple Uint8 Array", common.ValueTypeUint8Array, []int8{123, 21}},
   178  		{"Invalid Simple Uint16 Array", common.ValueTypeUint16Array, []int16{12345, 4321}},
   179  		{"Invalid Simple Uint32 Array", common.ValueTypeUint32Array, []int32{1234567890, 87654321}},
   180  		{"Invalid Simple Uint64 Array", common.ValueTypeUint64Array, []int64{1234567890987654321, 10987654321}},
   181  		{"Invalid Simple Int8 Array", common.ValueTypeInt8Array, []uint8{123, 123}},
   182  		{"Invalid Simple Int16 Array", common.ValueTypeInt16Array, []uint16{12345, 12345}},
   183  		{"Invalid Simple Int32 Array", common.ValueTypeInt32Array, []uint32{1234567890, 1234567890}},
   184  		{"Invalid Simple Int64 Array", common.ValueTypeInt64Array, []uint64{1234567890987654321, 1234567890987654321}},
   185  		{"Invalid Simple Float32 Array", common.ValueTypeFloat32Array, []float64{123.456, -654.321}},
   186  		{"Invalid Simple Float64 Array", common.ValueTypeFloat64Array, []float32{123456789.0987654321, -987654321.123456789}},
   187  	}
   188  
   189  	for _, tt := range tests {
   190  		t.Run(tt.name, func(t *testing.T) {
   191  			_, err := NewSimpleReading(TestDeviceProfileName, TestDeviceName, TestDeviceResourceName, tt.expectedValueType, tt.value)
   192  			require.Error(t, err)
   193  		})
   194  	}
   195  }
   196  
   197  func TestNewBinaryReading(t *testing.T) {
   198  	expectedDeviceName := TestDeviceName
   199  	expectedProfileName := TestDeviceProfileName
   200  	expectedResourceName := TestDeviceResourceName
   201  
   202  	expectedValueType := common.ValueTypeBinary
   203  	expectedBinaryValue := []byte("hello word, any one out there?")
   204  	expectedMediaType := "application/text"
   205  
   206  	actual := NewBinaryReading(expectedProfileName, expectedDeviceName, expectedResourceName, expectedBinaryValue, expectedMediaType)
   207  
   208  	assert.NotEmpty(t, actual.Id)
   209  	assert.Equal(t, expectedProfileName, actual.ProfileName)
   210  	assert.Equal(t, expectedDeviceName, actual.DeviceName)
   211  	assert.Equal(t, expectedResourceName, actual.ResourceName)
   212  	assert.Equal(t, expectedValueType, actual.ValueType)
   213  	assert.Equal(t, expectedBinaryValue, actual.BinaryValue)
   214  	assert.NotZero(t, actual.Origin)
   215  }
   216  
   217  func TestNewObjectReading(t *testing.T) {
   218  	expectedDeviceName := TestDeviceName
   219  	expectedProfileName := TestDeviceProfileName
   220  	expectedResourceName := TestDeviceResourceName
   221  	expectedValueType := common.ValueTypeObject
   222  	expectedValue := map[string]interface{}{
   223  		"Attr1": "yyz",
   224  		"Attr2": -45,
   225  		"Attr3": []interface{}{255, 1, 0},
   226  	}
   227  
   228  	actual := NewObjectReading(expectedProfileName, expectedDeviceName, expectedResourceName, expectedValue)
   229  
   230  	assert.NotEmpty(t, actual.Id)
   231  	assert.Equal(t, expectedProfileName, actual.ProfileName)
   232  	assert.Equal(t, expectedDeviceName, actual.DeviceName)
   233  	assert.Equal(t, expectedResourceName, actual.ResourceName)
   234  	assert.Equal(t, expectedValueType, actual.ValueType)
   235  	assert.Equal(t, expectedValue, actual.ObjectValue)
   236  	assert.NotZero(t, actual.Origin)
   237  }
   238  
   239  func TestValidateValue(t *testing.T) {
   240  	tests := []struct {
   241  		name      string
   242  		valueType string
   243  		value     string
   244  	}{
   245  		{"Simple Boolean (true)", common.ValueTypeBool, "True"},
   246  		{"Simple String", common.ValueTypeString, "hello world"},
   247  		{"Simple Uint8", common.ValueTypeUint8, "123"},
   248  		{"Simple Uint16", common.ValueTypeUint16, "12345"},
   249  		{"Simple Uint32", common.ValueTypeUint32, "1234567890"},
   250  		{"Simple uint64", common.ValueTypeUint64, "1234567890987654321"},
   251  		{"Simple int8", common.ValueTypeInt8, "-123"},
   252  		{"Simple int16", common.ValueTypeInt16, "-12345"},
   253  		{"Simple int32", common.ValueTypeInt32, "-1234567890"},
   254  		{"Simple int64", common.ValueTypeInt64, "-1234567890987654321"},
   255  		{"Simple Float32", common.ValueTypeFloat32, "123.456"},
   256  		{"Simple Float64", common.ValueTypeFloat64, "123456789.0987654321"},
   257  		{"Simple Boolean Array", common.ValueTypeBoolArray, "[true, false]"},
   258  		{"Simple String Array", common.ValueTypeStringArray, "[\"hello\", \"world\"]"},
   259  		{"Simple Uint8 Array", common.ValueTypeUint8Array, "[123, 21]"},
   260  		{"Simple Uint16 Array", common.ValueTypeUint16Array, "[12345, 4321]"},
   261  		{"Simple Uint32 Array", common.ValueTypeUint32Array, "[1234567890, 87654321]"},
   262  		{"Simple Uint64 Array", common.ValueTypeUint64Array, "[1234567890987654321, 10987654321]"},
   263  		{"Simple Int8 Array", common.ValueTypeInt8Array, "[-123, 123]"},
   264  		{"Simple Int16 Array", common.ValueTypeInt16Array, "[-12345, 12345]"},
   265  		{"Simple Int32 Array", common.ValueTypeInt32Array, "[-1234567890, 1234567890]"},
   266  		{"Simple Int64 Array", common.ValueTypeInt64Array, "[-1234567890987654321, 1234567890987654321]"},
   267  		{"Simple Float32 Array", common.ValueTypeFloat32Array, "[123.456, -654.321]"},
   268  		{"Simple Float64 Array", common.ValueTypeFloat64Array, "[123456789.0987654321, -987654321.123456789]"},
   269  	}
   270  
   271  	for _, tt := range tests {
   272  		t.Run(tt.name, func(t *testing.T) {
   273  			err := ValidateValue(tt.valueType, tt.value)
   274  			require.NoError(t, err)
   275  		})
   276  	}
   277  }
   278  
   279  func TestValidateArrayValue(t *testing.T) {
   280  	tests := []struct {
   281  		name        string
   282  		valueType   string
   283  		value       string
   284  		expectError bool
   285  	}{
   286  		{"Valid separator (comma followed by a space)", common.ValueTypeBoolArray, "[true, false]", false},
   287  		{"Valid separator (comma)", common.ValueTypeBoolArray, "[true,false]", false},
   288  		{"Invalid separator", common.ValueTypeBoolArray, "[true@false]", true},
   289  	}
   290  
   291  	for _, tt := range tests {
   292  		t.Run(tt.name, func(t *testing.T) {
   293  			err := ValidateValue(tt.valueType, tt.value)
   294  			if tt.expectError {
   295  				require.Error(t, err)
   296  			} else {
   297  				require.NoError(t, err)
   298  			}
   299  		})
   300  	}
   301  }
   302  
   303  func TestValidateValueError(t *testing.T) {
   304  	invalidValue := "invalid"
   305  	tests := []struct {
   306  		name      string
   307  		valueType string
   308  	}{
   309  		{"Invalid Simple Boolean (true)", common.ValueTypeBool},
   310  		{"Invalid Simple Uint8", common.ValueTypeUint8},
   311  		{"Invalid Simple Uint16", common.ValueTypeUint16},
   312  		{"Invalid Simple Uint32", common.ValueTypeUint32},
   313  		{"Invalid Simple uint64", common.ValueTypeUint64},
   314  		{"Invalid Simple int8", common.ValueTypeInt8},
   315  		{"Invalid Simple int16", common.ValueTypeInt16},
   316  		{"Invalid Simple int32", common.ValueTypeInt32},
   317  		{"Invalid Simple int64", common.ValueTypeInt64},
   318  		{"Invalid Simple Float32", common.ValueTypeFloat32},
   319  		{"Invalid Simple Float64", common.ValueTypeFloat64},
   320  		{"Invalid Simple Boolean Array", common.ValueTypeBoolArray},
   321  		{"Invalid Simple Uint8 Array", common.ValueTypeUint8Array},
   322  		{"Invalid Simple Uint16 Array", common.ValueTypeUint16Array},
   323  		{"Invalid Simple Uint32 Array", common.ValueTypeUint32Array},
   324  		{"Invalid Simple Uint64 Array", common.ValueTypeUint64Array},
   325  		{"Invalid Simple Int8 Array", common.ValueTypeInt8Array},
   326  		{"Invalid Simple Int16 Array", common.ValueTypeInt16Array},
   327  		{"Invalid Simple Int32 Array", common.ValueTypeInt32Array},
   328  		{"Invalid Simple Int64 Array", common.ValueTypeInt64Array},
   329  		{"Invalid Simple Float32 Array", common.ValueTypeFloat32Array},
   330  		{"Invalid Simple Float64 Array", common.ValueTypeFloat64Array},
   331  	}
   332  	for _, tt := range tests {
   333  		t.Run(tt.name, func(t *testing.T) {
   334  			err := ValidateValue(tt.valueType, invalidValue)
   335  			require.Error(t, err)
   336  		})
   337  	}
   338  }
   339  
   340  func TestUnmarshalObjectValue(t *testing.T) {
   341  	expectedDeviceName := TestDeviceName
   342  	expectedProfileName := TestDeviceProfileName
   343  	expectedResourceName := TestDeviceResourceName
   344  	expectedValueType := common.ValueTypeObject
   345  	type testObjectType struct {
   346  		StringField       string
   347  		BoolField         bool
   348  		IntField          int
   349  		UintField         uint
   350  		Float32Field      float32
   351  		Float64Field      float64
   352  		BoolArrayField    []bool
   353  		IntArrayField     []int
   354  		UintArrayField    []uint
   355  		Float32ArrayField []float32
   356  		Float64ArrayField []float64
   357  	}
   358  	testObject := testObjectType{
   359  		StringField:       "yyz",
   360  		BoolField:         true,
   361  		IntField:          -45,
   362  		UintField:         45,
   363  		Float32Field:      float32(123.456),
   364  		Float64Field:      456.789,
   365  		BoolArrayField:    []bool{true, false, true},
   366  		IntArrayField:     []int{-1, 1, -1},
   367  		UintArrayField:    []uint{1, 1, 1},
   368  		Float32ArrayField: []float32{float32(111.222), float32(333.444), float32(555.666)},
   369  		Float64ArrayField: []float64{111.222, 333.444, 555.666},
   370  	}
   371  
   372  	actual := NewObjectReading(expectedProfileName, expectedDeviceName, expectedResourceName, testObject)
   373  
   374  	assert.NotEmpty(t, actual.Id)
   375  	assert.Equal(t, expectedProfileName, actual.ProfileName)
   376  	assert.Equal(t, expectedDeviceName, actual.DeviceName)
   377  	assert.Equal(t, expectedResourceName, actual.ResourceName)
   378  	assert.Equal(t, expectedValueType, actual.ValueType)
   379  
   380  	target := testObjectType{}
   381  	assert.NoError(t, actual.UnmarshalObjectValue(&target))
   382  	assert.Equal(t, testObject, target)
   383  	assert.NotZero(t, actual.Origin)
   384  }
   385  
   386  func TestUnmarshalObjectValueError(t *testing.T) {
   387  	expectedDeviceName := TestDeviceName
   388  	expectedProfileName := TestDeviceProfileName
   389  	expectedResourceName := TestDeviceResourceName
   390  
   391  	tests := []struct {
   392  		name      string
   393  		valueType string
   394  		value     interface{}
   395  	}{
   396  		{"Invalid Simple Boolean", common.ValueTypeBool, true},
   397  		{"Invalid Simple Uint8", common.ValueTypeUint8, uint8(1)},
   398  		{"Invalid Simple Uint16", common.ValueTypeUint16, uint16(1)},
   399  		{"Invalid Simple Uint32", common.ValueTypeUint32, uint32(1)},
   400  		{"Invalid Simple uint64", common.ValueTypeUint64, uint64(1)},
   401  		{"Invalid Simple int8", common.ValueTypeInt8, int8(-1)},
   402  		{"Invalid Simple int16", common.ValueTypeInt16, int16(-1)},
   403  		{"Invalid Simple int32", common.ValueTypeInt32, int32(-1)},
   404  		{"Invalid Simple int64", common.ValueTypeInt64, int64(-1)},
   405  		{"Invalid Simple Float32", common.ValueTypeFloat32, float32(123.456)},
   406  		{"Invalid Simple Float64", common.ValueTypeFloat64, 123.456},
   407  		{"Invalid Simple Boolean Array", common.ValueTypeBoolArray, []bool{}},
   408  		{"Invalid Simple Uint8 Array", common.ValueTypeUint8Array, []uint8{}},
   409  		{"Invalid Simple Uint16 Array", common.ValueTypeUint16Array, []uint16{}},
   410  		{"Invalid Simple Uint32 Array", common.ValueTypeUint32Array, []uint32{}},
   411  		{"Invalid Simple Uint64 Array", common.ValueTypeUint64Array, []uint64{}},
   412  		{"Invalid Simple Int8 Array", common.ValueTypeInt8Array, []int8{}},
   413  		{"Invalid Simple Int16 Array", common.ValueTypeInt16Array, []int16{}},
   414  		{"Invalid Simple Int32 Array", common.ValueTypeInt32Array, []int32{}},
   415  		{"Invalid Simple Int64 Array", common.ValueTypeInt64Array, []int64{}},
   416  		{"Invalid Simple Float32 Array", common.ValueTypeFloat32Array, []float32{}},
   417  		{"Invalid Simple Float64 Array", common.ValueTypeFloat64Array, []float64{}},
   418  	}
   419  	for _, tt := range tests {
   420  		t.Run(tt.name, func(t *testing.T) {
   421  			reading, err := NewSimpleReading(expectedProfileName, expectedDeviceName, expectedResourceName, tt.valueType, tt.value)
   422  			require.NoError(t, err)
   423  			target := ""
   424  			err = reading.UnmarshalObjectValue(&target)
   425  			require.Error(t, err)
   426  		})
   427  	}
   428  }