github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/introduce/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 introduce_test
     8  
     9  import (
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"runtime"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/golang/mock/gomock"
    18  	"github.com/stretchr/testify/require"
    19  
    20  	"github.com/hyperledger/aries-framework-go/component/storageutil/mem"
    21  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model"
    22  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
    23  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/messenger"
    24  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator"
    25  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/introduce"
    26  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband"
    27  	serviceMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/common/service"
    28  	dispatcherMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/dispatcher"
    29  	messengerMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/messenger"
    30  	introduceMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/protocol/introduce"
    31  	storageMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/spi/storage"
    32  	"github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol"
    33  	"github.com/hyperledger/aries-framework-go/spi/storage"
    34  )
    35  
    36  const (
    37  	// Alice always plays introducer role.
    38  	Alice = "Alice"
    39  	// Bob always plays introducee (first) role.
    40  	Bob = "Bob"
    41  	// Bob always plays introducee (second) role.
    42  	Carol = "Carol"
    43  )
    44  
    45  func TestService_Initialize(t *testing.T) {
    46  	t.Run("success: already initialized", func(t *testing.T) {
    47  		prov := &protocol.MockProvider{}
    48  
    49  		ctrl := gomock.NewController(t)
    50  		defer ctrl.Finish()
    51  
    52  		svc := agentSetup(t, "agent", ctrl, map[string]chan payload{})
    53  
    54  		require.NoError(t, svc.Initialize(prov))
    55  	})
    56  
    57  	t.Run("fail: provider of wrong type", func(t *testing.T) {
    58  		prov := "this is not a provider"
    59  
    60  		svc := introduce.Service{}
    61  
    62  		err := svc.Initialize(prov)
    63  
    64  		require.Error(t, err)
    65  		require.Contains(t, err.Error(), "expected provider of type")
    66  	})
    67  }
    68  
    69  type props interface {
    70  	PIID() string
    71  	MyDID() string
    72  	TheirDID() string
    73  }
    74  
    75  // payload represents a transport message structure.
    76  type payload struct {
    77  	msg      []byte
    78  	myDID    string
    79  	theirDID string
    80  }
    81  
    82  func agentSetup(t *testing.T, agent string, ctrl *gomock.Controller, tr map[string]chan payload) *introduce.Service {
    83  	t.Helper()
    84  
    85  	storageProvider := mem.NewProvider()
    86  	didSvc := serviceMocks.NewMockEvent(ctrl)
    87  	didSvc.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
    88  
    89  	outbound := dispatcherMocks.NewMockOutbound(ctrl)
    90  	outbound.EXPECT().
    91  		SendToDID(gomock.Any(), gomock.Any(), gomock.Any()).
    92  		DoAndReturn(func(msg interface{}, myDID, theirDID string) error {
    93  			src, err := json.Marshal(msg)
    94  			require.NoError(t, err)
    95  
    96  			tr[theirDID] <- payload{
    97  				msg:      src,
    98  				myDID:    theirDID,
    99  				theirDID: myDID,
   100  			}
   101  
   102  			return nil
   103  		}).AnyTimes()
   104  
   105  	mProvider := messengerMocks.NewMockProvider(ctrl)
   106  	mProvider.EXPECT().StorageProvider().Return(storageProvider)
   107  	mProvider.EXPECT().OutboundDispatcher().Return(outbound)
   108  
   109  	provider := introduceMocks.NewMockProvider(ctrl)
   110  	provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
   111  	provider.EXPECT().Service(gomock.Any()).Return(didSvc, nil)
   112  
   113  	msgSvc, err := messenger.NewMessenger(mProvider)
   114  	require.NoError(t, err)
   115  
   116  	provider.EXPECT().Messenger().Return(msgSvc)
   117  
   118  	svc, err := introduce.New(provider)
   119  	require.NoError(t, err)
   120  
   121  	go func() {
   122  		for {
   123  			select {
   124  			case msg := <-tr[agent]:
   125  				didMap, err := service.ParseDIDCommMsgMap(msg.msg)
   126  				require.NoError(t, err)
   127  
   128  				if didMap.Type() == outofband.InvitationMsgType {
   129  					require.NoError(t, svc.OOBMessageReceived(service.StateMsg{
   130  						Type:    service.PreState,
   131  						StateID: "initial",
   132  						Msg:     didMap,
   133  					}))
   134  
   135  					continue
   136  				}
   137  
   138  				require.NoError(t, msgSvc.HandleInbound(didMap, service.NewDIDCommContext(msg.myDID, msg.theirDID, nil)))
   139  				_, err = svc.HandleInbound(didMap, service.NewDIDCommContext(msg.myDID, msg.theirDID, nil))
   140  				require.NoError(t, err)
   141  			case <-time.After(time.Second):
   142  				return
   143  			}
   144  		}
   145  	}()
   146  
   147  	return svc
   148  }
   149  
   150  type (
   151  	checkEvent  func(service.StateMsg)
   152  	checkAction func(service.DIDCommAction)
   153  )
   154  
   155  func handle(t *testing.T, agent string, done chan struct{}, svc *introduce.Service, ce checkEvent, ca checkAction) {
   156  	t.Helper()
   157  
   158  	events := make(chan service.StateMsg)
   159  	require.NoError(t, svc.RegisterMsgEvent(events))
   160  
   161  	done <- struct{}{}
   162  
   163  	go func() {
   164  		defer func() { <-done }()
   165  
   166  		for {
   167  			select {
   168  			case event := <-events:
   169  				ce(event)
   170  			case <-time.After(time.Second):
   171  				t.Errorf("[%s] timeout waiting for state msg", agent)
   172  				return
   173  			}
   174  		}
   175  	}()
   176  
   177  	actions := make(chan service.DIDCommAction)
   178  	require.NoError(t, svc.RegisterActionEvent(actions))
   179  
   180  	done <- struct{}{}
   181  
   182  	go func() {
   183  		defer func() { <-done }()
   184  
   185  		if ca == nil {
   186  			return
   187  		}
   188  
   189  		for {
   190  			select {
   191  			case action := <-actions:
   192  				ca(action)
   193  			case <-time.After(time.Second):
   194  				t.Errorf("[%s] timeout waiting for DIDCommAction", agent)
   195  				return
   196  			}
   197  		}
   198  	}()
   199  }
   200  
   201  func checkStateMsg(t *testing.T, agent string, expected ...string) checkEvent {
   202  	t.Helper()
   203  
   204  	var i int
   205  
   206  	return func(msg service.StateMsg) {
   207  		if msg.StateID != expected[i] {
   208  			t.Errorf("[%s] got %s, expected %s", agent, msg.StateID, expected[i])
   209  		}
   210  
   211  		i++
   212  
   213  		if len(expected) == i {
   214  			runtime.Goexit()
   215  		}
   216  	}
   217  }
   218  
   219  type action struct {
   220  	Expected string
   221  	Opt      interface{}
   222  }
   223  
   224  func checkDIDCommAction(t *testing.T, agent string, expected ...action) checkAction {
   225  	var i int
   226  
   227  	return func(action service.DIDCommAction) {
   228  		if action.Message.Type() != expected[i].Expected {
   229  			t.Errorf("[%s] got %s, expected %s", agent, action.Message.Type(), expected[i])
   230  		}
   231  
   232  		properties, ok := action.Properties.(props)
   233  		require.True(t, ok)
   234  		require.NotEmpty(t, properties.PIID())
   235  		require.NotEmpty(t, properties.MyDID())
   236  		require.NotEmpty(t, properties.TheirDID())
   237  
   238  		action.Continue(expected[i].Opt)
   239  
   240  		i++
   241  
   242  		if len(expected) == i {
   243  			runtime.Goexit()
   244  		}
   245  	}
   246  }
   247  
   248  func wait(t *testing.T, done chan struct{}) {
   249  	for i := 0; i < len(done); i++ {
   250  		select {
   251  		case done <- struct{}{}:
   252  		case <-time.After(time.Second * 2):
   253  			t.Error("timeout")
   254  		}
   255  	}
   256  }
   257  
   258  // Bob received proposal from Alice.
   259  // Alice received response from Bob.
   260  // Bob received invitation from Alice.
   261  func TestService_SkipProposal(t *testing.T) {
   262  	ctrl := gomock.NewController(t)
   263  	defer ctrl.Finish()
   264  
   265  	transport := map[string]chan payload{
   266  		Alice: make(chan payload),
   267  		Bob:   make(chan payload),
   268  	}
   269  
   270  	done := make(chan struct{}, len(transport)*2)
   271  	defer wait(t, done)
   272  
   273  	alice := agentSetup(t, Alice, ctrl, transport)
   274  
   275  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   276  		"arranging", "arranging",
   277  		"arranging", "arranging",
   278  		"delivering", "delivering",
   279  		"done", "done",
   280  	), nil)
   281  
   282  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   283  		"deciding", "deciding",
   284  		"waiting", "waiting",
   285  		"done", "done",
   286  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType}))
   287  
   288  	proposal := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   289  	introduce.WrapWithMetadataPublicOOBInvitation(proposal, &outofband.Invitation{
   290  		Type: outofband.InvitationMsgType,
   291  	})
   292  
   293  	_, err := alice.HandleOutbound(proposal, Alice, Bob)
   294  	require.NoError(t, err)
   295  }
   296  
   297  // Bob received proposal from Alice.
   298  // Carol received proposal from Alice.
   299  // Alice received response from Bob.
   300  // Alice received response from Carol.
   301  // Carol received invitation from Alice.
   302  // Bob received ack from Alice.
   303  func TestService_Proposal(t *testing.T) {
   304  	ctrl := gomock.NewController(t)
   305  	defer ctrl.Finish()
   306  
   307  	transport := map[string]chan payload{
   308  		Alice: make(chan payload),
   309  		Bob:   make(chan payload),
   310  		Carol: make(chan payload),
   311  	}
   312  
   313  	alice := agentSetup(t, Alice, ctrl, transport)
   314  
   315  	done := make(chan struct{}, len(transport)*2)
   316  	defer wait(t, done)
   317  
   318  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   319  		"arranging", "arranging",
   320  		"arranging", "arranging",
   321  		"arranging", "arranging",
   322  		"arranging", "arranging",
   323  		"delivering", "delivering",
   324  		"confirming", "confirming",
   325  		"done", "done",
   326  	), nil)
   327  
   328  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   329  		"deciding", "deciding",
   330  		"waiting", "waiting",
   331  		"done", "done",
   332  	), checkDIDCommAction(t, Bob,
   333  		action{
   334  			Expected: introduce.ProposalMsgType,
   335  			Opt: introduce.WithOOBInvitation(&outofband.Invitation{
   336  				Type: outofband.InvitationMsgType,
   337  			}),
   338  		},
   339  	))
   340  
   341  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
   342  		"deciding", "deciding",
   343  		"waiting", "waiting",
   344  		"done", "done",
   345  	), checkDIDCommAction(t, Carol, action{Expected: introduce.ProposalMsgType}))
   346  
   347  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   348  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   349  
   350  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   351  
   352  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   353  	require.NoError(t, err)
   354  
   355  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   356  	require.NoError(t, err)
   357  }
   358  
   359  // Bob received proposal from Alice.
   360  // Carol received proposal from Alice.
   361  // Alice received response from Bob.
   362  // Alice received response from Carol.
   363  // Carol received invitation from Alice.
   364  // Bob received ack from Alice.
   365  func TestService_ProposalActionContinue(t *testing.T) {
   366  	ctrl := gomock.NewController(t)
   367  	defer ctrl.Finish()
   368  
   369  	transport := map[string]chan payload{
   370  		Alice: make(chan payload),
   371  		Bob:   make(chan payload),
   372  		Carol: make(chan payload),
   373  	}
   374  
   375  	alice := agentSetup(t, Alice, ctrl, transport)
   376  
   377  	done := make(chan struct{}, len(transport)*2)
   378  	defer wait(t, done)
   379  
   380  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   381  		"arranging", "arranging",
   382  		"arranging", "arranging",
   383  		"arranging", "arranging",
   384  		"arranging", "arranging",
   385  		"delivering", "delivering",
   386  		"confirming", "confirming",
   387  		"done", "done",
   388  	), nil)
   389  
   390  	bob := agentSetup(t, Bob, ctrl, transport)
   391  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
   392  		"deciding", "deciding",
   393  		"waiting", "waiting",
   394  		"done", "done",
   395  	), func(_ service.DIDCommAction) {
   396  		actions, err := bob.Actions()
   397  		require.NoError(t, err)
   398  		require.Equal(t, 1, len(actions))
   399  
   400  		require.Equal(t, actions[0].MyDID, Bob)
   401  		require.Equal(t, actions[0].TheirDID, Alice)
   402  
   403  		require.NoError(t, bob.ActionContinue(actions[0].PIID, introduce.WithOOBInvitation(&outofband.Invitation{
   404  			Type: outofband.InvitationMsgType,
   405  		})))
   406  
   407  		runtime.Goexit()
   408  	})
   409  
   410  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
   411  		"deciding", "deciding",
   412  		"waiting", "waiting",
   413  		"done", "done",
   414  	), checkDIDCommAction(t, Carol, action{Expected: introduce.ProposalMsgType}))
   415  
   416  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   417  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   418  
   419  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   420  
   421  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   422  	require.NoError(t, err)
   423  
   424  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   425  	require.NoError(t, err)
   426  }
   427  
   428  // Bob received proposal from Alice.
   429  // Carol received proposal from Alice.
   430  // Alice received response from Bob.
   431  // Alice received response from Carol.
   432  // Bob received invitation from Alice.
   433  // Carol received ack from Alice.
   434  func TestService_ProposalSecond(t *testing.T) {
   435  	ctrl := gomock.NewController(t)
   436  	defer ctrl.Finish()
   437  
   438  	transport := map[string]chan payload{
   439  		Alice: make(chan payload),
   440  		Bob:   make(chan payload),
   441  		Carol: make(chan payload),
   442  	}
   443  
   444  	done := make(chan struct{}, len(transport)*2)
   445  	defer wait(t, done)
   446  
   447  	alice := agentSetup(t, Alice, ctrl, transport)
   448  
   449  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   450  		"arranging", "arranging",
   451  		"arranging", "arranging",
   452  		"arranging", "arranging",
   453  		"arranging", "arranging",
   454  		"delivering", "delivering",
   455  		"confirming", "confirming",
   456  		"done", "done",
   457  	), nil)
   458  
   459  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   460  		"deciding", "deciding",
   461  		"waiting", "waiting",
   462  		"done", "done",
   463  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType}))
   464  
   465  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
   466  		"deciding", "deciding",
   467  		"waiting", "waiting",
   468  		"done", "done",
   469  	), checkDIDCommAction(t, Carol,
   470  		action{
   471  			Expected: introduce.ProposalMsgType,
   472  			Opt: introduce.WithOOBInvitation(&outofband.Invitation{
   473  				Type: outofband.InvitationMsgType,
   474  			}),
   475  		},
   476  	))
   477  
   478  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   479  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   480  
   481  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   482  
   483  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   484  	require.NoError(t, err)
   485  
   486  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   487  	require.NoError(t, err)
   488  }
   489  
   490  // Bob received proposal from Alice.
   491  // Carol received proposal from Alice.
   492  // Alice received response from Bob.
   493  // Alice received response from Carol.
   494  // Bob received invitation from Alice.
   495  // Carol received ack from Alice.
   496  func TestService_ProposalSecondActionContinue(t *testing.T) {
   497  	ctrl := gomock.NewController(t)
   498  	defer ctrl.Finish()
   499  
   500  	transport := map[string]chan payload{
   501  		Alice: make(chan payload),
   502  		Bob:   make(chan payload),
   503  		Carol: make(chan payload),
   504  	}
   505  
   506  	done := make(chan struct{}, len(transport)*2)
   507  	defer wait(t, done)
   508  
   509  	alice := agentSetup(t, Alice, ctrl, transport)
   510  
   511  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   512  		"arranging", "arranging",
   513  		"arranging", "arranging",
   514  		"arranging", "arranging",
   515  		"arranging", "arranging",
   516  		"delivering", "delivering",
   517  		"confirming", "confirming",
   518  		"done", "done",
   519  	), nil)
   520  
   521  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   522  		"deciding", "deciding",
   523  		"waiting", "waiting",
   524  		"done", "done",
   525  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType}))
   526  
   527  	carol := agentSetup(t, Carol, ctrl, transport)
   528  	handle(t, Carol, done, carol, checkStateMsg(t, Carol,
   529  		"deciding", "deciding",
   530  		"waiting", "waiting",
   531  		"done", "done",
   532  	), func(_ service.DIDCommAction) {
   533  		actions, err := carol.Actions()
   534  		require.NoError(t, err)
   535  		require.Equal(t, 1, len(actions))
   536  
   537  		require.Equal(t, actions[0].MyDID, Carol)
   538  		require.Equal(t, actions[0].TheirDID, Alice)
   539  
   540  		require.NoError(t, carol.ActionContinue(actions[0].PIID, introduce.WithOOBInvitation(&outofband.Invitation{
   541  			Type: outofband.InvitationMsgType,
   542  		})))
   543  
   544  		runtime.Goexit()
   545  	})
   546  
   547  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   548  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   549  
   550  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   551  
   552  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   553  	require.NoError(t, err)
   554  
   555  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   556  	require.NoError(t, err)
   557  }
   558  
   559  // Bob received proposal from Alice.
   560  // Carol received proposal from Alice.
   561  // Alice received response from Bob.
   562  // Alice received response from Carol.
   563  // Carol received problem-report from Alice ( no invitation ).
   564  // Bob received problem-report from Alice ( no invitation ).
   565  func TestService_ProposalNoInvitation(t *testing.T) {
   566  	ctrl := gomock.NewController(t)
   567  	defer ctrl.Finish()
   568  
   569  	transport := map[string]chan payload{
   570  		Alice: make(chan payload),
   571  		Bob:   make(chan payload),
   572  		Carol: make(chan payload),
   573  	}
   574  
   575  	done := make(chan struct{}, len(transport)*2)
   576  	defer wait(t, done)
   577  
   578  	alice := agentSetup(t, Alice, ctrl, transport)
   579  
   580  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   581  		"arranging", "arranging",
   582  		"arranging", "arranging",
   583  		"arranging", "arranging",
   584  		"arranging", "arranging",
   585  		"delivering", "delivering",
   586  		"abandoning", "abandoning",
   587  		"done", "done",
   588  	), nil)
   589  
   590  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   591  		"deciding", "deciding",
   592  		"waiting", "waiting",
   593  		"abandoning", "abandoning",
   594  		"done", "done",
   595  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType},
   596  		action{Expected: introduce.ProblemReportMsgType}))
   597  
   598  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
   599  		"deciding", "deciding",
   600  		"waiting", "waiting",
   601  		"abandoning", "abandoning",
   602  		"done", "done",
   603  	), checkDIDCommAction(t, Carol, action{Expected: introduce.ProposalMsgType},
   604  		action{Expected: introduce.ProblemReportMsgType}))
   605  
   606  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   607  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   608  
   609  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   610  
   611  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   612  	require.NoError(t, err)
   613  
   614  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   615  	require.NoError(t, err)
   616  }
   617  
   618  // Bob received proposal from Alice.
   619  // Alice received response from Bob.
   620  func TestService_SkipProposalStopIntroducee(t *testing.T) {
   621  	ctrl := gomock.NewController(t)
   622  	defer ctrl.Finish()
   623  
   624  	transport := map[string]chan payload{
   625  		Alice: make(chan payload),
   626  		Bob:   make(chan payload),
   627  	}
   628  
   629  	done := make(chan struct{}, len(transport)*2)
   630  	defer wait(t, done)
   631  
   632  	alice := agentSetup(t, Alice, ctrl, transport)
   633  
   634  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   635  		"arranging", "arranging",
   636  		"arranging", "arranging",
   637  		"abandoning", "abandoning",
   638  		"done", "done",
   639  	), nil)
   640  
   641  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   642  		"deciding", "deciding",
   643  		"abandoning", "abandoning",
   644  		"done", "done",
   645  	), func(action service.DIDCommAction) {
   646  		properties, ok := action.Properties.(props)
   647  		require.True(t, ok)
   648  		require.NotEmpty(t, properties.PIID())
   649  		require.Equal(t, properties.MyDID(), Bob)
   650  		require.Equal(t, properties.TheirDID(), Alice)
   651  
   652  		action.Stop(errors.New("hmm... I don't wanna know her"))
   653  		runtime.Goexit()
   654  	})
   655  
   656  	proposal := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   657  	introduce.WrapWithMetadataPublicOOBInvitation(proposal, &outofband.Invitation{
   658  		Type: outofband.InvitationMsgType,
   659  	})
   660  
   661  	_, err := alice.HandleOutbound(proposal, Alice, Bob)
   662  	require.NoError(t, err)
   663  }
   664  
   665  // Bob received proposal from Alice.
   666  // Alice received response from Bob.
   667  func TestService_SkipProposalActionStopIntroducee(t *testing.T) {
   668  	ctrl := gomock.NewController(t)
   669  	defer ctrl.Finish()
   670  
   671  	transport := map[string]chan payload{
   672  		Alice: make(chan payload),
   673  		Bob:   make(chan payload),
   674  	}
   675  
   676  	done := make(chan struct{}, len(transport)*2)
   677  	defer wait(t, done)
   678  
   679  	alice := agentSetup(t, Alice, ctrl, transport)
   680  	bob := agentSetup(t, Bob, ctrl, transport)
   681  
   682  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   683  		"arranging", "arranging",
   684  		"arranging", "arranging",
   685  		"abandoning", "abandoning",
   686  		"done", "done",
   687  	), nil)
   688  
   689  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
   690  		"deciding", "deciding",
   691  		"abandoning", "abandoning",
   692  		"done", "done",
   693  	), func(_ service.DIDCommAction) {
   694  		actions, err := bob.Actions()
   695  		require.NoError(t, err)
   696  		require.Equal(t, 1, len(actions))
   697  
   698  		require.Equal(t, actions[0].MyDID, Bob)
   699  		require.Equal(t, actions[0].TheirDID, Alice)
   700  
   701  		require.NoError(t, bob.ActionStop(actions[0].PIID, errors.New("hmm... I don't wanna know her")))
   702  		runtime.Goexit()
   703  	})
   704  
   705  	proposal := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   706  	introduce.WrapWithMetadataPublicOOBInvitation(proposal, &outofband.Invitation{
   707  		Type: outofband.InvitationMsgType,
   708  	})
   709  
   710  	_, err := alice.HandleOutbound(proposal, Alice, Bob)
   711  	require.NoError(t, err)
   712  }
   713  
   714  // Bob received proposal from Alice.
   715  // Carol received proposal from Alice.
   716  // Alice received response from Bob.
   717  // Alice received response from Carol.
   718  // Carol received problem-report from Alice ( not approved ).
   719  func TestService_ProposalStopIntroduceeFirst(t *testing.T) {
   720  	ctrl := gomock.NewController(t)
   721  	defer ctrl.Finish()
   722  
   723  	transport := map[string]chan payload{
   724  		Alice: make(chan payload),
   725  		Bob:   make(chan payload),
   726  		Carol: make(chan payload),
   727  	}
   728  
   729  	done := make(chan struct{}, len(transport)*2)
   730  	defer wait(t, done)
   731  
   732  	alice := agentSetup(t, Alice, ctrl, transport)
   733  
   734  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   735  		"arranging", "arranging",
   736  		"arranging", "arranging",
   737  		"arranging", "arranging",
   738  		"arranging", "arranging",
   739  		"abandoning", "abandoning",
   740  		"done", "done",
   741  	), nil)
   742  
   743  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   744  		"deciding", "deciding",
   745  		"abandoning", "abandoning",
   746  		"done", "done",
   747  	), func(action service.DIDCommAction) {
   748  		properties, ok := action.Properties.(props)
   749  		require.True(t, ok)
   750  		require.NotEmpty(t, properties.PIID())
   751  		require.Equal(t, properties.MyDID(), Bob)
   752  		require.Equal(t, properties.TheirDID(), Alice)
   753  
   754  		action.Stop(errors.New("hmm... I don't wanna know her"))
   755  		runtime.Goexit()
   756  	})
   757  
   758  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
   759  		"deciding", "deciding",
   760  		"waiting", "waiting",
   761  		"abandoning", "abandoning",
   762  		"done", "done",
   763  	), checkDIDCommAction(t, Carol, action{Expected: introduce.ProposalMsgType},
   764  		action{Expected: introduce.ProblemReportMsgType}))
   765  
   766  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   767  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   768  
   769  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   770  
   771  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   772  	require.NoError(t, err)
   773  
   774  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   775  	require.NoError(t, err)
   776  }
   777  
   778  // Carol received proposal from Alice.
   779  // Bob received proposal from Alice.
   780  // Alice received response from Bob.
   781  // Alice received response from Carol.
   782  // Bob received problem-report from Alice ( not approved ).
   783  func TestService_ProposalStopIntroduceeSecond(t *testing.T) {
   784  	ctrl := gomock.NewController(t)
   785  	defer ctrl.Finish()
   786  
   787  	transport := map[string]chan payload{
   788  		Alice: make(chan payload),
   789  		Bob:   make(chan payload),
   790  		Carol: make(chan payload),
   791  	}
   792  
   793  	done := make(chan struct{}, len(transport)*2)
   794  	defer wait(t, done)
   795  
   796  	alice := agentSetup(t, Alice, ctrl, transport)
   797  
   798  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   799  		"arranging", "arranging",
   800  		"arranging", "arranging",
   801  		"arranging", "arranging",
   802  		"arranging", "arranging",
   803  		"abandoning", "abandoning",
   804  		"done", "done",
   805  	), nil)
   806  
   807  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   808  		"deciding", "deciding",
   809  		"waiting", "waiting",
   810  		"abandoning", "abandoning",
   811  		"done", "done",
   812  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType},
   813  		action{Expected: introduce.ProblemReportMsgType}))
   814  
   815  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
   816  		"deciding", "deciding",
   817  		"abandoning", "abandoning",
   818  		"done", "done",
   819  	), func(action service.DIDCommAction) {
   820  		properties, ok := action.Properties.(props)
   821  		require.True(t, ok)
   822  		require.NotEmpty(t, properties.PIID())
   823  		require.Equal(t, properties.MyDID(), Carol)
   824  		require.Equal(t, properties.TheirDID(), Alice)
   825  
   826  		action.Stop(errors.New("hmm... I don't wanna know him"))
   827  		runtime.Goexit()
   828  	})
   829  
   830  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   831  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   832  
   833  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   834  
   835  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   836  	require.NoError(t, err)
   837  
   838  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   839  	require.NoError(t, err)
   840  }
   841  
   842  // Carol received proposal from Alice.
   843  // Bob received proposal from Alice.
   844  // Alice received response from Bob.
   845  // Alice received response from Carol.
   846  // Bob received problem-report from Alice ( not approved ).
   847  func TestService_ProposalActionStopIntroduceeSecond(t *testing.T) {
   848  	ctrl := gomock.NewController(t)
   849  	defer ctrl.Finish()
   850  
   851  	transport := map[string]chan payload{
   852  		Alice: make(chan payload),
   853  		Bob:   make(chan payload),
   854  		Carol: make(chan payload),
   855  	}
   856  
   857  	done := make(chan struct{}, len(transport)*2)
   858  	defer wait(t, done)
   859  
   860  	alice := agentSetup(t, Alice, ctrl, transport)
   861  	carol := agentSetup(t, Carol, ctrl, transport)
   862  
   863  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
   864  		"arranging", "arranging",
   865  		"arranging", "arranging",
   866  		"arranging", "arranging",
   867  		"arranging", "arranging",
   868  		"abandoning", "abandoning",
   869  		"done", "done",
   870  	), nil)
   871  
   872  	handle(t, Bob, done, agentSetup(t, Bob, ctrl, transport), checkStateMsg(t, Bob,
   873  		"deciding", "deciding",
   874  		"waiting", "waiting",
   875  		"abandoning", "abandoning",
   876  		"done", "done",
   877  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType},
   878  		action{Expected: introduce.ProblemReportMsgType}))
   879  
   880  	handle(t, Carol, done, carol, checkStateMsg(t, Carol,
   881  		"deciding", "deciding",
   882  		"abandoning", "abandoning",
   883  		"done", "done",
   884  	), func(_ service.DIDCommAction) {
   885  		actions, err := carol.Actions()
   886  		require.NoError(t, err)
   887  		require.Equal(t, 1, len(actions))
   888  
   889  		require.Equal(t, actions[0].MyDID, Carol)
   890  		require.Equal(t, actions[0].TheirDID, Alice)
   891  
   892  		require.NoError(t, carol.ActionStop(actions[0].PIID, errors.New("hmm... I don't wanna know him")))
   893  		runtime.Goexit()
   894  		runtime.Goexit()
   895  	})
   896  
   897  	proposal1 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Carol}})
   898  	proposal2 := introduce.CreateProposal(&introduce.Recipient{To: &introduce.To{Name: Bob}})
   899  
   900  	introduce.WrapWithMetadataPIID(proposal1, proposal2)
   901  
   902  	_, err := alice.HandleOutbound(proposal1, Alice, Bob)
   903  	require.NoError(t, err)
   904  
   905  	_, err = alice.HandleOutbound(proposal2, Alice, Carol)
   906  	require.NoError(t, err)
   907  }
   908  
   909  // Alice received request from Bob.
   910  // Bob received proposal from Alice.
   911  // Carol received proposal from Alice.
   912  // Alice received response from Bob.
   913  // Alice received response from Carol.
   914  // Carol received invitation from Alice.
   915  // Bob received ack from Alice.
   916  func TestService_ProposalWithRequest(t *testing.T) {
   917  	ctrl := gomock.NewController(t)
   918  	defer ctrl.Finish()
   919  
   920  	transport := map[string]chan payload{
   921  		Alice: make(chan payload),
   922  		Bob:   make(chan payload),
   923  		Carol: make(chan payload),
   924  	}
   925  
   926  	done := make(chan struct{}, len(transport)*2)
   927  	defer wait(t, done)
   928  
   929  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
   930  		"arranging", "arranging",
   931  		"arranging", "arranging",
   932  		"arranging", "arranging",
   933  		"delivering", "delivering",
   934  		"confirming", "confirming",
   935  		"done", "done",
   936  	), checkDIDCommAction(t, Alice,
   937  		action{
   938  			Expected: introduce.RequestMsgType,
   939  			Opt: introduce.WithRecipients(&introduce.To{
   940  				Name: Carol,
   941  			}, &introduce.Recipient{
   942  				To: &introduce.To{
   943  					Name: Bob,
   944  				},
   945  				MyDID:    Alice,
   946  				TheirDID: Carol,
   947  			}),
   948  		},
   949  	))
   950  
   951  	bob := agentSetup(t, Bob, ctrl, transport)
   952  
   953  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
   954  		"requesting", "requesting",
   955  		"deciding", "deciding",
   956  		"waiting", "waiting",
   957  		"done", "done",
   958  	), checkDIDCommAction(t, Bob,
   959  		action{
   960  			Expected: introduce.ProposalMsgType,
   961  			Opt: introduce.WithOOBInvitation(&outofband.Invitation{
   962  				Type: outofband.InvitationMsgType,
   963  			}),
   964  		},
   965  	))
   966  
   967  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
   968  		"deciding", "deciding",
   969  		"waiting", "waiting",
   970  		"done", "done",
   971  	), checkDIDCommAction(t, Carol, action{Expected: introduce.ProposalMsgType}))
   972  
   973  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
   974  		Type: introduce.RequestMsgType,
   975  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
   976  			Name: Carol,
   977  		}},
   978  	}), Bob, Alice)
   979  	require.NoError(t, err)
   980  }
   981  
   982  // Alice received request from Bob.
   983  // Bob received proposal from Alice.
   984  // Carol received proposal from Alice.
   985  // Alice received response from Bob.
   986  // Alice received response from Carol.
   987  // Carol received invitation from Alice.
   988  // Bob received ack from Alice.
   989  func TestService_ProposalWithRequestActionContinue(t *testing.T) {
   990  	ctrl := gomock.NewController(t)
   991  	defer ctrl.Finish()
   992  
   993  	transport := map[string]chan payload{
   994  		Alice: make(chan payload),
   995  		Bob:   make(chan payload),
   996  		Carol: make(chan payload),
   997  	}
   998  
   999  	done := make(chan struct{}, len(transport)*2)
  1000  	defer wait(t, done)
  1001  
  1002  	alice := agentSetup(t, Alice, ctrl, transport)
  1003  	handle(t, Alice, done, alice, checkStateMsg(t, Alice,
  1004  		"arranging", "arranging",
  1005  		"arranging", "arranging",
  1006  		"arranging", "arranging",
  1007  		"delivering", "delivering",
  1008  		"confirming", "confirming",
  1009  		"done", "done",
  1010  	), func(_ service.DIDCommAction) {
  1011  		actions, err := alice.Actions()
  1012  		require.NoError(t, err)
  1013  		require.Equal(t, 1, len(actions))
  1014  
  1015  		require.Equal(t, actions[0].MyDID, Alice)
  1016  		require.Equal(t, actions[0].TheirDID, Bob)
  1017  
  1018  		require.NoError(t, alice.ActionContinue(actions[0].PIID, introduce.WithRecipients(&introduce.To{
  1019  			Name: Carol,
  1020  		}, &introduce.Recipient{
  1021  			To: &introduce.To{
  1022  				Name: Bob,
  1023  			},
  1024  			MyDID:    Alice,
  1025  			TheirDID: Carol,
  1026  		})))
  1027  
  1028  		runtime.Goexit()
  1029  	})
  1030  
  1031  	bob := agentSetup(t, Bob, ctrl, transport)
  1032  
  1033  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1034  		"requesting", "requesting",
  1035  		"deciding", "deciding",
  1036  		"waiting", "waiting",
  1037  		"done", "done",
  1038  	), func(commAction service.DIDCommAction) {
  1039  		actions, err := bob.Actions()
  1040  		require.NoError(t, err)
  1041  		require.Equal(t, 1, len(actions))
  1042  
  1043  		require.Equal(t, actions[0].MyDID, Bob)
  1044  		require.Equal(t, actions[0].TheirDID, Alice)
  1045  
  1046  		require.NoError(t, bob.ActionContinue(actions[0].PIID, introduce.WithOOBInvitation(&outofband.Invitation{
  1047  			Type: outofband.InvitationMsgType,
  1048  		})))
  1049  
  1050  		runtime.Goexit()
  1051  	})
  1052  
  1053  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
  1054  		"deciding", "deciding",
  1055  		"waiting", "waiting",
  1056  		"done", "done",
  1057  	), checkDIDCommAction(t, Carol, action{Expected: introduce.ProposalMsgType}))
  1058  
  1059  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1060  		Type: introduce.RequestMsgType,
  1061  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1062  			Name: Carol,
  1063  		}},
  1064  	}), Bob, Alice)
  1065  	require.NoError(t, err)
  1066  }
  1067  
  1068  // Alice received request from Bob.
  1069  // Bob received proposal from Alice.
  1070  // Carol received proposal from Alice.
  1071  // Alice received response from Bob.
  1072  // Alice received response from Carol.
  1073  // Bob received invitation from Alice.
  1074  // Carol received ack from Alice.
  1075  func TestService_ProposalWithRequestSecond(t *testing.T) {
  1076  	ctrl := gomock.NewController(t)
  1077  	defer ctrl.Finish()
  1078  
  1079  	transport := map[string]chan payload{
  1080  		Alice: make(chan payload),
  1081  		Bob:   make(chan payload),
  1082  		Carol: make(chan payload),
  1083  	}
  1084  
  1085  	done := make(chan struct{}, len(transport)*2)
  1086  	defer wait(t, done)
  1087  
  1088  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
  1089  		"arranging", "arranging",
  1090  		"arranging", "arranging",
  1091  		"arranging", "arranging",
  1092  		"delivering", "delivering",
  1093  		"confirming", "confirming",
  1094  		"done", "done",
  1095  	), checkDIDCommAction(t, Alice,
  1096  		action{
  1097  			Expected: introduce.RequestMsgType,
  1098  			Opt: introduce.WithRecipients(&introduce.To{
  1099  				Name: Carol,
  1100  			}, &introduce.Recipient{
  1101  				To: &introduce.To{
  1102  					Name: Bob,
  1103  				},
  1104  				MyDID:    Alice,
  1105  				TheirDID: Carol,
  1106  			}),
  1107  		},
  1108  	))
  1109  
  1110  	bob := agentSetup(t, Bob, ctrl, transport)
  1111  
  1112  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1113  		"requesting", "requesting",
  1114  		"deciding", "deciding",
  1115  		"waiting", "waiting",
  1116  		"done", "done",
  1117  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType}))
  1118  
  1119  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
  1120  		"deciding", "deciding",
  1121  		"waiting", "waiting",
  1122  		"done", "done",
  1123  	), checkDIDCommAction(t, Carol,
  1124  		action{
  1125  			Expected: introduce.ProposalMsgType,
  1126  			Opt: introduce.WithOOBInvitation(&outofband.Invitation{
  1127  				Type: outofband.InvitationMsgType,
  1128  			}),
  1129  		},
  1130  	))
  1131  
  1132  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1133  		Type: introduce.RequestMsgType,
  1134  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1135  			Name: Carol,
  1136  		}},
  1137  	}), Bob, Alice)
  1138  	require.NoError(t, err)
  1139  }
  1140  
  1141  // Alice received request from Bob.
  1142  // Bob received proposal from Alice.
  1143  // Carol received proposal from Alice.
  1144  // Alice received response from Bob.
  1145  // Alice received response from Carol.
  1146  // Carol received problem-report from Alice ( not approved ).
  1147  func TestService_ProposalWithRequestStopIntroduceeFirst(t *testing.T) {
  1148  	ctrl := gomock.NewController(t)
  1149  	defer ctrl.Finish()
  1150  
  1151  	transport := map[string]chan payload{
  1152  		Alice: make(chan payload),
  1153  		Bob:   make(chan payload),
  1154  		Carol: make(chan payload),
  1155  	}
  1156  
  1157  	done := make(chan struct{}, len(transport)*2)
  1158  	defer wait(t, done)
  1159  
  1160  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
  1161  		"arranging", "arranging",
  1162  		"arranging", "arranging",
  1163  		"arranging", "arranging",
  1164  		"abandoning", "abandoning",
  1165  		"done", "done",
  1166  	), checkDIDCommAction(t, Alice,
  1167  		action{
  1168  			Expected: introduce.RequestMsgType,
  1169  			Opt: introduce.WithRecipients(&introduce.To{
  1170  				Name: Carol,
  1171  			}, &introduce.Recipient{
  1172  				To: &introduce.To{
  1173  					Name: Bob,
  1174  				},
  1175  				MyDID:    Alice,
  1176  				TheirDID: Carol,
  1177  			}),
  1178  		},
  1179  	))
  1180  
  1181  	bob := agentSetup(t, Bob, ctrl, transport)
  1182  
  1183  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1184  		"requesting", "requesting",
  1185  		"deciding", "deciding",
  1186  		"abandoning", "abandoning",
  1187  		"done", "done",
  1188  	), func(action service.DIDCommAction) {
  1189  		properties, ok := action.Properties.(props)
  1190  		require.True(t, ok)
  1191  		require.NotEmpty(t, properties.PIID())
  1192  		require.Equal(t, properties.MyDID(), Bob)
  1193  		require.Equal(t, properties.TheirDID(), Alice)
  1194  
  1195  		action.Stop(errors.New("hmm... I don't wanna know her"))
  1196  		runtime.Goexit()
  1197  	})
  1198  
  1199  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
  1200  		"deciding", "deciding",
  1201  		"waiting", "waiting",
  1202  		"abandoning", "abandoning",
  1203  		"done", "done",
  1204  	), checkDIDCommAction(t, Carol, action{Expected: introduce.ProposalMsgType},
  1205  		action{Expected: introduce.ProblemReportMsgType}))
  1206  
  1207  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1208  		Type: introduce.RequestMsgType,
  1209  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1210  			Name: Carol,
  1211  		}},
  1212  	}), Bob, Alice)
  1213  	require.NoError(t, err)
  1214  }
  1215  
  1216  // Alice received request from Bob.
  1217  // Carol received proposal from Alice.
  1218  // Bob received proposal from Alice.
  1219  // Alice received response from Carol.
  1220  // Alice received response from Bob.
  1221  // Bob received problem-report from Alice ( not approved ).
  1222  func TestService_ProposalWithRequestStopIntroduceeSecond(t *testing.T) {
  1223  	ctrl := gomock.NewController(t)
  1224  	defer ctrl.Finish()
  1225  
  1226  	transport := map[string]chan payload{
  1227  		Alice: make(chan payload),
  1228  		Bob:   make(chan payload),
  1229  		Carol: make(chan payload),
  1230  	}
  1231  
  1232  	done := make(chan struct{}, len(transport)*2)
  1233  	defer wait(t, done)
  1234  
  1235  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
  1236  		"arranging", "arranging",
  1237  		"arranging", "arranging",
  1238  		"arranging", "arranging",
  1239  		"abandoning", "abandoning",
  1240  		"done", "done",
  1241  	), checkDIDCommAction(t, Alice,
  1242  		action{
  1243  			Expected: introduce.RequestMsgType,
  1244  			Opt: introduce.WithRecipients(&introduce.To{
  1245  				Name: Carol,
  1246  			}, &introduce.Recipient{
  1247  				To: &introduce.To{
  1248  					Name: Bob,
  1249  				},
  1250  				MyDID:    Alice,
  1251  				TheirDID: Carol,
  1252  			}),
  1253  		},
  1254  	))
  1255  
  1256  	bob := agentSetup(t, Bob, ctrl, transport)
  1257  
  1258  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1259  		"requesting", "requesting",
  1260  		"deciding", "deciding",
  1261  		"waiting", "waiting",
  1262  		"abandoning", "abandoning",
  1263  		"done", "done",
  1264  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType},
  1265  		action{Expected: introduce.ProblemReportMsgType}))
  1266  
  1267  	handle(t, Carol, done, agentSetup(t, Carol, ctrl, transport), checkStateMsg(t, Carol,
  1268  		"deciding", "deciding",
  1269  		"abandoning", "abandoning",
  1270  		"done", "done",
  1271  	), func(action service.DIDCommAction) {
  1272  		properties, ok := action.Properties.(props)
  1273  		require.True(t, ok)
  1274  		require.NotEmpty(t, properties.PIID())
  1275  		require.Equal(t, properties.MyDID(), Carol)
  1276  		require.Equal(t, properties.TheirDID(), Alice)
  1277  
  1278  		action.Stop(errors.New("hmm... I don't wanna know him"))
  1279  		runtime.Goexit()
  1280  	})
  1281  
  1282  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1283  		Type: introduce.RequestMsgType,
  1284  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1285  			Name: Carol,
  1286  		}},
  1287  	}), Bob, Alice)
  1288  	require.NoError(t, err)
  1289  }
  1290  
  1291  // Alice received request from Bob.
  1292  // Bob received problem-report from Alice ( request declined ).
  1293  func TestService_ProposalWithRequestIntroducerStop(t *testing.T) {
  1294  	ctrl := gomock.NewController(t)
  1295  	defer ctrl.Finish()
  1296  
  1297  	transport := map[string]chan payload{
  1298  		Alice: make(chan payload),
  1299  		Bob:   make(chan payload),
  1300  	}
  1301  
  1302  	done := make(chan struct{}, len(transport)*2)
  1303  	defer wait(t, done)
  1304  
  1305  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
  1306  		"abandoning", "abandoning",
  1307  		"done", "done",
  1308  	), func(action service.DIDCommAction) {
  1309  		properties, ok := action.Properties.(props)
  1310  		require.True(t, ok)
  1311  		require.NotEmpty(t, properties.PIID())
  1312  		require.Equal(t, properties.MyDID(), Alice)
  1313  		require.Equal(t, properties.TheirDID(), Bob)
  1314  
  1315  		action.Stop(errors.New("sorry, I don't know her"))
  1316  		runtime.Goexit()
  1317  	})
  1318  
  1319  	bob := agentSetup(t, Bob, ctrl, transport)
  1320  
  1321  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1322  		"requesting", "requesting",
  1323  		"abandoning", "abandoning",
  1324  		"done", "done",
  1325  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProblemReportMsgType}))
  1326  
  1327  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1328  		Type: introduce.RequestMsgType,
  1329  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1330  			Name: Carol,
  1331  		}},
  1332  	}), Bob, Alice)
  1333  	require.NoError(t, err)
  1334  }
  1335  
  1336  // Alice received request from Bob.
  1337  // Bob received proposal from Alice.
  1338  // Alice received response from Bob.
  1339  // Bob received invitation from Alice.
  1340  func TestService_SkipProposalWithRequest(t *testing.T) {
  1341  	ctrl := gomock.NewController(t)
  1342  	defer ctrl.Finish()
  1343  
  1344  	transport := map[string]chan payload{
  1345  		Alice: make(chan payload),
  1346  		Bob:   make(chan payload),
  1347  	}
  1348  
  1349  	done := make(chan struct{}, len(transport)*2)
  1350  	defer wait(t, done)
  1351  
  1352  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
  1353  		"arranging", "arranging",
  1354  		"arranging", "arranging",
  1355  		"delivering", "delivering",
  1356  		"done", "done",
  1357  	), checkDIDCommAction(t, Alice,
  1358  		action{
  1359  			Expected: introduce.RequestMsgType,
  1360  			Opt: introduce.WithPublicOOBInvitation(&outofband.Invitation{
  1361  				Type: outofband.InvitationMsgType,
  1362  			}, &introduce.To{
  1363  				Name: Carol,
  1364  			}),
  1365  		},
  1366  	))
  1367  
  1368  	bob := agentSetup(t, Bob, ctrl, transport)
  1369  
  1370  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1371  		"requesting", "requesting",
  1372  		"deciding", "deciding",
  1373  		"waiting", "waiting",
  1374  		"done", "done",
  1375  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProposalMsgType}))
  1376  
  1377  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1378  		Type: introduce.RequestMsgType,
  1379  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1380  			Name: Carol,
  1381  		}},
  1382  	}), Bob, Alice)
  1383  	require.NoError(t, err)
  1384  }
  1385  
  1386  // Alice received request from Bob.
  1387  // Bob received proposal from Alice.
  1388  // Alice received response from Bob.
  1389  func TestService_SkipProposalWithRequestStopIntroducee(t *testing.T) {
  1390  	ctrl := gomock.NewController(t)
  1391  	defer ctrl.Finish()
  1392  
  1393  	transport := map[string]chan payload{
  1394  		Alice: make(chan payload),
  1395  		Bob:   make(chan payload),
  1396  	}
  1397  
  1398  	done := make(chan struct{}, len(transport)*2)
  1399  	defer wait(t, done)
  1400  
  1401  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
  1402  		"arranging", "arranging",
  1403  		"arranging", "arranging",
  1404  		"abandoning", "abandoning",
  1405  		"done", "done",
  1406  	), checkDIDCommAction(t, Alice,
  1407  		action{
  1408  			Expected: introduce.RequestMsgType,
  1409  			Opt: introduce.WithPublicOOBInvitation(&outofband.Invitation{
  1410  				Type: outofband.InvitationMsgType,
  1411  			}, &introduce.To{
  1412  				Name: Carol,
  1413  			}),
  1414  		},
  1415  	))
  1416  
  1417  	bob := agentSetup(t, Bob, ctrl, transport)
  1418  
  1419  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1420  		"requesting", "requesting",
  1421  		"deciding", "deciding",
  1422  		"abandoning", "abandoning",
  1423  		"done", "done",
  1424  	), func(action service.DIDCommAction) {
  1425  		properties, ok := action.Properties.(props)
  1426  		require.True(t, ok)
  1427  		require.NotEmpty(t, properties.PIID())
  1428  		require.Equal(t, properties.MyDID(), Bob)
  1429  		require.Equal(t, properties.TheirDID(), Alice)
  1430  
  1431  		action.Stop(errors.New("hmm... I don't wanna know her"))
  1432  		runtime.Goexit()
  1433  	})
  1434  
  1435  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1436  		Type: introduce.RequestMsgType,
  1437  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1438  			Name: Carol,
  1439  		}},
  1440  	}), Bob, Alice)
  1441  	require.NoError(t, err)
  1442  }
  1443  
  1444  // Alice received request from Bob.
  1445  // Bob received problem-report from Alice.
  1446  func TestService_ProposalWithRequestNoRecipients(t *testing.T) {
  1447  	ctrl := gomock.NewController(t)
  1448  	defer ctrl.Finish()
  1449  
  1450  	transport := map[string]chan payload{
  1451  		Alice: make(chan payload),
  1452  		Bob:   make(chan payload),
  1453  	}
  1454  
  1455  	done := make(chan struct{}, len(transport)*2)
  1456  	defer wait(t, done)
  1457  
  1458  	handle(t, Alice, done, agentSetup(t, Alice, ctrl, transport), checkStateMsg(t, Alice,
  1459  		"abandoning", "abandoning",
  1460  		"done", "done",
  1461  	), checkDIDCommAction(t, Alice,
  1462  		action{Expected: introduce.RequestMsgType},
  1463  	))
  1464  
  1465  	bob := agentSetup(t, Bob, ctrl, transport)
  1466  
  1467  	handle(t, Bob, done, bob, checkStateMsg(t, Bob,
  1468  		"requesting", "requesting",
  1469  		"abandoning", "abandoning",
  1470  		"done", "done",
  1471  	), checkDIDCommAction(t, Bob, action{Expected: introduce.ProblemReportMsgType}))
  1472  
  1473  	_, err := bob.HandleOutbound(service.NewDIDCommMsgMap(&introduce.Request{
  1474  		Type: introduce.RequestMsgType,
  1475  		PleaseIntroduceTo: &introduce.PleaseIntroduceTo{To: introduce.To{
  1476  			Name: Carol,
  1477  		}},
  1478  	}), Bob, Alice)
  1479  	require.NoError(t, err)
  1480  }
  1481  
  1482  func TestService_Accept(t *testing.T) {
  1483  	svc := &introduce.Service{}
  1484  
  1485  	require.False(t, svc.Accept(""))
  1486  	require.True(t, svc.Accept(introduce.ProposalMsgType))
  1487  	require.True(t, svc.Accept(introduce.RequestMsgType))
  1488  	require.True(t, svc.Accept(introduce.ResponseMsgType))
  1489  	require.True(t, svc.Accept(introduce.AckMsgType))
  1490  	require.True(t, svc.Accept(introduce.ProblemReportMsgType))
  1491  }
  1492  
  1493  func TestService_Name(t *testing.T) {
  1494  	require.Equal(t, introduce.Introduce, (&introduce.Service{}).Name())
  1495  }
  1496  
  1497  func TestService_New(t *testing.T) {
  1498  	const errMsg = "test err"
  1499  
  1500  	ctrl := gomock.NewController(t)
  1501  	defer ctrl.Finish()
  1502  
  1503  	t.Run("OpenStore Error", func(t *testing.T) {
  1504  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1505  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(nil, errors.New(errMsg))
  1506  
  1507  		provider := introduceMocks.NewMockProvider(ctrl)
  1508  		provider.EXPECT().StorageProvider().Return(storageProvider)
  1509  
  1510  		svc, err := introduce.New(provider)
  1511  		require.EqualError(t, err, "test err")
  1512  		require.Nil(t, svc)
  1513  	})
  1514  
  1515  	t.Run("Service Error", func(t *testing.T) {
  1516  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1517  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(nil, nil)
  1518  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1519  
  1520  		provider := introduceMocks.NewMockProvider(ctrl)
  1521  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1522  		provider.EXPECT().Service(outofband.Name).Return(nil, errors.New(errMsg))
  1523  
  1524  		svc, err := introduce.New(provider)
  1525  		require.EqualError(t, err, "load the out-of-band service: test err")
  1526  		require.Nil(t, svc)
  1527  	})
  1528  
  1529  	t.Run("Cast Service Error", func(t *testing.T) {
  1530  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1531  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(nil, nil)
  1532  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1533  
  1534  		provider := introduceMocks.NewMockProvider(ctrl)
  1535  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1536  		provider.EXPECT().Service(outofband.Name).Return(nil, nil)
  1537  
  1538  		svc, err := introduce.New(provider)
  1539  		require.EqualError(t, err, "cast service to service.Event")
  1540  		require.Nil(t, svc)
  1541  	})
  1542  
  1543  	t.Run("wraps error returned during msg event registration", func(t *testing.T) {
  1544  		expected := errors.New("test")
  1545  
  1546  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1547  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(nil, nil)
  1548  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1549  		provider := introduceMocks.NewMockProvider(ctrl)
  1550  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1551  		provider.EXPECT().Messenger().Return(nil)
  1552  
  1553  		oobService := serviceMocks.NewMockDIDComm(ctrl)
  1554  		oobService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(expected)
  1555  		provider.EXPECT().Service(outofband.Name).Return(oobService, nil)
  1556  
  1557  		_, err := introduce.New(provider)
  1558  		require.Error(t, err)
  1559  		require.True(t, errors.Is(err, expected))
  1560  	})
  1561  }
  1562  
  1563  func TestService_HandleOutbound(t *testing.T) {
  1564  	t.Run("Invalid state", func(t *testing.T) {
  1565  		ctrl := gomock.NewController(t)
  1566  		defer ctrl.Finish()
  1567  
  1568  		store := storageMocks.NewMockStore(ctrl)
  1569  		raw := fmt.Sprintf(`{"state_name":%q, "wait_count":%d}`, "unknown", 1)
  1570  		store.EXPECT().Get(gomock.Any()).Return([]byte(raw), nil)
  1571  
  1572  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1573  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1574  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1575  
  1576  		didService := serviceMocks.NewMockDIDComm(ctrl)
  1577  		didService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1578  
  1579  		provider := introduceMocks.NewMockProvider(ctrl)
  1580  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1581  		provider.EXPECT().Messenger().Return(nil)
  1582  		provider.EXPECT().Service(outofband.Name).Return(didService, nil)
  1583  
  1584  		svc, err := introduce.New(provider)
  1585  
  1586  		require.NoError(t, err)
  1587  
  1588  		msg, err := service.ParseDIDCommMsgMap([]byte(fmt.Sprintf(`{"@id":"ID","@type":%q}`, introduce.ProposalMsgType)))
  1589  		require.NoError(t, err)
  1590  		ch := make(chan service.DIDCommAction)
  1591  		require.NoError(t, svc.RegisterActionEvent(ch))
  1592  		const errMsg = "doHandle: invalid state transition: noop -> arranging"
  1593  		_, err = svc.HandleOutbound(msg, "", "")
  1594  		require.EqualError(t, err, errMsg)
  1595  	})
  1596  }
  1597  
  1598  func TestService_HandleInbound(t *testing.T) {
  1599  	t.Parallel()
  1600  
  1601  	t.Run("No clients", func(t *testing.T) {
  1602  		ctrl := gomock.NewController(t)
  1603  		defer ctrl.Finish()
  1604  
  1605  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1606  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(nil, nil)
  1607  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1608  
  1609  		didService := serviceMocks.NewMockDIDComm(ctrl)
  1610  		didService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1611  
  1612  		provider := introduceMocks.NewMockProvider(ctrl)
  1613  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1614  		provider.EXPECT().Messenger().Return(nil)
  1615  		provider.EXPECT().Service(outofband.Name).Return(didService, nil)
  1616  
  1617  		svc, err := introduce.New(provider)
  1618  		require.NoError(t, err)
  1619  
  1620  		_, err = svc.HandleInbound(service.DIDCommMsgMap{}, service.EmptyDIDCommContext())
  1621  		require.EqualError(t, err, "no clients are registered to handle the message")
  1622  	})
  1623  
  1624  	t.Run("Storage error", func(t *testing.T) {
  1625  		const errMsg = "test err"
  1626  
  1627  		ctrl := gomock.NewController(t)
  1628  		defer ctrl.Finish()
  1629  
  1630  		store := storageMocks.NewMockStore(ctrl)
  1631  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1632  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
  1633  
  1634  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1635  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1636  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1637  
  1638  		didService := serviceMocks.NewMockDIDComm(ctrl)
  1639  		didService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1640  
  1641  		provider := introduceMocks.NewMockProvider(ctrl)
  1642  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1643  		provider.EXPECT().Messenger().Return(nil)
  1644  		provider.EXPECT().Service(outofband.Name).Return(didService, nil)
  1645  
  1646  		svc, err := introduce.New(provider)
  1647  		require.NoError(t, err)
  1648  
  1649  		msg, err := service.ParseDIDCommMsgMap([]byte(fmt.Sprintf(`{"@id":"ID","@type":%q}`, introduce.ProposalMsgType)))
  1650  		require.NoError(t, err)
  1651  		ch := make(chan service.DIDCommAction)
  1652  		require.NoError(t, svc.RegisterActionEvent(ch))
  1653  
  1654  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
  1655  		require.EqualError(t, err, "doHandle: currentStateName: test err")
  1656  	})
  1657  
  1658  	t.Run("Populate metadata error", func(t *testing.T) {
  1659  		const errMsg = "test err"
  1660  
  1661  		ctrl := gomock.NewController(t)
  1662  		defer ctrl.Finish()
  1663  
  1664  		store := storageMocks.NewMockStore(ctrl)
  1665  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
  1666  
  1667  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1668  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1669  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1670  
  1671  		didService := serviceMocks.NewMockDIDComm(ctrl)
  1672  		didService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1673  
  1674  		provider := introduceMocks.NewMockProvider(ctrl)
  1675  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1676  		provider.EXPECT().Messenger().Return(nil)
  1677  		provider.EXPECT().Service(outofband.Name).Return(didService, nil)
  1678  
  1679  		svc, err := introduce.New(provider)
  1680  		require.NoError(t, err)
  1681  
  1682  		msg, err := service.ParseDIDCommMsgMap([]byte(fmt.Sprintf(`{"@id":"ID","@type":%q}`, introduce.ProposalMsgType)))
  1683  		require.NoError(t, err)
  1684  		ch := make(chan service.DIDCommAction)
  1685  		require.NoError(t, svc.RegisterActionEvent(ch))
  1686  
  1687  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
  1688  		require.EqualError(t, err, "populate metadata: get record: test err")
  1689  	})
  1690  
  1691  	t.Run("Bad transition", func(t *testing.T) {
  1692  		ctrl := gomock.NewController(t)
  1693  		defer ctrl.Finish()
  1694  
  1695  		store := storageMocks.NewMockStore(ctrl)
  1696  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1697  		store.EXPECT().Get(gomock.Any()).Return([]byte(`{"state_name":"noop","wait_count":1}`), nil)
  1698  
  1699  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1700  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1701  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1702  
  1703  		didService := serviceMocks.NewMockDIDComm(ctrl)
  1704  		didService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1705  
  1706  		provider := introduceMocks.NewMockProvider(ctrl)
  1707  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1708  		provider.EXPECT().Messenger().Return(nil)
  1709  		provider.EXPECT().Service(outofband.Name).Return(didService, nil)
  1710  
  1711  		svc, err := introduce.New(provider)
  1712  		require.NoError(t, err)
  1713  
  1714  		msg, err := service.ParseDIDCommMsgMap([]byte(fmt.Sprintf(`{"@id":"ID","@type":%q}`, introduce.ProposalMsgType)))
  1715  		require.NoError(t, err)
  1716  		ch := make(chan service.DIDCommAction)
  1717  		require.NoError(t, svc.RegisterActionEvent(ch))
  1718  
  1719  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
  1720  		require.EqualError(t, err, "doHandle: invalid state transition: noop -> deciding")
  1721  	})
  1722  
  1723  	t.Run("Unknown msg type error", func(t *testing.T) {
  1724  		ctrl := gomock.NewController(t)
  1725  		defer ctrl.Finish()
  1726  
  1727  		store := storageMocks.NewMockStore(ctrl)
  1728  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1729  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound)
  1730  
  1731  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1732  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1733  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1734  
  1735  		didService := serviceMocks.NewMockDIDComm(ctrl)
  1736  		didService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1737  
  1738  		provider := introduceMocks.NewMockProvider(ctrl)
  1739  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1740  		provider.EXPECT().Messenger().Return(nil)
  1741  		provider.EXPECT().Service(outofband.Name).Return(didService, nil)
  1742  
  1743  		svc, err := introduce.New(provider)
  1744  		require.NoError(t, err)
  1745  
  1746  		msg, err := service.ParseDIDCommMsgMap([]byte(`{"@id":"ID","@type":"unknown"}`))
  1747  		require.NoError(t, err)
  1748  		ch := make(chan service.DIDCommAction)
  1749  		require.NoError(t, svc.RegisterActionEvent(ch))
  1750  
  1751  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
  1752  		require.EqualError(t, err, "doHandle: nextState: unrecognized msgType: unknown")
  1753  	})
  1754  }
  1755  
  1756  func TestService_ActionStop(t *testing.T) {
  1757  	ctrl := gomock.NewController(t)
  1758  	defer ctrl.Finish()
  1759  
  1760  	const errMsg = "error"
  1761  
  1762  	store := storageMocks.NewMockStore(ctrl)
  1763  	store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
  1764  
  1765  	storageProvider := storageMocks.NewMockProvider(ctrl)
  1766  	storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1767  	storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1768  
  1769  	oobService := serviceMocks.NewMockDIDComm(ctrl)
  1770  	oobService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1771  
  1772  	provider := introduceMocks.NewMockProvider(ctrl)
  1773  	provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1774  	provider.EXPECT().Messenger().Return(nil)
  1775  	provider.EXPECT().Service(outofband.Name).Return(oobService, nil)
  1776  
  1777  	s, err := introduce.New(provider)
  1778  	require.NoError(t, err)
  1779  
  1780  	require.EqualError(t, s.ActionStop("piid", nil), "get transitional payload: store get: "+errMsg)
  1781  }
  1782  
  1783  func TestOOBMessageReceived(t *testing.T) {
  1784  	ctrl := gomock.NewController(t)
  1785  	defer ctrl.Finish()
  1786  
  1787  	t.Run("ignores msg not in requested state", func(t *testing.T) {
  1788  		ignored := true
  1789  		store := storageMocks.NewMockStore(ctrl)
  1790  		store.EXPECT().Get(gomock.Any()).MaxTimes(0).DoAndReturn(
  1791  			func(string) ([]byte, error) {
  1792  				ignored = false
  1793  				return nil, nil
  1794  			},
  1795  		)
  1796  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1797  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1798  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1799  		provider := introduceMocks.NewMockProvider(ctrl)
  1800  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1801  		provider.EXPECT().Messenger().Return(nil)
  1802  		oobService := serviceMocks.NewMockDIDComm(ctrl)
  1803  		oobService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1804  		provider.EXPECT().Service(outofband.Name).Return(oobService, nil)
  1805  
  1806  		s, err := introduce.New(provider)
  1807  		require.NoError(t, err)
  1808  
  1809  		err = s.OOBMessageReceived(service.StateMsg{
  1810  			Type:    service.PostState,
  1811  			StateID: "invalid",
  1812  			Msg: service.NewDIDCommMsgMap(&model.Ack{
  1813  				Thread: &decorator.Thread{
  1814  					PID: "123",
  1815  				},
  1816  			}),
  1817  		})
  1818  		require.NoError(t, err)
  1819  		require.True(t, ignored)
  1820  	})
  1821  	t.Run("ignores pre-state msgs", func(t *testing.T) {
  1822  		ignored := true
  1823  		store := storageMocks.NewMockStore(ctrl)
  1824  		store.EXPECT().Get(gomock.Any()).MaxTimes(0).DoAndReturn(
  1825  			func(string) ([]byte, error) {
  1826  				ignored = false
  1827  				return nil, nil
  1828  			},
  1829  		)
  1830  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1831  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1832  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1833  		provider := introduceMocks.NewMockProvider(ctrl)
  1834  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1835  		provider.EXPECT().Messenger().Return(nil)
  1836  		oobService := serviceMocks.NewMockDIDComm(ctrl)
  1837  		oobService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1838  		provider.EXPECT().Service(outofband.Name).Return(oobService, nil)
  1839  
  1840  		s, err := introduce.New(provider)
  1841  		require.NoError(t, err)
  1842  
  1843  		err = s.OOBMessageReceived(service.StateMsg{
  1844  			Type:    service.PreState,
  1845  			StateID: "requested",
  1846  			Msg: service.NewDIDCommMsgMap(&model.Ack{
  1847  				Thread: &decorator.Thread{
  1848  					PID: "123",
  1849  				},
  1850  			}),
  1851  		})
  1852  		require.NoError(t, err)
  1853  		require.True(t, ignored)
  1854  	})
  1855  	t.Run("ignores msgs with no parent thread", func(t *testing.T) {
  1856  		ignored := true
  1857  		store := storageMocks.NewMockStore(ctrl)
  1858  		store.EXPECT().Get(gomock.Any()).MaxTimes(0).DoAndReturn(
  1859  			func(string) ([]byte, error) {
  1860  				ignored = false
  1861  				return nil, nil
  1862  			},
  1863  		)
  1864  		storageProvider := storageMocks.NewMockProvider(ctrl)
  1865  		storageProvider.EXPECT().OpenStore(introduce.Introduce).Return(store, nil)
  1866  		storageProvider.EXPECT().SetStoreConfig(introduce.Introduce, gomock.Any()).Return(nil)
  1867  		provider := introduceMocks.NewMockProvider(ctrl)
  1868  		provider.EXPECT().StorageProvider().Return(storageProvider).Times(2)
  1869  		provider.EXPECT().Messenger().Return(nil)
  1870  		oobService := serviceMocks.NewMockDIDComm(ctrl)
  1871  		oobService.EXPECT().RegisterMsgEvent(gomock.Any()).Return(nil)
  1872  		provider.EXPECT().Service(outofband.Name).Return(oobService, nil)
  1873  
  1874  		s, err := introduce.New(provider)
  1875  		require.NoError(t, err)
  1876  
  1877  		err = s.OOBMessageReceived(service.StateMsg{
  1878  			Type:    service.PostState,
  1879  			StateID: "requested",
  1880  			Msg:     service.NewDIDCommMsgMap(&model.Ack{}),
  1881  		})
  1882  		require.NoError(t, err)
  1883  		require.True(t, ignored)
  1884  	})
  1885  }