github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/issuecredential/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 issuecredential
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/golang/mock/gomock"
    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/decorator"
    23  	"github.com/hyperledger/aries-framework-go/pkg/doc/util"
    24  	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
    25  	serviceMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/common/service"
    26  	issuecredentialMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/protocol/issuecredential"
    27  	storageMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/spi/storage"
    28  	"github.com/hyperledger/aries-framework-go/spi/storage"
    29  )
    30  
    31  const (
    32  	Alice = "Alice"
    33  	Bob   = "Bob"
    34  )
    35  
    36  func TestService_UseV2(t *testing.T) {
    37  	ctrl := gomock.NewController(t)
    38  	defer ctrl.Finish()
    39  
    40  	t.Run("Success (one function)", func(t *testing.T) {
    41  		storeProvider := mem.NewProvider()
    42  
    43  		provider := issuecredentialMocks.NewMockProvider(ctrl)
    44  		provider.EXPECT().Messenger().Return(nil)
    45  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
    46  
    47  		svc, err := New(provider)
    48  		require.NoError(t, err)
    49  		require.NotNil(t, svc)
    50  
    51  		meta := &MetaData{
    52  			state: &done{},
    53  			msgClone: service.NewDIDCommMsgMap(struct {
    54  				Type string `json:"@type"`
    55  			}{
    56  				Type: IssueCredentialMsgTypeV2,
    57  			}),
    58  			offerCredentialV2:   &OfferCredentialV2{Type: OfferCredentialMsgTypeV2},
    59  			proposeCredentialV2: &ProposeCredentialV2{Type: ProposeCredentialMsgTypeV2},
    60  			issueCredentialV2:   &IssueCredentialV2{Type: IssueCredentialMsgTypeV2},
    61  			requestCredentialV2: &RequestCredentialV2{Type: RequestCredentialMsgTypeV2},
    62  			credentialNames:     []string{"name"},
    63  		}
    64  		var executed bool
    65  		svc.Use(func(next Handler) Handler {
    66  			return HandlerFunc(func(metadata Metadata) error {
    67  				require.Equal(t, meta.msgClone, metadata.Message())
    68  				require.Equal(t, metadata.Message().Type(), IssueCredentialMsgTypeV2)
    69  				require.Equal(t, meta.offerCredentialV2, metadata.OfferCredentialV2())
    70  				require.Equal(t, meta.proposeCredentialV2, metadata.ProposeCredentialV2())
    71  				require.Equal(t, meta.issueCredentialV2, metadata.IssueCredentialV2())
    72  				require.Equal(t, meta.requestCredentialV2, metadata.RequestCredentialV2())
    73  				require.Equal(t, meta.credentialNames, metadata.CredentialNames())
    74  				require.Equal(t, meta.state.Name(), metadata.StateName())
    75  
    76  				executed = true
    77  				return next.Handle(metadata)
    78  			})
    79  		})
    80  
    81  		_, _, err = svc.execute(meta.state, meta)
    82  		require.EqualError(t, err, "done: ExecuteOutbound is not implemented yet")
    83  
    84  		require.True(t, executed)
    85  	})
    86  
    87  	t.Run("Success (two function)", func(t *testing.T) {
    88  		storeProvider := mem.NewProvider()
    89  
    90  		provider := issuecredentialMocks.NewMockProvider(ctrl)
    91  		provider.EXPECT().Messenger().Return(nil)
    92  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
    93  
    94  		svc, err := New(provider)
    95  		require.NoError(t, err)
    96  		require.NotNil(t, svc)
    97  
    98  		var executed bool
    99  		svc.Use(func(next Handler) Handler {
   100  			return HandlerFunc(func(metadata Metadata) error {
   101  				executed = true
   102  				return next.Handle(metadata)
   103  			})
   104  		}, func(next Handler) Handler {
   105  			return HandlerFunc(func(metadata Metadata) error {
   106  				require.True(t, executed)
   107  				return next.Handle(metadata)
   108  			})
   109  		})
   110  
   111  		_, _, err = svc.execute(&done{}, &MetaData{})
   112  		require.EqualError(t, err, "done: ExecuteOutbound is not implemented yet")
   113  	})
   114  
   115  	t.Run("Failed", func(t *testing.T) {
   116  		storeProvider := mem.NewProvider()
   117  
   118  		provider := issuecredentialMocks.NewMockProvider(ctrl)
   119  		provider.EXPECT().Messenger().Return(nil)
   120  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
   121  
   122  		svc, err := New(provider)
   123  		require.NoError(t, err)
   124  		require.NotNil(t, svc)
   125  
   126  		const msgErr = "error message"
   127  		svc.Use(func(next Handler) Handler {
   128  			return HandlerFunc(func(metadata Metadata) error {
   129  				return errors.New(msgErr)
   130  			})
   131  		})
   132  
   133  		_, _, err = svc.execute(&done{}, &MetaData{})
   134  		require.EqualError(t, err, "middleware: "+msgErr)
   135  	})
   136  }
   137  
   138  func TestService_UseV3(t *testing.T) {
   139  	ctrl := gomock.NewController(t)
   140  	defer ctrl.Finish()
   141  
   142  	t.Run("Success (one function)", func(t *testing.T) {
   143  		storeProvider := mem.NewProvider()
   144  
   145  		provider := issuecredentialMocks.NewMockProvider(ctrl)
   146  		provider.EXPECT().Messenger().Return(nil)
   147  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
   148  
   149  		svc, err := New(provider)
   150  		require.NoError(t, err)
   151  		require.NotNil(t, svc)
   152  
   153  		meta := &MetaData{
   154  			state: &done{},
   155  			msgClone: service.NewDIDCommMsgMap(struct {
   156  				Type string `json:"@type"`
   157  			}{
   158  				Type: IssueCredentialMsgTypeV3,
   159  			}),
   160  			offerCredentialV2:   &OfferCredentialV2{Type: OfferCredentialMsgTypeV3},
   161  			proposeCredentialV2: &ProposeCredentialV2{Type: ProposeCredentialMsgTypeV3},
   162  			issueCredentialV2:   &IssueCredentialV2{Type: IssueCredentialMsgTypeV3},
   163  			requestCredentialV2: &RequestCredentialV2{Type: RequestCredentialMsgTypeV3},
   164  			credentialNames:     []string{"name"},
   165  		}
   166  		var executed bool
   167  		svc.Use(func(next Handler) Handler {
   168  			return HandlerFunc(func(metadata Metadata) error {
   169  				require.Equal(t, meta.msgClone, metadata.Message())
   170  				require.Equal(t, metadata.Message().Type(), IssueCredentialMsgTypeV3)
   171  				require.Equal(t, meta.offerCredentialV2, metadata.OfferCredentialV2())
   172  				require.Equal(t, meta.proposeCredentialV2, metadata.ProposeCredentialV2())
   173  				require.Equal(t, meta.issueCredentialV2, metadata.IssueCredentialV2())
   174  				require.Equal(t, meta.requestCredentialV2, metadata.RequestCredentialV2())
   175  				require.Equal(t, meta.credentialNames, metadata.CredentialNames())
   176  				require.Equal(t, meta.state.Name(), metadata.StateName())
   177  
   178  				executed = true
   179  				return next.Handle(metadata)
   180  			})
   181  		})
   182  
   183  		_, _, err = svc.execute(meta.state, meta)
   184  		require.EqualError(t, err, "done: ExecuteOutbound is not implemented yet")
   185  
   186  		require.True(t, executed)
   187  	})
   188  }
   189  
   190  func TestNew(t *testing.T) {
   191  	ctrl := gomock.NewController(t)
   192  	defer ctrl.Finish()
   193  
   194  	t.Run("Success", func(t *testing.T) {
   195  		storeProvider := mem.NewProvider()
   196  
   197  		provider := issuecredentialMocks.NewMockProvider(ctrl)
   198  		provider.EXPECT().Messenger().Return(nil)
   199  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
   200  
   201  		svc, err := New(provider)
   202  		require.NoError(t, err)
   203  		require.NotNil(t, svc)
   204  	})
   205  
   206  	t.Run("Error open store", func(t *testing.T) {
   207  		const errMsg = "error"
   208  
   209  		storeProvider := storageMocks.NewMockProvider(ctrl)
   210  		storeProvider.EXPECT().OpenStore(Name).Return(nil, errors.New(errMsg))
   211  
   212  		provider := issuecredentialMocks.NewMockProvider(ctrl)
   213  		provider.EXPECT().StorageProvider().Return(storeProvider)
   214  
   215  		svc, err := New(provider)
   216  		require.Contains(t, fmt.Sprintf("%v", err), errMsg)
   217  		require.Nil(t, svc)
   218  	})
   219  }
   220  
   221  func TestService_Initialize(t *testing.T) {
   222  	ctrl := gomock.NewController(t)
   223  	defer ctrl.Finish()
   224  
   225  	t.Run("Success", func(t *testing.T) {
   226  		storeProvider := mem.NewProvider()
   227  
   228  		provider := issuecredentialMocks.NewMockProvider(ctrl)
   229  		provider.EXPECT().Messenger().Return(nil)
   230  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
   231  
   232  		svc := Service{}
   233  
   234  		err := svc.Initialize(provider)
   235  		require.NoError(t, err)
   236  
   237  		// second init is no-op
   238  		err = svc.Initialize(provider)
   239  		require.NoError(t, err)
   240  	})
   241  
   242  	t.Run("failure, not given a valid provider", func(t *testing.T) {
   243  		svc := Service{}
   244  
   245  		err := svc.Initialize("not a provider")
   246  		require.Error(t, err)
   247  		require.Contains(t, err.Error(), "expected provider of type")
   248  	})
   249  }
   250  
   251  // nolint: gocyclo,gocognit
   252  func TestService_HandleInboundV2(t *testing.T) {
   253  	ctrl := gomock.NewController(t)
   254  	defer ctrl.Finish()
   255  
   256  	const errMsg = "error"
   257  
   258  	store := storageMocks.NewMockStore(ctrl)
   259  
   260  	storeProvider := storageMocks.NewMockProvider(ctrl)
   261  	storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
   262  	storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
   263  
   264  	messenger := serviceMocks.NewMockMessenger(ctrl)
   265  
   266  	provider := issuecredentialMocks.NewMockProvider(ctrl)
   267  	provider.EXPECT().Messenger().Return(messenger).AnyTimes()
   268  	provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
   269  
   270  	t.Run("No clients", func(t *testing.T) {
   271  		svc, err := New(provider)
   272  		require.NoError(t, err)
   273  
   274  		_, err = svc.HandleInbound(nil, service.EmptyDIDCommContext())
   275  		require.Contains(t, fmt.Sprintf("%v", err), "no clients")
   276  	})
   277  
   278  	t.Run("DB error", func(t *testing.T) {
   279  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
   280  
   281  		svc, err := New(provider)
   282  		require.NoError(t, err)
   283  
   284  		require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction)))
   285  
   286  		msg := service.NewDIDCommMsgMap(struct{}{})
   287  		msg.SetID(uuid.New().String())
   288  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
   289  		require.Contains(t, fmt.Sprintf("%v", err), "doHandle: getCurrentStateNameAndPIID: currentStateName: "+errMsg)
   290  	})
   291  
   292  	t.Run("DB error (saveTransitionalPayload)", func(t *testing.T) {
   293  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   294  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New(errMsg))
   295  
   296  		svc, err := New(provider)
   297  		require.NoError(t, err)
   298  
   299  		require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction)))
   300  
   301  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
   302  			Type: ProposeCredentialMsgTypeV2,
   303  		})
   304  		msg.SetID(uuid.New().String())
   305  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
   306  		require.Contains(t, fmt.Sprintf("%v", err), "save transitional payload: "+errMsg)
   307  	})
   308  
   309  	t.Run("Unrecognized msgType", func(t *testing.T) {
   310  		svc, err := New(provider)
   311  		require.NoError(t, err)
   312  
   313  		require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction)))
   314  
   315  		_, err = svc.HandleInbound(service.NewDIDCommMsgMap(struct{}{}), service.EmptyDIDCommContext())
   316  		require.Contains(t, fmt.Sprintf("%v", err), "doHandle: nextState: unrecognized msgType: ")
   317  	})
   318  
   319  	t.Run("Receive Propose Credential Stop", func(t *testing.T) {
   320  		done := make(chan struct{})
   321  
   322  		messenger.EXPECT().
   323  			ReplyToNested(gomock.Any(), gomock.Any()).
   324  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   325  				defer close(done)
   326  
   327  				r := &model.ProblemReport{}
   328  				require.NoError(t, msg.Decode(r))
   329  				require.Equal(t, codeRejectedError, r.Description.Code)
   330  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
   331  
   332  				return nil
   333  			})
   334  
   335  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   336  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   337  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   338  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   339  			require.Equal(t, "done", string(name))
   340  
   341  			return nil
   342  		})
   343  
   344  		svc, err := New(provider)
   345  		require.NoError(t, err)
   346  
   347  		ch := make(chan service.DIDCommAction, 1)
   348  		require.NoError(t, svc.RegisterActionEvent(ch))
   349  
   350  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
   351  			Type: ProposeCredentialMsgTypeV2,
   352  		})
   353  
   354  		msg.SetID(uuid.New().String())
   355  
   356  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   357  		require.NoError(t, err)
   358  
   359  		action := <-ch
   360  
   361  		properties, ok := action.Properties.(*eventProps)
   362  		require.True(t, ok)
   363  		require.NotEmpty(t, properties.PIID())
   364  		require.Equal(t, properties.MyDID(), Alice)
   365  		require.Equal(t, properties.TheirDID(), Bob)
   366  		require.Equal(t, properties.All()["myDID"], Alice)
   367  		require.Equal(t, properties.All()["theirDID"], Bob)
   368  
   369  		action.Stop(nil)
   370  
   371  		select {
   372  		case <-done:
   373  			return
   374  		case <-time.After(time.Second):
   375  			t.Error("timeout")
   376  		}
   377  	})
   378  
   379  	t.Run("Receive Propose Credential Continue", func(t *testing.T) {
   380  		done := make(chan struct{})
   381  
   382  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   383  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   384  				defer close(done)
   385  
   386  				r := &OfferCredentialV2{}
   387  				require.NoError(t, msg.Decode(r))
   388  				require.Equal(t, OfferCredentialMsgTypeV2, r.Type)
   389  
   390  				return nil
   391  			})
   392  
   393  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   394  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   395  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   396  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   397  			require.Equal(t, "offer-sent", string(name))
   398  
   399  			return nil
   400  		})
   401  
   402  		svc, err := New(provider)
   403  		require.NoError(t, err)
   404  
   405  		ch := make(chan service.DIDCommAction, 1)
   406  		require.NoError(t, svc.RegisterActionEvent(ch))
   407  
   408  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
   409  			Type: ProposeCredentialMsgTypeV2,
   410  		})
   411  
   412  		msg.SetID(uuid.New().String())
   413  
   414  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   415  		require.NoError(t, err)
   416  
   417  		action := <-ch
   418  
   419  		properties, ok := action.Properties.(*eventProps)
   420  		require.True(t, ok)
   421  		require.NotEmpty(t, properties.PIID())
   422  		require.Equal(t, properties.MyDID(), Alice)
   423  		require.Equal(t, properties.TheirDID(), Bob)
   424  
   425  		action.Continue(WithOfferCredential(&OfferCredentialParams{}))
   426  
   427  		select {
   428  		case <-done:
   429  			return
   430  		case <-time.After(time.Second):
   431  			t.Error("timeout")
   432  		}
   433  	})
   434  
   435  	t.Run("Receive Propose Credential Continue (async)", func(t *testing.T) {
   436  		done := make(chan struct{})
   437  
   438  		newProvider := issuecredentialMocks.NewMockProvider(ctrl)
   439  		newProvider.EXPECT().Messenger().Return(messenger).AnyTimes()
   440  		newProvider.EXPECT().StorageProvider().Return(mem.NewProvider()).AnyTimes()
   441  
   442  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   443  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   444  				defer close(done)
   445  
   446  				r := &OfferCredentialV2{}
   447  				require.NoError(t, msg.Decode(r))
   448  				require.Equal(t, OfferCredentialMsgTypeV2, r.Type)
   449  
   450  				return nil
   451  			})
   452  
   453  		svc, err := New(newProvider)
   454  		require.NoError(t, err)
   455  
   456  		ch := make(chan service.DIDCommAction, 1)
   457  		require.NoError(t, svc.RegisterActionEvent(ch))
   458  
   459  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
   460  			Type: ProposeCredentialMsgTypeV2,
   461  		})
   462  
   463  		msg.SetID(uuid.New().String())
   464  
   465  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   466  		require.NoError(t, err)
   467  
   468  		actions, err := svc.Actions()
   469  		require.NoError(t, err)
   470  		for _, action := range actions {
   471  			require.Equal(t, action.MyDID, Alice)
   472  			require.Equal(t, action.TheirDID, Bob)
   473  			require.NoError(t, svc.ActionContinue(action.PIID, WithOfferCredential(&OfferCredentialParams{})))
   474  		}
   475  
   476  		select {
   477  		case <-done:
   478  			return
   479  		case <-time.After(time.Second):
   480  			t.Error("timeout")
   481  		}
   482  	})
   483  
   484  	t.Run("Receive Propose Credential Stop (async)", func(t *testing.T) {
   485  		done := make(chan struct{})
   486  
   487  		newProvider := issuecredentialMocks.NewMockProvider(ctrl)
   488  		newProvider.EXPECT().Messenger().Return(messenger).AnyTimes()
   489  		newProvider.EXPECT().StorageProvider().Return(mem.NewProvider()).AnyTimes()
   490  
   491  		messenger.EXPECT().
   492  			ReplyToNested(gomock.Any(), gomock.Any()).
   493  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   494  				defer close(done)
   495  
   496  				r := &model.ProblemReport{}
   497  				require.NoError(t, msg.Decode(r))
   498  				require.Equal(t, codeRejectedError, r.Description.Code)
   499  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
   500  
   501  				return nil
   502  			})
   503  
   504  		svc, err := New(newProvider)
   505  		require.NoError(t, err)
   506  
   507  		ch := make(chan service.DIDCommAction, 1)
   508  		require.NoError(t, svc.RegisterActionEvent(ch))
   509  
   510  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
   511  			Type: ProposeCredentialMsgTypeV2,
   512  		})
   513  
   514  		msg.SetID(uuid.New().String())
   515  
   516  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   517  		require.NoError(t, err)
   518  
   519  		actions, err := svc.Actions()
   520  		require.NoError(t, err)
   521  		for _, action := range actions {
   522  			require.Equal(t, action.MyDID, Alice)
   523  			require.Equal(t, action.TheirDID, Bob)
   524  			require.NoError(t, svc.ActionStop(action.PIID, nil))
   525  		}
   526  
   527  		select {
   528  		case <-done:
   529  			return
   530  		case <-time.After(time.Second):
   531  			t.Error("timeout")
   532  		}
   533  	})
   534  
   535  	t.Run("Receive Offer Credential Stop", func(t *testing.T) {
   536  		done := make(chan struct{})
   537  
   538  		messenger.EXPECT().
   539  			ReplyToNested(gomock.Any(), gomock.Any()).
   540  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   541  				defer close(done)
   542  
   543  				r := &model.ProblemReport{}
   544  				require.NoError(t, msg.Decode(r))
   545  				require.Equal(t, codeRejectedError, r.Description.Code)
   546  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
   547  
   548  				return nil
   549  			})
   550  
   551  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   552  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   553  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   554  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   555  			require.Equal(t, "done", string(name))
   556  
   557  			return nil
   558  		})
   559  
   560  		svc, err := New(provider)
   561  		require.NoError(t, err)
   562  
   563  		ch := make(chan service.DIDCommAction, 1)
   564  		require.NoError(t, svc.RegisterActionEvent(ch))
   565  
   566  		msg := service.NewDIDCommMsgMap(OfferCredentialV2{
   567  			Type: OfferCredentialMsgTypeV2,
   568  		})
   569  
   570  		msg.SetID(uuid.New().String())
   571  
   572  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   573  		require.NoError(t, err)
   574  
   575  		action := <-ch
   576  
   577  		properties, ok := action.Properties.(*eventProps)
   578  		require.True(t, ok)
   579  		require.NotEmpty(t, properties.PIID())
   580  		require.Equal(t, properties.MyDID(), Alice)
   581  		require.Equal(t, properties.TheirDID(), Bob)
   582  
   583  		action.Stop(nil)
   584  
   585  		select {
   586  		case <-done:
   587  			return
   588  		case <-time.After(time.Second):
   589  			t.Error("timeout")
   590  		}
   591  	})
   592  
   593  	t.Run("Receive Offer Credential Continue with Proposal", func(t *testing.T) {
   594  		done := make(chan struct{})
   595  
   596  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   597  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   598  				defer close(done)
   599  
   600  				r := &ProposeCredentialV2{}
   601  				require.NoError(t, msg.Decode(r))
   602  				require.Equal(t, ProposeCredentialMsgTypeV2, r.Type)
   603  
   604  				return nil
   605  			})
   606  
   607  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   608  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   609  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   610  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   611  			require.Equal(t, "proposal-sent", string(name))
   612  
   613  			return nil
   614  		})
   615  
   616  		svc, err := New(provider)
   617  		require.NoError(t, err)
   618  
   619  		ch := make(chan service.DIDCommAction, 1)
   620  		require.NoError(t, svc.RegisterActionEvent(ch))
   621  
   622  		msg := service.NewDIDCommMsgMap(OfferCredentialV2{
   623  			Type: OfferCredentialMsgTypeV2,
   624  		})
   625  
   626  		msg.SetID(uuid.New().String())
   627  
   628  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   629  		require.NoError(t, err)
   630  
   631  		action := <-ch
   632  
   633  		properties, ok := action.Properties.(*eventProps)
   634  		require.True(t, ok)
   635  		require.NotEmpty(t, properties.PIID())
   636  		require.Equal(t, properties.MyDID(), Alice)
   637  		require.Equal(t, properties.TheirDID(), Bob)
   638  
   639  		action.Continue(WithProposeCredential(&ProposeCredentialParams{}))
   640  
   641  		select {
   642  		case <-done:
   643  			return
   644  		case <-time.After(time.Second):
   645  			t.Error("timeout")
   646  		}
   647  	})
   648  
   649  	t.Run("Receive Offer Credential Continue with Invitation", func(t *testing.T) {
   650  		done := make(chan struct{})
   651  
   652  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   653  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   654  				defer close(done)
   655  
   656  				r := &RequestCredentialV2{}
   657  				require.NoError(t, msg.Decode(r))
   658  				require.Equal(t, RequestCredentialMsgTypeV2, r.Type)
   659  
   660  				return nil
   661  			})
   662  
   663  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   664  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   665  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   666  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   667  			require.Equal(t, "request-sent", string(name))
   668  
   669  			return nil
   670  		})
   671  
   672  		svc, err := New(provider)
   673  		require.NoError(t, err)
   674  
   675  		ch := make(chan service.DIDCommAction, 1)
   676  		require.NoError(t, svc.RegisterActionEvent(ch))
   677  
   678  		msg := service.NewDIDCommMsgMap(OfferCredentialV2{
   679  			Type: OfferCredentialMsgTypeV2,
   680  		})
   681  
   682  		msg.SetID(uuid.New().String())
   683  
   684  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   685  		require.NoError(t, err)
   686  
   687  		action := <-ch
   688  
   689  		properties, ok := action.Properties.(*eventProps)
   690  		require.True(t, ok)
   691  		require.NotEmpty(t, properties.PIID())
   692  		require.Equal(t, properties.MyDID(), Alice)
   693  		require.Equal(t, properties.TheirDID(), Bob)
   694  
   695  		action.Continue(WithRequestCredential(&RequestCredentialParams{Comment: "test"}))
   696  
   697  		select {
   698  		case <-done:
   699  			return
   700  		case <-time.After(time.Second):
   701  			t.Error("timeout")
   702  		}
   703  	})
   704  
   705  	t.Run("Receive Offer Credential", func(t *testing.T) {
   706  		done := make(chan struct{})
   707  		attachment := []decorator.Attachment{{ID: "ID1"}, {ID: "ID2"}}
   708  
   709  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   710  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   711  				defer close(done)
   712  
   713  				r := &RequestCredentialV2{}
   714  				require.NoError(t, msg.Decode(r))
   715  				require.Equal(t, RequestCredentialMsgTypeV2, r.Type)
   716  				require.Equal(t, attachment, r.RequestsAttach)
   717  
   718  				return nil
   719  			})
   720  
   721  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   722  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   723  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   724  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   725  			require.Equal(t, "request-sent", string(name))
   726  
   727  			return nil
   728  		})
   729  
   730  		svc, err := New(provider)
   731  		require.NoError(t, err)
   732  
   733  		ch := make(chan service.DIDCommAction, 1)
   734  		require.NoError(t, svc.RegisterActionEvent(ch))
   735  
   736  		msg := service.NewDIDCommMsgMap(OfferCredentialV2{
   737  			Type:         OfferCredentialMsgTypeV2,
   738  			OffersAttach: attachment,
   739  		})
   740  
   741  		msg.SetID(uuid.New().String())
   742  
   743  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   744  		require.NoError(t, err)
   745  
   746  		action := <-ch
   747  
   748  		properties, ok := action.Properties.(*eventProps)
   749  		require.True(t, ok)
   750  		require.NotEmpty(t, properties.PIID())
   751  		require.Equal(t, properties.MyDID(), Alice)
   752  		require.Equal(t, properties.TheirDID(), Bob)
   753  
   754  		action.Continue(nil)
   755  
   756  		select {
   757  		case <-done:
   758  			return
   759  		case <-time.After(time.Second):
   760  			t.Error("timeout")
   761  		}
   762  	})
   763  
   764  	t.Run("Receive Invitation Credential Stop", func(t *testing.T) {
   765  		done := make(chan struct{})
   766  
   767  		messenger.EXPECT().
   768  			ReplyToNested(gomock.Any(), gomock.Any()).
   769  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   770  				defer close(done)
   771  
   772  				r := &model.ProblemReport{}
   773  				require.NoError(t, msg.Decode(r))
   774  				require.Equal(t, codeRejectedError, r.Description.Code)
   775  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
   776  
   777  				return nil
   778  			})
   779  
   780  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   781  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   782  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   783  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   784  			require.Equal(t, "done", string(name))
   785  
   786  			return nil
   787  		})
   788  
   789  		svc, err := New(provider)
   790  		require.NoError(t, err)
   791  
   792  		ch := make(chan service.DIDCommAction, 1)
   793  		require.NoError(t, svc.RegisterActionEvent(ch))
   794  
   795  		msg := service.NewDIDCommMsgMap(RequestCredentialV2{
   796  			Type: RequestCredentialMsgTypeV2,
   797  		})
   798  
   799  		msg.SetID(uuid.New().String())
   800  
   801  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   802  		require.NoError(t, err)
   803  
   804  		action := <-ch
   805  
   806  		properties, ok := action.Properties.(*eventProps)
   807  		require.True(t, ok)
   808  		require.NotEmpty(t, properties.PIID())
   809  		require.Equal(t, properties.MyDID(), Alice)
   810  		require.Equal(t, properties.TheirDID(), Bob)
   811  
   812  		action.Stop(nil)
   813  
   814  		select {
   815  		case <-done:
   816  			return
   817  		case <-time.After(time.Second):
   818  			t.Error("timeout")
   819  		}
   820  	})
   821  
   822  	t.Run("Receive Invitation Credential Continue", func(t *testing.T) {
   823  		done := make(chan struct{})
   824  
   825  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   826  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   827  				defer close(done)
   828  
   829  				r := &IssueCredentialV2{}
   830  				require.NoError(t, msg.Decode(r))
   831  				require.Equal(t, IssueCredentialMsgTypeV2, r.Type)
   832  
   833  				return nil
   834  			})
   835  
   836  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
   837  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   838  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   839  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   840  			require.Equal(t, "credential-issued", string(name))
   841  
   842  			return nil
   843  		})
   844  
   845  		svc, err := New(provider)
   846  		require.NoError(t, err)
   847  
   848  		ch := make(chan service.DIDCommAction, 1)
   849  		require.NoError(t, svc.RegisterActionEvent(ch))
   850  
   851  		msg := service.NewDIDCommMsgMap(RequestCredentialV2{
   852  			Type: RequestCredentialMsgTypeV2,
   853  		})
   854  
   855  		msg.SetID(uuid.New().String())
   856  
   857  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   858  		require.NoError(t, err)
   859  
   860  		action := <-ch
   861  
   862  		properties, ok := action.Properties.(*eventProps)
   863  		require.True(t, ok)
   864  		require.NotEmpty(t, properties.PIID())
   865  		require.Equal(t, properties.MyDID(), Alice)
   866  		require.Equal(t, properties.TheirDID(), Bob)
   867  
   868  		action.Continue(WithIssueCredential(&IssueCredentialParams{}))
   869  
   870  		select {
   871  		case <-done:
   872  			return
   873  		case <-time.After(time.Second):
   874  			t.Error("timeout")
   875  		}
   876  	})
   877  
   878  	t.Run("Receive Problem Report (continue)", func(t *testing.T) {
   879  		done := make(chan struct{})
   880  
   881  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
   882  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   883  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   884  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   885  			defer close(done)
   886  
   887  			require.Equal(t, "done", string(name))
   888  
   889  			return nil
   890  		})
   891  
   892  		svc, err := New(provider)
   893  		require.NoError(t, err)
   894  
   895  		ch := make(chan service.DIDCommAction, 1)
   896  		require.NoError(t, svc.RegisterActionEvent(ch))
   897  
   898  		msg := service.NewDIDCommMsgMap(RequestCredentialV2{
   899  			Type: ProblemReportMsgTypeV2,
   900  		})
   901  
   902  		msg.SetID(uuid.New().String())
   903  
   904  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   905  		require.NoError(t, err)
   906  
   907  		action := <-ch
   908  
   909  		properties, ok := action.Properties.(*eventProps)
   910  		require.True(t, ok)
   911  		require.NotEmpty(t, properties.PIID())
   912  		require.Equal(t, properties.MyDID(), Alice)
   913  		require.Equal(t, properties.TheirDID(), Bob)
   914  
   915  		action.Continue(WithIssueCredential(&IssueCredentialParams{}))
   916  
   917  		select {
   918  		case <-done:
   919  			return
   920  		case <-time.After(time.Second):
   921  			t.Error("timeout")
   922  		}
   923  	})
   924  
   925  	t.Run("Receive Problem Report (stop)", func(t *testing.T) {
   926  		done := make(chan struct{})
   927  
   928  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
   929  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   930  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   931  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   932  			defer close(done)
   933  
   934  			require.Equal(t, "done", string(name))
   935  
   936  			return nil
   937  		})
   938  
   939  		svc, err := New(provider)
   940  		require.NoError(t, err)
   941  
   942  		ch := make(chan service.DIDCommAction, 1)
   943  		require.NoError(t, svc.RegisterActionEvent(ch))
   944  
   945  		msg := service.NewDIDCommMsgMap(RequestCredentialV2{
   946  			Type: ProblemReportMsgTypeV2,
   947  		})
   948  
   949  		msg.SetID(uuid.New().String())
   950  
   951  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   952  		require.NoError(t, err)
   953  
   954  		action := <-ch
   955  
   956  		properties, ok := action.Properties.(*eventProps)
   957  		require.True(t, ok)
   958  		require.NotEmpty(t, properties.PIID())
   959  		require.Equal(t, properties.MyDID(), Alice)
   960  		require.Equal(t, properties.TheirDID(), Bob)
   961  
   962  		action.Stop(nil)
   963  
   964  		select {
   965  		case <-done:
   966  			return
   967  		case <-time.After(time.Second):
   968  			t.Error("timeout")
   969  		}
   970  	})
   971  
   972  	t.Run("Receive Issue Credential Continue", func(t *testing.T) {
   973  		done := make(chan struct{})
   974  
   975  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   976  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   977  				defer close(done)
   978  
   979  				r := &model.Ack{}
   980  				require.NoError(t, msg.Decode(r))
   981  				require.Equal(t, AckMsgTypeV2, r.Type)
   982  
   983  				return nil
   984  			})
   985  
   986  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
   987  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   988  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   989  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
   990  			require.Equal(t, "done", string(name))
   991  
   992  			return nil
   993  		})
   994  
   995  		svc, err := New(provider)
   996  		require.NoError(t, err)
   997  
   998  		ch := make(chan service.DIDCommAction, 1)
   999  		require.NoError(t, svc.RegisterActionEvent(ch))
  1000  		issued := time.Date(2010, time.January, 1, 19, 23, 24, 0, time.UTC)
  1001  		msg := service.NewDIDCommMsgMap(IssueCredentialV2{
  1002  			Type: IssueCredentialMsgTypeV2,
  1003  			CredentialsAttach: []decorator.Attachment{
  1004  				{Data: decorator.AttachmentData{JSON: &verifiable.Credential{
  1005  					Context: []string{
  1006  						"https://www.w3.org/2018/credentials/v1",
  1007  						"https://www.w3.org/2018/credentials/examples/v1",
  1008  					},
  1009  					ID: "http://example.edu/credentials/1872",
  1010  					Types: []string{
  1011  						"VerifiableCredential",
  1012  						"UniversityDegreeCredential",
  1013  					},
  1014  					Subject: struct {
  1015  						ID string
  1016  					}{ID: "SubjectID"},
  1017  					Issuer: verifiable.Issuer{
  1018  						ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
  1019  						CustomFields: verifiable.CustomFields{"name": "Example University"},
  1020  					},
  1021  					Issued:  util.NewTime(issued),
  1022  					Schemas: []verifiable.TypedID{},
  1023  					CustomFields: map[string]interface{}{
  1024  						"referenceNumber": 83294847,
  1025  					},
  1026  				}}},
  1027  			},
  1028  		})
  1029  
  1030  		msg.SetID(uuid.New().String())
  1031  
  1032  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1033  		require.NoError(t, err)
  1034  
  1035  		action := <-ch
  1036  
  1037  		properties, ok := action.Properties.(*eventProps)
  1038  		require.True(t, ok)
  1039  		require.NotEmpty(t, properties.PIID())
  1040  		require.Equal(t, properties.MyDID(), Alice)
  1041  		require.Equal(t, properties.TheirDID(), Bob)
  1042  
  1043  		action.Continue(WithFriendlyNames("UniversityDegree"))
  1044  
  1045  		select {
  1046  		case <-done:
  1047  			return
  1048  		case <-time.After(time.Second * 5):
  1049  			t.Error("timeout")
  1050  		}
  1051  	})
  1052  
  1053  	t.Run("Receive Issue Credential Stop", func(t *testing.T) {
  1054  		done := make(chan struct{})
  1055  
  1056  		messenger.EXPECT().ReplyToNested(gomock.Any(), gomock.Any()).
  1057  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
  1058  				defer close(done)
  1059  
  1060  				r := &model.ProblemReport{}
  1061  				require.NoError(t, msg.Decode(r))
  1062  				require.Equal(t, codeRejectedError, r.Description.Code)
  1063  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
  1064  
  1065  				return nil
  1066  			})
  1067  
  1068  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
  1069  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1070  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1071  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1072  			require.Equal(t, "done", string(name))
  1073  
  1074  			return nil
  1075  		})
  1076  
  1077  		svc, err := New(provider)
  1078  		require.NoError(t, err)
  1079  
  1080  		ch := make(chan service.DIDCommAction, 1)
  1081  		require.NoError(t, svc.RegisterActionEvent(ch))
  1082  
  1083  		msg := service.NewDIDCommMsgMap(IssueCredentialV2{
  1084  			Type: IssueCredentialMsgTypeV2,
  1085  		})
  1086  
  1087  		msg.SetID(uuid.New().String())
  1088  
  1089  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1090  		require.NoError(t, err)
  1091  
  1092  		action := <-ch
  1093  
  1094  		properties, ok := action.Properties.(*eventProps)
  1095  		require.True(t, ok)
  1096  		require.NotEmpty(t, properties.PIID())
  1097  		require.Equal(t, properties.MyDID(), Alice)
  1098  		require.Equal(t, properties.TheirDID(), Bob)
  1099  
  1100  		action.Stop(errors.New("invalid credential"))
  1101  
  1102  		select {
  1103  		case <-done:
  1104  			return
  1105  		case <-time.After(time.Second):
  1106  			t.Error("timeout")
  1107  		}
  1108  	})
  1109  
  1110  	t.Run("Receive Ack message", func(t *testing.T) {
  1111  		done := make(chan struct{})
  1112  
  1113  		store.EXPECT().Get(gomock.Any()).Return([]byte("credential-issued"), nil)
  1114  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1115  			defer close(done)
  1116  
  1117  			require.Equal(t, "done", string(name))
  1118  
  1119  			return nil
  1120  		})
  1121  
  1122  		svc, err := New(provider)
  1123  		require.NoError(t, err)
  1124  
  1125  		require.NoError(t, svc.RegisterActionEvent(make(chan service.DIDCommAction)))
  1126  
  1127  		msg := service.NewDIDCommMsgMap(model.Ack{
  1128  			Type: AckMsgTypeV2,
  1129  		})
  1130  
  1131  		msg.SetID(uuid.New().String())
  1132  
  1133  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1134  		require.NoError(t, err)
  1135  
  1136  		select {
  1137  		case <-done:
  1138  			return
  1139  		case <-time.After(time.Second):
  1140  			t.Error("timeout")
  1141  		}
  1142  	})
  1143  
  1144  	t.Run("Invalid state transition", func(t *testing.T) {
  1145  		svc, err := New(provider)
  1146  		require.NoError(t, err)
  1147  
  1148  		ch := make(chan service.DIDCommAction, 1)
  1149  		require.NoError(t, svc.RegisterActionEvent(ch))
  1150  
  1151  		chState := make(chan service.StateMsg, 2)
  1152  		require.NoError(t, svc.RegisterMsgEvent(chState))
  1153  
  1154  		_, err = svc.HandleInbound(service.NewDIDCommMsgMap(model.ProblemReport{
  1155  			Type: ProblemReportMsgTypeV2,
  1156  		}), service.EmptyDIDCommContext())
  1157  		require.Contains(t, fmt.Sprintf("%v", err), "doHandle: invalid state transition")
  1158  	})
  1159  }
  1160  
  1161  // nolint: gocyclo,gocognit
  1162  func TestService_HandleInboundV3(t *testing.T) {
  1163  	ctrl := gomock.NewController(t)
  1164  	defer ctrl.Finish()
  1165  
  1166  	const errMsg = "error"
  1167  
  1168  	initMocks := func(controller *gomock.Controller) (
  1169  		store *storageMocks.MockStore,
  1170  		messenger *serviceMocks.MockMessenger,
  1171  		provider *issuecredentialMocks.MockProvider,
  1172  	) {
  1173  		store = storageMocks.NewMockStore(controller)
  1174  
  1175  		storeProvider := storageMocks.NewMockProvider(controller)
  1176  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
  1177  		storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  1178  
  1179  		messenger = serviceMocks.NewMockMessenger(controller)
  1180  
  1181  		provider = issuecredentialMocks.NewMockProvider(controller)
  1182  		provider.EXPECT().Messenger().Return(messenger).AnyTimes()
  1183  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  1184  
  1185  		return store, messenger, provider
  1186  	}
  1187  
  1188  	t.Run("DB error (saveTransitionalPayload)", func(t *testing.T) {
  1189  		store, _, provider := initMocks(ctrl)
  1190  
  1191  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1192  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New(errMsg))
  1193  
  1194  		svc, err := New(provider)
  1195  		require.NoError(t, err)
  1196  
  1197  		require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction)))
  1198  
  1199  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
  1200  			Type: ProposeCredentialMsgTypeV3,
  1201  		})
  1202  		msg.SetID(uuid.New().String())
  1203  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
  1204  		require.Contains(t, fmt.Sprintf("%v", err), "save transitional payload: "+errMsg)
  1205  	})
  1206  
  1207  	t.Run("Receive Propose Credential Stop", func(t *testing.T) {
  1208  		store, messenger, provider := initMocks(ctrl)
  1209  
  1210  		done := make(chan struct{})
  1211  
  1212  		messenger.EXPECT().
  1213  			ReplyToNested(gomock.Any(), gomock.Any()).
  1214  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
  1215  				defer close(done)
  1216  
  1217  				r := &model.ProblemReportV2{}
  1218  				require.NoError(t, msg.Decode(r))
  1219  				require.Equal(t, codeRejectedError, r.Body.Code)
  1220  				require.Equal(t, ProblemReportMsgTypeV3, r.Type)
  1221  
  1222  				return nil
  1223  			})
  1224  
  1225  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1226  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1227  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1228  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1229  			require.Equal(t, "done", string(name))
  1230  
  1231  			return nil
  1232  		})
  1233  
  1234  		svc, err := New(provider)
  1235  		require.NoError(t, err)
  1236  
  1237  		ch := make(chan service.DIDCommAction, 1)
  1238  		require.NoError(t, svc.RegisterActionEvent(ch))
  1239  
  1240  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
  1241  			Type: ProposeCredentialMsgTypeV3,
  1242  		})
  1243  
  1244  		msg.SetID(uuid.New().String())
  1245  
  1246  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1247  		require.NoError(t, err)
  1248  
  1249  		action := <-ch
  1250  
  1251  		properties, ok := action.Properties.(*eventProps)
  1252  		require.True(t, ok)
  1253  		require.NotEmpty(t, properties.PIID())
  1254  		require.Equal(t, properties.MyDID(), Alice)
  1255  		require.Equal(t, properties.TheirDID(), Bob)
  1256  		require.Equal(t, properties.All()["myDID"], Alice)
  1257  		require.Equal(t, properties.All()["theirDID"], Bob)
  1258  
  1259  		action.Stop(nil)
  1260  
  1261  		select {
  1262  		case <-done:
  1263  			return
  1264  		case <-time.After(time.Second):
  1265  			t.Error("timeout")
  1266  		}
  1267  	})
  1268  
  1269  	t.Run("Receive Propose Credential Continue", func(t *testing.T) {
  1270  		store, messenger, provider := initMocks(ctrl)
  1271  
  1272  		done := make(chan struct{})
  1273  
  1274  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1275  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1276  				defer close(done)
  1277  
  1278  				r := &OfferCredentialV3{}
  1279  				require.NoError(t, msg.Decode(r))
  1280  				require.Equal(t, OfferCredentialMsgTypeV3, r.Type)
  1281  
  1282  				return nil
  1283  			})
  1284  
  1285  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1286  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1287  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1288  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1289  			require.Equal(t, "offer-sent", string(name))
  1290  
  1291  			return nil
  1292  		})
  1293  
  1294  		svc, err := New(provider)
  1295  		require.NoError(t, err)
  1296  
  1297  		ch := make(chan service.DIDCommAction, 1)
  1298  		require.NoError(t, svc.RegisterActionEvent(ch))
  1299  
  1300  		msg := service.NewDIDCommMsgMap(ProposeCredentialV3{
  1301  			Type: ProposeCredentialMsgTypeV3,
  1302  		})
  1303  
  1304  		msg.SetID(uuid.New().String())
  1305  
  1306  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1307  		require.NoError(t, err)
  1308  
  1309  		action := <-ch
  1310  
  1311  		properties, ok := action.Properties.(*eventProps)
  1312  		require.True(t, ok)
  1313  		require.NotEmpty(t, properties.PIID())
  1314  		require.Equal(t, properties.MyDID(), Alice)
  1315  		require.Equal(t, properties.TheirDID(), Bob)
  1316  
  1317  		action.Continue(WithOfferCredential(&OfferCredentialParams{}))
  1318  
  1319  		select {
  1320  		case <-done:
  1321  			return
  1322  		case <-time.After(time.Second):
  1323  			t.Error("timeout")
  1324  		}
  1325  	})
  1326  
  1327  	t.Run("Receive Propose Credential Continue (async)", func(t *testing.T) {
  1328  		_, messenger, _ := initMocks(ctrl)
  1329  
  1330  		done := make(chan struct{})
  1331  
  1332  		newProvider := issuecredentialMocks.NewMockProvider(ctrl)
  1333  		newProvider.EXPECT().Messenger().Return(messenger).AnyTimes()
  1334  		newProvider.EXPECT().StorageProvider().Return(mem.NewProvider()).AnyTimes()
  1335  
  1336  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1337  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1338  				defer close(done)
  1339  
  1340  				r := &OfferCredentialV3{}
  1341  				require.NoError(t, msg.Decode(r))
  1342  				require.Equal(t, OfferCredentialMsgTypeV3, r.Type)
  1343  
  1344  				return nil
  1345  			})
  1346  
  1347  		svc, err := New(newProvider)
  1348  		require.NoError(t, err)
  1349  
  1350  		ch := make(chan service.DIDCommAction, 1)
  1351  		require.NoError(t, svc.RegisterActionEvent(ch))
  1352  
  1353  		msg := service.NewDIDCommMsgMap(ProposeCredentialV3{
  1354  			Type: ProposeCredentialMsgTypeV3,
  1355  		})
  1356  
  1357  		msg.SetID(uuid.New().String())
  1358  
  1359  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1360  		require.NoError(t, err)
  1361  
  1362  		actions, err := svc.Actions()
  1363  		require.NoError(t, err)
  1364  		for _, action := range actions {
  1365  			require.Equal(t, action.MyDID, Alice)
  1366  			require.Equal(t, action.TheirDID, Bob)
  1367  			require.NoError(t, svc.ActionContinue(action.PIID, WithOfferCredential(&OfferCredentialParams{})))
  1368  		}
  1369  
  1370  		select {
  1371  		case <-done:
  1372  			return
  1373  		case <-time.After(time.Second):
  1374  			t.Error("timeout")
  1375  		}
  1376  	})
  1377  
  1378  	t.Run("Receive Propose Credential Stop (async)", func(t *testing.T) {
  1379  		_, messenger, _ := initMocks(ctrl)
  1380  
  1381  		done := make(chan struct{})
  1382  
  1383  		newProvider := issuecredentialMocks.NewMockProvider(ctrl)
  1384  		newProvider.EXPECT().Messenger().Return(messenger).AnyTimes()
  1385  		newProvider.EXPECT().StorageProvider().Return(mem.NewProvider()).AnyTimes()
  1386  
  1387  		messenger.EXPECT().
  1388  			ReplyToNested(gomock.Any(), gomock.Any()).
  1389  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
  1390  				defer close(done)
  1391  
  1392  				r := &model.ProblemReportV2{}
  1393  				require.NoError(t, msg.Decode(r))
  1394  				require.Equal(t, codeRejectedError, r.Body.Code)
  1395  				require.Equal(t, ProblemReportMsgTypeV3, r.Type)
  1396  
  1397  				return nil
  1398  			})
  1399  
  1400  		svc, err := New(newProvider)
  1401  		require.NoError(t, err)
  1402  
  1403  		ch := make(chan service.DIDCommAction, 1)
  1404  		require.NoError(t, svc.RegisterActionEvent(ch))
  1405  
  1406  		msg := service.NewDIDCommMsgMap(ProposeCredentialV3{
  1407  			Type: ProposeCredentialMsgTypeV3,
  1408  		})
  1409  
  1410  		msg.SetID(uuid.New().String())
  1411  
  1412  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1413  		require.NoError(t, err)
  1414  
  1415  		actions, err := svc.Actions()
  1416  		require.NoError(t, err)
  1417  		for _, action := range actions {
  1418  			require.Equal(t, action.MyDID, Alice)
  1419  			require.Equal(t, action.TheirDID, Bob)
  1420  			require.NoError(t, svc.ActionStop(action.PIID, nil))
  1421  		}
  1422  
  1423  		select {
  1424  		case <-done:
  1425  			return
  1426  		case <-time.After(time.Second):
  1427  			t.Error("timeout")
  1428  		}
  1429  	})
  1430  
  1431  	t.Run("Receive Offer Credential Stop", func(t *testing.T) {
  1432  		store, messenger, provider := initMocks(ctrl)
  1433  
  1434  		done := make(chan struct{})
  1435  
  1436  		messenger.EXPECT().
  1437  			ReplyToNested(gomock.Any(), gomock.Any()).
  1438  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
  1439  				defer close(done)
  1440  
  1441  				r := &model.ProblemReportV2{}
  1442  				require.NoError(t, msg.Decode(r))
  1443  				require.Equal(t, codeRejectedError, r.Body.Code)
  1444  				require.Equal(t, ProblemReportMsgTypeV3, r.Type)
  1445  
  1446  				return nil
  1447  			})
  1448  
  1449  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1450  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1451  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1452  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1453  			require.Equal(t, "done", string(name))
  1454  
  1455  			return nil
  1456  		})
  1457  
  1458  		svc, err := New(provider)
  1459  		require.NoError(t, err)
  1460  
  1461  		ch := make(chan service.DIDCommAction, 1)
  1462  		require.NoError(t, svc.RegisterActionEvent(ch))
  1463  
  1464  		msg := service.NewDIDCommMsgMap(OfferCredentialV3{
  1465  			Type: OfferCredentialMsgTypeV3,
  1466  		})
  1467  
  1468  		msg.SetID(uuid.New().String())
  1469  
  1470  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1471  		require.NoError(t, err)
  1472  
  1473  		action := <-ch
  1474  
  1475  		properties, ok := action.Properties.(*eventProps)
  1476  		require.True(t, ok)
  1477  		require.NotEmpty(t, properties.PIID())
  1478  		require.Equal(t, properties.MyDID(), Alice)
  1479  		require.Equal(t, properties.TheirDID(), Bob)
  1480  
  1481  		action.Stop(nil)
  1482  
  1483  		select {
  1484  		case <-done:
  1485  			return
  1486  		case <-time.After(time.Second):
  1487  			t.Error("timeout")
  1488  		}
  1489  	})
  1490  
  1491  	t.Run("Receive Offer Credential Continue with Proposal", func(t *testing.T) {
  1492  		store, messenger, provider := initMocks(ctrl)
  1493  
  1494  		done := make(chan struct{})
  1495  
  1496  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1497  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1498  				defer close(done)
  1499  
  1500  				r := &ProposeCredentialV3{}
  1501  				require.NoError(t, msg.Decode(r))
  1502  				require.Equal(t, ProposeCredentialMsgTypeV3, r.Type)
  1503  
  1504  				return nil
  1505  			})
  1506  
  1507  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1508  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1509  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1510  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1511  			require.Equal(t, "proposal-sent", string(name))
  1512  
  1513  			return nil
  1514  		})
  1515  
  1516  		svc, err := New(provider)
  1517  		require.NoError(t, err)
  1518  
  1519  		ch := make(chan service.DIDCommAction, 1)
  1520  		require.NoError(t, svc.RegisterActionEvent(ch))
  1521  
  1522  		msg := service.NewDIDCommMsgMap(OfferCredentialV3{
  1523  			Type: OfferCredentialMsgTypeV3,
  1524  		})
  1525  
  1526  		msg.SetID(uuid.New().String())
  1527  
  1528  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1529  		require.NoError(t, err)
  1530  
  1531  		action := <-ch
  1532  
  1533  		properties, ok := action.Properties.(*eventProps)
  1534  		require.True(t, ok)
  1535  		require.NotEmpty(t, properties.PIID())
  1536  		require.Equal(t, properties.MyDID(), Alice)
  1537  		require.Equal(t, properties.TheirDID(), Bob)
  1538  
  1539  		action.Continue(WithProposeCredential(&ProposeCredentialParams{}))
  1540  
  1541  		select {
  1542  		case <-done:
  1543  			return
  1544  		case <-time.After(time.Second):
  1545  			t.Error("timeout")
  1546  		}
  1547  	})
  1548  
  1549  	t.Run("Receive Offer Credential Continue with Invitation", func(t *testing.T) {
  1550  		store, messenger, provider := initMocks(ctrl)
  1551  
  1552  		done := make(chan struct{})
  1553  
  1554  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1555  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1556  				defer close(done)
  1557  
  1558  				r := &RequestCredentialV3{}
  1559  				require.NoError(t, msg.Decode(r))
  1560  				require.Equal(t, RequestCredentialMsgTypeV3, r.Type)
  1561  
  1562  				return nil
  1563  			})
  1564  
  1565  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1566  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1567  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1568  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1569  			require.Equal(t, "request-sent", string(name))
  1570  
  1571  			return nil
  1572  		})
  1573  
  1574  		svc, err := New(provider)
  1575  		require.NoError(t, err)
  1576  
  1577  		ch := make(chan service.DIDCommAction, 1)
  1578  		require.NoError(t, svc.RegisterActionEvent(ch))
  1579  
  1580  		msg := service.NewDIDCommMsgMap(OfferCredentialV3{
  1581  			Type: OfferCredentialMsgTypeV3,
  1582  		})
  1583  
  1584  		msg.SetID(uuid.New().String())
  1585  
  1586  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1587  		require.NoError(t, err)
  1588  
  1589  		action := <-ch
  1590  
  1591  		properties, ok := action.Properties.(*eventProps)
  1592  		require.True(t, ok)
  1593  		require.NotEmpty(t, properties.PIID())
  1594  		require.Equal(t, properties.MyDID(), Alice)
  1595  		require.Equal(t, properties.TheirDID(), Bob)
  1596  
  1597  		action.Continue(WithRequestCredential(&RequestCredentialParams{Comment: "test"}))
  1598  
  1599  		select {
  1600  		case <-done:
  1601  			return
  1602  		case <-time.After(time.Second):
  1603  			t.Error("timeout")
  1604  		}
  1605  	})
  1606  
  1607  	t.Run("Receive Offer Credential", func(t *testing.T) {
  1608  		store, messenger, provider := initMocks(ctrl)
  1609  
  1610  		done := make(chan struct{})
  1611  		attachment := []decorator.AttachmentV2{{ID: "ID1"}, {ID: "ID2"}}
  1612  
  1613  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1614  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1615  				defer close(done)
  1616  
  1617  				r := &RequestCredentialV3{}
  1618  				require.NoError(t, msg.Decode(r))
  1619  				require.Equal(t, RequestCredentialMsgTypeV3, r.Type)
  1620  				require.Equal(t, attachment, r.Attachments)
  1621  
  1622  				return nil
  1623  			})
  1624  
  1625  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1626  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1627  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1628  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1629  			require.Equal(t, "request-sent", string(name))
  1630  
  1631  			return nil
  1632  		})
  1633  
  1634  		svc, err := New(provider)
  1635  		require.NoError(t, err)
  1636  
  1637  		ch := make(chan service.DIDCommAction, 1)
  1638  		require.NoError(t, svc.RegisterActionEvent(ch))
  1639  
  1640  		msg := service.NewDIDCommMsgMap(OfferCredentialV3{
  1641  			Type:        OfferCredentialMsgTypeV3,
  1642  			Attachments: attachment,
  1643  		})
  1644  
  1645  		msg.SetID(uuid.New().String())
  1646  
  1647  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1648  		require.NoError(t, err)
  1649  
  1650  		action := <-ch
  1651  
  1652  		properties, ok := action.Properties.(*eventProps)
  1653  		require.True(t, ok)
  1654  		require.NotEmpty(t, properties.PIID())
  1655  		require.Equal(t, properties.MyDID(), Alice)
  1656  		require.Equal(t, properties.TheirDID(), Bob)
  1657  
  1658  		action.Continue(nil)
  1659  
  1660  		select {
  1661  		case <-done:
  1662  			return
  1663  		case <-time.After(time.Second):
  1664  			t.Error("timeout")
  1665  		}
  1666  	})
  1667  
  1668  	t.Run("Receive Invitation Credential Stop", func(t *testing.T) {
  1669  		store, messenger, provider := initMocks(ctrl)
  1670  
  1671  		done := make(chan struct{})
  1672  
  1673  		messenger.EXPECT().
  1674  			ReplyToNested(gomock.Any(), gomock.Any()).
  1675  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
  1676  				defer close(done)
  1677  
  1678  				r := &model.ProblemReportV2{}
  1679  				require.NoError(t, msg.Decode(r))
  1680  				require.Equal(t, codeRejectedError, r.Body.Code)
  1681  				require.Equal(t, ProblemReportMsgTypeV3, r.Type)
  1682  
  1683  				return nil
  1684  			})
  1685  
  1686  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1687  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1688  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1689  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1690  			require.Equal(t, "done", string(name))
  1691  
  1692  			return nil
  1693  		})
  1694  
  1695  		svc, err := New(provider)
  1696  		require.NoError(t, err)
  1697  
  1698  		ch := make(chan service.DIDCommAction, 1)
  1699  		require.NoError(t, svc.RegisterActionEvent(ch))
  1700  
  1701  		msg := service.NewDIDCommMsgMap(RequestCredentialV3{
  1702  			Type: RequestCredentialMsgTypeV3,
  1703  		})
  1704  
  1705  		msg.SetID(uuid.New().String())
  1706  
  1707  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1708  		require.NoError(t, err)
  1709  
  1710  		action := <-ch
  1711  
  1712  		properties, ok := action.Properties.(*eventProps)
  1713  		require.True(t, ok)
  1714  		require.NotEmpty(t, properties.PIID())
  1715  		require.Equal(t, properties.MyDID(), Alice)
  1716  		require.Equal(t, properties.TheirDID(), Bob)
  1717  
  1718  		action.Stop(nil)
  1719  
  1720  		select {
  1721  		case <-done:
  1722  			return
  1723  		case <-time.After(time.Second):
  1724  			t.Error("timeout")
  1725  		}
  1726  	})
  1727  
  1728  	t.Run("Receive Invitation Credential Continue", func(t *testing.T) {
  1729  		store, messenger, provider := initMocks(ctrl)
  1730  
  1731  		done := make(chan struct{})
  1732  
  1733  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1734  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1735  				defer close(done)
  1736  
  1737  				r := &IssueCredentialV3{}
  1738  				require.NoError(t, msg.Decode(r))
  1739  				require.Equal(t, IssueCredentialMsgTypeV3, r.Type)
  1740  
  1741  				return nil
  1742  			})
  1743  
  1744  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1745  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1746  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1747  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1748  			require.Equal(t, "credential-issued", string(name))
  1749  
  1750  			return nil
  1751  		})
  1752  
  1753  		svc, err := New(provider)
  1754  		require.NoError(t, err)
  1755  
  1756  		ch := make(chan service.DIDCommAction, 1)
  1757  		require.NoError(t, svc.RegisterActionEvent(ch))
  1758  
  1759  		msg := service.NewDIDCommMsgMap(RequestCredentialV3{
  1760  			Type: RequestCredentialMsgTypeV3,
  1761  		})
  1762  
  1763  		msg.SetID(uuid.New().String())
  1764  
  1765  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1766  		require.NoError(t, err)
  1767  
  1768  		action := <-ch
  1769  
  1770  		properties, ok := action.Properties.(*eventProps)
  1771  		require.True(t, ok)
  1772  		require.NotEmpty(t, properties.PIID())
  1773  		require.Equal(t, properties.MyDID(), Alice)
  1774  		require.Equal(t, properties.TheirDID(), Bob)
  1775  
  1776  		action.Continue(WithIssueCredential(&IssueCredentialParams{}))
  1777  
  1778  		select {
  1779  		case <-done:
  1780  			return
  1781  		case <-time.After(time.Second):
  1782  			t.Error("timeout")
  1783  		}
  1784  	})
  1785  
  1786  	t.Run("Receive Problem Report (continue)", func(t *testing.T) {
  1787  		store, _, provider := initMocks(ctrl)
  1788  
  1789  		done := make(chan struct{})
  1790  
  1791  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
  1792  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1793  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1794  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1795  			defer close(done)
  1796  
  1797  			require.Equal(t, "done", string(name))
  1798  
  1799  			return nil
  1800  		})
  1801  
  1802  		svc, err := New(provider)
  1803  		require.NoError(t, err)
  1804  
  1805  		ch := make(chan service.DIDCommAction, 1)
  1806  		require.NoError(t, svc.RegisterActionEvent(ch))
  1807  
  1808  		msg := service.NewDIDCommMsgMap(RequestCredentialV3{
  1809  			Type: ProblemReportMsgTypeV3,
  1810  		})
  1811  
  1812  		msg.SetID(uuid.New().String())
  1813  
  1814  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1815  		require.NoError(t, err)
  1816  
  1817  		action := <-ch
  1818  
  1819  		properties, ok := action.Properties.(*eventProps)
  1820  		require.True(t, ok)
  1821  		require.NotEmpty(t, properties.PIID())
  1822  		require.Equal(t, properties.MyDID(), Alice)
  1823  		require.Equal(t, properties.TheirDID(), Bob)
  1824  
  1825  		action.Continue(WithIssueCredential(&IssueCredentialParams{}))
  1826  
  1827  		select {
  1828  		case <-done:
  1829  			return
  1830  		case <-time.After(time.Second):
  1831  			t.Error("timeout")
  1832  		}
  1833  	})
  1834  
  1835  	t.Run("Receive Problem Report (stop)", func(t *testing.T) {
  1836  		store, _, provider := initMocks(ctrl)
  1837  
  1838  		done := make(chan struct{})
  1839  
  1840  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
  1841  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1842  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1843  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1844  			defer close(done)
  1845  
  1846  			require.Equal(t, "done", string(name))
  1847  
  1848  			return nil
  1849  		})
  1850  
  1851  		svc, err := New(provider)
  1852  		require.NoError(t, err)
  1853  
  1854  		ch := make(chan service.DIDCommAction, 1)
  1855  		require.NoError(t, svc.RegisterActionEvent(ch))
  1856  
  1857  		msg := service.NewDIDCommMsgMap(RequestCredentialV3{
  1858  			Type: ProblemReportMsgTypeV3,
  1859  		})
  1860  
  1861  		msg.SetID(uuid.New().String())
  1862  
  1863  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1864  		require.NoError(t, err)
  1865  
  1866  		action := <-ch
  1867  
  1868  		properties, ok := action.Properties.(*eventProps)
  1869  		require.True(t, ok)
  1870  		require.NotEmpty(t, properties.PIID())
  1871  		require.Equal(t, properties.MyDID(), Alice)
  1872  		require.Equal(t, properties.TheirDID(), Bob)
  1873  
  1874  		action.Stop(nil)
  1875  
  1876  		select {
  1877  		case <-done:
  1878  			return
  1879  		case <-time.After(time.Second):
  1880  			t.Error("timeout")
  1881  		}
  1882  	})
  1883  
  1884  	t.Run("Receive Issue Credential Continue", func(t *testing.T) {
  1885  		store, messenger, provider := initMocks(ctrl)
  1886  
  1887  		done := make(chan struct{})
  1888  
  1889  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1890  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1891  				defer close(done)
  1892  
  1893  				r := &model.AckV2{}
  1894  				require.NoError(t, msg.Decode(r))
  1895  				require.Equal(t, AckMsgTypeV3, r.Type)
  1896  
  1897  				return nil
  1898  			})
  1899  
  1900  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
  1901  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1902  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1903  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1904  			require.Equal(t, "done", string(name))
  1905  
  1906  			return nil
  1907  		})
  1908  
  1909  		svc, err := New(provider)
  1910  		require.NoError(t, err)
  1911  
  1912  		ch := make(chan service.DIDCommAction, 1)
  1913  		require.NoError(t, svc.RegisterActionEvent(ch))
  1914  		issued := time.Date(2010, time.January, 1, 19, 23, 24, 0, time.UTC)
  1915  		msg := service.NewDIDCommMsgMap(IssueCredentialV3{
  1916  			Type: IssueCredentialMsgTypeV3,
  1917  			Attachments: []decorator.AttachmentV2{
  1918  				{Data: decorator.AttachmentData{JSON: &verifiable.Credential{
  1919  					Context: []string{
  1920  						"https://www.w3.org/2018/credentials/v1",
  1921  						"https://www.w3.org/2018/credentials/examples/v1",
  1922  					},
  1923  					ID: "http://example.edu/credentials/1872",
  1924  					Types: []string{
  1925  						"VerifiableCredential",
  1926  						"UniversityDegreeCredential",
  1927  					},
  1928  					Subject: struct {
  1929  						ID string
  1930  					}{ID: "SubjectID"},
  1931  					Issuer: verifiable.Issuer{
  1932  						ID:           "did:example:76e12ec712ebc6f1c221ebfeb1f",
  1933  						CustomFields: verifiable.CustomFields{"name": "Example University"},
  1934  					},
  1935  					Issued:  util.NewTime(issued),
  1936  					Schemas: []verifiable.TypedID{},
  1937  					CustomFields: map[string]interface{}{
  1938  						"referenceNumber": 83294847,
  1939  					},
  1940  				}}},
  1941  			},
  1942  		})
  1943  
  1944  		msg.SetID(uuid.New().String())
  1945  
  1946  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1947  		require.NoError(t, err)
  1948  
  1949  		action := <-ch
  1950  
  1951  		properties, ok := action.Properties.(*eventProps)
  1952  		require.True(t, ok)
  1953  		require.NotEmpty(t, properties.PIID())
  1954  		require.Equal(t, properties.MyDID(), Alice)
  1955  		require.Equal(t, properties.TheirDID(), Bob)
  1956  
  1957  		action.Continue(WithFriendlyNames("UniversityDegree"))
  1958  
  1959  		select {
  1960  		case <-done:
  1961  			return
  1962  		case <-time.After(time.Second * 5):
  1963  			t.Error("timeout")
  1964  		}
  1965  	})
  1966  
  1967  	t.Run("Receive Issue Credential Stop", func(t *testing.T) {
  1968  		store, messenger, provider := initMocks(ctrl)
  1969  
  1970  		done := make(chan struct{})
  1971  
  1972  		messenger.EXPECT().ReplyToNested(gomock.Any(), gomock.Any()).
  1973  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
  1974  				defer close(done)
  1975  
  1976  				r := &model.ProblemReportV2{}
  1977  				require.NoError(t, msg.Decode(r))
  1978  				require.Equal(t, codeRejectedError, r.Body.Code)
  1979  				require.Equal(t, ProblemReportMsgTypeV3, r.Type)
  1980  
  1981  				return nil
  1982  			})
  1983  
  1984  		store.EXPECT().Get(gomock.Any()).Return([]byte("request-sent"), nil)
  1985  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1986  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1987  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  1988  			require.Equal(t, "done", string(name))
  1989  
  1990  			return nil
  1991  		})
  1992  
  1993  		svc, err := New(provider)
  1994  		require.NoError(t, err)
  1995  
  1996  		ch := make(chan service.DIDCommAction, 1)
  1997  		require.NoError(t, svc.RegisterActionEvent(ch))
  1998  
  1999  		msg := service.NewDIDCommMsgMap(IssueCredentialV3{
  2000  			Type: IssueCredentialMsgTypeV3,
  2001  		})
  2002  
  2003  		msg.SetID(uuid.New().String())
  2004  
  2005  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  2006  		require.NoError(t, err)
  2007  
  2008  		action := <-ch
  2009  
  2010  		properties, ok := action.Properties.(*eventProps)
  2011  		require.True(t, ok)
  2012  		require.NotEmpty(t, properties.PIID())
  2013  		require.Equal(t, properties.MyDID(), Alice)
  2014  		require.Equal(t, properties.TheirDID(), Bob)
  2015  
  2016  		action.Stop(errors.New("invalid credential"))
  2017  
  2018  		select {
  2019  		case <-done:
  2020  			return
  2021  		case <-time.After(time.Second):
  2022  			t.Error("timeout")
  2023  		}
  2024  	})
  2025  
  2026  	t.Run("Receive Ack message", func(t *testing.T) {
  2027  		store, _, provider := initMocks(ctrl)
  2028  
  2029  		done := make(chan struct{})
  2030  
  2031  		store.EXPECT().Get(gomock.Any()).Return([]byte("credential-issued"), nil)
  2032  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  2033  			defer close(done)
  2034  
  2035  			require.Equal(t, "done", string(name))
  2036  
  2037  			return nil
  2038  		})
  2039  
  2040  		svc, err := New(provider)
  2041  		require.NoError(t, err)
  2042  
  2043  		require.NoError(t, svc.RegisterActionEvent(make(chan service.DIDCommAction)))
  2044  
  2045  		msg := service.NewDIDCommMsgMap(model.AckV2{
  2046  			Type: AckMsgTypeV3,
  2047  		})
  2048  
  2049  		msg.SetID(uuid.New().String())
  2050  
  2051  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  2052  		require.NoError(t, err)
  2053  
  2054  		select {
  2055  		case <-done:
  2056  			return
  2057  		case <-time.After(time.Second):
  2058  			t.Error("timeout")
  2059  		}
  2060  	})
  2061  
  2062  	t.Run("Invalid state transition", func(t *testing.T) {
  2063  		store, _, provider := initMocks(ctrl)
  2064  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  2065  
  2066  		svc, err := New(provider)
  2067  		require.NoError(t, err)
  2068  
  2069  		ch := make(chan service.DIDCommAction, 1)
  2070  		require.NoError(t, svc.RegisterActionEvent(ch))
  2071  
  2072  		chState := make(chan service.StateMsg, 2)
  2073  		require.NoError(t, svc.RegisterMsgEvent(chState))
  2074  
  2075  		_, err = svc.HandleInbound(service.NewDIDCommMsgMap(model.ProblemReportV2{
  2076  			Type: ProblemReportMsgTypeV3,
  2077  		}), service.EmptyDIDCommContext())
  2078  		require.Contains(t, fmt.Sprintf("%v", err), "doHandle: invalid state transition")
  2079  	})
  2080  }
  2081  
  2082  func TestService_HandleOutbound(t *testing.T) {
  2083  	ctrl := gomock.NewController(t)
  2084  	defer ctrl.Finish()
  2085  
  2086  	const errMsg = "error"
  2087  
  2088  	initMocks := func(controller *gomock.Controller) (
  2089  		store *storageMocks.MockStore,
  2090  		messenger *serviceMocks.MockMessenger,
  2091  		provider *issuecredentialMocks.MockProvider,
  2092  	) {
  2093  		store = storageMocks.NewMockStore(controller)
  2094  
  2095  		storeProvider := storageMocks.NewMockProvider(controller)
  2096  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
  2097  		storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  2098  
  2099  		messenger = serviceMocks.NewMockMessenger(controller)
  2100  
  2101  		provider = issuecredentialMocks.NewMockProvider(controller)
  2102  		provider.EXPECT().Messenger().Return(messenger).AnyTimes()
  2103  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  2104  
  2105  		return store, messenger, provider
  2106  	}
  2107  
  2108  	t.Run("DB error", func(t *testing.T) {
  2109  		store, _, provider := initMocks(ctrl)
  2110  
  2111  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
  2112  
  2113  		svc, err := New(provider)
  2114  		require.NoError(t, err)
  2115  
  2116  		msg := service.NewDIDCommMsgMap(struct{}{})
  2117  		msg.SetID(uuid.New().String())
  2118  
  2119  		piid, err := svc.HandleOutbound(msg, "", "")
  2120  		require.Empty(t, piid)
  2121  		require.Contains(t, fmt.Sprintf("%v", err), "doHandle: getCurrentStateNameAndPIID: currentStateName: "+errMsg)
  2122  	})
  2123  
  2124  	t.Run("Unrecognized msgType", func(t *testing.T) {
  2125  		store, _, provider := initMocks(ctrl)
  2126  
  2127  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  2128  
  2129  		svc, err := New(provider)
  2130  		require.NoError(t, err)
  2131  
  2132  		piid, err := svc.HandleOutbound(service.NewDIDCommMsgMap(ProposeCredentialV2{
  2133  			Type: "none",
  2134  		}), "", "")
  2135  		require.Empty(t, piid)
  2136  		require.Contains(t, fmt.Sprintf("%v", err), "doHandle: nextState: unrecognized msgType: none")
  2137  	})
  2138  
  2139  	t.Run("Send Propose Credential", func(t *testing.T) {
  2140  		store, messenger, provider := initMocks(ctrl)
  2141  
  2142  		done := make(chan struct{})
  2143  
  2144  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  2145  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  2146  			require.Equal(t, "proposal-sent", string(name))
  2147  
  2148  			return nil
  2149  		})
  2150  
  2151  		svc, err := New(provider)
  2152  		require.NoError(t, err)
  2153  
  2154  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
  2155  			Type: ProposeCredentialMsgTypeV2,
  2156  		})
  2157  
  2158  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).
  2159  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  2160  				defer close(done)
  2161  
  2162  				return nil
  2163  			})
  2164  
  2165  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2166  		require.NoError(t, err)
  2167  		require.NotEmpty(t, piid)
  2168  
  2169  		select {
  2170  		case <-done:
  2171  			return
  2172  		case <-time.After(time.Second):
  2173  			t.Error("timeout")
  2174  		}
  2175  	})
  2176  
  2177  	t.Run("Send Propose Credential with error", func(t *testing.T) {
  2178  		store, messenger, provider := initMocks(ctrl)
  2179  
  2180  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  2181  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil)
  2182  
  2183  		svc, err := New(provider)
  2184  		require.NoError(t, err)
  2185  
  2186  		msg := service.NewDIDCommMsgMap(ProposeCredentialV2{
  2187  			Type: ProposeCredentialMsgTypeV2,
  2188  		})
  2189  
  2190  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  2191  
  2192  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2193  		require.Empty(t, piid)
  2194  		require.Contains(t, fmt.Sprintf("%v", err), "action proposal-sent: "+errMsg)
  2195  	})
  2196  
  2197  	t.Run("Send Offer Credential", func(t *testing.T) {
  2198  		store, messenger, provider := initMocks(ctrl)
  2199  
  2200  		done := make(chan struct{})
  2201  
  2202  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  2203  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  2204  			require.Equal(t, "offer-sent", string(name))
  2205  
  2206  			return nil
  2207  		})
  2208  
  2209  		svc, err := New(provider)
  2210  		require.NoError(t, err)
  2211  
  2212  		msg := service.NewDIDCommMsgMap(OfferCredentialV2{
  2213  			Type: OfferCredentialMsgTypeV2,
  2214  		})
  2215  
  2216  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).
  2217  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  2218  				defer close(done)
  2219  
  2220  				return nil
  2221  			})
  2222  
  2223  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2224  		require.NotEmpty(t, piid)
  2225  		require.NoError(t, err)
  2226  
  2227  		select {
  2228  		case <-done:
  2229  			return
  2230  		case <-time.After(time.Second):
  2231  			t.Error("timeout")
  2232  		}
  2233  	})
  2234  
  2235  	t.Run("Send Offer with error", func(t *testing.T) {
  2236  		store, messenger, provider := initMocks(ctrl)
  2237  
  2238  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  2239  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil)
  2240  
  2241  		svc, err := New(provider)
  2242  		require.NoError(t, err)
  2243  
  2244  		msg := service.NewDIDCommMsgMap(OfferCredentialV2{
  2245  			Type: OfferCredentialMsgTypeV2,
  2246  		})
  2247  
  2248  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  2249  
  2250  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2251  		require.Empty(t, piid)
  2252  		require.Contains(t, fmt.Sprintf("%v", err), "action offer-sent: "+errMsg)
  2253  	})
  2254  
  2255  	t.Run("Send Invitation Credential", func(t *testing.T) {
  2256  		store, messenger, provider := initMocks(ctrl)
  2257  
  2258  		done := make(chan struct{})
  2259  
  2260  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  2261  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  2262  			require.Equal(t, "request-sent", string(name))
  2263  
  2264  			return nil
  2265  		})
  2266  
  2267  		svc, err := New(provider)
  2268  		require.NoError(t, err)
  2269  
  2270  		msg := service.NewDIDCommMsgMap(RequestCredentialV2{
  2271  			Type: RequestCredentialMsgTypeV2,
  2272  		})
  2273  
  2274  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).
  2275  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  2276  				defer close(done)
  2277  
  2278  				return nil
  2279  			})
  2280  
  2281  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2282  		require.NotEmpty(t, piid)
  2283  		require.NoError(t, err)
  2284  
  2285  		select {
  2286  		case <-done:
  2287  			return
  2288  		case <-time.After(time.Second):
  2289  			t.Error("timeout")
  2290  		}
  2291  	})
  2292  
  2293  	t.Run("Send Invitation with error", func(t *testing.T) {
  2294  		store, messenger, provider := initMocks(ctrl)
  2295  
  2296  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  2297  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil)
  2298  
  2299  		svc, err := New(provider)
  2300  		require.NoError(t, err)
  2301  
  2302  		msg := service.NewDIDCommMsgMap(RequestCredentialV2{
  2303  			Type: RequestCredentialMsgTypeV2,
  2304  		})
  2305  
  2306  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  2307  
  2308  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2309  		require.Empty(t, piid)
  2310  		require.Contains(t, fmt.Sprintf("%v", err), "action request-sent: "+errMsg)
  2311  	})
  2312  }
  2313  
  2314  func TestService_HandleOutboundV3(t *testing.T) {
  2315  	ctrl := gomock.NewController(t)
  2316  	defer ctrl.Finish()
  2317  
  2318  	const errMsg = "error"
  2319  
  2320  	initMocks := func(controller *gomock.Controller) (
  2321  		store *storageMocks.MockStore,
  2322  		messenger *serviceMocks.MockMessenger,
  2323  		provider *issuecredentialMocks.MockProvider,
  2324  	) {
  2325  		store = storageMocks.NewMockStore(controller)
  2326  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  2327  
  2328  		storeProvider := storageMocks.NewMockProvider(controller)
  2329  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
  2330  		storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  2331  
  2332  		messenger = serviceMocks.NewMockMessenger(controller)
  2333  
  2334  		provider = issuecredentialMocks.NewMockProvider(controller)
  2335  		provider.EXPECT().Messenger().Return(messenger).AnyTimes()
  2336  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  2337  
  2338  		return store, messenger, provider
  2339  	}
  2340  
  2341  	t.Run("Send Propose Credential", func(t *testing.T) {
  2342  		store, messenger, provider := initMocks(ctrl)
  2343  
  2344  		done := make(chan struct{})
  2345  
  2346  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  2347  			require.Equal(t, "proposal-sent", string(name))
  2348  
  2349  			return nil
  2350  		})
  2351  
  2352  		svc, err := New(provider)
  2353  		require.NoError(t, err)
  2354  
  2355  		msg := service.NewDIDCommMsgMap(ProposeCredentialV3{
  2356  			Type: ProposeCredentialMsgTypeV3,
  2357  		})
  2358  
  2359  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).
  2360  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  2361  				defer close(done)
  2362  
  2363  				return nil
  2364  			})
  2365  
  2366  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2367  		require.NotEmpty(t, piid)
  2368  		require.NoError(t, err)
  2369  
  2370  		select {
  2371  		case <-done:
  2372  			return
  2373  		case <-time.After(time.Second):
  2374  			t.Error("timeout")
  2375  		}
  2376  	})
  2377  
  2378  	t.Run("Send Propose Credential with error", func(t *testing.T) {
  2379  		store, messenger, provider := initMocks(ctrl)
  2380  
  2381  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil)
  2382  
  2383  		svc, err := New(provider)
  2384  		require.NoError(t, err)
  2385  
  2386  		msg := service.NewDIDCommMsgMap(ProposeCredentialV3{
  2387  			Type: ProposeCredentialMsgTypeV3,
  2388  		})
  2389  
  2390  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  2391  
  2392  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2393  		require.Empty(t, piid)
  2394  		require.Contains(t, fmt.Sprintf("%v", err), "action proposal-sent: "+errMsg)
  2395  	})
  2396  
  2397  	t.Run("Send Offer Credential", func(t *testing.T) {
  2398  		store, messenger, provider := initMocks(ctrl)
  2399  
  2400  		done := make(chan struct{})
  2401  
  2402  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  2403  			require.Equal(t, "offer-sent", string(name))
  2404  
  2405  			return nil
  2406  		})
  2407  
  2408  		svc, err := New(provider)
  2409  		require.NoError(t, err)
  2410  
  2411  		msg := service.NewDIDCommMsgMap(OfferCredentialV3{
  2412  			Type: OfferCredentialMsgTypeV3,
  2413  		})
  2414  
  2415  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).
  2416  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  2417  				defer close(done)
  2418  
  2419  				return nil
  2420  			})
  2421  
  2422  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2423  		require.NotEmpty(t, piid)
  2424  		require.NoError(t, err)
  2425  
  2426  		select {
  2427  		case <-done:
  2428  			return
  2429  		case <-time.After(time.Second):
  2430  			t.Error("timeout")
  2431  		}
  2432  	})
  2433  
  2434  	t.Run("Send Offer with error", func(t *testing.T) {
  2435  		store, messenger, provider := initMocks(ctrl)
  2436  
  2437  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil)
  2438  
  2439  		svc, err := New(provider)
  2440  		require.NoError(t, err)
  2441  
  2442  		msg := service.NewDIDCommMsgMap(OfferCredentialV3{
  2443  			Type: OfferCredentialMsgTypeV3,
  2444  		})
  2445  
  2446  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  2447  
  2448  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2449  		require.Empty(t, piid)
  2450  		require.Contains(t, fmt.Sprintf("%v", err), "action offer-sent: "+errMsg)
  2451  	})
  2452  
  2453  	t.Run("Send Invitation Credential", func(t *testing.T) {
  2454  		store, messenger, provider := initMocks(ctrl)
  2455  
  2456  		done := make(chan struct{})
  2457  
  2458  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, name []byte) error {
  2459  			require.Equal(t, "request-sent", string(name))
  2460  
  2461  			return nil
  2462  		})
  2463  
  2464  		svc, err := New(provider)
  2465  		require.NoError(t, err)
  2466  
  2467  		msg := service.NewDIDCommMsgMap(RequestCredentialV3{
  2468  			Type: RequestCredentialMsgTypeV3,
  2469  		})
  2470  
  2471  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).
  2472  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  2473  				defer close(done)
  2474  
  2475  				return nil
  2476  			})
  2477  
  2478  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2479  		require.NotEmpty(t, piid)
  2480  		require.NoError(t, err)
  2481  
  2482  		select {
  2483  		case <-done:
  2484  			return
  2485  		case <-time.After(time.Second):
  2486  			t.Error("timeout")
  2487  		}
  2488  	})
  2489  
  2490  	t.Run("Send Invitation with error", func(t *testing.T) {
  2491  		store, messenger, provider := initMocks(ctrl)
  2492  
  2493  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil)
  2494  
  2495  		svc, err := New(provider)
  2496  		require.NoError(t, err)
  2497  
  2498  		msg := service.NewDIDCommMsgMap(RequestCredentialV3{
  2499  			Type: RequestCredentialMsgTypeV3,
  2500  		})
  2501  
  2502  		messenger.EXPECT().Send(msg, Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  2503  
  2504  		piid, err := svc.HandleOutbound(msg, Alice, Bob)
  2505  		require.Empty(t, piid)
  2506  		require.Contains(t, fmt.Sprintf("%v", err), "action request-sent: "+errMsg)
  2507  	})
  2508  }
  2509  
  2510  func TestService_ActionContinue(t *testing.T) {
  2511  	t.Run("Error transitional payload (get)", func(t *testing.T) {
  2512  		ctrl := gomock.NewController(t)
  2513  		defer ctrl.Finish()
  2514  
  2515  		const errMsg = "error"
  2516  
  2517  		store := storageMocks.NewMockStore(ctrl)
  2518  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
  2519  
  2520  		storeProvider := storageMocks.NewMockProvider(ctrl)
  2521  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
  2522  		storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  2523  
  2524  		messenger := serviceMocks.NewMockMessenger(ctrl)
  2525  
  2526  		provider := issuecredentialMocks.NewMockProvider(ctrl)
  2527  		provider.EXPECT().Messenger().Return(messenger)
  2528  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  2529  
  2530  		svc, err := New(provider)
  2531  		require.NoError(t, err)
  2532  
  2533  		err = svc.ActionContinue("piID", nil)
  2534  		require.Contains(t, fmt.Sprintf("%v", err), "get transitional payload: store get: "+errMsg)
  2535  	})
  2536  
  2537  	t.Run("Error transitional payload (delete)", func(t *testing.T) {
  2538  		ctrl := gomock.NewController(t)
  2539  		defer ctrl.Finish()
  2540  
  2541  		const errMsg = "error"
  2542  
  2543  		store := storageMocks.NewMockStore(ctrl)
  2544  		store.EXPECT().Get(gomock.Any()).Return([]byte(`{}`), nil)
  2545  		store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg))
  2546  
  2547  		storeProvider := storageMocks.NewMockProvider(ctrl)
  2548  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
  2549  		storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  2550  
  2551  		messenger := serviceMocks.NewMockMessenger(ctrl)
  2552  
  2553  		provider := issuecredentialMocks.NewMockProvider(ctrl)
  2554  		provider.EXPECT().Messenger().Return(messenger)
  2555  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  2556  
  2557  		svc, err := New(provider)
  2558  		require.NoError(t, err)
  2559  
  2560  		err = svc.ActionContinue("piID")
  2561  		require.Contains(t, fmt.Sprintf("%v", err), "delete transitional payload: "+errMsg)
  2562  	})
  2563  }
  2564  
  2565  func TestService_ActionStop(t *testing.T) {
  2566  	t.Run("Error transitional payload (get)", func(t *testing.T) {
  2567  		ctrl := gomock.NewController(t)
  2568  		defer ctrl.Finish()
  2569  
  2570  		const errMsg = "error"
  2571  
  2572  		store := storageMocks.NewMockStore(ctrl)
  2573  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
  2574  
  2575  		storeProvider := storageMocks.NewMockProvider(ctrl)
  2576  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
  2577  		storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  2578  
  2579  		messenger := serviceMocks.NewMockMessenger(ctrl)
  2580  
  2581  		provider := issuecredentialMocks.NewMockProvider(ctrl)
  2582  		provider.EXPECT().Messenger().Return(messenger)
  2583  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  2584  
  2585  		svc, err := New(provider)
  2586  		require.NoError(t, err)
  2587  
  2588  		err = svc.ActionStop("piID", nil)
  2589  		require.Contains(t, fmt.Sprintf("%v", err), "get transitional payload: store get: "+errMsg)
  2590  	})
  2591  
  2592  	t.Run("Error transitional payload (delete)", func(t *testing.T) {
  2593  		ctrl := gomock.NewController(t)
  2594  		defer ctrl.Finish()
  2595  
  2596  		const errMsg = "error"
  2597  
  2598  		store := storageMocks.NewMockStore(ctrl)
  2599  		store.EXPECT().Get(gomock.Any()).Return([]byte(`{}`), nil)
  2600  		store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg))
  2601  
  2602  		storeProvider := storageMocks.NewMockProvider(ctrl)
  2603  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
  2604  		storeProvider.EXPECT().SetStoreConfig(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
  2605  
  2606  		messenger := serviceMocks.NewMockMessenger(ctrl)
  2607  
  2608  		provider := issuecredentialMocks.NewMockProvider(ctrl)
  2609  		provider.EXPECT().Messenger().Return(messenger)
  2610  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  2611  
  2612  		svc, err := New(provider)
  2613  		require.NoError(t, err)
  2614  
  2615  		err = svc.ActionStop("piID", nil)
  2616  		require.Contains(t, fmt.Sprintf("%v", err), "delete transitional payload: "+errMsg)
  2617  	})
  2618  }
  2619  
  2620  func Test_stateFromName(t *testing.T) {
  2621  	require.Equal(t, stateFromName(stateNameStart, SpecV2), &start{})
  2622  	require.Equal(t, stateFromName(stateNameAbandoning, SpecV2), &abandoning{V: SpecV2})
  2623  	require.Equal(t, stateFromName(stateNameDone, SpecV2), &done{V: SpecV2})
  2624  	require.Equal(t, stateFromName(stateNameProposalReceived, SpecV2), &proposalReceived{V: SpecV2})
  2625  	require.Equal(t, stateFromName(stateNameOfferSent, SpecV2), &offerSent{V: SpecV2})
  2626  	require.Equal(t, stateFromName(stateNameRequestReceived, SpecV2), &requestReceived{V: SpecV2})
  2627  	require.Equal(t, stateFromName(stateNameCredentialIssued, SpecV2), &credentialIssued{V: SpecV2})
  2628  	require.Equal(t, stateFromName(stateNameProposalSent, SpecV2), &proposalSent{V: SpecV2})
  2629  	require.Equal(t, stateFromName(stateNameOfferReceived, SpecV2), &offerReceived{V: SpecV2})
  2630  	require.Equal(t, stateFromName(stateNameRequestSent, SpecV2), &requestSent{V: SpecV2})
  2631  	require.Equal(t, stateFromName(stateNameCredentialReceived, SpecV2), &credentialReceived{V: SpecV2})
  2632  	require.Equal(t, stateFromName("unknown", SpecV2), &noOp{})
  2633  }
  2634  
  2635  func Test_nextState(t *testing.T) {
  2636  	next, err := nextState(service.NewDIDCommMsgMap(ProposeCredentialV2{
  2637  		Type: ProposeCredentialMsgTypeV2,
  2638  	}), true)
  2639  	require.NoError(t, err)
  2640  	require.Equal(t, next, &proposalSent{V: SpecV2})
  2641  
  2642  	next, err = nextState(service.NewDIDCommMsgMap(ProposeCredentialV2{
  2643  		Type: ProposeCredentialMsgTypeV2,
  2644  	}), false)
  2645  	require.NoError(t, err)
  2646  	require.Equal(t, next, &proposalReceived{V: SpecV2})
  2647  
  2648  	next, err = nextState(service.NewDIDCommMsgMap(OfferCredentialV2{
  2649  		Type: OfferCredentialMsgTypeV2,
  2650  	}), true)
  2651  	require.NoError(t, err)
  2652  	require.Equal(t, next, &offerSent{V: SpecV2})
  2653  
  2654  	next, err = nextState(service.NewDIDCommMsgMap(OfferCredentialV2{
  2655  		Type: OfferCredentialMsgTypeV2,
  2656  	}), false)
  2657  	require.NoError(t, err)
  2658  	require.Equal(t, next, &offerReceived{V: SpecV2})
  2659  
  2660  	next, err = nextState(service.NewDIDCommMsgMap(RequestCredentialV2{
  2661  		Type: RequestCredentialMsgTypeV2,
  2662  	}), true)
  2663  	require.NoError(t, err)
  2664  	require.Equal(t, next, &requestSent{V: SpecV2})
  2665  
  2666  	next, err = nextState(service.NewDIDCommMsgMap(RequestCredentialV2{
  2667  		Type: RequestCredentialMsgTypeV2,
  2668  	}), false)
  2669  	require.NoError(t, err)
  2670  	require.Equal(t, next, &requestReceived{V: SpecV2})
  2671  
  2672  	next, err = nextState(service.NewDIDCommMsgMap(IssueCredentialV2{
  2673  		Type: IssueCredentialMsgTypeV2,
  2674  	}), false)
  2675  	require.NoError(t, err)
  2676  	require.Equal(t, next, &credentialReceived{V: SpecV2})
  2677  
  2678  	next, err = nextState(service.NewDIDCommMsgMap(model.Ack{
  2679  		Type: AckMsgTypeV2,
  2680  	}), false)
  2681  	require.NoError(t, err)
  2682  	require.Equal(t, next, &done{V: SpecV2})
  2683  
  2684  	next, err = nextState(service.NewDIDCommMsgMap(model.ProblemReport{
  2685  		Type: ProblemReportMsgTypeV2,
  2686  	}), false)
  2687  	require.NoError(t, err)
  2688  	require.Equal(t, next, &abandoning{V: SpecV2})
  2689  
  2690  	next, err = nextState(service.NewDIDCommMsgMap(struct{}{}), false)
  2691  	require.Error(t, err)
  2692  	require.Nil(t, next)
  2693  }
  2694  
  2695  func TestService_Name(t *testing.T) {
  2696  	require.Equal(t, (*Service).Name(nil), Name)
  2697  }
  2698  
  2699  func TestService_Accept(t *testing.T) {
  2700  	require.True(t, (*Service).Accept(nil, ProposeCredentialMsgTypeV2))
  2701  	require.True(t, (*Service).Accept(nil, OfferCredentialMsgTypeV2))
  2702  	require.True(t, (*Service).Accept(nil, RequestCredentialMsgTypeV2))
  2703  	require.True(t, (*Service).Accept(nil, IssueCredentialMsgTypeV2))
  2704  	require.True(t, (*Service).Accept(nil, AckMsgTypeV2))
  2705  	require.True(t, (*Service).Accept(nil, ProblemReportMsgTypeV2))
  2706  	require.False(t, (*Service).Accept(nil, "unknown"))
  2707  }
  2708  
  2709  func TestService_canTriggerActionEvents(t *testing.T) {
  2710  	require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(ProposeCredentialV2{
  2711  		Type: ProposeCredentialMsgTypeV2,
  2712  	})))
  2713  
  2714  	require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(OfferCredentialV2{
  2715  		Type: OfferCredentialMsgTypeV2,
  2716  	})))
  2717  
  2718  	require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(IssueCredentialV2{
  2719  		Type: IssueCredentialMsgTypeV2,
  2720  	})))
  2721  
  2722  	require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(RequestCredentialV2{
  2723  		Type: RequestCredentialMsgTypeV2,
  2724  	})))
  2725  
  2726  	require.False(t, canTriggerActionEvents(service.NewDIDCommMsgMap(struct{}{})))
  2727  }