github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/mediator/service_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package mediator 8 9 import ( 10 "encoding/json" 11 "errors" 12 "fmt" 13 "testing" 14 "time" 15 16 "github.com/google/uuid" 17 "github.com/stretchr/testify/require" 18 19 "github.com/hyperledger/aries-framework-go/component/storageutil/mem" 20 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model" 21 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 22 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/messagepickup" 23 "github.com/hyperledger/aries-framework-go/pkg/didcomm/transport" 24 "github.com/hyperledger/aries-framework-go/pkg/doc/did" 25 vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 26 mockdispatcher "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/dispatcher" 27 mockmessagep "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/messagepickup" 28 mockdiddoc "github.com/hyperledger/aries-framework-go/pkg/mock/diddoc" 29 mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms" 30 mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider" 31 mockstore "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 32 mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr" 33 "github.com/hyperledger/aries-framework-go/pkg/store/connection" 34 "github.com/hyperledger/aries-framework-go/spi/storage" 35 ) 36 37 const ( 38 MYDID = "myDID" 39 THEIRDID = "theirDID" 40 ENDPOINT = "http://router.example.com" 41 ) 42 43 type updateResult struct { 44 action string 45 result string 46 } 47 48 func TestServiceNew(t *testing.T) { 49 t.Run("test new service - success", func(t *testing.T) { 50 svc, err := New(&mockprovider.Provider{ 51 ServiceMap: map[string]interface{}{ 52 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 53 }, 54 StorageProviderValue: mem.NewProvider(), 55 ProtocolStateStorageProviderValue: mem.NewProvider(), 56 }) 57 require.NoError(t, err) 58 require.Equal(t, Coordination, svc.Name()) 59 }) 60 61 t.Run("test new service name - failure", func(t *testing.T) { 62 svc, err := New(&mockprovider.Provider{ 63 StorageProviderValue: &mockstore.MockStoreProvider{ 64 ErrOpenStoreHandle: fmt.Errorf("error opening the store"), 65 }, 66 }) 67 require.Error(t, err) 68 require.Contains(t, err.Error(), "open route coordination store") 69 require.Nil(t, svc) 70 }) 71 } 72 73 func TestService_Initialize(t *testing.T) { 74 t.Run("Success", func(t *testing.T) { 75 prov := &mockprovider.Provider{ 76 ServiceMap: map[string]interface{}{ 77 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 78 }, 79 StorageProviderValue: mem.NewProvider(), 80 ProtocolStateStorageProviderValue: mem.NewProvider(), 81 } 82 svc := Service{} 83 84 err := svc.Initialize(prov) 85 require.NoError(t, err) 86 87 // second init is no-op 88 err = svc.Initialize(prov) 89 require.NoError(t, err) 90 }) 91 92 t.Run("failure, not given a valid provider", func(t *testing.T) { 93 svc := Service{} 94 95 err := svc.Initialize("not a provider") 96 require.Error(t, err) 97 require.Contains(t, err.Error(), "expected provider of type") 98 }) 99 } 100 101 func TestServiceAccept(t *testing.T) { 102 s := &Service{} 103 104 require.Equal(t, true, s.Accept(RequestMsgType)) 105 require.Equal(t, true, s.Accept(GrantMsgType)) 106 require.Equal(t, true, s.Accept(KeylistUpdateMsgType)) 107 require.Equal(t, true, s.Accept(KeylistUpdateResponseMsgType)) 108 require.Equal(t, true, s.Accept(service.ForwardMsgType)) 109 require.Equal(t, false, s.Accept("unsupported msg type")) 110 } 111 112 func TestServiceHandleInbound(t *testing.T) { 113 t.Run("test handle inbound ", func(t *testing.T) { 114 svc, err := New(&mockprovider.Provider{ 115 ServiceMap: map[string]interface{}{ 116 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 117 }, 118 StorageProviderValue: mem.NewProvider(), 119 ProtocolStateStorageProviderValue: mem.NewProvider(), 120 }) 121 require.NoError(t, err) 122 123 msgID := randomID() 124 125 id, err := svc.HandleInbound(&service.DIDCommMsgMap{"@id": msgID}, service.EmptyDIDCommContext()) 126 require.NoError(t, err) 127 require.Equal(t, msgID, id) 128 }) 129 } 130 131 func TestServiceHandleOutbound(t *testing.T) { 132 t.Run("outbound route-request", func(t *testing.T) { 133 msgID := make(chan string) 134 135 provider := &mockprovider.Provider{ 136 ServiceMap: map[string]interface{}{ 137 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 138 }, 139 StorageProviderValue: mem.NewProvider(), 140 ProtocolStateStorageProviderValue: mem.NewProvider(), 141 KMSValue: &mockkms.KeyManager{}, 142 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 143 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 144 require.Equal(t, myDID, MYDID) 145 require.Equal(t, theirDID, THEIRDID) 146 147 reqMsgMap, ok := msg.(service.DIDCommMsgMap) 148 require.True(t, ok) 149 150 request := &Request{} 151 152 err := reqMsgMap.Decode(request) 153 require.NoError(t, err) 154 155 msgID <- request.ID 156 return nil 157 }, 158 }, 159 } 160 connRec := &connection.Record{ 161 ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "completed", 162 } 163 164 r, err := connection.NewRecorder(provider) 165 require.NoError(t, err) 166 err = r.SaveConnectionRecord(connRec) 167 require.NoError(t, err) 168 169 svc, err := New(provider) 170 require.NoError(t, err) 171 172 go func() { 173 id := <-msgID 174 require.NoError(t, svc.saveGrant(generateGrantMsgPayload(t, id))) 175 }() 176 }) 177 178 t.Run("rejects invalid msg types", func(t *testing.T) { 179 _, err := (&Service{}).HandleOutbound(service.NewDIDCommMsgMap(&Request{ 180 Type: "invalid", 181 }), "myDID", "theirDID") 182 require.Error(t, err) 183 }) 184 185 t.Run("rejects unsupported route protocol messages", func(t *testing.T) { 186 _, err := (&Service{}).HandleOutbound(service.NewDIDCommMsgMap(&Request{ 187 Type: GrantMsgType, 188 }), "myDID", "theirDID") 189 require.Error(t, err) 190 }) 191 192 t.Run("wraps error getting connection ID", func(t *testing.T) { 193 expected := errors.New("test") 194 s, err := New(&mockprovider.Provider{ 195 ServiceMap: map[string]interface{}{ 196 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 197 }, 198 StorageProviderValue: mockstore.NewMockStoreProvider(), 199 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 200 }) 201 require.NoError(t, err) 202 s.connectionLookup = &connectionsStub{ 203 getConnIDByDIDs: func(string, string) (string, error) { 204 return "", expected 205 }, 206 } 207 _, err = s.HandleOutbound(service.NewDIDCommMsgMap( 208 &Request{Type: RequestMsgType}), 209 "myDID", "theirDID", 210 ) 211 require.Error(t, err) 212 require.True(t, errors.Is(err, expected)) 213 }) 214 215 t.Run("wraps error getting connection record", func(t *testing.T) { 216 expected := errors.New("test") 217 s, err := New(&mockprovider.Provider{ 218 ServiceMap: map[string]interface{}{ 219 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 220 }, 221 StorageProviderValue: mockstore.NewMockStoreProvider(), 222 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 223 }) 224 require.NoError(t, err) 225 s.connectionLookup = &connectionsStub{ 226 getConnRecord: func(string) (*connection.Record, error) { 227 return nil, expected 228 }, 229 } 230 _, err = s.HandleOutbound(service.NewDIDCommMsgMap( 231 &Request{Type: RequestMsgType}), 232 "myDID", "theirDID", 233 ) 234 require.Error(t, err) 235 require.True(t, errors.Is(err, expected)) 236 }) 237 } 238 239 func TestServiceRequestMsg(t *testing.T) { 240 t.Run("test service handle inbound request msg - success", func(t *testing.T) { 241 svc, err := New(&mockprovider.Provider{ 242 ServiceMap: map[string]interface{}{ 243 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 244 }, 245 StorageProviderValue: mockstore.NewMockStoreProvider(), 246 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 247 KMSValue: &mockkms.KeyManager{}, 248 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 249 }) 250 require.NoError(t, err) 251 252 err = svc.RegisterActionEvent(make(chan service.DIDCommAction)) 253 require.NoError(t, err) 254 255 msgID := randomID() 256 257 id, err := svc.HandleInbound(generateRequestMsgPayload(t, msgID), service.EmptyDIDCommContext()) 258 require.NoError(t, err) 259 require.Equal(t, msgID, id) 260 }) 261 262 t.Run("test service handle request msg - success", func(t *testing.T) { 263 svc, err := New(&mockprovider.Provider{ 264 ServiceMap: map[string]interface{}{ 265 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 266 }, 267 StorageProviderValue: mockstore.NewMockStoreProvider(), 268 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 269 KMSValue: &mockkms.KeyManager{}, 270 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 271 }) 272 require.NoError(t, err) 273 274 msg := &service.DIDCommMsgMap{"@id": map[int]int{}} 275 276 err = svc.handleInboundRequest(&callback{ 277 msg: msg, 278 myDID: MYDID, 279 theirDID: THEIRDID, 280 }) 281 require.Error(t, err) 282 require.Contains(t, err.Error(), "route request message unmarshal") 283 }) 284 285 t.Run("test service handle request msg - verify outbound message", func(t *testing.T) { 286 endpoint := "ws://agent.example.com" 287 svc, err := New(&mockprovider.Provider{ 288 ServiceMap: map[string]interface{}{ 289 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 290 }, 291 StorageProviderValue: mockstore.NewMockStoreProvider(), 292 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 293 KMSValue: &mockkms.KeyManager{}, 294 ServiceEndpointValue: endpoint, 295 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 296 ValidateSend: func(msg interface{}, senderVerKey string, des *service.Destination) error { 297 res, err := json.Marshal(msg) 298 require.NoError(t, err) 299 300 grant := &Grant{} 301 err = json.Unmarshal(res, grant) 302 require.NoError(t, err) 303 304 require.Equal(t, endpoint, grant.Endpoint) 305 require.Equal(t, 1, len(grant.RoutingKeys)) 306 307 return nil 308 }, 309 }, 310 MediaTypeProfilesValue: []string{transport.MediaTypeAIP2RFC0019Profile}, 311 }) 312 require.NoError(t, err) 313 314 msgID := randomID() 315 316 err = svc.handleInboundRequest(&callback{ 317 msg: generateRequestMsgPayload(t, msgID), 318 myDID: MYDID, 319 theirDID: THEIRDID, 320 options: &Options{}, 321 }) 322 require.NoError(t, err) 323 }) 324 325 t.Run("test service handle request msg - kms failure", func(t *testing.T) { 326 expected := errors.New("test") 327 svc, err := New(&mockprovider.Provider{ 328 ServiceMap: map[string]interface{}{ 329 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 330 }, 331 StorageProviderValue: mockstore.NewMockStoreProvider(), 332 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 333 KMSValue: &mockkms.KeyManager{ 334 CrAndExportPubKeyErr: expected, 335 }, 336 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 337 MediaTypeProfilesValue: []string{"value"}, 338 }) 339 require.NoError(t, err) 340 341 err = svc.handleInboundRequest(&callback{ 342 msg: service.NewDIDCommMsgMap(&Request{ID: "test", Type: RequestMsgType}), 343 myDID: MYDID, 344 theirDID: THEIRDID, 345 options: &Options{}, 346 }) 347 require.Error(t, err) 348 require.True(t, errors.Is(err, expected)) 349 }) 350 } 351 352 //nolint:gocyclo 353 func TestEvents(t *testing.T) { 354 t.Run("HandleInbound dispatches action events", func(t *testing.T) { 355 svc, err := New(&mockprovider.Provider{ 356 ServiceMap: map[string]interface{}{ 357 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 358 }, 359 StorageProviderValue: mockstore.NewMockStoreProvider(), 360 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 361 KMSValue: &mockkms.KeyManager{}, 362 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 363 }) 364 require.NoError(t, err) 365 366 events := make(chan service.DIDCommAction) 367 368 err = svc.RegisterActionEvent(events) 369 require.NoError(t, err) 370 371 msgID := randomID() 372 msg := generateRequestMsgPayload(t, msgID) 373 374 id, err := svc.HandleInbound(msg, service.EmptyDIDCommContext()) 375 require.NoError(t, err) 376 require.Equal(t, msgID, id) 377 378 select { 379 case e := <-events: 380 require.Equal(t, msg, e.Message) 381 case <-time.After(time.Second): 382 require.Fail(t, "timeout") 383 } 384 }) 385 386 t.Run("continuing inbound request event dispatches outbound grant", func(t *testing.T) { 387 dispatched := make(chan struct{}) 388 svc, err := New(&mockprovider.Provider{ 389 ServiceMap: map[string]interface{}{ 390 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 391 }, 392 StorageProviderValue: mockstore.NewMockStoreProvider(), 393 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 394 KMSValue: &mockkms.KeyManager{}, 395 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 396 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 397 dispatched <- struct{}{} 398 return nil 399 }, 400 }, 401 MediaTypeProfilesValue: []string{transport.MediaTypeAIP2RFC0019Profile}, 402 }) 403 require.NoError(t, err) 404 405 events := make(chan service.DIDCommAction) 406 407 err = svc.RegisterActionEvent(events) 408 require.NoError(t, err) 409 410 _, err = svc.HandleInbound(generateRequestMsgPayload(t, "123"), service.EmptyDIDCommContext()) 411 require.NoError(t, err) 412 413 select { 414 case e := <-events: 415 e.Continue(service.Empty{}) 416 case <-time.After(time.Second): 417 require.Fail(t, "timeout") 418 } 419 420 select { 421 case <-dispatched: 422 case <-time.After(time.Second): 423 require.Fail(t, "timeout") 424 } 425 }) 426 427 t.Run("stopping inbound request event does not dispatch outbound grant", func(t *testing.T) { 428 dispatched := make(chan struct{}) 429 svc, err := New(&mockprovider.Provider{ 430 ServiceMap: map[string]interface{}{ 431 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 432 }, 433 StorageProviderValue: mockstore.NewMockStoreProvider(), 434 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 435 KMSValue: &mockkms.KeyManager{}, 436 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 437 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 438 dispatched <- struct{}{} 439 return nil 440 }, 441 }, 442 }) 443 require.NoError(t, err) 444 445 events := make(chan service.DIDCommAction) 446 447 err = svc.RegisterActionEvent(events) 448 require.NoError(t, err) 449 450 _, err = svc.HandleInbound(generateRequestMsgPayload(t, "123"), service.EmptyDIDCommContext()) 451 require.NoError(t, err) 452 453 select { 454 case e := <-events: 455 e.Stop(errors.New("rejected")) 456 case <-time.After(time.Second): 457 require.Fail(t, "timeout") 458 } 459 460 select { 461 case <-dispatched: 462 require.Fail(t, "stopping the protocol flow should not result in an outbound message dispatch") 463 case <-time.After(time.Second): 464 } 465 }) 466 467 t.Run("fails when no listeners are registered for action events", func(t *testing.T) { 468 svc, err := New(&mockprovider.Provider{ 469 ServiceMap: map[string]interface{}{ 470 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 471 }, 472 StorageProviderValue: mockstore.NewMockStoreProvider(), 473 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 474 KMSValue: &mockkms.KeyManager{}, 475 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 476 }) 477 require.NoError(t, err) 478 479 _, err = svc.HandleInbound(generateRequestMsgPayload(t, "123"), service.EmptyDIDCommContext()) 480 require.Error(t, err) 481 }) 482 483 t.Run("Continue assigns keys and endpoint provided by user", func(t *testing.T) { 484 endpoint := "ws://agent.example.com" 485 routingKeys := []string{"key1", "key2"} 486 dispatched := make(chan struct{}) 487 svc, err := New(&mockprovider.Provider{ 488 ServiceMap: map[string]interface{}{ 489 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 490 }, 491 StorageProviderValue: mockstore.NewMockStoreProvider(), 492 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 493 KMSValue: &mockkms.KeyManager{}, 494 ServiceEndpointValue: "http://other.com", 495 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 496 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 497 res, err := json.Marshal(msg) 498 require.NoError(t, err) 499 500 grant := &Grant{} 501 err = json.Unmarshal(res, grant) 502 require.NoError(t, err) 503 504 require.Equal(t, endpoint, grant.Endpoint) 505 require.Equal(t, routingKeys, grant.RoutingKeys) 506 507 dispatched <- struct{}{} 508 509 return nil 510 }, 511 }, 512 MediaTypeProfilesValue: []string{transport.MediaTypeAIP2RFC0019Profile}, 513 }) 514 require.NoError(t, err) 515 516 events := make(chan service.DIDCommAction) 517 err = svc.RegisterActionEvent(events) 518 require.NoError(t, err) 519 520 t.Run("with Options as a struct type", func(t *testing.T) { 521 _, err = svc.HandleInbound(generateRequestMsgPayload(t, randomID()), service.NewDIDCommContext(MYDID, THEIRDID, nil)) 522 require.NoError(t, err) 523 524 select { 525 case event := <-events: 526 event.Continue(Options{ 527 ServiceEndpoint: endpoint, 528 RoutingKeys: routingKeys, 529 }) 530 case <-time.After(time.Second): 531 require.Fail(t, "timeout") 532 } 533 534 select { 535 case <-dispatched: 536 case <-time.After(time.Second): 537 require.Fail(t, "timeout") 538 } 539 }) 540 541 t.Run("with Options as a pointer type", func(t *testing.T) { 542 _, err = svc.HandleInbound(generateRequestMsgPayload(t, randomID()), service.NewDIDCommContext(MYDID, THEIRDID, nil)) 543 require.NoError(t, err) 544 545 select { 546 case event := <-events: 547 event.Continue(&Options{ 548 ServiceEndpoint: endpoint, 549 RoutingKeys: routingKeys, 550 }) 551 case <-time.After(time.Second): 552 require.Fail(t, "timeout") 553 } 554 555 select { 556 case <-dispatched: 557 case <-time.After(time.Second): 558 require.Fail(t, "timeout") 559 } 560 }) 561 }) 562 } 563 564 func TestServiceGrantMsg(t *testing.T) { 565 t.Run("test service handle inbound grant msg - success", func(t *testing.T) { 566 svc, err := New(&mockprovider.Provider{ 567 ServiceMap: map[string]interface{}{ 568 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 569 }, 570 StorageProviderValue: mockstore.NewMockStoreProvider(), 571 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 572 KMSValue: &mockkms.KeyManager{}, 573 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 574 }) 575 require.NoError(t, err) 576 577 msgID := randomID() 578 579 id, err := svc.HandleInbound(generateGrantMsgPayload(t, msgID), service.EmptyDIDCommContext()) 580 require.NoError(t, err) 581 require.Equal(t, msgID, id) 582 }) 583 584 t.Run("service handle grant msg - marshal error", func(t *testing.T) { 585 svc, err := New(&mockprovider.Provider{ 586 ServiceMap: map[string]interface{}{ 587 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 588 }, 589 StorageProviderValue: mockstore.NewMockStoreProvider(), 590 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 591 KMSValue: &mockkms.KeyManager{}, 592 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 593 }) 594 require.NoError(t, err) 595 596 msg := &service.DIDCommMsgMap{"@id": make(chan int64)} 597 598 err = svc.saveGrant(msg) 599 require.Error(t, err) 600 require.Contains(t, err.Error(), "marshal grant: json") 601 }) 602 } 603 604 func TestServiceUpdateKeyListMsg(t *testing.T) { 605 t.Run("test service handle inbound key list update msg - success", func(t *testing.T) { 606 svc, err := New(&mockprovider.Provider{ 607 ServiceMap: map[string]interface{}{ 608 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 609 }, 610 StorageProviderValue: mockstore.NewMockStoreProvider(), 611 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 612 KMSValue: &mockkms.KeyManager{}, 613 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 614 }) 615 require.NoError(t, err) 616 617 msgID := randomID() 618 619 id, err := svc.HandleInbound(generateKeyUpdateListMsgPayload(t, msgID, []Update{{ 620 RecipientKey: "ABC", 621 Action: "add", 622 }}), service.EmptyDIDCommContext()) 623 require.NoError(t, err) 624 require.Equal(t, msgID, id) 625 }) 626 627 t.Run("test service handle key list update msg - success", func(t *testing.T) { 628 svc, err := New(&mockprovider.Provider{ 629 ServiceMap: map[string]interface{}{ 630 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 631 }, 632 StorageProviderValue: mockstore.NewMockStoreProvider(), 633 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 634 KMSValue: &mockkms.KeyManager{}, 635 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 636 }) 637 require.NoError(t, err) 638 639 msg := &service.DIDCommMsgMap{"@id": map[int]int{}} 640 641 err = svc.handleKeylistUpdate(msg, MYDID, THEIRDID) 642 require.Error(t, err) 643 require.Contains(t, err.Error(), "route key list update message unmarshal") 644 }) 645 646 t.Run("test service handle request msg - verify outbound message", func(t *testing.T) { 647 update := make(map[string]updateResult) 648 update["ABC"] = updateResult{action: add, result: success} 649 update["XYZ"] = updateResult{action: remove, result: serverError} 650 update[""] = updateResult{action: add, result: success} 651 652 svc, err := New(&mockprovider.Provider{ 653 ServiceMap: map[string]interface{}{ 654 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 655 }, 656 StorageProviderValue: mockstore.NewMockStoreProvider(), 657 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 658 KMSValue: &mockkms.KeyManager{}, 659 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 660 ValidateSend: func(msg interface{}, senderVerKey string, des *service.Destination) error { 661 res, err := json.Marshal(msg) 662 require.NoError(t, err) 663 664 updateRes := &KeylistUpdateResponse{} 665 err = json.Unmarshal(res, updateRes) 666 require.NoError(t, err) 667 668 require.Equal(t, len(update), len(updateRes.Updated)) 669 670 for _, v := range updateRes.Updated { 671 require.Equal(t, update[v.RecipientKey].action, v.Action) 672 require.Equal(t, update[v.RecipientKey].result, v.Result) 673 } 674 675 return nil 676 }, 677 }, 678 }) 679 require.NoError(t, err) 680 681 msgID := randomID() 682 683 var updates []Update 684 for k, v := range update { 685 updates = append(updates, Update{ 686 RecipientKey: k, 687 Action: v.action, 688 }) 689 } 690 691 err = svc.handleKeylistUpdate(generateKeyUpdateListMsgPayload(t, msgID, updates), MYDID, THEIRDID) 692 require.NoError(t, err) 693 }) 694 } 695 696 func TestServiceKeylistUpdateResponseMsg(t *testing.T) { 697 t.Run("test service handle inbound key list update response msg - success", func(t *testing.T) { 698 svc, err := New(&mockprovider.Provider{ 699 ServiceMap: map[string]interface{}{ 700 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 701 }, 702 StorageProviderValue: mockstore.NewMockStoreProvider(), 703 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 704 KMSValue: &mockkms.KeyManager{}, 705 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 706 }) 707 require.NoError(t, err) 708 709 msgID := randomID() 710 711 id, err := svc.HandleInbound(generateKeylistUpdateResponseMsgPayload(t, msgID, []UpdateResponse{{ 712 RecipientKey: "ABC", 713 Action: "add", 714 Result: success, 715 }}), service.EmptyDIDCommContext()) 716 require.NoError(t, err) 717 require.Equal(t, msgID, id) 718 }) 719 720 t.Run("test service handle key list update response msg - success", func(t *testing.T) { 721 svc, err := New(&mockprovider.Provider{ 722 ServiceMap: map[string]interface{}{ 723 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 724 }, 725 StorageProviderValue: mockstore.NewMockStoreProvider(), 726 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 727 KMSValue: &mockkms.KeyManager{}, 728 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 729 }) 730 require.NoError(t, err) 731 732 msg := &service.DIDCommMsgMap{"@id": map[int]int{}} 733 734 err = svc.handleKeylistUpdateResponse(msg) 735 require.Error(t, err) 736 require.Contains(t, err.Error(), "route keylist update response message unmarshal") 737 }) 738 } 739 740 func TestServiceForwardMsg(t *testing.T) { 741 t.Run("test service handle inbound forward msg - success", func(t *testing.T) { 742 to := randomID() 743 svc, err := New(&mockprovider.Provider{ 744 ServiceMap: map[string]interface{}{ 745 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 746 }, 747 StorageProviderValue: mockstore.NewMockStoreProvider(), 748 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 749 KMSValue: &mockkms.KeyManager{}, 750 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 751 }) 752 require.NoError(t, err) 753 754 err = svc.routeStore.Put(to, []byte("did:example:123")) 755 require.NoError(t, err) 756 757 msgID := randomID() 758 759 id, err := svc.HandleInbound(generateForwardMsgPayload(t, msgID, to, nil), service.EmptyDIDCommContext()) 760 require.NoError(t, err) 761 require.Equal(t, msgID, id) 762 }) 763 764 t.Run("test service handle forward msg - success", func(t *testing.T) { 765 svc, err := New(&mockprovider.Provider{ 766 ServiceMap: map[string]interface{}{ 767 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 768 }, 769 StorageProviderValue: mockstore.NewMockStoreProvider(), 770 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 771 KMSValue: &mockkms.KeyManager{}, 772 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 773 }) 774 require.NoError(t, err) 775 776 msg := &service.DIDCommMsgMap{"@id": map[int]int{}} 777 778 err = svc.handleForward(msg) 779 require.Error(t, err) 780 require.Contains(t, err.Error(), "forward message unmarshal") 781 }) 782 783 t.Run("test service handle forward msg - route key fetch fail", func(t *testing.T) { 784 to := randomID() 785 msgID := randomID() 786 787 svc, err := New(&mockprovider.Provider{ 788 ServiceMap: map[string]interface{}{ 789 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 790 }, 791 StorageProviderValue: mockstore.NewMockStoreProvider(), 792 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 793 KMSValue: &mockkms.KeyManager{}, 794 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 795 }) 796 require.NoError(t, err) 797 798 err = svc.handleForward(generateForwardMsgPayload(t, msgID, to, nil)) 799 require.Error(t, err) 800 require.Contains(t, err.Error(), "route key fetch") 801 }) 802 803 t.Run("test service handle forward msg - validate forward message content", func(t *testing.T) { 804 to := randomID() 805 msgID := randomID() 806 invalidDID := "did:error:123" 807 808 content := []byte(`{ 809 Protected: "eyJ0eXAiOiJwcnMuaHlwZXJsZWRnZXIuYXJpZXMtYXV0aC1t" + 810 "ZXNzYWdlIiwiYWxnIjoiRUNESC1TUytYQzIwUEtXIiwiZW5jIjoiWEMyMFAifQ", 811 IV: "JS2FxjEKdndnt-J7QX5pEnVwyBTu0_3d", 812 CipherText: "qQyzvajdvCDJbwxM", 813 Tag: "2FqZMMQuNPYfL0JsSkj8LQ", 814 }`) 815 816 msg := generateForwardMsgPayload(t, msgID, to, content) 817 818 svc, err := New(&mockprovider.Provider{ 819 ServiceMap: map[string]interface{}{ 820 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 821 }, 822 StorageProviderValue: mockstore.NewMockStoreProvider(), 823 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 824 KMSValue: &mockkms.KeyManager{}, 825 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 826 ValidateForward: func(msg interface{}, des *service.Destination) error { 827 require.Equal(t, content, msg) 828 829 return nil 830 }, 831 }, 832 VDRegistryValue: &mockvdr.MockVDRegistry{ 833 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (doc *did.DocResolution, e error) { 834 if didID == invalidDID { 835 return nil, errors.New("invalid") 836 } 837 return &did.DocResolution{DIDDocument: mockdiddoc.GetMockDIDDoc(t, false)}, nil 838 }, 839 }, 840 }) 841 require.NoError(t, err) 842 843 err = svc.routeStore.Put(dataKey(to), []byte("did:example:123")) 844 require.NoError(t, err) 845 846 err = svc.handleForward(msg) 847 require.NoError(t, err) 848 849 err = svc.routeStore.Put(dataKey(to), []byte(invalidDID)) 850 require.NoError(t, err) 851 852 err = svc.handleForward(msg) 853 require.Error(t, err) 854 require.Contains(t, err.Error(), "get destination") 855 }) 856 } 857 858 func TestMessagePickup(t *testing.T) { 859 t.Run("test service handle inbound message pick up - success", func(t *testing.T) { 860 to := randomID() 861 862 content := []byte(`{ 863 Protected: "eyJ0eXAiOiJwcnMuaHlwZXJsZWRnZXIuYXJpZXMtYXV0aC1t" + 864 "ZXNzYWdlIiwiYWxnIjoiRUNESC1TUytYQzIwUEtXIiwiZW5jIjoiWEMyMFAifQ", 865 IV: "JS2FxjEKdndnt-J7QX5pEnVwyBTu0_3d", 866 CipherText: "qQyzvajdvCDJbwxM", 867 Tag: "2FqZMMQuNPYfL0JsSkj8LQ", 868 }`) 869 870 svc, err := New( 871 &mockprovider.Provider{ 872 ServiceMap: map[string]interface{}{ 873 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{ 874 AddMessageFunc: func(message []byte, theirDID string) error { 875 require.Equal(t, content, message) 876 return nil 877 }, 878 }, 879 }, 880 StorageProviderValue: mockstore.NewMockStoreProvider(), 881 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 882 KMSValue: &mockkms.KeyManager{}, 883 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 884 ValidateForward: func(_ interface{}, _ *service.Destination) error { 885 return errors.New("websocket connection failed") 886 }, 887 }, 888 VDRegistryValue: &mockvdr.MockVDRegistry{ 889 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 890 return &did.DocResolution{DIDDocument: mockdiddoc.GetMockDIDDoc(t, false)}, nil 891 }, 892 }, 893 }) 894 require.NoError(t, err) 895 896 err = svc.routeStore.Put(dataKey(to), []byte("did:example:123")) 897 require.NoError(t, err) 898 899 msgID := randomID() 900 msg := generateForwardMsgPayload(t, msgID, to, content) 901 902 err = svc.handleForward(msg) 903 require.NoError(t, err) 904 }) 905 906 t.Run("test service handle inbound message pick up - add message error", func(t *testing.T) { 907 to := randomID() 908 909 content := []byte(`{ 910 Protected: "eyJ0eXAiOiJwcnMuaHlwZXJsZWRnZXIuYXJpZXMtYXV0aC1t" + 911 "ZXNzYWdlIiwiYWxnIjoiRUNESC1TUytYQzIwUEtXIiwiZW5jIjoiWEMyMFAifQ", 912 IV: "JS2FxjEKdndnt-J7QX5pEnVwyBTu0_3d", 913 CipherText: "qQyzvajdvCDJbwxM", 914 Tag: "2FqZMMQuNPYfL0JsSkj8LQ", 915 }`) 916 917 svc, err := New(&mockprovider.Provider{ 918 ServiceMap: map[string]interface{}{ 919 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{ 920 AddMessageErr: errors.New("add error"), 921 }, 922 }, 923 StorageProviderValue: mockstore.NewMockStoreProvider(), 924 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 925 KMSValue: &mockkms.KeyManager{}, 926 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 927 ValidateForward: func(_ interface{}, _ *service.Destination) error { 928 return errors.New("websocket connection failed") 929 }, 930 }, 931 VDRegistryValue: &mockvdr.MockVDRegistry{ 932 ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (doc *did.DocResolution, e error) { 933 return &did.DocResolution{DIDDocument: mockdiddoc.GetMockDIDDoc(t, false)}, nil 934 }, 935 }, 936 }) 937 require.NoError(t, err) 938 939 err = svc.routeStore.Put(dataKey(to), []byte("did:example:123")) 940 require.NoError(t, err) 941 942 msgID := randomID() 943 msg := generateForwardMsgPayload(t, msgID, to, content) 944 945 err = svc.handleForward(msg) 946 require.Error(t, err) 947 require.Contains(t, err.Error(), "add error") 948 }) 949 } 950 951 func TestRegister(t *testing.T) { 952 t.Run("test register route - success", func(t *testing.T) { 953 msgID := make(chan string) 954 955 s := make(map[string]mockstore.DBEntry) 956 svc, err := New(&mockprovider.Provider{ 957 ServiceMap: map[string]interface{}{ 958 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 959 }, 960 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 961 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 962 KMSValue: &mockkms.KeyManager{}, 963 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 964 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 965 require.Equal(t, myDID, MYDID) 966 require.Equal(t, theirDID, THEIRDID) 967 968 reqMsgMap, ok := msg.(service.DIDCommMsgMap) 969 require.True(t, ok) 970 971 request := &Request{} 972 973 err := reqMsgMap.Decode(request) 974 require.NoError(t, err) 975 976 msgID <- request.ID 977 return nil 978 }, 979 }, 980 }) 981 require.NoError(t, err) 982 983 connRec := &connection.Record{ 984 ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "complete", 985 } 986 connBytes, err := json.Marshal(connRec) 987 require.NoError(t, err) 988 s["conn_conn"] = mockstore.DBEntry{Value: connBytes} 989 990 go func() { 991 id := <-msgID 992 require.NoError(t, svc.saveGrant(generateGrantMsgPayload(t, id))) 993 }() 994 995 err = svc.Register("conn") 996 require.NoError(t, err) 997 998 err = svc.Register("conn") 999 require.Error(t, err) 1000 require.Contains(t, err.Error(), "router is already registered") 1001 }) 1002 1003 t.Run("test register route - with client timeout error", func(t *testing.T) { 1004 s := make(map[string]mockstore.DBEntry) 1005 svc, err := New(&mockprovider.Provider{ 1006 ServiceMap: map[string]interface{}{ 1007 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1008 }, 1009 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1010 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1011 KMSValue: &mockkms.KeyManager{}, 1012 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1013 }) 1014 require.NoError(t, err) 1015 1016 connRec := &connection.Record{ 1017 ConnectionID: "conn2", MyDID: MYDID, TheirDID: THEIRDID, State: "complete", 1018 } 1019 connBytes, err := json.Marshal(connRec) 1020 require.NoError(t, err) 1021 s["conn_conn2"] = mockstore.DBEntry{Value: connBytes} 1022 1023 err = svc.Register("conn2", func(opts *ClientOptions) { 1024 opts.Timeout = 1 * time.Millisecond 1025 }) 1026 1027 require.Error(t, err) 1028 require.Contains(t, err.Error(), "get grant for request ID '") 1029 require.Contains(t, err.Error(), "': store: data not found") 1030 }) 1031 1032 t.Run("test register route - router connection not found", func(t *testing.T) { 1033 svc, err := New(&mockprovider.Provider{ 1034 ServiceMap: map[string]interface{}{ 1035 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1036 }, 1037 StorageProviderValue: mockstore.NewMockStoreProvider(), 1038 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1039 KMSValue: &mockkms.KeyManager{}, 1040 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 1041 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 1042 return fmt.Errorf("error send") 1043 }, 1044 }, 1045 }) 1046 require.NoError(t, err) 1047 1048 err = svc.Register("conn") 1049 require.Error(t, err) 1050 require.Contains(t, err.Error(), ErrConnectionNotFound.Error()) 1051 }) 1052 1053 t.Run("test register route - router connection fetch error", func(t *testing.T) { 1054 svc, err := New(&mockprovider.Provider{ 1055 ServiceMap: map[string]interface{}{ 1056 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1057 }, 1058 StorageProviderValue: &mockstore.MockStoreProvider{ 1059 Store: &mockstore.MockStore{ErrGet: fmt.Errorf("get error")}, 1060 }, 1061 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1062 KMSValue: &mockkms.KeyManager{}, 1063 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 1064 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 1065 return fmt.Errorf("error send") 1066 }, 1067 }, 1068 }) 1069 require.NoError(t, err) 1070 1071 err = svc.Register("conn") 1072 require.Error(t, err) 1073 require.Contains(t, err.Error(), "fetch connection record from store") 1074 }) 1075 } 1076 1077 func TestUnregister(t *testing.T) { 1078 const connID = "conn-id" 1079 1080 t.Run("test unregister route - success", func(t *testing.T) { 1081 s := make(map[string]mockstore.DBEntry) 1082 svc, err := New( 1083 &mockprovider.Provider{ 1084 ServiceMap: map[string]interface{}{ 1085 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1086 }, 1087 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1088 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1089 }, 1090 ) 1091 require.NoError(t, err) 1092 1093 s[fmt.Sprintf(routeConnIDDataKey, connID)] = mockstore.DBEntry{Value: []byte("{\"connectionID\":\"conn-abc-xyz\"}")} 1094 1095 err = svc.Unregister(connID) 1096 require.NoError(t, err) 1097 }) 1098 1099 t.Run("test unregister route - router not registered", func(t *testing.T) { 1100 s := make(map[string]mockstore.DBEntry) 1101 svc, err := New( 1102 &mockprovider.Provider{ 1103 ServiceMap: map[string]interface{}{ 1104 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1105 }, 1106 StorageProviderValue: &mockstore.MockStoreProvider{ 1107 Store: &mockstore.MockStore{Store: s}, 1108 }, 1109 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1110 }, 1111 ) 1112 require.NoError(t, err) 1113 1114 err = svc.Unregister(connID) 1115 require.Error(t, err) 1116 require.Contains(t, err.Error(), "router not registered") 1117 }) 1118 1119 t.Run("test unregister route - db error", func(t *testing.T) { 1120 s := make(map[string]mockstore.DBEntry) 1121 svc, err := New( 1122 &mockprovider.Provider{ 1123 ServiceMap: map[string]interface{}{ 1124 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1125 }, 1126 StorageProviderValue: &mockstore.MockStoreProvider{ 1127 Store: &mockstore.MockStore{Store: s, ErrGet: errors.New("get error")}, 1128 }, 1129 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1130 }, 1131 ) 1132 require.NoError(t, err) 1133 1134 err = svc.Unregister(connID) 1135 require.Error(t, err) 1136 require.EqualError(t, err, "ensure connection exists: get error") 1137 }) 1138 } 1139 1140 func TestKeylistUpdate(t *testing.T) { 1141 const connID = "conn-id" 1142 1143 t.Run("test keylist update - success", func(t *testing.T) { 1144 keyUpdateMsg := make(chan KeylistUpdate) 1145 recKey := "ojaosdjoajs123jkas" 1146 1147 s := make(map[string]mockstore.DBEntry) 1148 svc, err := New(&mockprovider.Provider{ 1149 ServiceMap: map[string]interface{}{ 1150 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1151 }, 1152 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1153 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1154 KMSValue: &mockkms.KeyManager{}, 1155 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 1156 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 1157 require.Equal(t, myDID, MYDID) 1158 require.Equal(t, theirDID, THEIRDID) 1159 1160 reqMsgMap, ok := msg.(service.DIDCommMsgMap) 1161 require.True(t, ok) 1162 1163 request := &KeylistUpdate{} 1164 1165 err := reqMsgMap.Decode(request) 1166 require.NoError(t, err) 1167 1168 keyUpdateMsg <- *request 1169 return nil 1170 }, 1171 }, 1172 }) 1173 require.NoError(t, err) 1174 1175 // save router connID 1176 require.NoError(t, svc.saveRouterConnectionID("conn", "")) 1177 1178 // save connections 1179 connRec := &connection.Record{ 1180 ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "complete", 1181 } 1182 connBytes, err := json.Marshal(connRec) 1183 require.NoError(t, err) 1184 s["conn_conn"] = mockstore.DBEntry{Value: connBytes} 1185 1186 go func() { 1187 updateMsg := <-keyUpdateMsg 1188 1189 updates := []UpdateResponse{ 1190 { 1191 RecipientKey: updateMsg.Updates[0].RecipientKey, 1192 Action: updateMsg.Updates[0].Action, 1193 Result: success, 1194 }, 1195 } 1196 require.NoError(t, svc.handleKeylistUpdateResponse(generateKeylistUpdateResponseMsgPayload( 1197 t, updateMsg.ID, updates))) 1198 }() 1199 1200 err = svc.AddKey("conn", recKey) 1201 require.NoError(t, err) 1202 }) 1203 1204 t.Run("test keylist update - failure", func(t *testing.T) { 1205 keyUpdateMsg := make(chan KeylistUpdate) 1206 recKey := "ojaosdjoajs123jkas" 1207 1208 s := make(map[string]mockstore.DBEntry) 1209 svc, err := New(&mockprovider.Provider{ 1210 ServiceMap: map[string]interface{}{ 1211 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1212 }, 1213 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1214 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1215 KMSValue: &mockkms.KeyManager{}, 1216 OutboundDispatcherValue: &mockdispatcher.MockOutbound{ 1217 ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error { 1218 require.Equal(t, myDID, MYDID) 1219 require.Equal(t, theirDID, THEIRDID) 1220 1221 reqMsgMap, ok := msg.(service.DIDCommMsgMap) 1222 require.True(t, ok) 1223 1224 request := &KeylistUpdate{} 1225 1226 err := reqMsgMap.Decode(request) 1227 require.NoError(t, err) 1228 1229 keyUpdateMsg <- *request 1230 return nil 1231 }, 1232 }, 1233 }) 1234 require.NoError(t, err) 1235 1236 // no router registered 1237 err = svc.AddKey(connID, recKey) 1238 require.Error(t, err) 1239 require.Contains(t, err.Error(), "router not registered") 1240 1241 // save router connID 1242 require.NoError(t, svc.saveRouterConnectionID("conn", "")) 1243 1244 // no connections saved 1245 err = svc.AddKey("conn", recKey) 1246 require.Error(t, err) 1247 require.Contains(t, err.Error(), "connection not found") 1248 1249 // save connections 1250 connRec := &connection.Record{ 1251 ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "complete", 1252 } 1253 connBytes, err := json.Marshal(connRec) 1254 require.NoError(t, err) 1255 s["conn_conn"] = mockstore.DBEntry{Value: connBytes} 1256 1257 go func() { 1258 updateMsg := <-keyUpdateMsg 1259 1260 updates := []UpdateResponse{ 1261 { 1262 RecipientKey: updateMsg.Updates[0].RecipientKey, 1263 Action: updateMsg.Updates[0].Action, 1264 Result: serverError, 1265 }, 1266 } 1267 require.NoError(t, svc.handleKeylistUpdateResponse(generateKeylistUpdateResponseMsgPayload( 1268 t, updateMsg.ID, updates))) 1269 }() 1270 1271 err = svc.AddKey("conn", recKey) 1272 require.Error(t, err) 1273 require.Contains(t, err.Error(), "failed to update the recipient key with the router") 1274 }) 1275 1276 t.Run("test keylist update - timeout error", func(t *testing.T) { 1277 s := make(map[string]mockstore.DBEntry) 1278 svc, err := New(&mockprovider.Provider{ 1279 ServiceMap: map[string]interface{}{ 1280 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1281 }, 1282 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1283 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1284 KMSValue: &mockkms.KeyManager{}, 1285 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1286 }) 1287 require.NoError(t, err) 1288 1289 connRec := &connection.Record{ 1290 ConnectionID: "conn2", MyDID: MYDID, TheirDID: THEIRDID, State: "complete", 1291 } 1292 connBytes, err := json.Marshal(connRec) 1293 require.NoError(t, err) 1294 s["conn_conn2"] = mockstore.DBEntry{Value: connBytes} 1295 require.NoError(t, svc.saveRouterConnectionID("conn2", "")) 1296 1297 err = svc.AddKey("conn2", "recKey") 1298 require.Error(t, err) 1299 require.Contains(t, err.Error(), "timeout waiting for keylist update response from the router") 1300 }) 1301 1302 t.Run("test keylist update - router connectionID fetch error", func(t *testing.T) { 1303 s := make(map[string]mockstore.DBEntry) 1304 svc, err := New(&mockprovider.Provider{ 1305 ServiceMap: map[string]interface{}{ 1306 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1307 }, 1308 StorageProviderValue: &mockstore.MockStoreProvider{ 1309 Store: &mockstore.MockStore{Store: s, ErrGet: errors.New("get error")}, 1310 }, 1311 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1312 KMSValue: &mockkms.KeyManager{}, 1313 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1314 }) 1315 require.NoError(t, err) 1316 1317 err = svc.AddKey("conn", "recKey") 1318 require.Error(t, err) 1319 require.EqualError(t, err, "ensure connection exists: get error") 1320 }) 1321 } 1322 1323 func TestConfig(t *testing.T) { 1324 routingKeys := []string{"abc", "xyz"} 1325 1326 t.Run("test config - success", func(t *testing.T) { 1327 s := make(map[string]mockstore.DBEntry) 1328 svc, err := New(&mockprovider.Provider{ 1329 ServiceMap: map[string]interface{}{ 1330 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1331 }, 1332 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1333 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1334 KMSValue: &mockkms.KeyManager{}, 1335 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1336 }) 1337 require.NoError(t, err) 1338 1339 require.NoError(t, svc.saveRouterConnectionID("connID-123", "")) 1340 require.NoError(t, svc.saveRouterConfig("connID-123", &config{ 1341 RouterEndpoint: ENDPOINT, 1342 RoutingKeys: routingKeys, 1343 })) 1344 1345 conf, err := svc.Config("connID-123") 1346 require.NoError(t, err) 1347 require.Equal(t, ENDPOINT, conf.Endpoint()) 1348 require.Equal(t, routingKeys, conf.Keys()) 1349 }) 1350 1351 t.Run("test config - no router registered", func(t *testing.T) { 1352 s := make(map[string]mockstore.DBEntry) 1353 svc, err := New(&mockprovider.Provider{ 1354 ServiceMap: map[string]interface{}{ 1355 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1356 }, 1357 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1358 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1359 KMSValue: &mockkms.KeyManager{}, 1360 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1361 }) 1362 require.NoError(t, err) 1363 1364 conf, err := svc.Config("conn") 1365 require.Error(t, err) 1366 require.True(t, errors.Is(err, ErrRouterNotRegistered)) 1367 require.Nil(t, conf) 1368 }) 1369 1370 t.Run("test config - missing configs", func(t *testing.T) { 1371 s := make(map[string]mockstore.DBEntry) 1372 svc, err := New(&mockprovider.Provider{ 1373 ServiceMap: map[string]interface{}{ 1374 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1375 }, 1376 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1377 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1378 KMSValue: &mockkms.KeyManager{}, 1379 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1380 }) 1381 require.NoError(t, err) 1382 1383 require.NoError(t, svc.saveRouterConnectionID("connID-123", "")) 1384 1385 conf, err := svc.Config("connID-123") 1386 require.Error(t, err) 1387 require.Contains(t, err.Error(), "get router config data") 1388 require.Nil(t, conf) 1389 }) 1390 1391 t.Run("test config - invalid config data in db", func(t *testing.T) { 1392 s := make(map[string]mockstore.DBEntry) 1393 svc, err := New(&mockprovider.Provider{ 1394 ServiceMap: map[string]interface{}{ 1395 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1396 }, 1397 StorageProviderValue: &mockstore.MockStoreProvider{Store: &mockstore.MockStore{Store: s}}, 1398 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1399 KMSValue: &mockkms.KeyManager{}, 1400 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1401 }) 1402 require.NoError(t, err) 1403 1404 const conn = "connID-123" 1405 1406 require.NoError(t, svc.saveRouterConnectionID(conn, "")) 1407 require.NoError(t, svc.routeStore.Put(fmt.Sprintf(routeConfigDataKey, conn), []byte("invalid data"))) 1408 1409 conf, err := svc.Config(conn) 1410 require.Error(t, err) 1411 require.Contains(t, err.Error(), "unmarshal router config data") 1412 require.Nil(t, conf) 1413 }) 1414 1415 t.Run("test config - router connectionID fetch error", func(t *testing.T) { 1416 s := make(map[string]mockstore.DBEntry) 1417 svc, err := New(&mockprovider.Provider{ 1418 ServiceMap: map[string]interface{}{ 1419 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1420 }, 1421 StorageProviderValue: &mockstore.MockStoreProvider{ 1422 Store: &mockstore.MockStore{Store: s, ErrGet: errors.New("get error")}, 1423 }, 1424 ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(), 1425 KMSValue: &mockkms.KeyManager{}, 1426 OutboundDispatcherValue: &mockdispatcher.MockOutbound{}, 1427 }) 1428 require.NoError(t, err) 1429 1430 require.NoError(t, svc.saveRouterConnectionID("connID-123", "")) 1431 require.NoError(t, svc.routeStore.Put(routeConfigDataKey, []byte("invalid data"))) 1432 1433 conf, err := svc.Config("connID-123") 1434 require.Error(t, err) 1435 require.EqualError(t, err, "ensure connection exists: get error") 1436 require.Nil(t, conf) 1437 }) 1438 } 1439 1440 func TestGetConnections(t *testing.T) { 1441 routerConnectionID := "conn-abc-xyz" 1442 1443 t.Run("test get connection - success", func(t *testing.T) { 1444 svc, err := New( 1445 &mockprovider.Provider{ 1446 ServiceMap: map[string]interface{}{ 1447 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1448 }, 1449 StorageProviderValue: mem.NewProvider(), 1450 ProtocolStateStorageProviderValue: mem.NewProvider(), 1451 }, 1452 ) 1453 require.NoError(t, err) 1454 1455 err = svc.saveRouterConnectionID(routerConnectionID, "") 1456 require.NoError(t, err) 1457 1458 connID, err := svc.GetConnections() 1459 require.NoError(t, err) 1460 require.Equal(t, routerConnectionID, connID[0]) 1461 }) 1462 1463 t.Run("test get connection - no data found", func(t *testing.T) { 1464 svc, err := New( 1465 &mockprovider.Provider{ 1466 ServiceMap: map[string]interface{}{ 1467 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1468 }, 1469 StorageProviderValue: mem.NewProvider(), 1470 ProtocolStateStorageProviderValue: mem.NewProvider(), 1471 }, 1472 ) 1473 require.NoError(t, err) 1474 1475 connID, err := svc.GetConnections() 1476 require.NoError(t, err) 1477 require.Empty(t, connID) 1478 }) 1479 1480 t.Run("test get connection - filter by didcomm version", func(t *testing.T) { 1481 svc, err := New( 1482 &mockprovider.Provider{ 1483 ServiceMap: map[string]interface{}{ 1484 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1485 }, 1486 StorageProviderValue: mem.NewProvider(), 1487 ProtocolStateStorageProviderValue: mem.NewProvider(), 1488 }, 1489 ) 1490 require.NoError(t, err) 1491 1492 const ( 1493 connID1 = "conn-id-1" 1494 connID2 = "conn-id-2" 1495 ) 1496 1497 err = svc.saveRouterConnectionID(connID1, service.V1) 1498 require.NoError(t, err) 1499 1500 err = svc.saveRouterConnectionID(connID2, service.V2) 1501 require.NoError(t, err) 1502 1503 connIDs, err := svc.GetConnections() 1504 require.NoError(t, err) 1505 require.Len(t, connIDs, 2) 1506 1507 connIDs, err = svc.GetConnections(ConnectionByVersion(service.V1)) 1508 require.NoError(t, err) 1509 require.Len(t, connIDs, 1) 1510 require.Equal(t, connID1, connIDs[0]) 1511 1512 connIDs, err = svc.GetConnections(ConnectionByVersion(service.V2)) 1513 require.NoError(t, err) 1514 require.Len(t, connIDs, 1) 1515 require.Equal(t, connID2, connIDs[0]) 1516 }) 1517 1518 t.Run("test get connection - fail to parse connection entry", func(t *testing.T) { 1519 svc, err := New( 1520 &mockprovider.Provider{ 1521 ServiceMap: map[string]interface{}{ 1522 messagepickup.MessagePickup: &mockmessagep.MockMessagePickupSvc{}, 1523 }, 1524 StorageProviderValue: mem.NewProvider(), 1525 ProtocolStateStorageProviderValue: mem.NewProvider(), 1526 }, 1527 ) 1528 require.NoError(t, err) 1529 1530 err = svc.routeStore.Put( 1531 fmt.Sprintf(routeConnIDDataKey, routerConnectionID), 1532 []byte("foo"), 1533 storage.Tag{Name: routeConnIDDataKey}, 1534 ) 1535 require.NoError(t, err) 1536 1537 _, err = svc.GetConnections() 1538 require.Error(t, err) 1539 require.Contains(t, err.Error(), "failed to unmarshal router connection entry") 1540 }) 1541 } 1542 1543 func generateRequestMsgPayload(t *testing.T, id string) service.DIDCommMsg { 1544 requestBytes, err := json.Marshal(&Request{ 1545 Type: RequestMsgType, 1546 ID: id, 1547 }) 1548 require.NoError(t, err) 1549 1550 didMsg, err := service.ParseDIDCommMsgMap(requestBytes) 1551 require.NoError(t, err) 1552 1553 return didMsg 1554 } 1555 1556 func generateGrantMsgPayload(t *testing.T, id string) service.DIDCommMsg { 1557 grantBytes, err := json.Marshal(&Grant{ 1558 Type: GrantMsgType, 1559 ID: id, 1560 }) 1561 require.NoError(t, err) 1562 1563 didMsg, err := service.ParseDIDCommMsgMap(grantBytes) 1564 require.NoError(t, err) 1565 1566 return didMsg 1567 } 1568 1569 func generateKeyUpdateListMsgPayload(t *testing.T, id string, updates []Update) service.DIDCommMsg { 1570 requestBytes, err := json.Marshal(&KeylistUpdate{ 1571 Type: KeylistUpdateMsgType, 1572 ID: id, 1573 Updates: updates, 1574 }) 1575 require.NoError(t, err) 1576 1577 didMsg, err := service.ParseDIDCommMsgMap(requestBytes) 1578 require.NoError(t, err) 1579 1580 return didMsg 1581 } 1582 1583 func generateKeylistUpdateResponseMsgPayload(t *testing.T, id string, updates []UpdateResponse) service.DIDCommMsg { 1584 respBytes, err := json.Marshal(&KeylistUpdateResponse{ 1585 Type: KeylistUpdateResponseMsgType, 1586 ID: id, 1587 Updated: updates, 1588 }) 1589 require.NoError(t, err) 1590 1591 didMsg, err := service.ParseDIDCommMsgMap(respBytes) 1592 require.NoError(t, err) 1593 1594 return didMsg 1595 } 1596 1597 func generateForwardMsgPayload(t *testing.T, id, to string, msg []byte) service.DIDCommMsg { 1598 requestBytes, err := json.Marshal(&model.Forward{ 1599 Type: service.ForwardMsgType, 1600 ID: id, 1601 To: to, 1602 Msg: msg, 1603 }) 1604 require.NoError(t, err) 1605 1606 didMsg, err := service.ParseDIDCommMsgMap(requestBytes) 1607 require.NoError(t, err) 1608 1609 return didMsg 1610 } 1611 1612 func randomID() string { 1613 return uuid.New().String() 1614 } 1615 1616 type connectionsStub struct { 1617 getConnIDByDIDs func(string, string) (string, error) 1618 getConnRecord func(string) (*connection.Record, error) 1619 } 1620 1621 func (c *connectionsStub) GetConnectionRecordByDIDs(myDID, theirDID string) (*connection.Record, error) { 1622 connID, err := c.GetConnectionIDByDIDs(myDID, theirDID) 1623 if err != nil { 1624 return nil, err 1625 } 1626 1627 return c.GetConnectionRecord(connID) 1628 } 1629 1630 func (c *connectionsStub) GetConnectionIDByDIDs(myDID, theirDID string) (string, error) { 1631 if c.getConnIDByDIDs != nil { 1632 return c.getConnIDByDIDs(myDID, theirDID) 1633 } 1634 1635 return "", nil 1636 } 1637 1638 func (c *connectionsStub) GetConnectionRecord(id string) (*connection.Record, error) { 1639 if c.getConnRecord != nil { 1640 return c.getConnRecord(id) 1641 } 1642 1643 return nil, nil 1644 }