github.com/enbility/spine-go@v0.7.0/spine/feature_local_test.go (about) 1 package spine 2 3 import ( 4 "errors" 5 "reflect" 6 "testing" 7 "time" 8 9 "github.com/enbility/spine-go/api" 10 "github.com/enbility/spine-go/mocks" 11 "github.com/enbility/spine-go/model" 12 "github.com/enbility/spine-go/util" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/mock" 15 "github.com/stretchr/testify/suite" 16 ) 17 18 func TestLocalFeatureTestSuite(t *testing.T) { 19 suite.Run(t, new(LocalFeatureTestSuite)) 20 } 21 22 type LocalFeatureTestSuite struct { 23 suite.Suite 24 senderMock *mocks.SenderInterface 25 localDevice *DeviceLocal 26 localEntity *EntityLocal 27 function, serverWriteFunction model.FunctionType 28 featureType, subFeatureType model.FeatureTypeType 29 msgCounter model.MsgCounterType 30 remoteFeature, remote2Feature, 31 remoteServerFeature, remoteSubFeature api.FeatureRemoteInterface 32 localFeature, localServerFeature, localServerFeatureWrite api.FeatureLocalInterface 33 } 34 35 func (s *LocalFeatureTestSuite) BeforeTest(suiteName, testName string) { 36 s.senderMock = mocks.NewSenderInterface(s.T()) 37 s.function = model.FunctionTypeDeviceClassificationManufacturerData 38 s.featureType = model.FeatureTypeTypeDeviceClassification 39 s.subFeatureType = model.FeatureTypeTypeLoadControl 40 s.serverWriteFunction = model.FunctionTypeLoadControlLimitListData 41 s.msgCounter = model.MsgCounterType(1) 42 43 s.localDevice, s.localEntity = createLocalDeviceAndEntity(1) 44 s.localFeature, s.localServerFeature = createLocalFeatures(s.localEntity, s.featureType, "") 45 _, s.localServerFeatureWrite = createLocalFeatures(s.localEntity, s.subFeatureType, s.serverWriteFunction) 46 47 remoteDevice := createRemoteDevice(s.localDevice, "ski", s.senderMock) 48 remoteDevice2 := createRemoteDevice(s.localDevice, "iks", s.senderMock) 49 s.remoteFeature, s.remoteServerFeature = createRemoteEntityAndFeature(remoteDevice, 1, s.featureType, s.function) 50 s.remoteSubFeature, _ = createRemoteEntityAndFeature(remoteDevice, 2, s.subFeatureType, s.serverWriteFunction) 51 s.remote2Feature, _ = createRemoteEntityAndFeature(remoteDevice2, 1, s.featureType, s.function) 52 } 53 54 func (s *LocalFeatureTestSuite) TestDeviceClassification_Functions() { 55 fcts := s.localServerFeatureWrite.Functions() 56 assert.NotNil(s.T(), fcts) 57 assert.Equal(s.T(), 1, len(fcts)) 58 assert.Equal(s.T(), s.serverWriteFunction, fcts[0]) 59 } 60 61 func (s *LocalFeatureTestSuite) TestDeviceClassification_ResponseCB() { 62 testFct := func(msg api.ResponseMessage) {} 63 msgCounter := model.MsgCounterType(100) 64 err := s.localFeature.AddResponseCallback(msgCounter, testFct) 65 assert.Nil(s.T(), err) 66 67 err = s.localFeature.AddResponseCallback(msgCounter, testFct) 68 assert.NotNil(s.T(), err) 69 70 s.localFeature.AddResultCallback(testFct) 71 } 72 73 func (s *LocalFeatureTestSuite) TestDeviceClassification_Request_Reply() { 74 dummyAddress := &model.FeatureAddressType{ 75 Device: util.Ptr(model.AddressDeviceType("")), 76 Entity: []model.AddressEntityType{2}, 77 Feature: util.Ptr(model.AddressFeatureType(100)), 78 } 79 80 s.senderMock.EXPECT().Request( 81 model.CmdClassifierTypeRead, 82 s.localFeature.Address(), 83 s.remoteFeature.Address(), 84 false, 85 mock.AnythingOfType("[]model.CmdType")).Return(&s.msgCounter, nil).Maybe() 86 s.senderMock.EXPECT().Request( 87 model.CmdClassifierTypeRead, 88 s.localFeature.Address(), 89 dummyAddress, 90 false, 91 mock.AnythingOfType("[]model.CmdType")).Return(nil, errors.New("test")) 92 93 msgCounter, err := s.localFeature.RequestRemoteData(model.FunctionTypeBillListData, nil, nil, s.remoteFeature) 94 assert.NotNil(s.T(), err) 95 assert.Nil(s.T(), msgCounter) 96 97 msgCounter, err = s.localFeature.RequestRemoteDataBySenderAddress(model.CmdType{}, s.senderMock, "dummyfail", dummyAddress, 0) 98 assert.NotNil(s.T(), err) 99 assert.Nil(s.T(), msgCounter) 100 101 // send data request 102 msgCounter, err = s.localFeature.RequestRemoteData(s.function, nil, nil, s.remoteFeature) 103 assert.Nil(s.T(), err) 104 assert.NotNil(s.T(), msgCounter) 105 106 manufacturerData := &model.DeviceClassificationManufacturerDataType{ 107 BrandName: util.Ptr(model.DeviceClassificationStringType("brand name")), 108 VendorName: util.Ptr(model.DeviceClassificationStringType("vendor name")), 109 DeviceName: util.Ptr(model.DeviceClassificationStringType("device name")), 110 DeviceCode: util.Ptr(model.DeviceClassificationStringType("device code")), 111 SerialNumber: util.Ptr(model.DeviceClassificationStringType("serial number")), 112 } 113 114 replyMsg := api.Message{ 115 Cmd: model.CmdType{ 116 DeviceClassificationManufacturerData: manufacturerData, 117 }, 118 CmdClassifier: model.CmdClassifierTypeReply, 119 RequestHeader: &model.HeaderType{ 120 MsgCounter: util.Ptr(model.MsgCounterType(1)), 121 MsgCounterReference: &s.msgCounter, 122 }, 123 FeatureRemote: s.remoteFeature, 124 } 125 // set response 126 msgErr := s.localFeature.HandleMessage(&replyMsg) 127 if assert.Nil(s.T(), msgErr) { 128 remoteData := s.remoteFeature.DataCopy(s.function) 129 assert.IsType(s.T(), &model.DeviceClassificationManufacturerDataType{}, remoteData, "Data has wrong type") 130 } 131 } 132 133 func (s *LocalFeatureTestSuite) TestDeviceClassification_Request_Error() { 134 s.senderMock.On("Request", model.CmdClassifierTypeRead, s.localFeature.Address(), s.remoteFeature.Address(), false, mock.AnythingOfType("[]model.CmdType")).Return(&s.msgCounter, nil) 135 136 const errorNumber = model.ErrorNumberTypeGeneralError 137 const errorDescription = "error occurred" 138 139 // send data request 140 msgCounter, err := s.localFeature.RequestRemoteData(s.function, nil, nil, s.remoteFeature) 141 assert.NotNil(s.T(), msgCounter) 142 assert.Nil(s.T(), err) 143 144 replyMsg := api.Message{ 145 Cmd: model.CmdType{ 146 ResultData: &model.ResultDataType{ 147 ErrorNumber: util.Ptr(model.ErrorNumberType(errorNumber)), 148 Description: util.Ptr(model.DescriptionType(errorDescription)), 149 }, 150 }, 151 CmdClassifier: model.CmdClassifierTypeResult, 152 RequestHeader: &model.HeaderType{ 153 MsgCounter: util.Ptr(model.MsgCounterType(1)), 154 MsgCounterReference: &s.msgCounter, 155 }, 156 FeatureRemote: s.remoteFeature, 157 EntityRemote: s.remoteFeature.Entity(), 158 DeviceRemote: s.remoteFeature.Device(), 159 } 160 161 // set response 162 msgErr := s.localFeature.HandleMessage(&replyMsg) 163 if assert.Nil(s.T(), msgErr) { 164 remoteData := s.remoteFeature.DataCopy(s.function) 165 assert.Nil(s.T(), remoteData) 166 } 167 } 168 169 func (s *LocalFeatureTestSuite) TestDeviceClassification_Subscriptions() { 170 s.senderMock.On("Subscribe", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 171 s.senderMock.On("Unsubscribe", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 172 173 msgCounter, err := s.localFeature.SubscribeToRemote(s.remoteFeature.Address()) 174 assert.NotNil(s.T(), err) 175 assert.Nil(s.T(), msgCounter) 176 177 msgCounter, err = s.localFeature.RemoveRemoteSubscription(s.remoteFeature.Address()) 178 assert.NotNil(s.T(), err) 179 assert.Nil(s.T(), msgCounter) 180 181 s.localFeature.Device().AddRemoteDeviceForSki(s.remoteFeature.Device().Ski(), s.remoteFeature.Device()) 182 183 msgCounter, err = s.localServerFeature.SubscribeToRemote(s.remoteFeature.Address()) 184 assert.NotNil(s.T(), err) 185 assert.Nil(s.T(), msgCounter) 186 187 msgCounter, err = s.localFeature.RemoveRemoteSubscription(s.remoteFeature.Address()) 188 assert.Nil(s.T(), err) 189 assert.NotNil(s.T(), msgCounter) 190 191 subscribed := s.localFeature.HasSubscriptionToRemote(s.remoteFeature.Address()) 192 assert.Equal(s.T(), false, subscribed) 193 194 msgCounter, err = s.localFeature.SubscribeToRemote(s.remoteFeature.Address()) 195 assert.Nil(s.T(), err) 196 assert.NotNil(s.T(), msgCounter) 197 198 subscribed = s.localFeature.HasSubscriptionToRemote(s.remoteFeature.Address()) 199 assert.Equal(s.T(), true, subscribed) 200 201 msgCounter, err = s.localFeature.SubscribeToRemote(s.remoteSubFeature.Address()) 202 assert.Nil(s.T(), err) 203 assert.NotNil(s.T(), msgCounter) 204 205 msgCounter, err = s.localFeature.RemoveRemoteSubscription(s.remoteFeature.Address()) 206 assert.Nil(s.T(), err) 207 assert.NotNil(s.T(), msgCounter) 208 209 s.localFeature.RemoveAllRemoteSubscriptions() 210 } 211 212 func (s *LocalFeatureTestSuite) TestDeviceClassification_Bindings() { 213 s.senderMock.On("Bind", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 214 s.senderMock.On("Unbind", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 215 216 msgCounter, err := s.localFeature.BindToRemote(s.remoteFeature.Address()) 217 assert.NotNil(s.T(), err) 218 assert.Nil(s.T(), msgCounter) 219 220 msgCounter, err = s.localFeature.RemoveRemoteBinding(s.remoteFeature.Address()) 221 assert.NotNil(s.T(), err) 222 assert.Nil(s.T(), msgCounter) 223 224 s.localFeature.Device().AddRemoteDeviceForSki(s.remoteFeature.Device().Ski(), s.remoteFeature.Device()) 225 226 msgCounter, err = s.localServerFeature.BindToRemote(s.remoteFeature.Address()) 227 assert.NotNil(s.T(), err) 228 assert.Nil(s.T(), msgCounter) 229 230 msgCounter, err = s.localFeature.RemoveRemoteBinding(s.remoteFeature.Address()) 231 assert.Nil(s.T(), err) 232 assert.NotNil(s.T(), msgCounter) 233 234 binding := s.localFeature.HasBindingToRemote(s.remoteFeature.Address()) 235 assert.Equal(s.T(), false, binding) 236 237 msgCounter, err = s.localFeature.BindToRemote(s.remoteFeature.Address()) 238 assert.Nil(s.T(), err) 239 assert.NotNil(s.T(), msgCounter) 240 241 binding = s.localFeature.HasBindingToRemote(s.remoteFeature.Address()) 242 assert.Equal(s.T(), true, binding) 243 244 msgCounter, err = s.localFeature.BindToRemote(s.remoteSubFeature.Address()) 245 assert.Nil(s.T(), err) 246 assert.NotNil(s.T(), msgCounter) 247 248 msgCounter, err = s.localFeature.RemoveRemoteBinding(s.remoteFeature.Address()) 249 assert.Nil(s.T(), err) 250 assert.NotNil(s.T(), msgCounter) 251 252 s.localFeature.RemoveAllRemoteBindings() 253 } 254 255 func (s *LocalFeatureTestSuite) Test_CleanRemoteDeviceCaches() { 256 s.senderMock.On("Subscribe", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 257 s.senderMock.On("Bind", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 258 259 s.localFeature.CleanWriteApprovalCaches("testdummytest") 260 s.localFeature.CleanRemoteDeviceCaches(nil) 261 262 address := &model.DeviceAddressType{} 263 s.localFeature.CleanRemoteDeviceCaches(address) 264 265 address.Device = util.Ptr(model.AddressDeviceType("dummy")) 266 s.localFeature.CleanRemoteDeviceCaches(address) 267 268 address.Device = s.remoteFeature.Address().Device 269 s.localFeature.CleanRemoteDeviceCaches(address) 270 271 s.localFeature.Device().AddRemoteDeviceForSki(s.remoteFeature.Device().Ski(), s.remoteFeature.Device()) 272 s.localFeature.Device().AddRemoteDeviceForSki(s.remote2Feature.Device().Ski(), s.remote2Feature.Device()) 273 274 msgCounter, err := s.localFeature.SubscribeToRemote(s.remote2Feature.Address()) 275 assert.Nil(s.T(), err) 276 assert.NotNil(s.T(), msgCounter) 277 278 msgCounter, err = s.localFeature.SubscribeToRemote(s.remoteFeature.Address()) 279 assert.Nil(s.T(), err) 280 assert.NotNil(s.T(), msgCounter) 281 282 msgCounter, err = s.localFeature.SubscribeToRemote(s.remoteSubFeature.Address()) 283 assert.Nil(s.T(), err) 284 assert.NotNil(s.T(), msgCounter) 285 286 value := s.localFeature.HasSubscriptionToRemote(s.remote2Feature.Address()) 287 assert.True(s.T(), value) 288 289 value = s.localFeature.HasSubscriptionToRemote(s.remoteFeature.Address()) 290 assert.True(s.T(), value) 291 292 value = s.localFeature.HasSubscriptionToRemote(s.remoteSubFeature.Address()) 293 assert.True(s.T(), value) 294 295 msgCounter, err = s.localFeature.BindToRemote(s.remote2Feature.Address()) 296 assert.Nil(s.T(), err) 297 assert.NotNil(s.T(), msgCounter) 298 299 msgCounter, err = s.localFeature.BindToRemote(s.remoteFeature.Address()) 300 assert.Nil(s.T(), err) 301 assert.NotNil(s.T(), msgCounter) 302 303 msgCounter, err = s.localFeature.BindToRemote(s.remoteSubFeature.Address()) 304 assert.Nil(s.T(), err) 305 assert.NotNil(s.T(), msgCounter) 306 307 value = s.localFeature.HasBindingToRemote(s.remoteFeature.Address()) 308 assert.True(s.T(), value) 309 310 value = s.localFeature.HasBindingToRemote(s.remoteSubFeature.Address()) 311 assert.True(s.T(), value) 312 313 s.localFeature.CleanRemoteDeviceCaches(address) 314 315 value = s.localFeature.HasSubscriptionToRemote(s.remote2Feature.Address()) 316 assert.True(s.T(), value) 317 318 value = s.localFeature.HasSubscriptionToRemote(s.remoteFeature.Address()) 319 assert.False(s.T(), value) 320 321 value = s.localFeature.HasSubscriptionToRemote(s.remoteSubFeature.Address()) 322 assert.False(s.T(), value) 323 324 value = s.localFeature.HasBindingToRemote(s.remote2Feature.Address()) 325 assert.True(s.T(), value) 326 327 value = s.localFeature.HasBindingToRemote(s.remoteFeature.Address()) 328 assert.False(s.T(), value) 329 330 value = s.localFeature.HasBindingToRemote(s.remoteSubFeature.Address()) 331 assert.False(s.T(), value) 332 } 333 334 func (s *LocalFeatureTestSuite) Test_CleanRemoteEntityCaches() { 335 s.senderMock.On("Subscribe", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 336 s.senderMock.On("Bind", mock.Anything, mock.Anything, mock.Anything).Return(&s.msgCounter, nil) 337 338 s.localFeature.CleanWriteApprovalCaches("testdummytest") 339 s.localFeature.CleanRemoteEntityCaches(nil) 340 341 address := &model.EntityAddressType{} 342 s.localFeature.CleanRemoteEntityCaches(address) 343 344 address.Device = util.Ptr(model.AddressDeviceType("dummy")) 345 s.localFeature.CleanRemoteEntityCaches(address) 346 347 address.Entity = []model.AddressEntityType{10} 348 s.localFeature.CleanRemoteEntityCaches(address) 349 350 address.Device = s.remoteFeature.Address().Device 351 s.localFeature.CleanRemoteEntityCaches(address) 352 353 address.Entity = s.remoteFeature.Address().Entity 354 s.localFeature.CleanRemoteEntityCaches(address) 355 356 s.localFeature.Device().AddRemoteDeviceForSki(s.remoteFeature.Device().Ski(), s.remoteFeature.Device()) 357 358 msgCounter, err := s.localFeature.SubscribeToRemote(s.remoteFeature.Address()) 359 assert.Nil(s.T(), err) 360 assert.NotNil(s.T(), msgCounter) 361 362 msgCounter, err = s.localFeature.SubscribeToRemote(s.remoteSubFeature.Address()) 363 assert.Nil(s.T(), err) 364 assert.NotNil(s.T(), msgCounter) 365 366 binding := s.localFeature.HasSubscriptionToRemote(s.remoteFeature.Address()) 367 assert.True(s.T(), binding) 368 369 binding = s.localFeature.HasSubscriptionToRemote(s.remoteSubFeature.Address()) 370 assert.True(s.T(), binding) 371 372 msgCounter, err = s.localFeature.BindToRemote(s.remoteFeature.Address()) 373 assert.Nil(s.T(), err) 374 assert.NotNil(s.T(), msgCounter) 375 376 msgCounter, err = s.localFeature.BindToRemote(s.remoteSubFeature.Address()) 377 assert.Nil(s.T(), err) 378 assert.NotNil(s.T(), msgCounter) 379 380 binding = s.localFeature.HasBindingToRemote(s.remoteFeature.Address()) 381 assert.True(s.T(), binding) 382 383 binding = s.localFeature.HasBindingToRemote(s.remoteSubFeature.Address()) 384 assert.True(s.T(), binding) 385 386 s.localFeature.CleanRemoteEntityCaches(address) 387 388 binding = s.localFeature.HasSubscriptionToRemote(s.remoteFeature.Address()) 389 assert.False(s.T(), binding) 390 391 binding = s.localFeature.HasSubscriptionToRemote(s.remoteSubFeature.Address()) 392 assert.True(s.T(), binding) 393 394 binding = s.localFeature.HasBindingToRemote(s.remoteFeature.Address()) 395 assert.False(s.T(), binding) 396 397 binding = s.localFeature.HasBindingToRemote(s.remoteSubFeature.Address()) 398 assert.True(s.T(), binding) 399 } 400 401 func (s *LocalFeatureTestSuite) Test_HandleMessage() { 402 msg := &api.Message{ 403 FeatureRemote: s.remoteServerFeature, 404 CmdClassifier: model.CmdClassifierType("buggy"), 405 Cmd: model.CmdType{}, 406 } 407 408 err := s.localFeature.HandleMessage(msg) 409 assert.NotNil(s.T(), err) 410 411 msg = &api.Message{ 412 FeatureRemote: s.remoteServerFeature, 413 CmdClassifier: model.CmdClassifierType("buggy"), 414 Cmd: model.CmdType{ 415 ResultData: &model.ResultDataType{}, 416 }, 417 } 418 419 err = s.localFeature.HandleMessage(msg) 420 assert.NotNil(s.T(), err) 421 } 422 423 func (s *LocalFeatureTestSuite) Test_Result() { 424 msg := &api.Message{ 425 FeatureRemote: s.remoteServerFeature, 426 CmdClassifier: model.CmdClassifierTypeResult, 427 Cmd: model.CmdType{ 428 ResultData: &model.ResultDataType{}, 429 }, 430 } 431 432 err := s.localFeature.HandleMessage(msg) 433 assert.NotNil(s.T(), err) 434 435 msg.RequestHeader = &model.HeaderType{ 436 MsgCounterReference: util.Ptr(model.MsgCounterType(100)), 437 } 438 msg.Cmd.ResultData = &model.ResultDataType{ 439 ErrorNumber: util.Ptr(model.ErrorNumberType(1)), 440 Description: util.Ptr(model.DescriptionType("test")), 441 } 442 err = s.localFeature.HandleMessage(msg) 443 assert.Nil(s.T(), err) 444 } 445 446 func (s *LocalFeatureTestSuite) Test_Read() { 447 msg := &api.Message{ 448 FeatureRemote: s.remoteFeature, 449 CmdClassifier: model.CmdClassifierTypeRead, 450 Cmd: model.CmdType{ 451 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 452 }, 453 } 454 455 err := s.localFeature.HandleMessage(msg) 456 assert.NotNil(s.T(), err) 457 458 s.senderMock.EXPECT().Reply(mock.Anything, mock.Anything, mock.Anything).Return(errors.New("test")).Once() 459 err = s.localServerFeature.HandleMessage(msg) 460 assert.NotNil(s.T(), err) 461 462 msg = &api.Message{ 463 FeatureRemote: s.remoteFeature, 464 CmdClassifier: model.CmdClassifierTypeRead, 465 Cmd: model.CmdType{ 466 DeviceClassificationManufacturerData: &model.DeviceClassificationManufacturerDataType{}, 467 }, 468 } 469 err = s.localFeature.HandleMessage(msg) 470 assert.NotNil(s.T(), err) 471 472 s.senderMock.EXPECT().Reply(mock.Anything, mock.Anything, mock.Anything).Return(errors.New("test")) 473 err = s.localServerFeature.HandleMessage(msg) 474 assert.NotNil(s.T(), err) 475 } 476 477 func (s *LocalFeatureTestSuite) Test_Reply() { 478 msg := &api.Message{ 479 FeatureRemote: s.remoteServerFeature, 480 CmdClassifier: model.CmdClassifierTypeReply, 481 Cmd: model.CmdType{ 482 DeviceClassificationManufacturerData: &model.DeviceClassificationManufacturerDataType{}, 483 }, 484 } 485 486 err := s.localFeature.HandleMessage(msg) 487 assert.Nil(s.T(), err) 488 489 msg.RequestHeader = &model.HeaderType{ 490 MsgCounterReference: util.Ptr(model.MsgCounterType(100)), 491 } 492 err = s.localFeature.HandleMessage(msg) 493 assert.Nil(s.T(), err) 494 } 495 496 func (s *LocalFeatureTestSuite) Test_Notify() { 497 msg := &api.Message{ 498 FeatureRemote: s.remoteServerFeature, 499 CmdClassifier: model.CmdClassifierTypeNotify, 500 Cmd: model.CmdType{ 501 DeviceClassificationManufacturerData: &model.DeviceClassificationManufacturerDataType{}, 502 }, 503 } 504 505 err := s.localFeature.HandleMessage(msg) 506 assert.Nil(s.T(), err) 507 } 508 509 func (s *LocalFeatureTestSuite) Test_Write() { 510 s.senderMock.EXPECT().ResultSuccess(mock.Anything, mock.Anything).Return(nil).Once() 511 512 msg := &api.Message{ 513 RequestHeader: &model.HeaderType{ 514 MsgCounter: util.Ptr(model.MsgCounterType(1)), 515 AckRequest: util.Ptr(true), 516 }, 517 CmdClassifier: model.CmdClassifierTypeWrite, 518 FeatureRemote: s.remoteSubFeature, 519 Cmd: model.CmdType{ 520 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 521 }, 522 } 523 524 err := s.localServerFeatureWrite.HandleMessage(msg) 525 assert.Nil(s.T(), err) 526 } 527 528 func (s *LocalFeatureTestSuite) Test_SetWriteApprovalCallback_Invalid() { 529 cb := func(msg *api.Message) {} 530 err := s.localFeature.AddWriteApprovalCallback(cb) 531 assert.NotNil(s.T(), err) 532 result := model.ErrorType{ 533 ErrorNumber: 0, 534 } 535 s.localFeature.ApproveOrDenyWrite(&api.Message{}, result) 536 } 537 538 func (s *LocalFeatureTestSuite) Test_AddPendingApproval_Invalid() { 539 cb := func(msg *api.Message) {} 540 err := s.localServerFeatureWrite.AddWriteApprovalCallback(cb) 541 assert.Nil(s.T(), err) 542 543 msg := &api.Message{ 544 CmdClassifier: model.CmdClassifierTypeWrite, 545 FeatureRemote: s.remoteSubFeature, 546 Cmd: model.CmdType{ 547 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 548 }, 549 } 550 551 err1 := s.localServerFeatureWrite.HandleMessage(msg) 552 assert.Nil(s.T(), err1) 553 } 554 555 func (s *LocalFeatureTestSuite) Test_Write_Callback_One() { 556 counter := model.MsgCounterType(1) 557 msg := &api.Message{ 558 RequestHeader: &model.HeaderType{ 559 MsgCounter: util.Ptr(counter), 560 AckRequest: util.Ptr(true), 561 }, 562 CmdClassifier: model.CmdClassifierTypeWrite, 563 FeatureRemote: s.remoteSubFeature, 564 DeviceRemote: s.remoteSubFeature.Device(), 565 Cmd: model.CmdType{ 566 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 567 }, 568 } 569 570 tempLSFWrite := s.localServerFeatureWrite 571 572 cb1 := func(msg *api.Message) { 573 result := model.ErrorType{ 574 ErrorNumber: 0, 575 } 576 tempLSFWrite.ApproveOrDenyWrite(msg, result) 577 } 578 tempLSFWrite.AddWriteApprovalCallback(cb1) 579 580 s.senderMock.EXPECT().ResultSuccess(mock.Anything, mock.Anything).Return(nil).Once() 581 err := tempLSFWrite.HandleMessage(msg) 582 assert.Nil(s.T(), err) 583 584 // callback is called asynchronously 585 time.Sleep(time.Millisecond * 200) 586 } 587 588 func (s *LocalFeatureTestSuite) Test_Write_Callback_One_Fail() { 589 counter := model.MsgCounterType(1) 590 msg := &api.Message{ 591 RequestHeader: &model.HeaderType{ 592 MsgCounter: util.Ptr(counter), 593 AckRequest: util.Ptr(true), 594 }, 595 CmdClassifier: model.CmdClassifierTypeWrite, 596 FeatureRemote: s.remoteSubFeature, 597 DeviceRemote: s.remoteSubFeature.Device(), 598 Cmd: model.CmdType{ 599 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 600 }, 601 } 602 603 tempLSFWrite := s.localServerFeatureWrite 604 605 cb1 := func(msg *api.Message) { 606 result := model.ErrorType{ 607 ErrorNumber: 7, 608 Description: util.Ptr(model.DescriptionType("not allowed by application")), 609 } 610 tempLSFWrite.ApproveOrDenyWrite(msg, result) 611 } 612 tempLSFWrite.AddWriteApprovalCallback(cb1) 613 614 s.senderMock.EXPECT().ResultError(mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() 615 err := tempLSFWrite.HandleMessage(msg) 616 assert.Nil(s.T(), err) 617 618 // callback is called asynchronously 619 time.Sleep(time.Millisecond * 200) 620 } 621 622 func (s *LocalFeatureTestSuite) Test_Write_Callback_Two() { 623 msg := &api.Message{ 624 RequestHeader: &model.HeaderType{ 625 MsgCounter: util.Ptr(model.MsgCounterType(1)), 626 AckRequest: util.Ptr(true), 627 }, 628 CmdClassifier: model.CmdClassifierTypeWrite, 629 FeatureRemote: s.remoteSubFeature, 630 DeviceRemote: s.remoteSubFeature.Device(), 631 Cmd: model.CmdType{ 632 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 633 }, 634 } 635 636 tempLSFWrite := s.localServerFeatureWrite 637 638 cb1 := func(msg *api.Message) { 639 result := model.ErrorType{ 640 ErrorNumber: 0, 641 } 642 tempLSFWrite.ApproveOrDenyWrite(msg, result) 643 } 644 tempLSFWrite.AddWriteApprovalCallback(cb1) 645 646 cb2 := func(msg *api.Message) { 647 result := model.ErrorType{ 648 ErrorNumber: 0, 649 } 650 tempLSFWrite.ApproveOrDenyWrite(msg, result) 651 } 652 tempLSFWrite.AddWriteApprovalCallback(cb2) 653 654 s.senderMock.EXPECT().ResultSuccess(mock.Anything, mock.Anything).Return(nil).Once() 655 err := tempLSFWrite.HandleMessage(msg) 656 assert.Nil(s.T(), err) 657 658 // callback is called asynchronously 659 time.Sleep(time.Millisecond * 200) 660 } 661 662 func (s *LocalFeatureTestSuite) Test_Write_Callback_Two_Fail() { 663 msg := &api.Message{ 664 RequestHeader: &model.HeaderType{ 665 MsgCounter: util.Ptr(model.MsgCounterType(1)), 666 AckRequest: util.Ptr(true), 667 }, 668 CmdClassifier: model.CmdClassifierTypeWrite, 669 FeatureRemote: s.remoteSubFeature, 670 DeviceRemote: s.remoteSubFeature.Device(), 671 Cmd: model.CmdType{ 672 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 673 }, 674 } 675 676 tempLSFWrite := s.localServerFeatureWrite 677 678 cb1 := func(msg *api.Message) { 679 result := model.ErrorType{ 680 ErrorNumber: 0, 681 } 682 tempLSFWrite.ApproveOrDenyWrite(msg, result) 683 } 684 tempLSFWrite.AddWriteApprovalCallback(cb1) 685 686 cb2 := func(msg *api.Message) { 687 result := model.ErrorType{ 688 ErrorNumber: 7, 689 Description: util.Ptr(model.DescriptionType("not allowed by application")), 690 } 691 tempLSFWrite.ApproveOrDenyWrite(msg, result) 692 } 693 tempLSFWrite.AddWriteApprovalCallback(cb2) 694 695 s.senderMock.EXPECT().ResultError(mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() 696 697 err := tempLSFWrite.HandleMessage(msg) 698 assert.Nil(s.T(), err) 699 700 // callback is called asynchronously 701 time.Sleep(time.Millisecond * 200) 702 } 703 704 func (s *LocalFeatureTestSuite) Test_Write_Callback_Timeout() { 705 s.localServerFeatureWrite.SetWriteApprovalTimeout(time.Millisecond * 500) 706 707 s.senderMock.EXPECT().ResultError(mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() 708 709 msg := &api.Message{ 710 RequestHeader: &model.HeaderType{ 711 MsgCounter: util.Ptr(model.MsgCounterType(1)), 712 AckRequest: util.Ptr(true), 713 }, 714 CmdClassifier: model.CmdClassifierTypeWrite, 715 FeatureRemote: s.remoteSubFeature, 716 DeviceRemote: s.remoteSubFeature.Device(), 717 Cmd: model.CmdType{ 718 LoadControlLimitListData: &model.LoadControlLimitListDataType{}, 719 }, 720 } 721 722 tempLSFWrite := s.localServerFeatureWrite 723 724 cb := func(msg *api.Message) { 725 time.Sleep(time.Second * 1) 726 result := model.ErrorType{ 727 ErrorNumber: 0, 728 } 729 tempLSFWrite.ApproveOrDenyWrite(msg, result) 730 } 731 732 tempLSFWrite.AddWriteApprovalCallback(cb) 733 err := tempLSFWrite.HandleMessage(msg) 734 assert.Nil(s.T(), err) 735 736 // callback is called asynchronously 737 time.Sleep(time.Second * 1) 738 } 739 740 func (s *LocalFeatureTestSuite) Test_Set_Update() { 741 partial := model.NewFilterTypePartial() 742 743 noData := s.localServerFeatureWrite.DataCopy("dummy") 744 assert.Nil(s.T(), noData) 745 746 data := &model.LoadControlLimitListDataType{ 747 LoadControlLimitData: []model.LoadControlLimitDataType{ 748 { 749 LimitId: util.Ptr(model.LoadControlLimitIdType(1)), 750 IsLimitActive: util.Ptr(false), 751 }, 752 }, 753 } 754 755 s.localServerFeatureWrite.SetData(s.serverWriteFunction, data) 756 757 dataCopy := s.localServerFeatureWrite.DataCopy(s.serverWriteFunction) 758 equal := reflect.DeepEqual(data, dataCopy) 759 assert.True(s.T(), equal) 760 761 newData := &model.LoadControlLimitListDataType{ 762 LoadControlLimitData: []model.LoadControlLimitDataType{ 763 { 764 LimitId: util.Ptr(model.LoadControlLimitIdType(1)), 765 IsLimitActive: util.Ptr(true), 766 }, 767 }, 768 } 769 770 err := s.localServerFeatureWrite.UpdateData(s.serverWriteFunction, newData, nil, nil) 771 assert.Nil(s.T(), err) 772 773 dataCopy = s.localServerFeatureWrite.DataCopy(s.serverWriteFunction) 774 equal = reflect.DeepEqual(data, dataCopy) 775 assert.False(s.T(), equal) 776 777 newData = &model.LoadControlLimitListDataType{ 778 LoadControlLimitData: []model.LoadControlLimitDataType{ 779 { 780 LimitId: util.Ptr(model.LoadControlLimitIdType(1)), 781 IsLimitActive: util.Ptr(true), 782 IsLimitChangeable: util.Ptr(true), 783 }, 784 }, 785 } 786 err = s.localServerFeatureWrite.UpdateData(s.serverWriteFunction, newData, partial, nil) 787 assert.Nil(s.T(), err) 788 789 dataCopy = s.localServerFeatureWrite.DataCopy(s.serverWriteFunction) 790 modelData, ok := dataCopy.(*model.LoadControlLimitListDataType) 791 assert.True(s.T(), ok) 792 assert.Equal(s.T(), 1, len(modelData.LoadControlLimitData)) 793 assert.Equal(s.T(), model.LoadControlLimitIdType(1), *modelData.LoadControlLimitData[0].LimitId) 794 assert.True(s.T(), *modelData.LoadControlLimitData[0].IsLimitActive) 795 assert.True(s.T(), *modelData.LoadControlLimitData[0].IsLimitChangeable) 796 797 moreData := &model.LoadControlLimitListDataType{ 798 LoadControlLimitData: []model.LoadControlLimitDataType{ 799 { 800 LimitId: util.Ptr(model.LoadControlLimitIdType(2)), 801 IsLimitActive: util.Ptr(false), 802 IsLimitChangeable: util.Ptr(false), 803 }, 804 }, 805 } 806 err = s.localServerFeatureWrite.UpdateData(s.serverWriteFunction, moreData, partial, nil) 807 assert.Nil(s.T(), err) 808 809 dataCopy = s.localServerFeatureWrite.DataCopy(s.serverWriteFunction) 810 modelData, ok = dataCopy.(*model.LoadControlLimitListDataType) 811 assert.True(s.T(), ok) 812 assert.Equal(s.T(), 2, len(modelData.LoadControlLimitData)) 813 assert.Equal(s.T(), model.LoadControlLimitIdType(2), *modelData.LoadControlLimitData[1].LimitId) 814 assert.False(s.T(), *modelData.LoadControlLimitData[1].IsLimitActive) 815 assert.False(s.T(), *modelData.LoadControlLimitData[1].IsLimitChangeable) 816 817 updateData := &model.LoadControlLimitListDataType{ 818 LoadControlLimitData: []model.LoadControlLimitDataType{ 819 { 820 LimitId: util.Ptr(model.LoadControlLimitIdType(2)), 821 IsLimitChangeable: util.Ptr(true), 822 TimePeriod: model.NewTimePeriodTypeWithRelativeEndTime(time.Minute * 2), 823 }, 824 }, 825 } 826 err = s.localServerFeatureWrite.UpdateData(s.serverWriteFunction, updateData, partial, nil) 827 assert.Nil(s.T(), err) 828 829 dataCopy = s.localServerFeatureWrite.DataCopy(s.serverWriteFunction) 830 modelData, ok = dataCopy.(*model.LoadControlLimitListDataType) 831 assert.True(s.T(), ok) 832 assert.Equal(s.T(), 2, len(modelData.LoadControlLimitData)) 833 assert.Equal(s.T(), model.LoadControlLimitIdType(2), *modelData.LoadControlLimitData[1].LimitId) 834 assert.False(s.T(), *modelData.LoadControlLimitData[1].IsLimitActive) 835 assert.True(s.T(), *modelData.LoadControlLimitData[1].IsLimitChangeable) 836 assert.NotNil(s.T(), modelData.LoadControlLimitData[1].TimePeriod) 837 838 deleteFilter := &model.FilterType{ 839 LoadControlLimitListDataSelectors: &model.LoadControlLimitListDataSelectorsType{ 840 LimitId: util.Ptr(model.LoadControlLimitIdType(2)), 841 }, 842 LoadControlLimitDataElements: &model.LoadControlLimitDataElementsType{ 843 TimePeriod: &model.TimePeriodElementsType{}, 844 }, 845 } 846 updateData = &model.LoadControlLimitListDataType{ 847 LoadControlLimitData: []model.LoadControlLimitDataType{ 848 { 849 LimitId: util.Ptr(model.LoadControlLimitIdType(2)), 850 IsLimitChangeable: util.Ptr(false), 851 }, 852 }, 853 } 854 err = s.localServerFeatureWrite.UpdateData(s.serverWriteFunction, updateData, partial, deleteFilter) 855 assert.Nil(s.T(), err) 856 857 dataCopy = s.localServerFeatureWrite.DataCopy(s.serverWriteFunction) 858 modelData, ok = dataCopy.(*model.LoadControlLimitListDataType) 859 assert.True(s.T(), ok) 860 assert.Equal(s.T(), 2, len(modelData.LoadControlLimitData)) 861 assert.False(s.T(), *modelData.LoadControlLimitData[1].IsLimitChangeable) 862 assert.Nil(s.T(), modelData.LoadControlLimitData[1].TimePeriod) 863 }