github.com/hyperledger/aries-framework-go@v0.3.2/pkg/store/connection/connection_recorder_test.go (about) 1 /* 2 * 3 * Copyright SecureKey Technologies Inc. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 * / 7 * 8 */ 9 10 package connection 11 12 import ( 13 "fmt" 14 "testing" 15 16 "github.com/google/uuid" 17 "github.com/stretchr/testify/require" 18 19 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 20 mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 21 "github.com/hyperledger/aries-framework-go/spi/storage" 22 ) 23 24 const ( 25 threadIDValue = "xyz" 26 sampleConnID = "sample-conn-ID" 27 stateNameInvited = "invited" 28 ) 29 30 func Test_NewConnectionRecorder(t *testing.T) { 31 t.Run("create new recorder - success", func(t *testing.T) { 32 recorder, err := NewRecorder(&mockProvider{}) 33 require.NoError(t, err) 34 require.NotNil(t, recorder) 35 }) 36 37 t.Run("create new connection recorder - protocol state store error", func(t *testing.T) { 38 lookup, err := NewRecorder(&mockProvider{protocolStateStoreError: fmt.Errorf(sampleErrMsg)}) 39 require.Error(t, err) 40 require.Contains(t, err.Error(), sampleErrMsg) 41 require.Nil(t, lookup) 42 }) 43 44 t.Run("create new connection recorder - permanent store error", func(t *testing.T) { 45 lookup, err := NewRecorder(&mockProvider{storeError: fmt.Errorf(sampleErrMsg)}) 46 require.Error(t, err) 47 require.Contains(t, err.Error(), sampleErrMsg) 48 require.Nil(t, lookup) 49 }) 50 } 51 52 func Test_ComputeHash(t *testing.T) { 53 h1, err := computeHash([]byte("sample-bytes-123")) 54 require.NoError(t, err) 55 require.NotEmpty(t, h1) 56 57 h2, err := computeHash([]byte("sample-bytes-321")) 58 require.NoError(t, err) 59 require.NotEmpty(t, h2) 60 61 h3, err := computeHash([]byte("sample-bytes-123")) 62 require.NoError(t, err) 63 require.NotEmpty(t, h1) 64 65 require.NotEqual(t, h1, h2) 66 require.Equal(t, h1, h3) 67 68 h4, err := computeHash([]byte("")) 69 require.Error(t, err) 70 require.Empty(t, h4) 71 } 72 73 func Test_RemoveMappings(t *testing.T) { 74 t.Run("test success", func(t *testing.T) { 75 recorder, err := NewRecorder(&mockProvider{}) 76 require.NoError(t, err) 77 require.NotNil(t, recorder) 78 79 record := &Record{ 80 ThreadID: threadIDValue, 81 } 82 83 err = removeMappings(recorder, record) 84 require.NoError(t, err) 85 }) 86 t.Run("test failed - empty bytes", func(t *testing.T) { 87 recorder, err := NewRecorder(&mockProvider{}) 88 require.NoError(t, err) 89 require.NotNil(t, recorder) 90 91 record := &Record{ 92 ThreadID: "", 93 } 94 95 err = removeMappings(recorder, record) 96 require.Error(t, err) 97 require.Contains(t, err.Error(), "empty bytes") 98 }) 99 t.Run("test failed to delete the record", func(t *testing.T) { 100 const errMsg = "get error" 101 recorder, err := NewRecorder(&mockProvider{ 102 store: &mockstorage.MockStore{ 103 Store: make(map[string]mockstorage.DBEntry), 104 ErrDelete: fmt.Errorf(errMsg), 105 }, 106 }) 107 require.NoError(t, err) 108 require.NotNil(t, recorder) 109 110 record := &Record{ 111 ThreadID: threadIDValue, 112 } 113 114 err = removeMappings(recorder, record) 115 require.Error(t, err) 116 require.Contains(t, err.Error(), errMsg) 117 }) 118 } 119 120 func Test_RemoveConnectionRecordsForStates(t *testing.T) { 121 t.Run("test success", func(t *testing.T) { 122 record := &Record{ 123 ThreadID: threadIDValue, 124 ConnectionID: uuid.New().String(), 125 State: StateNameCompleted, 126 Namespace: TheirNSPrefix, 127 MyDID: "did:mydid:123", 128 TheirDID: "did:theirdid:123", 129 } 130 131 store := &mockstorage.MockStore{ 132 Store: make(map[string]mockstorage.DBEntry), 133 } 134 135 err := marshalAndSave(getConnectionStateKeyPrefix()(record.ConnectionID, record.State), 136 record, store) 137 require.NoError(t, err) 138 139 recorder, err := NewRecorder(&mockProvider{ 140 protocolStateStore: store, 141 }) 142 require.NoError(t, err) 143 require.NotNil(t, recorder) 144 145 err = removeConnectionsForStates(recorder, record.ConnectionID) 146 require.NoError(t, err) 147 }) 148 t.Run("test failed to delete connection state record from the store", func(t *testing.T) { 149 const errMsg = "get error" 150 record := &Record{ 151 ThreadID: threadIDValue, 152 ConnectionID: uuid.New().String(), 153 State: StateNameCompleted, 154 Namespace: TheirNSPrefix, 155 MyDID: "did:mydid:123", 156 TheirDID: "did:theirdid:123", 157 } 158 159 store := &mockstorage.MockStore{ 160 Store: make(map[string]mockstorage.DBEntry), 161 ErrDelete: fmt.Errorf(errMsg), 162 } 163 164 err := marshalAndSave(getConnectionStateKeyPrefix()(record.ConnectionID, record.State), 165 record, store, storage.Tag{ 166 Name: connStateKeyPrefix, 167 Value: getConnectionStateKeyPrefix()(record.ConnectionID), 168 }) 169 require.NoError(t, err) 170 171 recorder, err := NewRecorder(&mockProvider{ 172 protocolStateStore: store, 173 }) 174 require.NoError(t, err) 175 require.NotNil(t, recorder) 176 177 err = removeConnectionsForStates(recorder, record.ConnectionID) 178 require.Error(t, err) 179 require.Contains(t, err.Error(), errMsg) 180 }) 181 } 182 183 func TestConnectionStore_SaveInvitation(t *testing.T) { 184 const id = "sample-inv-id" 185 186 t.Run("test save invitation success", func(t *testing.T) { 187 store := &mockstorage.MockStore{Store: make(map[string]mockstorage.DBEntry)} 188 recorder, err := NewRecorder(&mockProvider{ 189 store: store, 190 }) 191 require.NoError(t, err) 192 193 require.NotNil(t, recorder) 194 195 value := &mockInvitation{ 196 ID: id, 197 Label: "sample-label1", 198 } 199 200 err = recorder.SaveInvitation(value.ID, value) 201 require.NoError(t, err) 202 203 require.NotEmpty(t, store) 204 205 k := getInvitationKeyPrefix()(value.ID) 206 207 v, err := recorder.Lookup.store.Get(k) 208 require.NoError(t, err) 209 require.NotEmpty(t, v) 210 211 var v1 mockInvitation 212 err = getAndUnmarshal(k, &v1, recorder.store) 213 require.NoError(t, err) 214 require.Equal(t, value, &v1) 215 216 var v2 mockInvitation 217 err = getAndUnmarshal(k, &v2, recorder.protocolStateStore) 218 require.Error(t, err) 219 require.Contains(t, err.Error(), "data not found") 220 }) 221 222 t.Run("test save invitation failure due to invalid key", func(t *testing.T) { 223 store := &mockstorage.MockStore{Store: make(map[string]mockstorage.DBEntry)} 224 recorder, err := NewRecorder(&mockProvider{ 225 store: store, 226 }) 227 require.NoError(t, err) 228 require.NotNil(t, recorder) 229 230 value := &mockInvitation{ 231 Label: "sample-label2", 232 } 233 err = recorder.SaveInvitation("", value) 234 require.Error(t, err) 235 require.Contains(t, err.Error(), "invalid key") 236 }) 237 } 238 239 func TestConnectionStore_GetInvitation(t *testing.T) { 240 t.Run("test get invitation - success", func(t *testing.T) { 241 recorder, err := NewRecorder(&mockProvider{}) 242 require.NoError(t, err) 243 require.NotNil(t, recorder) 244 245 valueStored := &mockInvitation{ 246 ID: "sample-id-3", 247 Label: "sample-label-3", 248 } 249 250 err = recorder.SaveInvitation(valueStored.ID, valueStored) 251 require.NoError(t, err) 252 253 var valueFound mockInvitation 254 err = recorder.GetInvitation(valueStored.ID, &valueFound) 255 require.NoError(t, err) 256 require.Equal(t, valueStored, &valueFound) 257 }) 258 259 t.Run("test get invitation - not found scenario", func(t *testing.T) { 260 recorder, err := NewRecorder(&mockProvider{}) 261 require.NoError(t, err) 262 require.NotNil(t, recorder) 263 264 var valueFound mockInvitation 265 err = recorder.GetInvitation("sample-key4", &valueFound) 266 require.Error(t, err) 267 require.Equal(t, err, storage.ErrDataNotFound) 268 }) 269 270 t.Run("test get invitation - invalid key scenario", func(t *testing.T) { 271 recorder, err := NewRecorder(&mockProvider{}) 272 require.NoError(t, err) 273 require.NotNil(t, recorder) 274 275 var valueFound mockInvitation 276 err = recorder.GetInvitation("", &valueFound) 277 require.Error(t, err) 278 require.Contains(t, err.Error(), errMsgInvalidKey) 279 }) 280 } 281 282 func TestConnectionStore_SaveAndGetOOBv2Invitation(t *testing.T) { 283 t.Run("success", func(t *testing.T) { 284 recorder, err := NewRecorder(&mockProvider{}) 285 require.NoError(t, err) 286 require.NotNil(t, recorder) 287 288 mockDID := "did:test:abc:def" 289 290 valueStored := &mockInvitation{ 291 ID: "sample-id-3", 292 Label: "sample-label-3", 293 } 294 295 err = recorder.SaveOOBv2Invitation(mockDID, valueStored) 296 require.NoError(t, err) 297 298 var valueFound mockInvitation 299 err = recorder.GetOOBv2Invitation(mockDID, &valueFound) 300 require.NoError(t, err) 301 require.Equal(t, valueStored, &valueFound) 302 }) 303 304 t.Run("fail: lookup without key", func(t *testing.T) { 305 recorder, err := NewRecorder(&mockProvider{}) 306 require.NoError(t, err) 307 require.NotNil(t, recorder) 308 309 err = recorder.GetOOBv2Invitation("", nil) 310 require.Error(t, err) 311 require.Contains(t, err.Error(), errMsgInvalidKey) 312 }) 313 } 314 315 func TestConnectionStore_SaveAndGetEventData(t *testing.T) { 316 t.Run("test save and get event data - success", func(t *testing.T) { 317 recorder, err := NewRecorder(&mockProvider{}) 318 require.NoError(t, err) 319 require.NotNil(t, recorder) 320 321 valueStored := []byte("sample-event-data") 322 323 err = recorder.SaveEvent(sampleConnID, valueStored) 324 require.NoError(t, err) 325 326 valueFound, err := recorder.GetEvent(sampleConnID) 327 require.NoError(t, err) 328 require.Equal(t, valueStored, valueFound) 329 }) 330 331 t.Run("test get invitation - not found scenario", func(t *testing.T) { 332 recorder, err := NewRecorder(&mockProvider{}) 333 require.NoError(t, err) 334 require.NotNil(t, recorder) 335 336 value, err := recorder.GetEvent(sampleConnID) 337 require.Error(t, err) 338 require.Equal(t, err, storage.ErrDataNotFound) 339 require.Nil(t, value) 340 }) 341 342 t.Run("test get invitation - invalid key scenario", func(t *testing.T) { 343 recorder, err := NewRecorder(&mockProvider{}) 344 require.NoError(t, err) 345 require.NotNil(t, recorder) 346 347 value, err := recorder.GetEvent("") 348 require.Error(t, err) 349 require.Contains(t, err.Error(), errMsgInvalidKey) 350 require.Nil(t, value) 351 }) 352 } 353 354 func TestConnectionRecordByState(t *testing.T) { 355 recorder, err := NewRecorder(&mockProvider{}) 356 require.NoError(t, err) 357 358 connRec := &Record{ 359 ConnectionID: uuid.New().String(), ThreadID: threadIDValue, 360 Namespace: MyNSPrefix, State: "requested", 361 } 362 err = recorder.SaveConnectionRecord(connRec) 363 require.NoError(t, err) 364 365 // data exists 366 storedConnRec, err := recorder.GetConnectionRecordAtState(connRec.ConnectionID, "requested") 367 require.NoError(t, err) 368 require.Equal(t, storedConnRec, connRec) 369 370 // data doesn't exists 371 _, err = recorder.GetConnectionRecordAtState(connRec.ConnectionID, "invalid") 372 require.Error(t, err) 373 require.Contains(t, err.Error(), "data not found") 374 375 // data with no state details 376 connRec = &Record{ 377 ConnectionID: uuid.New().String(), ThreadID: threadIDValue, 378 Namespace: MyNSPrefix, 379 } 380 err = recorder.SaveConnectionRecord(connRec) 381 require.NoError(t, err) 382 _, err = recorder.GetConnectionRecordAtState(connRec.ConnectionID, "requested") 383 require.Error(t, err) 384 require.Contains(t, err.Error(), "data not found") 385 386 // get with empty stateID 387 _, err = recorder.GetConnectionRecordAtState(connRec.ConnectionID, "") 388 require.Error(t, err) 389 require.Contains(t, err.Error(), "stateID can't be empty") 390 } 391 392 func TestConnectionRecorder_SaveConnectionRecord(t *testing.T) { 393 t.Run("save connection record with invited state - success", func(t *testing.T) { 394 recorder, err := NewRecorder(&mockProvider{}) 395 require.NoError(t, err) 396 require.NotNil(t, recorder) 397 398 record := &Record{ 399 ThreadID: threadIDValue, 400 ConnectionID: uuid.New().String(), State: stateNameInvited, Namespace: TheirNSPrefix, 401 } 402 err = recorder.SaveConnectionRecord(record) 403 require.NoError(t, err) 404 405 recordFound, err := recorder.GetConnectionRecord(record.ConnectionID) 406 require.NoError(t, err) 407 require.NotNil(t, recordFound) 408 require.Equal(t, record, recordFound) 409 410 // make sure it exists only in protocol state store 411 var r1 Record 412 err = getAndUnmarshal(getConnectionKeyPrefix()(record.ConnectionID), &r1, recorder.store) 413 require.Error(t, err) 414 require.Contains(t, err.Error(), "data not found") 415 416 var r2 Record 417 err = getAndUnmarshal(getConnectionKeyPrefix()(record.ConnectionID), &r2, recorder.protocolStateStore) 418 require.NoError(t, err) 419 require.Equal(t, record, &r2) 420 }) 421 422 t.Run("save connection record with invited state - completed", func(t *testing.T) { 423 recorder, err := NewRecorder(&mockProvider{}) 424 require.NoError(t, err) 425 require.NotNil(t, recorder) 426 427 record := &Record{ 428 ThreadID: threadIDValue, 429 ConnectionID: uuid.New().String(), 430 State: StateNameCompleted, 431 Namespace: TheirNSPrefix, 432 MyDID: "did:mydid:123", 433 TheirDID: "did:theirdid:123", 434 } 435 err = recorder.SaveConnectionRecord(record) 436 require.NoError(t, err) 437 438 recordFound, err := recorder.GetConnectionRecord(record.ConnectionID) 439 require.NoError(t, err) 440 require.NotNil(t, recordFound) 441 require.Equal(t, record, recordFound) 442 443 // make sure it exists only in both permanent and protocol state store 444 var r1 Record 445 err = getAndUnmarshal(getConnectionKeyPrefix()(record.ConnectionID), &r1, recorder.protocolStateStore) 446 require.NoError(t, err) 447 require.Equal(t, record, &r1) 448 449 var r2 Record 450 err = getAndUnmarshal(getConnectionKeyPrefix()(record.ConnectionID), &r2, recorder.store) 451 require.NoError(t, err) 452 require.Equal(t, record, &r2) 453 }) 454 455 t.Run("save connection record error scenario 1", func(t *testing.T) { 456 const errMsg = "get error" 457 record, err := NewRecorder(&mockProvider{ 458 protocolStateStore: &mockstorage.MockStore{ 459 Store: make(map[string]mockstorage.DBEntry), 460 ErrPut: fmt.Errorf(errMsg), 461 }, 462 }) 463 require.NoError(t, err) 464 connRec := &Record{ 465 ThreadID: "", 466 ConnectionID: "test", State: stateNameInvited, Namespace: TheirNSPrefix, 467 } 468 err = record.SaveConnectionRecord(connRec) 469 require.Contains(t, err.Error(), errMsg) 470 }) 471 472 t.Run("save connection record error scenario 2", func(t *testing.T) { 473 const errMsg = "get error" 474 record, err := NewRecorder(&mockProvider{ 475 store: &mockstorage.MockStore{ 476 Store: make(map[string]mockstorage.DBEntry), 477 ErrPut: fmt.Errorf(errMsg), 478 }, 479 }) 480 require.NoError(t, err) 481 connRec := &Record{ 482 ThreadID: "", 483 ConnectionID: "test", State: StateNameCompleted, Namespace: TheirNSPrefix, 484 } 485 err = record.SaveConnectionRecord(connRec) 486 require.Contains(t, err.Error(), errMsg) 487 }) 488 } 489 490 func TestConnectionRecorder_RemoveConnection(t *testing.T) { 491 t.Run("save and remove connection record with invited state - completed", func(t *testing.T) { 492 recorder, err := NewRecorder(&mockProvider{}) 493 require.NoError(t, err) 494 require.NotNil(t, recorder) 495 496 record := &Record{ 497 ThreadID: threadIDValue, 498 ConnectionID: uuid.New().String(), 499 State: StateNameCompleted, 500 Namespace: TheirNSPrefix, 501 MyDID: "did:mydid:123", 502 TheirDID: "did:theirdid:123", 503 } 504 err = recorder.SaveConnectionRecord(record) 505 require.NoError(t, err) 506 507 recordFound, err := recorder.GetConnectionRecord(record.ConnectionID) 508 require.NoError(t, err) 509 require.NotNil(t, recordFound) 510 require.Equal(t, record, recordFound) 511 512 err = recorder.RemoveConnection(record.ConnectionID) 513 require.NoError(t, err) 514 515 // make sure no records exist in both permanent and protocol state store 516 var r1 Record 517 err = getAndUnmarshal(getConnectionKeyPrefix()(record.ConnectionID), &r1, recorder.protocolStateStore) 518 require.Error(t, err) 519 require.Contains(t, err.Error(), "data not found") 520 521 var r2 Record 522 err = getAndUnmarshal(getConnectionKeyPrefix()(record.ConnectionID), &r2, recorder.store) 523 require.Error(t, err) 524 require.Contains(t, err.Error(), "data not found") 525 526 itr, err := recorder.protocolStateStore.Query(connStateKeyPrefix) 527 require.NoError(t, err) 528 529 hasRecords, err := itr.Next() 530 require.NoError(t, err) 531 532 if hasRecords { 533 key, errKey := itr.Key() 534 require.NoError(t, errKey) 535 536 t.Errorf("protocol state store still has connection state records: key=%s", key) 537 } 538 539 _, err = recorder.GetConnectionRecordByDIDs(record.MyDID, record.TheirDID) 540 require.Error(t, err) 541 require.Contains(t, err.Error(), "data not found") 542 }) 543 t.Run("try to remove unexisting connection record", func(t *testing.T) { 544 recorder, err := NewRecorder(&mockProvider{}) 545 require.NoError(t, err) 546 require.NotNil(t, recorder) 547 548 record := &Record{ 549 ThreadID: threadIDValue, 550 ConnectionID: uuid.New().String(), 551 State: StateNameCompleted, 552 Namespace: TheirNSPrefix, 553 MyDID: "did:mydid:123", 554 TheirDID: "did:theirdid:123", 555 } 556 557 err = recorder.RemoveConnection(record.ConnectionID) 558 require.Error(t, err) 559 require.Contains(t, err.Error(), "data not found") 560 }) 561 t.Run("save and remove connection record - failed to delete from the store", func(t *testing.T) { 562 const errMsg = "get error" 563 recorder, err := NewRecorder(&mockProvider{ 564 store: &mockstorage.MockStore{ 565 Store: make(map[string]mockstorage.DBEntry), 566 ErrDelete: fmt.Errorf(errMsg), 567 }, 568 }) 569 require.NoError(t, err) 570 require.NotNil(t, recorder) 571 572 record := &Record{ 573 ThreadID: threadIDValue, 574 ConnectionID: uuid.New().String(), 575 State: StateNameCompleted, 576 Namespace: TheirNSPrefix, 577 MyDID: "did:mydid:123", 578 TheirDID: "did:theirdid:123", 579 } 580 err = recorder.SaveConnectionRecord(record) 581 require.NoError(t, err) 582 583 err = recorder.RemoveConnection(record.ConnectionID) 584 require.Error(t, err) 585 require.Contains(t, err.Error(), errMsg) 586 }) 587 t.Run("save and remove connection record - failed to delete from the protocol state store", func(t *testing.T) { 588 const errMsg = "get error" 589 recorder, err := NewRecorder(&mockProvider{ 590 protocolStateStore: &mockstorage.MockStore{ 591 Store: make(map[string]mockstorage.DBEntry), 592 ErrDelete: fmt.Errorf(errMsg), 593 }, 594 }) 595 require.NoError(t, err) 596 require.NotNil(t, recorder) 597 598 record := &Record{ 599 ThreadID: threadIDValue, 600 ConnectionID: uuid.New().String(), 601 State: StateNameCompleted, 602 Namespace: TheirNSPrefix, 603 MyDID: "did:mydid:123", 604 TheirDID: "did:theirdid:123", 605 } 606 err = recorder.SaveConnectionRecord(record) 607 require.NoError(t, err) 608 609 err = recorder.RemoveConnection(record.ConnectionID) 610 require.Error(t, err) 611 require.Contains(t, err.Error(), errMsg) 612 }) 613 t.Run("save and remove connection record - failed to delete connection mapping record", func(t *testing.T) { 614 recorder, err := NewRecorder(&mockProvider{}) 615 require.NoError(t, err) 616 require.NotNil(t, recorder) 617 618 record := &Record{ 619 ThreadID: "", 620 ConnectionID: uuid.New().String(), 621 State: StateNameCompleted, 622 Namespace: TheirNSPrefix, 623 MyDID: "did:mydid:123", 624 TheirDID: "did:theirdid:123", 625 } 626 err = recorder.SaveConnectionRecord(record) 627 require.NoError(t, err) 628 629 err = recorder.RemoveConnection(record.ConnectionID) 630 require.Error(t, err) 631 require.Contains(t, err.Error(), "empty bytes") 632 }) 633 } 634 635 func TestConnectionRecorder_ConnectionRecordMappings(t *testing.T) { 636 t.Run("get connection record by namespace threadID in my namespace", func(t *testing.T) { 637 recorder, err := NewRecorder(&mockProvider{}) 638 require.NoError(t, err) 639 640 require.NotNil(t, recorder) 641 connRec := &Record{ 642 ThreadID: threadIDValue, 643 ConnectionID: sampleConnID, State: stateNameInvited, Namespace: MyNSPrefix, 644 } 645 err = recorder.SaveConnectionRecordWithMappings(connRec) 646 require.NoError(t, err) 647 648 nsThreadID, err := CreateNamespaceKey(MyNSPrefix, threadIDValue) 649 require.NoError(t, err) 650 651 storedRecord, err := recorder.GetConnectionRecordByNSThreadID(nsThreadID) 652 require.NoError(t, err) 653 require.Equal(t, connRec, storedRecord) 654 }) 655 t.Run("get connection record by namespace threadID their namespace", func(t *testing.T) { 656 recorder, err := NewRecorder(&mockProvider{}) 657 require.NoError(t, err) 658 require.NotNil(t, recorder) 659 connRec := &Record{ 660 ThreadID: threadIDValue, 661 ConnectionID: sampleConnID, State: stateNameInvited, Namespace: TheirNSPrefix, 662 } 663 err = recorder.SaveConnectionRecordWithMappings(connRec) 664 require.NoError(t, err) 665 666 nsThreadID, err := CreateNamespaceKey(TheirNSPrefix, threadIDValue) 667 require.NoError(t, err) 668 669 storedRecord, err := recorder.GetConnectionRecordByNSThreadID(nsThreadID) 670 require.NoError(t, err) 671 require.Equal(t, connRec, storedRecord) 672 }) 673 t.Run("save connection record with mapping - validation failure", func(t *testing.T) { 674 recorder, err := NewRecorder(&mockProvider{}) 675 require.NoError(t, err) 676 677 require.NotNil(t, recorder) 678 connRec := &Record{ 679 ThreadID: "", 680 ConnectionID: sampleConnID, State: stateNameInvited, Namespace: MyNSPrefix, 681 } 682 err = recorder.SaveConnectionRecordWithMappings(connRec) 683 require.Error(t, err) 684 require.Contains(t, err.Error(), "validation failed") 685 }) 686 t.Run("save connection record with mapping - store failure", func(t *testing.T) { 687 const errMsg = "put error" 688 recorder, err := NewRecorder(&mockProvider{ 689 protocolStateStore: &mockstorage.MockStore{ 690 Store: make(map[string]mockstorage.DBEntry), 691 ErrPut: fmt.Errorf(errMsg), 692 }, 693 }) 694 695 require.NotNil(t, recorder) 696 require.NoError(t, err) 697 698 connRec := &Record{ 699 ThreadID: threadIDValue, 700 ConnectionID: sampleConnID, State: stateNameInvited, Namespace: MyNSPrefix, 701 } 702 err = recorder.SaveConnectionRecordWithMappings(connRec) 703 require.Error(t, err) 704 require.Contains(t, err.Error(), errMsg) 705 }) 706 t.Run("save connection record with mapping - namespace error", func(t *testing.T) { 707 recorder, err := NewRecorder(&mockProvider{}) 708 require.NoError(t, err) 709 710 require.NotNil(t, recorder) 711 connRec := &Record{ 712 ThreadID: threadIDValue, 713 ConnectionID: sampleConnID, State: stateNameInvited, Namespace: "invalid-ns", 714 } 715 err = recorder.SaveConnectionRecordWithMappings(connRec) 716 require.Error(t, err) 717 require.Contains(t, err.Error(), "namespace not supported") 718 }) 719 t.Run("data not found error due to missing input parameter", func(t *testing.T) { 720 recorder, err := NewRecorder(&mockProvider{}) 721 require.NoError(t, err) 722 require.NotNil(t, recorder) 723 connRec, err := recorder.GetConnectionRecordByNSThreadID("") 724 require.Contains(t, err.Error(), "data not found") 725 require.Nil(t, connRec) 726 }) 727 } 728 729 func TestConnectionRecorder_CreateNSKeys(t *testing.T) { 730 t.Run("creating their namespace key success", func(t *testing.T) { 731 key, err := CreateNamespaceKey(TheirNSPrefix, threadIDValue) 732 require.NoError(t, err) 733 require.NotNil(t, key) 734 }) 735 t.Run("check error while creating my namespace key", func(t *testing.T) { 736 _, err := CreateNamespaceKey(MyNSPrefix, "") 737 require.Contains(t, err.Error(), "empty bytes") 738 }) 739 } 740 741 func TestConnectionRecorder_SaveNamespaceThreadID(t *testing.T) { 742 t.Run("missing required parameters", func(t *testing.T) { 743 recorder, err := NewRecorder(&mockProvider{}) 744 require.NoError(t, err) 745 746 require.NotNil(t, recorder) 747 err = recorder.SaveNamespaceThreadID("", TheirNSPrefix, sampleConnID) 748 require.Error(t, err) 749 err = recorder.SaveNamespaceThreadID("", MyNSPrefix, sampleConnID) 750 require.Error(t, err) 751 err = recorder.SaveNamespaceThreadID(threadIDValue, "", sampleConnID) 752 require.Error(t, err) 753 }) 754 } 755 756 func TestConnectionRecorder_SaveAndGet(t *testing.T) { 757 const noOfRecords = 12 758 759 records := make([]*mockInvitation, noOfRecords) 760 for i := 0; i < noOfRecords; i++ { 761 records[i] = &mockInvitation{ID: fmt.Sprintf("conn-%d", i)} 762 } 763 764 t.Run("save and get in store - success", func(t *testing.T) { 765 require.NotEmpty(t, records) 766 store := &mockstorage.MockStore{Store: make(map[string]mockstorage.DBEntry)} 767 768 for _, record := range records { 769 err := marshalAndSave(record.ID, record, store) 770 require.NoError(t, err) 771 } 772 773 for _, record := range records { 774 var recordFound1 mockInvitation 775 err := getAndUnmarshal(record.ID, &recordFound1, store) 776 require.NoError(t, err) 777 require.Equal(t, record, &recordFound1) 778 } 779 }) 780 781 t.Run("save and get in store - store failure", func(t *testing.T) { 782 const errMsg = "put error" 783 784 store := &mockstorage.MockStore{ 785 Store: make(map[string]mockstorage.DBEntry), 786 ErrPut: fmt.Errorf(errMsg), 787 ErrGet: fmt.Errorf(errMsg), 788 } 789 790 require.NotEmpty(t, records) 791 792 for _, record := range records { 793 err := marshalAndSave(record.ID, record, store) 794 require.Error(t, err) 795 require.Contains(t, err.Error(), errMsg) 796 } 797 798 for _, record := range records { 799 var recordFound1 mockInvitation 800 err := getAndUnmarshal(record.ID, &recordFound1, store) 801 require.Error(t, err) 802 require.Contains(t, err.Error(), errMsg) 803 } 804 }) 805 806 t.Run("save and get in store - failure", func(t *testing.T) { 807 store := &mockstorage.MockStore{Store: make(map[string]mockstorage.DBEntry)} 808 809 err := marshalAndSave("sample-id", make(chan int), store) 810 require.Error(t, err) 811 812 err = marshalAndSave("sample-id", []byte("XYZ"), store) 813 require.NoError(t, err) 814 815 err = getAndUnmarshal("sample-id", make(chan int), store) 816 require.Error(t, err) 817 }) 818 } 819 820 type mockInvitation struct { 821 ImageURL string `json:"imageUrl,omitempty"` 822 ServiceEndpoint string `json:"serviceEndpoint,omitempty"` 823 RecipientKeys []string `json:"recipientKeys,omitempty"` 824 ID string `json:"@id,omitempty"` 825 Label string `json:"label,omitempty"` 826 DID string `json:"did,omitempty"` 827 RoutingKeys []string `json:"routingKeys,omitempty"` 828 Type string `json:"@type,omitempty"` 829 Thread *decorator.Thread `json:"~thread,omitempty"` 830 }