github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/presentproof/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 presentproof 8 9 import ( 10 "bytes" 11 "encoding/base64" 12 "encoding/json" 13 "errors" 14 "fmt" 15 "testing" 16 "time" 17 18 "github.com/golang/mock/gomock" 19 "github.com/google/uuid" 20 "github.com/stretchr/testify/require" 21 22 "github.com/hyperledger/aries-framework-go/component/storageutil/mem" 23 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model" 24 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 25 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 26 serviceMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/common/service" 27 presentproofMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/protocol/presentproof" 28 storageMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/spi/storage" 29 "github.com/hyperledger/aries-framework-go/spi/storage" 30 ) 31 32 const ( 33 Alice = "Alice" 34 Bob = "Bob" 35 ) 36 37 func TestNew(t *testing.T) { 38 ctrl := gomock.NewController(t) 39 defer ctrl.Finish() 40 41 t.Run("Success", func(t *testing.T) { 42 storeProvider := storageMocks.NewMockProvider(ctrl) 43 storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil) 44 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 45 46 provider := presentproofMocks.NewMockProvider(ctrl) 47 provider.EXPECT().Messenger().Return(nil) 48 provider.EXPECT().StorageProvider().Return(storeProvider).Times(2) 49 50 svc, err := New(provider) 51 require.NoError(t, err) 52 require.NotNil(t, svc) 53 }) 54 55 t.Run("Error open store", func(t *testing.T) { 56 const errMsg = "error" 57 58 storeProvider := storageMocks.NewMockProvider(ctrl) 59 storeProvider.EXPECT().OpenStore(Name).Return(nil, errors.New(errMsg)) 60 61 provider := presentproofMocks.NewMockProvider(ctrl) 62 provider.EXPECT().StorageProvider().Return(storeProvider) 63 64 svc, err := New(provider) 65 require.Contains(t, fmt.Sprintf("%v", err), errMsg) 66 require.Nil(t, svc) 67 }) 68 } 69 70 func TestService_Initialize(t *testing.T) { 71 ctrl := gomock.NewController(t) 72 defer ctrl.Finish() 73 74 t.Run("success", func(t *testing.T) { 75 storeProvider := storageMocks.NewMockProvider(ctrl) 76 storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil) 77 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 78 79 provider := presentproofMocks.NewMockProvider(ctrl) 80 provider.EXPECT().Messenger().Return(nil) 81 provider.EXPECT().StorageProvider().Return(storeProvider).Times(2) 82 83 svc := Service{} 84 85 err := svc.Initialize(provider) 86 require.NoError(t, err) 87 88 // second init is no-op 89 err = svc.Initialize(provider) 90 require.NoError(t, err) 91 }) 92 93 t.Run("failure, not given a valid provider", func(t *testing.T) { 94 svc := Service{} 95 96 err := svc.Initialize("not a provider") 97 require.Error(t, err) 98 require.Contains(t, err.Error(), "expected provider of type") 99 }) 100 } 101 102 func TestService_Use(t *testing.T) { 103 ctrl := gomock.NewController(t) 104 defer ctrl.Finish() 105 106 t.Run("Success (one function)", func(t *testing.T) { 107 storeProvider := storageMocks.NewMockProvider(ctrl) 108 storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil).Times(1) 109 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 110 111 provider := presentproofMocks.NewMockProvider(ctrl) 112 provider.EXPECT().Messenger().Return(nil) 113 provider.EXPECT().StorageProvider().Return(storeProvider).Times(2) 114 115 svc, err := New(provider) 116 require.NoError(t, err) 117 require.NotNil(t, svc) 118 119 meta := &metaData{ 120 state: &done{}, 121 msgClone: service.NewDIDCommMsgMap(struct { 122 Type string `json:"@type"` 123 }{ 124 Type: PresentationMsgTypeV2, 125 }), 126 presentation: &PresentationV2{Type: PresentationMsgTypeV2}, 127 presentationV3: &PresentationV3{Type: PresentationMsgTypeV3}, 128 proposePresentation: &ProposePresentationV2{Type: ProposePresentationMsgTypeV2}, 129 proposePresentationV3: &ProposePresentationV3{Type: ProposePresentationMsgTypeV3}, 130 request: &RequestPresentationV2{Type: RequestPresentationMsgTypeV2}, 131 requestV3: &RequestPresentationV3{Type: RequestPresentationMsgTypeV3}, 132 presentationNames: []string{"name"}, 133 } 134 var executed bool 135 svc.Use(func(next Handler) Handler { 136 return HandlerFunc(func(metadata Metadata) error { 137 require.Equal(t, meta.msgClone, metadata.Message()) 138 require.Equal(t, metadata.Message().Type(), PresentationMsgTypeV2) 139 require.Equal(t, meta.presentation, metadata.Presentation()) 140 require.Equal(t, meta.presentationV3, metadata.PresentationV3()) 141 require.Equal(t, meta.proposePresentation, metadata.ProposePresentation()) 142 require.Equal(t, meta.proposePresentationV3, metadata.ProposePresentationV3()) 143 require.Equal(t, meta.request, metadata.RequestPresentation()) 144 require.Equal(t, meta.requestV3, metadata.RequestPresentationV3()) 145 require.Equal(t, meta.presentationNames, metadata.PresentationNames()) 146 require.Equal(t, meta.state.Name(), metadata.StateName()) 147 require.Nil(t, metadata.GetAddProofFn()) 148 149 executed = true 150 return next.Handle(metadata) 151 }) 152 }) 153 154 _, _, err = svc.execute(meta.state, meta) 155 require.NoError(t, err) 156 require.True(t, executed) 157 }) 158 159 t.Run("Success (two function)", func(t *testing.T) { 160 storeProvider := storageMocks.NewMockProvider(ctrl) 161 storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil).Times(1) 162 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 163 164 provider := presentproofMocks.NewMockProvider(ctrl) 165 provider.EXPECT().Messenger().Return(nil) 166 provider.EXPECT().StorageProvider().Return(storeProvider).Times(2) 167 168 svc, err := New(provider) 169 require.NoError(t, err) 170 require.NotNil(t, svc) 171 172 var executed bool 173 svc.Use(func(next Handler) Handler { 174 return HandlerFunc(func(metadata Metadata) error { 175 executed = true 176 return next.Handle(metadata) 177 }) 178 }, func(next Handler) Handler { 179 return HandlerFunc(func(metadata Metadata) error { 180 require.True(t, executed) 181 return next.Handle(metadata) 182 }) 183 }) 184 185 _, _, err = svc.execute(&done{}, &metaData{}) 186 require.NoError(t, err) 187 }) 188 189 t.Run("Failed", func(t *testing.T) { 190 storeProvider := storageMocks.NewMockProvider(ctrl) 191 storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil).Times(1) 192 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 193 194 provider := presentproofMocks.NewMockProvider(ctrl) 195 provider.EXPECT().Messenger().Return(nil) 196 provider.EXPECT().StorageProvider().Return(storeProvider).Times(2) 197 198 svc, err := New(provider) 199 require.NoError(t, err) 200 require.NotNil(t, svc) 201 202 const msgErr = "error message" 203 svc.Use(func(next Handler) Handler { 204 return HandlerFunc(func(metadata Metadata) error { 205 return errors.New(msgErr) 206 }) 207 }) 208 209 _, _, err = svc.execute(&done{}, &metaData{}) 210 require.EqualError(t, err, "middleware: "+msgErr) 211 }) 212 } 213 214 func TestService_ActionContinue(t *testing.T) { 215 ctrl := gomock.NewController(t) 216 defer ctrl.Finish() 217 218 const errMsg = "error" 219 220 store := storageMocks.NewMockStore(ctrl) 221 storeProvider := storageMocks.NewMockProvider(ctrl) 222 storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes() 223 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil).AnyTimes() 224 225 provider := presentproofMocks.NewMockProvider(ctrl) 226 provider.EXPECT().Messenger().Return(nil).AnyTimes() 227 provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes() 228 229 t.Run("Error transitional payload (get)", func(t *testing.T) { 230 store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg)) 231 232 svc, err := New(provider) 233 require.NoError(t, err) 234 235 err = svc.ActionContinue("piID", nil) 236 require.Contains(t, fmt.Sprintf("%v", err), "get transitional payload: store get: "+errMsg) 237 }) 238 239 t.Run("Error transitional payload (delete)", func(t *testing.T) { 240 store.EXPECT().Get(gomock.Any()).Return([]byte(`{}`), nil) 241 store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg)) 242 243 svc, err := New(provider) 244 require.NoError(t, err) 245 246 err = svc.ActionContinue("piID") 247 require.Contains(t, fmt.Sprintf("%v", err), "delete transitional payload: "+errMsg) 248 }) 249 } 250 251 func TestService_ActionStop(t *testing.T) { 252 t.Run("Error transitional payload (get)", func(t *testing.T) { 253 ctrl := gomock.NewController(t) 254 defer ctrl.Finish() 255 256 const errMsg = "error" 257 258 store := storageMocks.NewMockStore(ctrl) 259 store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg)) 260 261 storeProvider := storageMocks.NewMockProvider(ctrl) 262 storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes() 263 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 264 265 provider := presentproofMocks.NewMockProvider(ctrl) 266 provider.EXPECT().Messenger().Return(nil) 267 provider.EXPECT().StorageProvider().Return(storeProvider).Times(2) 268 269 svc, err := New(provider) 270 require.NoError(t, err) 271 272 err = svc.ActionStop("piID", nil) 273 require.Contains(t, fmt.Sprintf("%v", err), "get transitional payload: store get: "+errMsg) 274 }) 275 276 t.Run("Error transitional payload (delete)", func(t *testing.T) { 277 ctrl := gomock.NewController(t) 278 defer ctrl.Finish() 279 280 const errMsg = "error" 281 282 store := storageMocks.NewMockStore(ctrl) 283 store.EXPECT().Get(gomock.Any()).Return([]byte(`{}`), nil) 284 store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg)) 285 286 storeProvider := storageMocks.NewMockProvider(ctrl) 287 storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes() 288 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 289 290 provider := presentproofMocks.NewMockProvider(ctrl) 291 provider.EXPECT().Messenger().Return(nil) 292 provider.EXPECT().StorageProvider().Return(storeProvider).Times(2) 293 294 svc, err := New(provider) 295 require.NoError(t, err) 296 297 err = svc.ActionStop("piID", nil) 298 require.Contains(t, fmt.Sprintf("%v", err), "delete transitional payload: "+errMsg) 299 }) 300 } 301 302 // nolint: gocyclo,gocognit 303 func TestService_HandleInboundOutbound(t *testing.T) { 304 ctrl := gomock.NewController(t) 305 defer ctrl.Finish() 306 307 const errMsg = "error" 308 309 initMocks := func(controller *gomock.Controller) ( 310 store *storageMocks.MockStore, 311 messenger *serviceMocks.MockMessenger, 312 provider *presentproofMocks.MockProvider, 313 ) { 314 store = storageMocks.NewMockStore(controller) 315 316 storeProvider := storageMocks.NewMockProvider(controller) 317 storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes() 318 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil).AnyTimes() 319 320 messenger = serviceMocks.NewMockMessenger(controller) 321 322 provider = presentproofMocks.NewMockProvider(controller) 323 provider.EXPECT().Messenger().Return(messenger).AnyTimes() 324 provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes() 325 326 return store, messenger, provider 327 } 328 329 t.Run("No clients", func(t *testing.T) { 330 _, _, provider := initMocks(ctrl) 331 332 svc, err := New(provider) 333 require.NoError(t, err) 334 335 _, err = svc.HandleInbound(randomInboundMessage(""), service.EmptyDIDCommContext()) 336 require.Contains(t, fmt.Sprintf("%v", err), "no clients") 337 }) 338 339 t.Run("DB error", func(t *testing.T) { 340 store, _, provider := initMocks(ctrl) 341 342 store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg)).AnyTimes() 343 344 svc, err := New(provider) 345 require.NoError(t, err) 346 347 require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction))) 348 349 msg := service.NewDIDCommMsgMap(struct { 350 ID string `json:"@id"` 351 Type string `json:"@type"` 352 Thread decorator.Thread `json:"~thread"` 353 }{ID: "ID", Type: "type", Thread: decorator.Thread{PID: "PID"}}) 354 msg.SetID(uuid.New().String()) 355 356 _, err = svc.HandleInbound(msg, service.EmptyDIDCommContext()) 357 require.Contains(t, fmt.Sprintf("%v", err), 358 "buildMetaData: current internal data and PIID: current internal data: "+errMsg) 359 }) 360 361 t.Run("DB error (saveTransitionalPayload)", func(t *testing.T) { 362 store, _, provider := initMocks(ctrl) 363 364 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 365 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New(errMsg)) 366 367 svc, err := New(provider) 368 require.NoError(t, err) 369 370 require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction))) 371 372 _, err = svc.HandleInbound(randomInboundMessage(RequestPresentationMsgTypeV2), service.EmptyDIDCommContext()) 373 require.Contains(t, fmt.Sprintf("%v", err), "save transitional payload: "+errMsg) 374 }) 375 376 t.Run("Unrecognized msgType", func(t *testing.T) { 377 store, _, provider := initMocks(ctrl) 378 379 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 380 381 svc, err := New(provider) 382 require.NoError(t, err) 383 384 require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction))) 385 386 msg := service.NewDIDCommMsgMap(struct{}{}) 387 msg.SetID(uuid.New().String()) 388 msg["@type"] = "type" 389 390 _, err = svc.HandleInbound(msg, service.EmptyDIDCommContext()) 391 require.Contains(t, fmt.Sprintf("%v", err), "buildMetaData: nextState: unrecognized msgType: ") 392 }) 393 394 t.Run("Invalid state transition", func(t *testing.T) { 395 _, _, provider := initMocks(ctrl) 396 397 svc, err := New(provider) 398 require.NoError(t, err) 399 400 ch := make(chan service.DIDCommAction, 1) 401 require.NoError(t, svc.RegisterActionEvent(ch)) 402 403 chState := make(chan service.StateMsg, 2) 404 require.NoError(t, svc.RegisterMsgEvent(chState)) 405 406 _, err = svc.HandleInbound(service.NewDIDCommMsgMap(model.ProblemReport{ 407 Type: ProblemReportMsgTypeV2, 408 }), service.EmptyDIDCommContext()) 409 require.Contains(t, fmt.Sprintf("%v", err), "buildMetaData: invalid state transition") 410 }) 411 412 t.Run("Receive Invitation Presentation (Stop)", func(t *testing.T) { 413 store, messenger, provider := initMocks(ctrl) 414 415 done := make(chan struct{}) 416 errChan := make(chan error) 417 418 messenger.EXPECT(). 419 ReplyToNested(gomock.Any(), gomock.Any()). 420 Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error { 421 defer close(done) 422 423 r := &model.ProblemReport{} 424 require.NoError(t, msg.Decode(r)) 425 require.Equal(t, codeRejectedError, r.Description.Code) 426 require.Equal(t, ProblemReportMsgTypeV2, r.Type) 427 428 return nil 429 }) 430 431 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 432 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 433 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 434 src, err := json.Marshal(&internalData{StateName: "abandoned", ProtocolVersion: version2}) 435 require.NoError(t, err) 436 require.True(t, bytes.Equal(src, data)) 437 438 if !bytes.Equal(src, data) { 439 errChan <- fmt.Errorf("data: %s\nsrc: %s", string(data), string(src)) 440 } 441 return nil 442 }) 443 store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg)) 444 445 svc, err := New(provider) 446 require.NoError(t, err) 447 448 ch := make(chan service.DIDCommAction, 1) 449 require.NoError(t, svc.RegisterActionEvent(ch)) 450 451 _, err = svc.HandleInbound( 452 randomInboundMessage(RequestPresentationMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil)) 453 require.NoError(t, err) 454 455 action := <-ch 456 457 properties, ok := action.Properties.(*eventProps) 458 require.True(t, ok) 459 require.NotEmpty(t, properties.PIID()) 460 require.Equal(t, properties.MyDID(), Alice) 461 require.Equal(t, properties.TheirDID(), Bob) 462 require.Equal(t, properties.All()["myDID"], Alice) 463 require.Equal(t, properties.All()["theirDID"], Bob) 464 465 action.Stop(nil) 466 467 select { 468 case e := <-errChan: 469 t.Error(e) 470 case <-done: 471 return 472 case <-time.After(time.Second): 473 t.Error("timeout") 474 } 475 }) 476 477 t.Run("Receive Invitation Presentation (continue with presentation)", func(t *testing.T) { 478 store, messenger, provider := initMocks(ctrl) 479 480 done := make(chan struct{}) 481 482 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 483 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 484 defer close(done) 485 486 r := &PresentationV2{} 487 require.NoError(t, msg.Decode(r)) 488 require.Equal(t, PresentationMsgTypeV2, r.Type) 489 490 return nil 491 }) 492 493 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 494 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 495 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 496 src, err := json.Marshal(&internalData{StateName: "request-received", ProtocolVersion: version2}) 497 require.NoError(t, err) 498 require.Equal(t, string(src), string(data)) 499 500 return nil 501 }) 502 store.EXPECT().Delete(gomock.Any()).Return(nil) 503 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 504 src, err := json.Marshal(&internalData{StateName: "presentation-sent", ProtocolVersion: version2}) 505 require.NoError(t, err) 506 require.Equal(t, string(src), string(data)) 507 508 return nil 509 }) 510 511 svc, err := New(provider) 512 require.NoError(t, err) 513 514 ch := make(chan service.DIDCommAction, 1) 515 require.NoError(t, svc.RegisterActionEvent(ch)) 516 517 msg := randomInboundMessage(RequestPresentationMsgTypeV2) 518 msg["will_confirm"] = true 519 520 _, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil)) 521 require.NoError(t, err) 522 523 action := <-ch 524 525 properties, ok := action.Properties.(*eventProps) 526 require.True(t, ok) 527 require.NotEmpty(t, properties.PIID()) 528 require.Equal(t, properties.MyDID(), Alice) 529 require.Equal(t, properties.TheirDID(), Bob) 530 531 action.Continue(WithMultiOptions(WithPresentation(&PresentationParams{}), WithAddProofFn(nil))) 532 533 select { 534 case <-done: 535 return 536 case <-time.After(time.Second): 537 t.Error("timeout") 538 } 539 }) 540 541 t.Run("Receive Invitation Presentation (continue with presentation) async", func(t *testing.T) { 542 _, messenger, _ := initMocks(ctrl) 543 544 done := make(chan struct{}) 545 546 memProvider := mem.NewProvider() 547 548 newProvider := presentproofMocks.NewMockProvider(ctrl) 549 newProvider.EXPECT().Messenger().Return(messenger) 550 newProvider.EXPECT().StorageProvider().Return(memProvider).Times(2) 551 552 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 553 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 554 defer close(done) 555 556 r := &PresentationV2{} 557 require.NoError(t, msg.Decode(r)) 558 require.Equal(t, PresentationMsgTypeV2, r.Type) 559 560 return nil 561 }) 562 563 svc, err := New(newProvider) 564 require.NoError(t, err) 565 566 ch := make(chan service.DIDCommAction, 1) 567 require.NoError(t, svc.RegisterActionEvent(ch)) 568 569 msg := randomInboundMessage(RequestPresentationMsgTypeV2) 570 msg["will_confirm"] = true 571 572 _, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil)) 573 require.NoError(t, err) 574 575 actions, err := svc.Actions() 576 require.NoError(t, err) 577 for _, action := range actions { 578 require.Equal(t, action.MyDID, Alice) 579 require.Equal(t, action.TheirDID, Bob) 580 require.NoError(t, svc.ActionContinue(action.PIID, WithPresentation(&PresentationParams{}))) 581 } 582 583 select { 584 case <-done: 585 return 586 case <-time.After(time.Second): 587 t.Error("timeout") 588 } 589 }) 590 591 t.Run("Receive Invitation Presentation (continue with presentation) async v3", func(t *testing.T) { 592 _, messenger, _ := initMocks(ctrl) 593 594 done := make(chan struct{}) 595 596 memProvider := mem.NewProvider() 597 598 newProvider := presentproofMocks.NewMockProvider(ctrl) 599 newProvider.EXPECT().Messenger().Return(messenger) 600 newProvider.EXPECT().StorageProvider().Return(memProvider).Times(2) 601 602 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 603 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 604 defer close(done) 605 606 r := &PresentationV3{} 607 require.NoError(t, msg.Decode(r)) 608 require.Equal(t, PresentationMsgTypeV3, r.Type) 609 610 return nil 611 }) 612 613 svc, err := New(newProvider) 614 require.NoError(t, err) 615 616 ch := make(chan service.DIDCommAction, 1) 617 require.NoError(t, svc.RegisterActionEvent(ch)) 618 619 msg := randomInboundMessageV3(RequestPresentationMsgTypeV3) 620 621 msg["data"] = map[string]interface{}{ 622 "will_confirm": true, 623 } 624 625 _, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil)) 626 require.NoError(t, err) 627 628 actions, err := svc.Actions() 629 require.NoError(t, err) 630 for _, action := range actions { 631 require.Equal(t, action.MyDID, Alice) 632 require.Equal(t, action.TheirDID, Bob) 633 require.NoError(t, svc.ActionContinue(action.PIID, WithPresentation(&PresentationParams{}))) 634 } 635 636 select { 637 case <-done: 638 return 639 case <-time.After(time.Second): 640 t.Error("timeout") 641 } 642 }) 643 644 t.Run("Receive Invitation Presentation (Stop) async", func(t *testing.T) { 645 _, messenger, _ := initMocks(ctrl) 646 647 done := make(chan struct{}) 648 649 memProvider := mem.NewProvider() 650 651 newProvider := presentproofMocks.NewMockProvider(ctrl) 652 newProvider.EXPECT().Messenger().Return(messenger) 653 newProvider.EXPECT().StorageProvider().Return(memProvider).Times(2) 654 655 messenger.EXPECT(). 656 ReplyToNested(gomock.Any(), gomock.Any()). 657 Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error { 658 defer close(done) 659 660 r := &model.ProblemReport{} 661 require.NoError(t, msg.Decode(r)) 662 require.Equal(t, codeRejectedError, r.Description.Code) 663 require.Equal(t, ProblemReportMsgTypeV2, r.Type) 664 665 return nil 666 }) 667 668 svc, err := New(newProvider) 669 require.NoError(t, err) 670 671 ch := make(chan service.DIDCommAction, 1) 672 require.NoError(t, svc.RegisterActionEvent(ch)) 673 674 _, err = svc.HandleInbound( 675 randomInboundMessage(RequestPresentationMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil)) 676 require.NoError(t, err) 677 678 actions, err := svc.Actions() 679 require.NoError(t, err) 680 for _, action := range actions { 681 require.Equal(t, action.MyDID, Alice) 682 require.Equal(t, action.TheirDID, Bob) 683 require.NoError(t, svc.ActionStop(action.PIID, nil)) 684 } 685 686 select { 687 case <-done: 688 return 689 case <-time.After(time.Second): 690 t.Error("timeout") 691 } 692 }) 693 694 t.Run("Receive Invitation Presentation (continue with proposal)", func(t *testing.T) { 695 store, messenger, provider := initMocks(ctrl) 696 697 done := make(chan struct{}) 698 699 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 700 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 701 defer close(done) 702 703 r := &ProposePresentationV2{} 704 require.NoError(t, msg.Decode(r)) 705 require.Equal(t, ProposePresentationMsgTypeV2, r.Type) 706 707 return nil 708 }) 709 710 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 711 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 712 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 713 src, err := json.Marshal(&internalData{StateName: "request-received", ProtocolVersion: version2}) 714 require.NoError(t, err) 715 require.Equal(t, string(src), string(data)) 716 717 return nil 718 }) 719 store.EXPECT().Delete(gomock.Any()).Return(nil) 720 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 721 src, err := json.Marshal(&internalData{StateName: "proposal-sent", ProtocolVersion: version2}) 722 require.NoError(t, err) 723 require.Equal(t, string(src), string(data)) 724 725 return nil 726 }) 727 728 svc, err := New(provider) 729 require.NoError(t, err) 730 731 ch := make(chan service.DIDCommAction, 1) 732 require.NoError(t, svc.RegisterActionEvent(ch)) 733 734 _, err = svc.HandleInbound( 735 randomInboundMessage(RequestPresentationMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil)) 736 require.NoError(t, err) 737 738 action := <-ch 739 740 properties, ok := action.Properties.(*eventProps) 741 require.True(t, ok) 742 require.NotEmpty(t, properties.PIID()) 743 require.Equal(t, properties.MyDID(), Alice) 744 require.Equal(t, properties.TheirDID(), Bob) 745 746 action.Continue(WithProposePresentation(&ProposePresentationParams{})) 747 748 select { 749 case <-done: 750 return 751 case <-time.After(time.Second): 752 t.Error("timeout") 753 } 754 }) 755 756 t.Run("Receive Invitation Presentation (continue with proposal) v3", func(t *testing.T) { 757 store, messenger, provider := initMocks(ctrl) 758 759 done := make(chan struct{}) 760 761 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 762 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 763 defer close(done) 764 765 r := &ProposePresentationV3{} 766 require.NoError(t, msg.Decode(r)) 767 require.Equal(t, ProposePresentationMsgTypeV3, r.Type) 768 769 return nil 770 }) 771 772 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 773 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 774 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 775 src, err := json.Marshal(&internalData{StateName: "request-received", ProtocolVersion: version3}) 776 require.NoError(t, err) 777 require.Equal(t, string(src), string(data)) 778 779 return nil 780 }) 781 store.EXPECT().Delete(gomock.Any()).Return(nil) 782 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 783 src, err := json.Marshal(&internalData{StateName: "proposal-sent", ProtocolVersion: version3}) 784 require.NoError(t, err) 785 require.Equal(t, string(src), string(data)) 786 787 return nil 788 }) 789 790 svc, err := New(provider) 791 require.NoError(t, err) 792 793 ch := make(chan service.DIDCommAction, 1) 794 require.NoError(t, svc.RegisterActionEvent(ch)) 795 796 _, err = svc.HandleInbound( 797 randomInboundMessageV3(RequestPresentationMsgTypeV3), service.NewDIDCommContext(Alice, Bob, nil)) 798 require.NoError(t, err) 799 800 action := <-ch 801 802 properties, ok := action.Properties.(*eventProps) 803 require.True(t, ok) 804 require.NotEmpty(t, properties.PIID()) 805 require.Equal(t, properties.MyDID(), Alice) 806 require.Equal(t, properties.TheirDID(), Bob) 807 808 action.Continue(WithProposePresentation(&ProposePresentationParams{})) 809 810 select { 811 case <-done: 812 return 813 case <-time.After(time.Second): 814 t.Error("timeout") 815 } 816 }) 817 818 t.Run("Receive Propose Presentation (continue)", func(t *testing.T) { 819 store, messenger, provider := initMocks(ctrl) 820 821 done := make(chan struct{}) 822 823 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 824 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 825 defer close(done) 826 827 r := &RequestPresentationV2{} 828 require.NoError(t, msg.Decode(r)) 829 require.Equal(t, RequestPresentationMsgTypeV2, r.Type) 830 831 return nil 832 }) 833 834 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 835 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 836 store.EXPECT().Delete(gomock.Any()).Return(nil) 837 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 838 src, err := json.Marshal(&internalData{StateName: "proposal-received", ProtocolVersion: version2}) 839 require.NoError(t, err) 840 require.Equal(t, string(src), string(data)) 841 842 return nil 843 }) 844 845 store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 846 src, err := json.Marshal(&internalData{StateName: "request-sent", ProtocolVersion: version2}) 847 require.NoError(t, err) 848 require.Equal(t, string(src), string(data)) 849 850 return nil 851 }) 852 853 svc, err := New(provider) 854 require.NoError(t, err) 855 856 ch := make(chan service.DIDCommAction, 1) 857 require.NoError(t, svc.RegisterActionEvent(ch)) 858 859 _, err = svc.HandleInbound( 860 randomInboundMessage(ProposePresentationMsgTypeV2), 861 service.NewDIDCommContext(Alice, Bob, nil)) 862 require.NoError(t, err) 863 864 action := <-ch 865 866 properties, ok := action.Properties.(*eventProps) 867 require.True(t, ok) 868 require.NotEmpty(t, properties.PIID()) 869 require.Equal(t, properties.MyDID(), Alice) 870 require.Equal(t, properties.TheirDID(), Bob) 871 872 action.Continue(WithRequestPresentation(&RequestPresentationParams{})) 873 874 select { 875 case <-done: 876 return 877 case <-time.After(time.Second): 878 t.Error("timeout") 879 } 880 }) 881 882 t.Run("Receive Propose Presentation (continue) v3", func(t *testing.T) { 883 store, messenger, provider := initMocks(ctrl) 884 885 done := make(chan struct{}) 886 887 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 888 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 889 defer close(done) 890 891 r := &RequestPresentationV3{} 892 require.NoError(t, msg.Decode(r)) 893 require.Equal(t, RequestPresentationMsgTypeV3, r.Type) 894 895 return nil 896 }) 897 898 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 899 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 900 store.EXPECT().Delete(gomock.Any()).Return(nil) 901 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 902 src, err := json.Marshal(&internalData{StateName: "proposal-received", ProtocolVersion: version3}) 903 require.NoError(t, err) 904 require.Equal(t, string(src), string(data)) 905 906 return nil 907 }) 908 909 store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 910 src, err := json.Marshal(&internalData{StateName: "request-sent", ProtocolVersion: version3}) 911 require.NoError(t, err) 912 require.Equal(t, string(src), string(data)) 913 914 return nil 915 }) 916 917 svc, err := New(provider) 918 require.NoError(t, err) 919 920 ch := make(chan service.DIDCommAction, 1) 921 require.NoError(t, svc.RegisterActionEvent(ch)) 922 923 _, err = svc.HandleInbound( 924 randomInboundMessageV3(ProposePresentationMsgTypeV3), 925 service.NewDIDCommContext(Alice, Bob, nil)) 926 require.NoError(t, err) 927 928 action := <-ch 929 930 properties, ok := action.Properties.(*eventProps) 931 require.True(t, ok) 932 require.NotEmpty(t, properties.PIID()) 933 require.Equal(t, properties.MyDID(), Alice) 934 require.Equal(t, properties.TheirDID(), Bob) 935 936 action.Continue(WithRequestPresentation(&RequestPresentationParams{})) 937 938 select { 939 case <-done: 940 return 941 case <-time.After(time.Second): 942 t.Error("timeout") 943 } 944 }) 945 946 t.Run("Receive Problem Report (continue)", func(t *testing.T) { 947 store, _, provider := initMocks(ctrl) 948 949 done := make(chan struct{}) 950 951 src, err := json.Marshal(&internalData{StateName: "request-sent", ProtocolVersion: version2}) 952 require.NoError(t, err) 953 954 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 955 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 956 store.EXPECT().Delete(gomock.Any()).Return(nil) 957 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 958 defer close(done) 959 960 src, err = json.Marshal(&internalData{StateName: "abandoned", ProtocolVersion: version2}) 961 require.NoError(t, err) 962 require.Equal(t, string(src), string(data)) 963 964 return nil 965 }) 966 967 svc, err := New(provider) 968 require.NoError(t, err) 969 970 ch := make(chan service.DIDCommAction, 1) 971 require.NoError(t, svc.RegisterActionEvent(ch)) 972 973 _, err = svc.HandleInbound(randomInboundMessage(ProblemReportMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil)) 974 require.NoError(t, err) 975 976 action := <-ch 977 978 properties, ok := action.Properties.(*eventProps) 979 require.True(t, ok) 980 require.NotEmpty(t, properties.PIID()) 981 require.Equal(t, properties.MyDID(), Alice) 982 require.Equal(t, properties.TheirDID(), Bob) 983 984 action.Continue(WithRequestPresentation(&RequestPresentationParams{})) 985 986 select { 987 case <-done: 988 return 989 case <-time.After(time.Second): 990 t.Error("timeout") 991 } 992 }) 993 994 t.Run("Receive Problem Report (stop)", func(t *testing.T) { 995 store, _, provider := initMocks(ctrl) 996 997 done := make(chan struct{}) 998 999 src, err := json.Marshal(&internalData{StateName: "request-sent"}) 1000 require.NoError(t, err) 1001 1002 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1003 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 1004 store.EXPECT().Delete(gomock.Any()).Return(nil) 1005 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1006 defer close(done) 1007 1008 src, err = json.Marshal(&internalData{StateName: "abandoned"}) 1009 require.NoError(t, err) 1010 require.Equal(t, src, data) 1011 1012 return nil 1013 }) 1014 1015 svc, err := New(provider) 1016 require.NoError(t, err) 1017 1018 ch := make(chan service.DIDCommAction, 1) 1019 require.NoError(t, svc.RegisterActionEvent(ch)) 1020 1021 _, err = svc.HandleInbound(randomInboundMessage(ProblemReportMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil)) 1022 require.NoError(t, err) 1023 1024 action := <-ch 1025 1026 properties, ok := action.Properties.(*eventProps) 1027 require.True(t, ok) 1028 require.NotEmpty(t, properties.PIID()) 1029 require.Equal(t, properties.MyDID(), Alice) 1030 require.Equal(t, properties.TheirDID(), Bob) 1031 1032 action.Stop(nil) 1033 1034 select { 1035 case <-done: 1036 return 1037 case <-time.After(time.Second): 1038 t.Error("timeout") 1039 } 1040 }) 1041 1042 t.Run("Receive Propose Presentation (continue without request)", func(t *testing.T) { 1043 store, messenger, provider := initMocks(ctrl) 1044 1045 done := make(chan struct{}) 1046 1047 messenger.EXPECT(). 1048 ReplyToNested(gomock.Any(), gomock.Any()). 1049 Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error { 1050 defer close(done) 1051 1052 r := &model.ProblemReport{} 1053 require.NoError(t, msg.Decode(r)) 1054 require.Equal(t, codeInternalError, r.Description.Code) 1055 require.Equal(t, ProblemReportMsgTypeV2, r.Type) 1056 1057 return nil 1058 }) 1059 1060 store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes() 1061 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 1062 store.EXPECT().Delete(gomock.Any()).Return(nil) 1063 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1064 src, err := json.Marshal(&internalData{StateName: "proposal-received", ProtocolVersion: version2}) 1065 require.NoError(t, err) 1066 require.Equal(t, string(src), string(data)) 1067 1068 return nil 1069 }) 1070 1071 store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1072 src, err := json.Marshal(&internalData{StateName: "abandoned", ProtocolVersion: version2}) 1073 require.NoError(t, err) 1074 require.Equal(t, string(src), string(data)) 1075 1076 return nil 1077 }) 1078 1079 svc, err := New(provider) 1080 require.NoError(t, err) 1081 1082 ch := make(chan service.DIDCommAction, 1) 1083 require.NoError(t, svc.RegisterActionEvent(ch)) 1084 1085 _, err = svc.HandleInbound( 1086 randomInboundMessage(ProposePresentationMsgTypeV2), 1087 service.NewDIDCommContext(Alice, Bob, nil)) 1088 require.NoError(t, err) 1089 1090 action := <-ch 1091 1092 properties, ok := action.Properties.(*eventProps) 1093 require.True(t, ok) 1094 require.NotEmpty(t, properties.PIID()) 1095 require.Equal(t, properties.MyDID(), Alice) 1096 require.Equal(t, properties.TheirDID(), Bob) 1097 1098 action.Continue(nil) 1099 1100 select { 1101 case <-done: 1102 return 1103 case <-time.After(time.Second): 1104 t.Error("timeout") 1105 } 1106 }) 1107 1108 t.Run("Receive Presentation (continue)", func(t *testing.T) { 1109 store, messenger, provider := initMocks(ctrl) 1110 1111 done := make(chan struct{}) 1112 1113 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 1114 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 1115 r := &model.Ack{} 1116 require.NoError(t, msg.Decode(r)) 1117 require.Equal(t, AckMsgTypeV2, r.Type) 1118 1119 return nil 1120 }) 1121 1122 src, err := json.Marshal(&internalData{AckRequired: true, StateName: "request-sent"}) 1123 require.NoError(t, err) 1124 1125 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1126 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 1127 store.EXPECT().Delete(gomock.Any()).Return(nil) 1128 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1129 src, err = json.Marshal(&internalData{AckRequired: true, StateName: "presentation-received"}) 1130 require.NoError(t, err) 1131 require.Equal(t, src, data) 1132 1133 return nil 1134 }) 1135 1136 store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1137 defer close(done) 1138 1139 src, err = json.Marshal(&internalData{AckRequired: true, StateName: "done"}) 1140 require.NoError(t, err) 1141 require.Equal(t, src, data) 1142 1143 return nil 1144 }) 1145 1146 svc, err := New(provider) 1147 require.NoError(t, err) 1148 1149 ch := make(chan service.DIDCommAction, 1) 1150 require.NoError(t, svc.RegisterActionEvent(ch)) 1151 1152 msg := service.NewDIDCommMsgMap(PresentationV2{ 1153 Type: PresentationMsgTypeV2, 1154 PresentationsAttach: []decorator.Attachment{{ 1155 Data: decorator.AttachmentData{ 1156 Base64: base64.StdEncoding.EncodeToString([]byte(`{}`)), 1157 }, 1158 }}, 1159 }) 1160 msg.SetID(uuid.New().String()) 1161 1162 msg["~thread"] = decorator.Thread{ID: uuid.New().String()} 1163 1164 _, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil)) 1165 require.NoError(t, err) 1166 1167 action := <-ch 1168 1169 properties, ok := action.Properties.(*eventProps) 1170 require.True(t, ok) 1171 require.NotEmpty(t, properties.PIID()) 1172 require.Equal(t, properties.MyDID(), Alice) 1173 require.Equal(t, properties.TheirDID(), Bob) 1174 1175 action.Continue(nil) 1176 1177 select { 1178 case <-done: 1179 return 1180 case <-time.After(time.Second * 10): 1181 t.Error("timeout") 1182 } 1183 }) 1184 1185 t.Run("Receive Presentation (continue) v3", func(t *testing.T) { 1186 store, messenger, provider := initMocks(ctrl) 1187 1188 done := make(chan struct{}) 1189 1190 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 1191 Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error { 1192 r := &model.AckV2{} 1193 require.NoError(t, msg.Decode(r)) 1194 require.Equal(t, AckMsgTypeV3, r.Type) 1195 1196 return nil 1197 }) 1198 1199 src, err := json.Marshal(&internalData{AckRequired: true, StateName: "request-sent"}) 1200 require.NoError(t, err) 1201 1202 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1203 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 1204 store.EXPECT().Delete(gomock.Any()).Return(nil) 1205 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1206 src, err = json.Marshal(&internalData{AckRequired: true, StateName: "presentation-received"}) 1207 require.NoError(t, err) 1208 require.Equal(t, src, data) 1209 1210 return nil 1211 }) 1212 1213 store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1214 defer close(done) 1215 1216 src, err = json.Marshal(&internalData{AckRequired: true, StateName: "done"}) 1217 require.NoError(t, err) 1218 require.Equal(t, src, data) 1219 1220 return nil 1221 }) 1222 1223 svc, err := New(provider) 1224 require.NoError(t, err) 1225 1226 ch := make(chan service.DIDCommAction, 1) 1227 require.NoError(t, svc.RegisterActionEvent(ch)) 1228 1229 msg := service.NewDIDCommMsgMap(PresentationV3{ 1230 Type: PresentationMsgTypeV3, 1231 Attachments: []decorator.AttachmentV2{{ 1232 Data: decorator.AttachmentData{ 1233 Base64: base64.StdEncoding.EncodeToString([]byte(`{}`)), 1234 }, 1235 }}, 1236 }) 1237 msg.SetID(uuid.New().String()) 1238 msg.SetThread(uuid.New().String(), "", service.WithVersion(service.V2)) 1239 1240 _, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil)) 1241 require.NoError(t, err) 1242 1243 action := <-ch 1244 1245 properties, ok := action.Properties.(*eventProps) 1246 require.True(t, ok) 1247 require.NotEmpty(t, properties.PIID()) 1248 require.Equal(t, properties.MyDID(), Alice) 1249 require.Equal(t, properties.TheirDID(), Bob) 1250 1251 action.Continue(nil) 1252 1253 select { 1254 case <-done: 1255 return 1256 case <-time.After(time.Second * 10): 1257 t.Error("timeout") 1258 } 1259 }) 1260 1261 t.Run("Receive Ack", func(t *testing.T) { 1262 store, _, provider := initMocks(ctrl) 1263 1264 done := make(chan struct{}) 1265 1266 src, err := json.Marshal(&internalData{StateName: "presentation-sent"}) 1267 require.NoError(t, err) 1268 1269 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1270 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1271 defer close(done) 1272 1273 src, err = json.Marshal(&internalData{StateName: "done"}) 1274 require.NoError(t, err) 1275 require.Equal(t, src, data) 1276 1277 return nil 1278 }) 1279 1280 svc, err := New(provider) 1281 require.NoError(t, err) 1282 1283 ch := make(chan service.DIDCommAction, 1) 1284 require.NoError(t, svc.RegisterActionEvent(ch)) 1285 1286 _, err = svc.HandleInbound(randomInboundMessage(AckMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil)) 1287 require.NoError(t, err) 1288 1289 select { 1290 case <-done: 1291 return 1292 case <-time.After(time.Second): 1293 t.Error("timeout") 1294 } 1295 }) 1296 1297 t.Run("Send Invitation Presentation", func(t *testing.T) { 1298 store, messenger, provider := initMocks(ctrl) 1299 1300 done := make(chan struct{}) 1301 1302 src, err := json.Marshal(&internalData{StateName: "proposal-received"}) 1303 require.NoError(t, err) 1304 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1305 1306 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1307 src, e := json.Marshal(&internalData{StateName: "request-sent"}) 1308 require.NoError(t, e) 1309 require.Equal(t, src, data) 1310 1311 return nil 1312 }) 1313 1314 svc, err := New(provider) 1315 require.NoError(t, err) 1316 1317 msg := service.NewDIDCommMsgMap(RequestPresentationV2{ 1318 Type: RequestPresentationMsgTypeV2, 1319 }) 1320 1321 messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()). 1322 Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error { 1323 require.NotEmpty(t, msg.ID()) 1324 require.Equal(t, RequestPresentationMsgTypeV2, msg.Type()) 1325 1326 defer close(done) 1327 1328 return nil 1329 }) 1330 1331 _, err = svc.HandleOutbound(msg, Alice, Bob) 1332 require.NoError(t, err) 1333 1334 select { 1335 case <-done: 1336 return 1337 case <-time.After(time.Second): 1338 t.Error("timeout") 1339 } 1340 }) 1341 1342 t.Run("Send Invitation Presentation with error", func(t *testing.T) { 1343 store, messenger, provider := initMocks(ctrl) 1344 1345 src, err := json.Marshal(&internalData{StateName: "proposal-received"}) 1346 require.NoError(t, err) 1347 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1348 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 1349 1350 svc, err := New(provider) 1351 require.NoError(t, err) 1352 1353 msg := service.NewDIDCommMsgMap(RequestPresentationV2{ 1354 Type: RequestPresentationMsgTypeV2, 1355 }) 1356 1357 messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()).Return(errors.New(errMsg)) 1358 1359 _, err = svc.HandleOutbound(msg, Alice, Bob) 1360 require.Contains(t, fmt.Sprintf("%v", err), "action request-sent: "+errMsg) 1361 }) 1362 1363 t.Run("Send Proposal", func(t *testing.T) { 1364 store, messenger, provider := initMocks(ctrl) 1365 1366 done := make(chan struct{}) 1367 1368 src, err := json.Marshal(&internalData{StateName: "request-received"}) 1369 require.NoError(t, err) 1370 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1371 store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error { 1372 s, e := json.Marshal(&internalData{StateName: "proposal-sent"}) 1373 require.NoError(t, e) 1374 require.Equal(t, s, data) 1375 1376 return nil 1377 }) 1378 1379 svc, err := New(provider) 1380 require.NoError(t, err) 1381 1382 msg := service.NewDIDCommMsgMap(ProposePresentationV2{ 1383 Type: ProposePresentationMsgTypeV2, 1384 }) 1385 1386 messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()). 1387 Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error { 1388 defer close(done) 1389 1390 require.NotEmpty(t, msg.ID()) 1391 require.Equal(t, ProposePresentationMsgTypeV2, msg.Type()) 1392 1393 return nil 1394 }) 1395 1396 _, err = svc.HandleOutbound(msg, Alice, Bob) 1397 require.NoError(t, err) 1398 1399 select { 1400 case <-done: 1401 return 1402 case <-time.After(time.Second): 1403 t.Error("timeout") 1404 } 1405 }) 1406 1407 t.Run("Send Proposal with error", func(t *testing.T) { 1408 store, messenger, provider := initMocks(ctrl) 1409 1410 src, err := json.Marshal(&internalData{StateName: "request-received"}) 1411 require.NoError(t, err) 1412 store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes() 1413 store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil) 1414 1415 svc, err := New(provider) 1416 require.NoError(t, err) 1417 1418 msg := service.NewDIDCommMsgMap(ProposePresentationV2{ 1419 Type: ProposePresentationMsgTypeV2, 1420 }) 1421 1422 messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()).Return(errors.New(errMsg)) 1423 1424 _, err = svc.HandleOutbound(msg, Alice, Bob) 1425 require.Contains(t, fmt.Sprintf("%v", err), "action proposal-sent: "+errMsg) 1426 }) 1427 } 1428 1429 func Test_stateFromName(t *testing.T) { 1430 require.Equal(t, stateFromName(stateNameStart, SpecV2), &start{}) 1431 require.Equal(t, stateFromName(StateNameAbandoned, SpecV2), &abandoned{V: SpecV2}) 1432 require.Equal(t, stateFromName(StateNameDone, SpecV2), &done{V: SpecV2}) 1433 require.Equal(t, stateFromName(stateNameRequestSent, SpecV2), &requestSent{V: SpecV2}) 1434 require.Equal(t, stateFromName(stateNamePresentationReceived, SpecV2), &presentationReceived{V: SpecV2}) 1435 require.Equal(t, stateFromName(stateNameProposalReceived, SpecV2), &proposalReceived{V: SpecV2}) 1436 require.Equal(t, stateFromName(stateNameRequestReceived, SpecV2), &requestReceived{V: SpecV2}) 1437 require.Equal(t, stateFromName(stateNamePresentationSent, SpecV2), &presentationSent{V: SpecV2}) 1438 require.Equal(t, stateFromName(stateNameProposalSent, SpecV2), &proposalSent{V: SpecV2}) 1439 require.Equal(t, stateFromName("unknown", SpecV2), &noOp{}) 1440 } 1441 1442 func TestService_Name(t *testing.T) { 1443 require.Equal(t, (*Service).Name(nil), Name) 1444 } 1445 1446 func TestService_Accept(t *testing.T) { 1447 require.True(t, (*Service).Accept(nil, ProposePresentationMsgTypeV2)) 1448 require.True(t, (*Service).Accept(nil, RequestPresentationMsgTypeV2)) 1449 require.True(t, (*Service).Accept(nil, PresentationMsgTypeV2)) 1450 require.True(t, (*Service).Accept(nil, AckMsgTypeV2)) 1451 require.True(t, (*Service).Accept(nil, ProblemReportMsgTypeV2)) 1452 require.False(t, (*Service).Accept(nil, "unknown")) 1453 } 1454 1455 func TestService_canTriggerActionEvents(t *testing.T) { 1456 require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(ProposePresentationV2{ 1457 Type: ProposePresentationMsgTypeV2, 1458 }))) 1459 1460 require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(RequestPresentationV2{ 1461 Type: RequestPresentationMsgTypeV2, 1462 }))) 1463 1464 require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(PresentationV2{ 1465 Type: PresentationMsgTypeV2, 1466 }))) 1467 1468 require.False(t, canTriggerActionEvents(service.NewDIDCommMsgMap(struct{}{}))) 1469 } 1470 1471 func Test_getTransitionalPayload(t *testing.T) { 1472 ctrl := gomock.NewController(t) 1473 defer ctrl.Finish() 1474 1475 store := storageMocks.NewMockStore(ctrl) 1476 1477 storeProvider := storageMocks.NewMockProvider(ctrl) 1478 storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes() 1479 storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil) 1480 1481 provider := presentproofMocks.NewMockProvider(ctrl) 1482 provider.EXPECT().Messenger().Return(nil).AnyTimes() 1483 provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes() 1484 1485 store.EXPECT().Get(fmt.Sprintf(transitionalPayloadKey, "ID")).Return([]byte(`[]`), nil) 1486 1487 svc, err := New(provider) 1488 require.NoError(t, err) 1489 1490 res, err := svc.getTransitionalPayload("ID") 1491 require.Nil(t, res) 1492 require.Contains(t, fmt.Sprintf("%v", err), "unmarshal transitional payload") 1493 } 1494 1495 func Test_nextState(t *testing.T) { 1496 next, err := nextState(service.NewDIDCommMsgMap(RequestPresentationV2{ 1497 Type: RequestPresentationMsgTypeV2, 1498 }), outboundMessage) 1499 require.NoError(t, err) 1500 require.Equal(t, next, &requestSent{V: SpecV2}) 1501 1502 next, err = nextState(randomInboundMessage(RequestPresentationMsgTypeV2), inboundMessage) 1503 require.NoError(t, err) 1504 require.Equal(t, next, &requestReceived{V: SpecV2}) 1505 1506 next, err = nextState(service.NewDIDCommMsgMap(ProposePresentationV2{ 1507 Type: ProposePresentationMsgTypeV2, 1508 }), outboundMessage) 1509 require.NoError(t, err) 1510 require.Equal(t, next, &proposalSent{V: SpecV2}) 1511 1512 next, err = nextState(randomInboundMessage(ProposePresentationMsgTypeV2), inboundMessage) 1513 require.NoError(t, err) 1514 require.Equal(t, next, &proposalReceived{V: SpecV2}) 1515 1516 next, err = nextState(randomInboundMessage(PresentationMsgTypeV2), inboundMessage) 1517 require.NoError(t, err) 1518 require.Equal(t, next, &presentationReceived{V: SpecV2}) 1519 1520 next, err = nextState(randomInboundMessage(AckMsgTypeV2), inboundMessage) 1521 require.NoError(t, err) 1522 require.Equal(t, next, &done{V: SpecV2, properties: map[string]interface{}{}}) 1523 1524 next, err = nextState(randomInboundMessage(ProblemReportMsgTypeV2), inboundMessage) 1525 require.NoError(t, err) 1526 require.Equal(t, next, &abandoned{V: SpecV2, properties: map[string]interface{}{}}) 1527 1528 next, err = nextState(service.NewDIDCommMsgMap(struct{}{}), outboundMessage) 1529 require.Error(t, err) 1530 require.Nil(t, next) 1531 }