github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/legacyconnection/service_test.go (about)

     1  /*
     2  Copyright Avast Software. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package legacyconnection
     8  
     9  import (
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/btcsuite/btcutil/base58"
    18  	"github.com/google/uuid"
    19  	"github.com/stretchr/testify/require"
    20  
    21  	commonmodel "github.com/hyperledger/aries-framework-go/pkg/common/model"
    22  	"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto"
    23  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model"
    24  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
    25  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator"
    26  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator"
    27  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/transport"
    28  	"github.com/hyperledger/aries-framework-go/pkg/doc/did"
    29  	vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr"
    30  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    31  	"github.com/hyperledger/aries-framework-go/pkg/kms/localkms"
    32  	"github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol"
    33  	mockroute "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator"
    34  	mockdiddoc "github.com/hyperledger/aries-framework-go/pkg/mock/diddoc"
    35  	mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
    36  	mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider"
    37  	mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    38  	mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr"
    39  	"github.com/hyperledger/aries-framework-go/pkg/secretlock"
    40  	"github.com/hyperledger/aries-framework-go/pkg/secretlock/noop"
    41  	"github.com/hyperledger/aries-framework-go/pkg/store/connection"
    42  	didstore "github.com/hyperledger/aries-framework-go/pkg/store/did"
    43  	"github.com/hyperledger/aries-framework-go/pkg/vdr/peer"
    44  	"github.com/hyperledger/aries-framework-go/spi/storage"
    45  )
    46  
    47  const (
    48  	testMethod    = "peer"
    49  	threadIDValue = "xyz"
    50  )
    51  
    52  type event interface {
    53  	// connection ID
    54  	ConnectionID() string
    55  
    56  	// invitation ID
    57  	InvitationID() string
    58  }
    59  
    60  func TestService_Name(t *testing.T) {
    61  	t.Run("test success", func(t *testing.T) {
    62  		prov, err := New(&protocol.MockProvider{
    63  			ServiceMap: map[string]interface{}{
    64  				mediator.Coordination: &mockroute.MockMediatorSvc{},
    65  			},
    66  		})
    67  		require.NoError(t, err)
    68  		require.Equal(t, LegacyConnection, prov.Name())
    69  	})
    70  }
    71  
    72  func TestServiceNew(t *testing.T) {
    73  	t.Run("test error from open store", func(t *testing.T) {
    74  		_, err := New(
    75  			&protocol.MockProvider{StoreProvider: &mockstorage.MockStoreProvider{
    76  				ErrOpenStoreHandle: fmt.Errorf("failed to open store"),
    77  			}})
    78  		require.Error(t, err)
    79  		require.Contains(t, err.Error(), "failed to open store")
    80  	})
    81  
    82  	t.Run("test error from open protocol state store", func(t *testing.T) {
    83  		_, err := New(
    84  			&protocol.MockProvider{ProtocolStateStoreProvider: &mockstorage.MockStoreProvider{
    85  				ErrOpenStoreHandle: fmt.Errorf("failed to open protocol state store"),
    86  			}})
    87  		require.Error(t, err)
    88  		require.Contains(t, err.Error(), "failed to open protocol state store")
    89  	})
    90  
    91  	t.Run("test service new error - no route service found", func(t *testing.T) {
    92  		_, err := New(&protocol.MockProvider{ServiceErr: errors.New("service not found")})
    93  		require.Error(t, err)
    94  		require.Contains(t, err.Error(), "service not found")
    95  	})
    96  
    97  	t.Run("test service new error - casting to route service failed", func(t *testing.T) {
    98  		_, err := New(&protocol.MockProvider{})
    99  		require.Error(t, err)
   100  		require.Contains(t, err.Error(), "cast service to Route Service failed")
   101  	})
   102  }
   103  
   104  func TestService_Initialize(t *testing.T) {
   105  	t.Run("success: already initialized", func(t *testing.T) {
   106  		prov := &protocol.MockProvider{
   107  			ServiceMap: map[string]interface{}{
   108  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   109  			},
   110  		}
   111  
   112  		svc, err := New(prov)
   113  		require.NoError(t, err)
   114  
   115  		require.NoError(t, svc.Initialize(prov))
   116  	})
   117  
   118  	t.Run("fail: provider of wrong type", func(t *testing.T) {
   119  		prov := "this is not a provider"
   120  
   121  		svc := Service{}
   122  
   123  		err := svc.Initialize(prov)
   124  
   125  		require.Error(t, err)
   126  		require.Contains(t, err.Error(), "expected provider of type")
   127  	})
   128  }
   129  
   130  // connection flow with role Inviter.
   131  func TestService_Handle_Inviter(t *testing.T) {
   132  	mockStore := &mockstorage.MockStore{Store: make(map[string]mockstorage.DBEntry)}
   133  	storeProv := mockstorage.NewCustomMockStoreProvider(mockStore)
   134  	k := newKMS(t, storeProv)
   135  	prov := &protocol.MockProvider{
   136  		StoreProvider: storeProv,
   137  		ServiceMap: map[string]interface{}{
   138  			mediator.Coordination: &mockroute.MockMediatorSvc{},
   139  		},
   140  		CustomKMS:             k,
   141  		KeyTypeValue:          kms.ED25519Type,
   142  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
   143  	}
   144  
   145  	ctx := &context{
   146  		outboundDispatcher: prov.OutboundDispatcher(),
   147  		crypto:             &tinkcrypto.Crypto{},
   148  		kms:                k,
   149  		keyType:            kms.ED25519Type,
   150  		keyAgreementType:   kms.X25519ECDHKWType,
   151  	}
   152  
   153  	_, pubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
   154  	require.NoError(t, err)
   155  
   156  	ctx.vdRegistry = &mockvdr.MockVDRegistry{CreateValue: createDIDDocWithKey(pubKey)}
   157  
   158  	connRec, err := connection.NewRecorder(prov)
   159  	require.NoError(t, err)
   160  	require.NotNil(t, connRec)
   161  
   162  	ctx.connectionRecorder = connRec
   163  
   164  	doc, err := ctx.vdRegistry.Create(testMethod, nil)
   165  	require.NoError(t, err)
   166  
   167  	s, err := New(prov)
   168  	require.NoError(t, err)
   169  
   170  	actionCh := make(chan service.DIDCommAction, 10)
   171  	err = s.RegisterActionEvent(actionCh)
   172  	require.NoError(t, err)
   173  
   174  	statusCh := make(chan service.StateMsg, 10)
   175  	err = s.RegisterMsgEvent(statusCh)
   176  	require.NoError(t, err)
   177  
   178  	completedFlag := make(chan struct{})
   179  	respondedFlag := make(chan struct{})
   180  
   181  	go msgEventListener(t, statusCh, respondedFlag, completedFlag)
   182  
   183  	go func() { service.AutoExecuteActionEvent(actionCh) }()
   184  
   185  	invitation := &Invitation{
   186  		Type:            InvitationMsgType,
   187  		ID:              randomString(),
   188  		Label:           "Bob",
   189  		RecipientKeys:   []string{base58.Encode(pubKey)},
   190  		ServiceEndpoint: "http://alice.agent.example.com:8081",
   191  	}
   192  
   193  	err = ctx.connectionRecorder.SaveInvitation(invitation.ID, invitation)
   194  	require.NoError(t, err)
   195  
   196  	thid := randomString()
   197  
   198  	// Invitation was previously sent by Alice to Bob.
   199  	// Bob now sends a connection Request
   200  	payloadBytes, err := json.Marshal(
   201  		&Request{
   202  			Type:  RequestMsgType,
   203  			ID:    thid,
   204  			Label: "Bob",
   205  			Thread: &decorator.Thread{
   206  				PID: invitation.ID,
   207  			},
   208  			Connection: &Connection{
   209  				DID:    doc.DIDDocument.ID,
   210  				DIDDoc: doc.DIDDocument,
   211  			},
   212  		})
   213  	require.NoError(t, err)
   214  	msg, err := service.ParseDIDCommMsgMap(payloadBytes)
   215  	require.NoError(t, err)
   216  	_, err = s.HandleInbound(msg, service.NewDIDCommContext(doc.DIDDocument.ID, "", nil))
   217  	require.NoError(t, err)
   218  
   219  	select {
   220  	case <-respondedFlag:
   221  	case <-time.After(2 * time.Second):
   222  		require.Fail(t, "didn't receive post event responded")
   223  	}
   224  	// Alice automatically sends connection Response to Bob
   225  	// Bob replies with an ACK
   226  	payloadBytes, err = json.Marshal(
   227  		&model.Ack{
   228  			Type:   AckMsgType,
   229  			ID:     randomString(),
   230  			Status: "OK",
   231  			Thread: &decorator.Thread{ID: thid},
   232  		})
   233  	require.NoError(t, err)
   234  
   235  	didMsg, err := service.ParseDIDCommMsgMap(payloadBytes)
   236  	require.NoError(t, err)
   237  
   238  	_, err = s.HandleInbound(didMsg, service.NewDIDCommContext(doc.DIDDocument.ID, "", nil))
   239  	require.NoError(t, err)
   240  
   241  	select {
   242  	case <-completedFlag:
   243  	case <-time.After(2 * time.Second):
   244  		require.Fail(t, "didn't receive post event complete")
   245  	}
   246  
   247  	validateState(t, s, thid, findNamespace(AckMsgType), (&completed{}).Name())
   248  }
   249  
   250  func msgEventListener(t *testing.T, statusCh chan service.StateMsg, respondedFlag, completedFlag chan struct{}) {
   251  	for e := range statusCh {
   252  		require.Equal(t, LegacyConnection, e.ProtocolName)
   253  
   254  		prop, ok := e.Properties.(event)
   255  		if !ok {
   256  			require.Fail(t, "Failed to cast the event properties to service.Event")
   257  		}
   258  		// Get the connectionID when it's created
   259  		if e.Type == service.PreState {
   260  			if e.StateID == "requested" {
   261  				require.NotNil(t, prop.ConnectionID())
   262  				require.NotNil(t, prop.InvitationID())
   263  			}
   264  		}
   265  
   266  		if e.Type == service.PostState {
   267  			// receive the events
   268  			if e.StateID == "completed" {
   269  				// validate connectionID received during state transition with original connectionID
   270  				require.NotNil(t, prop.ConnectionID())
   271  				require.NotNil(t, prop.InvitationID())
   272  				close(completedFlag)
   273  			}
   274  
   275  			if e.StateID == "responded" {
   276  				// validate connectionID received during state transition with original connectionID
   277  				require.NotNil(t, prop.ConnectionID())
   278  				require.NotNil(t, prop.InvitationID())
   279  				close(respondedFlag)
   280  			}
   281  		}
   282  	}
   283  }
   284  
   285  type kmsProvider struct {
   286  	store             kms.Store
   287  	secretLockService secretlock.Service
   288  }
   289  
   290  func (k *kmsProvider) StorageProvider() kms.Store {
   291  	return k.store
   292  }
   293  
   294  func (k *kmsProvider) SecretLock() secretlock.Service {
   295  	return k.secretLockService
   296  }
   297  
   298  func newKMS(t *testing.T, store storage.Provider) kms.KeyManager {
   299  	t.Helper()
   300  
   301  	kmsStore, err := kms.NewAriesProviderWrapper(store)
   302  	require.NoError(t, err)
   303  
   304  	kmsProv := &kmsProvider{
   305  		store:             kmsStore,
   306  		secretLockService: &noop.NoLock{},
   307  	}
   308  
   309  	customKMS, err := localkms.New("local-lock://primary/test/", kmsProv)
   310  	require.NoError(t, err)
   311  
   312  	return customKMS
   313  }
   314  
   315  // connection flow with role Invitee.
   316  func TestService_Handle_Invitee(t *testing.T) {
   317  	protocolStateStore := mockstorage.NewMockStoreProvider()
   318  	store := mockstorage.NewMockStoreProvider()
   319  	k := newKMS(t, store)
   320  	prov := &protocol.MockProvider{
   321  		StoreProvider:              store,
   322  		ProtocolStateStoreProvider: protocolStateStore,
   323  		ServiceMap: map[string]interface{}{
   324  			mediator.Coordination: &mockroute.MockMediatorSvc{},
   325  		},
   326  		CustomKMS:             k,
   327  		KeyTypeValue:          kms.ED25519Type,
   328  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
   329  	}
   330  
   331  	mtp := transport.MediaTypeRFC0019EncryptedEnvelope
   332  
   333  	ctx := &context{
   334  		outboundDispatcher: prov.OutboundDispatcher(),
   335  		crypto:             &tinkcrypto.Crypto{},
   336  		kms:                k,
   337  		keyType:            kms.ED25519Type,
   338  		keyAgreementType:   kms.X25519ECDHKWType,
   339  		mediaTypeProfiles:  []string{mtp},
   340  	}
   341  
   342  	_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
   343  	require.NoError(t, err)
   344  
   345  	ctx.vdRegistry = &mockvdr.MockVDRegistry{CreateValue: createDIDDocWithKey(verPubKey)}
   346  
   347  	connRec, err := connection.NewRecorder(prov)
   348  	require.NoError(t, err)
   349  	require.NotNil(t, connRec)
   350  
   351  	ctx.connectionRecorder = connRec
   352  
   353  	doc, err := ctx.vdRegistry.Create(testMethod, nil)
   354  	require.NoError(t, err)
   355  
   356  	s, err := New(prov)
   357  	require.NoError(t, err)
   358  
   359  	s.ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: doc.DIDDocument}
   360  	actionCh := make(chan service.DIDCommAction, 10)
   361  	err = s.RegisterActionEvent(actionCh)
   362  	require.NoError(t, err)
   363  
   364  	statusCh := make(chan service.StateMsg, 10)
   365  	err = s.RegisterMsgEvent(statusCh)
   366  	require.NoError(t, err)
   367  
   368  	requestedCh := make(chan string)
   369  	completedCh := make(chan struct{})
   370  
   371  	go handleMessagesInvitee(statusCh, requestedCh, completedCh)
   372  
   373  	go func() { service.AutoExecuteActionEvent(actionCh) }()
   374  
   375  	invitation := &Invitation{
   376  		Type:            InvitationMsgType,
   377  		ID:              randomString(),
   378  		Label:           "Bob",
   379  		RecipientKeys:   []string{base58.Encode(verPubKey)},
   380  		ServiceEndpoint: "http://alice.agent.example.com:8081",
   381  	}
   382  
   383  	err = ctx.connectionRecorder.SaveInvitation(invitation.ID, invitation)
   384  	require.NoError(t, err)
   385  	// Alice receives an invitation from Bob
   386  	payloadBytes, err := json.Marshal(invitation)
   387  	require.NoError(t, err)
   388  
   389  	didMsg, err := service.ParseDIDCommMsgMap(payloadBytes)
   390  	require.NoError(t, err)
   391  
   392  	_, err = s.HandleInbound(didMsg, service.EmptyDIDCommContext())
   393  	require.NoError(t, err)
   394  
   395  	var connID string
   396  	select {
   397  	case connID = <-requestedCh:
   398  	case <-time.After(2 * time.Second):
   399  		require.Fail(t, "didn't receive post event requested")
   400  	}
   401  
   402  	// Alice automatically sends a Request to Bob and is now in REQUESTED state.
   403  	connRecord, err := s.connectionRecorder.GetConnectionRecord(connID)
   404  	require.NoError(t, err)
   405  	require.Equal(t, (&requested{}).Name(), connRecord.State)
   406  	require.Equal(t, invitation.ID, connRecord.InvitationID)
   407  	require.Equal(t, invitation.RecipientKeys, connRecord.RecipientKeys)
   408  	uri, err := connRecord.ServiceEndPoint.URI()
   409  	require.NoError(t, err)
   410  	require.Equal(t, invitation.ServiceEndpoint, uri)
   411  
   412  	connectionSignature, err := ctx.prepareConnectionSignature(doc.DIDDocument, invitation.RecipientKeys[0])
   413  	require.NoError(t, err)
   414  
   415  	// Bob replies with a Response
   416  	payloadBytes, err = json.Marshal(
   417  		&Response{
   418  			Type: ResponseMsgType,
   419  			ID:   randomString(),
   420  			Thread: &decorator.Thread{
   421  				ID: connRecord.ThreadID,
   422  			},
   423  			ConnectionSignature: connectionSignature,
   424  			PleaseAck: &PleaseAck{
   425  				On: []string{PlsAckOnReceipt},
   426  			},
   427  		},
   428  	)
   429  	require.NoError(t, err)
   430  
   431  	didMsg, err = service.ParseDIDCommMsgMap(payloadBytes)
   432  	require.NoError(t, err)
   433  
   434  	_, err = s.HandleInbound(didMsg, service.EmptyDIDCommContext())
   435  	require.NoError(t, err)
   436  
   437  	// Alice automatically sends an ACK to Bob
   438  	// Alice must now be in COMPLETED state
   439  	select {
   440  	case <-completedCh:
   441  	case <-time.After(2 * time.Second):
   442  		require.Fail(t, "didn't receive post event complete")
   443  	}
   444  
   445  	validateState(t, s, connRecord.ThreadID, findNamespace(ResponseMsgType), (&completed{}).Name())
   446  }
   447  
   448  func handleMessagesInvitee(statusCh chan service.StateMsg, requestedCh chan string, completedCh chan struct{}) {
   449  	for e := range statusCh {
   450  		if e.Type == service.PostState {
   451  			// receive the events
   452  			if e.StateID == StateIDCompleted {
   453  				close(completedCh)
   454  			} else if e.StateID == StateIDRequested {
   455  				prop, ok := e.Properties.(event)
   456  				if !ok {
   457  					panic("Failed to cast the event properties to service.Event")
   458  				}
   459  
   460  				requestedCh <- prop.ConnectionID()
   461  			}
   462  		}
   463  	}
   464  }
   465  
   466  func TestService_Handle_EdgeCases(t *testing.T) {
   467  	t.Run("handleInbound - must not transition to same state", func(t *testing.T) {
   468  		s, err := New(&protocol.MockProvider{
   469  			ServiceMap: map[string]interface{}{
   470  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   471  			},
   472  		})
   473  		require.NoError(t, err)
   474  
   475  		err = s.RegisterActionEvent(make(chan service.DIDCommAction))
   476  		require.NoError(t, err)
   477  
   478  		response, err := json.Marshal(
   479  			&Response{
   480  				Type:   ResponseMsgType,
   481  				ID:     randomString(),
   482  				Thread: &decorator.Thread{ID: randomString()},
   483  			},
   484  		)
   485  		require.NoError(t, err)
   486  
   487  		didMsg, err := service.ParseDIDCommMsgMap(response)
   488  		require.NoError(t, err)
   489  
   490  		_, err = s.HandleInbound(didMsg, service.EmptyDIDCommContext())
   491  		require.Error(t, err)
   492  		require.Contains(t, err.Error(), "handle inbound - next state : invalid state transition: "+
   493  			"null -> responded")
   494  	})
   495  
   496  	t.Run("handleInbound - connection record error", func(t *testing.T) {
   497  		protocolStateStore := &mockstorage.MockStore{
   498  			Store:  make(map[string]mockstorage.DBEntry),
   499  			ErrPut: errors.New("db error"),
   500  		}
   501  		prov := &protocol.MockProvider{
   502  			ProtocolStateStoreProvider: mockstorage.NewCustomMockStoreProvider(protocolStateStore),
   503  			ServiceMap: map[string]interface{}{
   504  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   505  			},
   506  		}
   507  		svc, err := New(prov)
   508  		require.NoError(t, err)
   509  
   510  		err = svc.RegisterActionEvent(make(chan service.DIDCommAction))
   511  		require.NoError(t, err)
   512  
   513  		svc.connectionRecorder, err = connection.NewRecorder(prov)
   514  		require.NotNil(t, svc.connectionRecorder)
   515  		require.NoError(t, err)
   516  
   517  		_, err = svc.HandleInbound(
   518  			generateRequestMsgPayload(t, &protocol.MockProvider{}, randomString(), randomString()),
   519  			service.EmptyDIDCommContext())
   520  		require.Error(t, err)
   521  		require.Contains(t, err.Error(), "save connection record")
   522  	})
   523  
   524  	t.Run("handleInbound - no error", func(t *testing.T) {
   525  		svc, err := New(&protocol.MockProvider{
   526  			ServiceMap: map[string]interface{}{
   527  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   528  			},
   529  		})
   530  		require.NoError(t, err)
   531  
   532  		err = svc.RegisterActionEvent(make(chan service.DIDCommAction))
   533  		require.NoError(t, err)
   534  
   535  		protocolStateStore := &mockStore{
   536  			get: func(s string) (bytes []byte, e error) {
   537  				return nil, storage.ErrDataNotFound
   538  			},
   539  			put: func(s string, bytes []byte, tags ...storage.Tag) error {
   540  				if strings.Contains(s, "didex-event-") {
   541  					return errors.New("db error")
   542  				}
   543  
   544  				return nil
   545  			},
   546  		}
   547  
   548  		svc.connectionRecorder, err = connection.NewRecorder(&protocol.MockProvider{
   549  			ProtocolStateStoreProvider: mockstorage.NewCustomMockStoreProvider(protocolStateStore),
   550  		})
   551  		require.NotNil(t, svc.connectionRecorder)
   552  		require.NoError(t, err)
   553  
   554  		requestBytes, err := json.Marshal(&Request{
   555  			Type: RequestMsgType,
   556  			ID:   generateRandomID(),
   557  			Connection: &Connection{
   558  				DID: "xyz",
   559  			},
   560  			Thread: &decorator.Thread{
   561  				PID: randomString(),
   562  			},
   563  		})
   564  		require.NoError(t, err)
   565  
   566  		// send invite
   567  		didMsg, err := service.ParseDIDCommMsgMap(requestBytes)
   568  		require.NoError(t, err)
   569  
   570  		_, err = svc.HandleInbound(didMsg, service.EmptyDIDCommContext())
   571  		require.NoError(t, err)
   572  	})
   573  }
   574  
   575  func TestService_Accept(t *testing.T) {
   576  	s := &Service{}
   577  
   578  	require.Equal(t, true, s.Accept("https://didcomm.org/connections/1.0/invitation"))
   579  	require.Equal(t, true, s.Accept("https://didcomm.org/connections/1.0/request"))
   580  	require.Equal(t, true, s.Accept("https://didcomm.org/connections/1.0/response"))
   581  	require.Equal(t, true, s.Accept("https://didcomm.org/notification/1.0/ack"))
   582  	require.Equal(t, false, s.Accept("unsupported msg type"))
   583  }
   584  
   585  func TestService_CurrentState(t *testing.T) {
   586  	t.Run("null state if not found in store", func(t *testing.T) {
   587  		connRec, err := connection.NewRecorder(&protocol.MockProvider{
   588  			StoreProvider: mockstorage.NewCustomMockStoreProvider(&mockStore{
   589  				get: func(string) ([]byte, error) { return nil, storage.ErrDataNotFound },
   590  			}),
   591  		})
   592  		require.NotNil(t, connRec)
   593  		require.NoError(t, err)
   594  
   595  		svc := &Service{
   596  			connectionRecorder: connRec,
   597  		}
   598  		thid, err := connection.CreateNamespaceKey(theirNSPrefix, "ignored")
   599  		require.NoError(t, err)
   600  		s, err := svc.currentState(thid)
   601  		require.NoError(t, err)
   602  		require.Equal(t, (&null{}).Name(), s.Name())
   603  	})
   604  
   605  	t.Run("returns state from store", func(t *testing.T) {
   606  		expected := &requested{}
   607  		connRecord, err := json.Marshal(&connection.Record{State: expected.Name()})
   608  		require.NoError(t, err)
   609  
   610  		connRec, err := connection.NewRecorder(&protocol.MockProvider{
   611  			ProtocolStateStoreProvider: mockstorage.NewCustomMockStoreProvider(&mockStore{
   612  				get: func(string) ([]byte, error) { return connRecord, nil },
   613  			}),
   614  		})
   615  		require.NotNil(t, connRec)
   616  		require.NoError(t, err)
   617  
   618  		svc := &Service{
   619  			connectionRecorder: connRec,
   620  		}
   621  		thid, err := connection.CreateNamespaceKey(theirNSPrefix, "ignored")
   622  		require.NoError(t, err)
   623  		actual, err := svc.currentState(thid)
   624  		require.NoError(t, err)
   625  		require.Equal(t, expected.Name(), actual.Name())
   626  	})
   627  
   628  	t.Run("forwards generic error from store", func(t *testing.T) {
   629  		connRec, err := connection.NewRecorder(&protocol.MockProvider{
   630  			ProtocolStateStoreProvider: mockstorage.NewCustomMockStoreProvider(&mockStore{
   631  				get: func(string) ([]byte, error) {
   632  					return nil, errors.New("test")
   633  				},
   634  			}),
   635  		})
   636  		require.NotNil(t, connRec)
   637  		require.NoError(t, err)
   638  
   639  		svc := &Service{connectionRecorder: connRec}
   640  		thid, err := connection.CreateNamespaceKey(theirNSPrefix, "ignored")
   641  		require.NoError(t, err)
   642  		_, err = svc.currentState(thid)
   643  		require.Error(t, err)
   644  		require.Contains(t, err.Error(), "cannot fetch state from store")
   645  	})
   646  }
   647  
   648  func TestService_Update(t *testing.T) {
   649  	s := &requested{}
   650  	data := make(map[string][]byte)
   651  	connRecord := &connection.Record{
   652  		ThreadID: "123", ConnectionID: "123456", State: s.Name(),
   653  		Namespace: findNamespace(RequestMsgType),
   654  	}
   655  	bytes, err := json.Marshal(connRecord)
   656  	require.NoError(t, err)
   657  
   658  	connRec, err := connection.NewRecorder(&protocol.MockProvider{
   659  		StoreProvider: mockstorage.NewCustomMockStoreProvider(&mockStore{
   660  			put: func(k string, v []byte, tags ...storage.Tag) error {
   661  				data[k] = bytes
   662  				return nil
   663  			},
   664  			get: func(k string) ([]byte, error) {
   665  				return bytes, nil
   666  			},
   667  		}),
   668  	})
   669  	require.NotNil(t, connRec)
   670  	require.NoError(t, err)
   671  
   672  	svc := &Service{connectionRecorder: connRec}
   673  
   674  	require.NoError(t, svc.update(RequestMsgType, connRecord))
   675  
   676  	cr := &connection.Record{}
   677  	err = json.Unmarshal(bytes, cr)
   678  	require.NoError(t, err)
   679  	require.Equal(t, cr, connRecord)
   680  }
   681  
   682  func TestCreateConnection(t *testing.T) {
   683  	store := mockstorage.NewMockStoreProvider()
   684  	k := newKMS(t, store)
   685  
   686  	t.Run("create connection", func(t *testing.T) {
   687  		theirDID := newPeerDID(t, k)
   688  		record := &connection.Record{
   689  			ConnectionID:    uuid.New().String(),
   690  			State:           StateIDCompleted,
   691  			ThreadID:        uuid.New().String(),
   692  			ParentThreadID:  uuid.New().String(),
   693  			TheirLabel:      uuid.New().String(),
   694  			TheirDID:        theirDID.ID,
   695  			MyDID:           newPeerDID(t, k).ID,
   696  			ServiceEndPoint: commonmodel.NewDIDCommV1Endpoint("http://example.com"),
   697  			RecipientKeys:   []string{"testkeys"},
   698  			InvitationID:    uuid.New().String(),
   699  			Namespace:       myNSPrefix,
   700  		}
   701  		storedInVDR := false
   702  		storageProvider := &mockprovider.Provider{
   703  			StorageProviderValue:              mockstorage.NewMockStoreProvider(),
   704  			ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(),
   705  		}
   706  		provider := &mockprovider.Provider{
   707  			KMSValue:                          &mockkms.KeyManager{},
   708  			StorageProviderValue:              storageProvider.StorageProvider(),
   709  			ProtocolStateStorageProviderValue: storageProvider.ProtocolStateStorageProvider(),
   710  			VDRegistryValue: &mockvdr.MockVDRegistry{
   711  				CreateFunc: func(method string, result *did.Doc, _ ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
   712  					storedInVDR = true
   713  					require.Equal(t, theirDID, result)
   714  
   715  					return nil, nil
   716  				},
   717  			},
   718  			ServiceMap: map[string]interface{}{
   719  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   720  			},
   721  			DIDConnectionStoreValue: &mockConnectionStore{},
   722  		}
   723  		s, err := New(provider)
   724  		require.NoError(t, err)
   725  
   726  		err = s.CreateConnection(record, theirDID)
   727  		require.True(t, storedInVDR)
   728  		require.NoError(t, err)
   729  
   730  		connRec, err := connection.NewRecorder(provider)
   731  		require.NoError(t, err)
   732  		result, err := connRec.GetConnectionRecord(record.ConnectionID)
   733  		require.NoError(t, err)
   734  		require.Equal(t, record, result)
   735  	})
   736  
   737  	t.Run("wraps vdr registry error", func(t *testing.T) {
   738  		expected := errors.New("test")
   739  		s, err := New(&mockprovider.Provider{
   740  			KMSValue:                          &mockkms.KeyManager{},
   741  			StorageProviderValue:              mockstorage.NewMockStoreProvider(),
   742  			ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(),
   743  			VDRegistryValue: &mockvdr.MockVDRegistry{
   744  				CreateFunc: func(s string, doc *did.Doc, option ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
   745  					return nil, expected
   746  				},
   747  			},
   748  			ServiceMap: map[string]interface{}{
   749  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   750  			},
   751  		})
   752  		require.NoError(t, err)
   753  
   754  		err = s.CreateConnection(&connection.Record{}, newPeerDID(t, k))
   755  		require.Error(t, err)
   756  		require.True(t, errors.Is(err, expected))
   757  	})
   758  
   759  	t.Run("wraps connection store error", func(t *testing.T) {
   760  		expected := errors.New("test")
   761  		s, err := New(&mockprovider.Provider{
   762  			KMSValue: &mockkms.KeyManager{},
   763  			StorageProviderValue: &mockstorage.MockStoreProvider{
   764  				Store: &mockstorage.MockStore{ErrPut: expected},
   765  			},
   766  			ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(),
   767  			VDRegistryValue:                   &mockvdr.MockVDRegistry{},
   768  			ServiceMap: map[string]interface{}{
   769  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   770  			},
   771  			DIDConnectionStoreValue: &mockConnectionStore{},
   772  		})
   773  		require.NoError(t, err)
   774  
   775  		err = s.CreateConnection(&connection.Record{
   776  			State: StateIDCompleted,
   777  		}, newPeerDID(t, k))
   778  		require.Error(t, err)
   779  		require.True(t, errors.Is(err, expected))
   780  	})
   781  
   782  	t.Run("wraps did.ConnectionStore.SaveDIDFromDoc error", func(t *testing.T) {
   783  		expected := errors.New("test")
   784  		s, err := New(&mockprovider.Provider{
   785  			KMSValue:                          &mockkms.KeyManager{},
   786  			KeyTypeValue:                      kms.ECDSAP384TypeIEEEP1363,
   787  			KeyAgreementTypeValue:             kms.X25519ECDHKWType,
   788  			StorageProviderValue:              mockstorage.NewMockStoreProvider(),
   789  			ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(),
   790  			VDRegistryValue:                   &mockvdr.MockVDRegistry{},
   791  			ServiceMap: map[string]interface{}{
   792  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   793  			},
   794  			DIDConnectionStoreValue: &mockConnectionStore{
   795  				saveDIDFromDocErr: expected,
   796  			},
   797  		})
   798  		require.NoError(t, err)
   799  
   800  		err = s.CreateConnection(&connection.Record{
   801  			State: StateIDCompleted,
   802  		}, newPeerDID(t, k))
   803  		require.Error(t, err)
   804  		require.True(t, errors.Is(err, expected))
   805  	})
   806  
   807  	t.Run("wraps did.ConnectionStore.SaveDIDByResolving error", func(t *testing.T) {
   808  		expected := errors.New("test")
   809  		s, err := New(&mockprovider.Provider{
   810  			KMSValue:                          &mockkms.KeyManager{},
   811  			KeyTypeValue:                      kms.ED25519Type,
   812  			KeyAgreementTypeValue:             kms.X25519ECDHKWType,
   813  			StorageProviderValue:              mockstorage.NewMockStoreProvider(),
   814  			ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(),
   815  			VDRegistryValue:                   &mockvdr.MockVDRegistry{},
   816  			ServiceMap: map[string]interface{}{
   817  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   818  			},
   819  			DIDConnectionStoreValue: &mockConnectionStore{
   820  				saveDIDByResolvingErr: expected,
   821  			},
   822  		})
   823  		require.NoError(t, err)
   824  
   825  		err = s.CreateConnection(&connection.Record{
   826  			State: StateIDCompleted,
   827  		}, newPeerDID(t, k))
   828  		require.Error(t, err)
   829  		require.True(t, errors.Is(err, expected))
   830  	})
   831  }
   832  
   833  type mockStore struct {
   834  	put    func(string, []byte, ...storage.Tag) error
   835  	get    func(string) ([]byte, error)
   836  	delete func(string) error
   837  }
   838  
   839  // Put stores the key and the record.
   840  func (m *mockStore) Put(k string, v []byte, tags ...storage.Tag) error {
   841  	return m.put(k, v, tags...)
   842  }
   843  
   844  // Get fetches the record based on key.
   845  func (m *mockStore) Get(k string) ([]byte, error) {
   846  	return m.get(k)
   847  }
   848  
   849  func (m *mockStore) GetTags(key string) ([]storage.Tag, error) {
   850  	panic("implement me")
   851  }
   852  
   853  func (m *mockStore) GetBulk(keys ...string) ([][]byte, error) {
   854  	panic("implement me")
   855  }
   856  
   857  func (m *mockStore) Query(expression string, options ...storage.QueryOption) (storage.Iterator, error) {
   858  	panic("implement me")
   859  }
   860  
   861  // Delete the record based on key.
   862  func (m *mockStore) Delete(k string) error {
   863  	return m.delete(k)
   864  }
   865  
   866  func (m *mockStore) Batch(operations []storage.Operation) error {
   867  	panic("implement me")
   868  }
   869  
   870  func (m *mockStore) Flush() error {
   871  	panic("implement me")
   872  }
   873  
   874  func (m *mockStore) Close() error {
   875  	panic("implement me")
   876  }
   877  
   878  func TestEventsSuccess(t *testing.T) {
   879  	sp := mockstorage.NewMockStoreProvider()
   880  	k := newKMS(t, sp)
   881  	ctx := &context{
   882  		kms:              k,
   883  		keyType:          kms.ED25519Type,
   884  		keyAgreementType: kms.X25519ECDHKWType,
   885  	}
   886  
   887  	svc, err := New(&protocol.MockProvider{
   888  		ServiceMap: map[string]interface{}{
   889  			mediator.Coordination: &mockroute.MockMediatorSvc{},
   890  		},
   891  		CustomKMS:             k,
   892  		KeyTypeValue:          ctx.keyType,
   893  		KeyAgreementTypeValue: ctx.keyAgreementType,
   894  	})
   895  	require.NoError(t, err)
   896  
   897  	actionCh := make(chan service.DIDCommAction, 10)
   898  	err = svc.RegisterActionEvent(actionCh)
   899  	require.NoError(t, err)
   900  
   901  	go func() { service.AutoExecuteActionEvent(actionCh) }()
   902  
   903  	statusCh := make(chan service.StateMsg, 10)
   904  	err = svc.RegisterMsgEvent(statusCh)
   905  	require.NoError(t, err)
   906  
   907  	done := make(chan struct{})
   908  
   909  	go func() {
   910  		for e := range statusCh {
   911  			if e.Type == service.PostState && e.StateID == StateIDRequested {
   912  				done <- struct{}{}
   913  			}
   914  		}
   915  	}()
   916  
   917  	_, pubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
   918  	require.NoError(t, err)
   919  
   920  	id := randomString()
   921  	invite, err := json.Marshal(
   922  		&Invitation{
   923  			Type:          InvitationMsgType,
   924  			ID:            id,
   925  			Label:         "test",
   926  			RecipientKeys: []string{base58.Encode(pubKey)},
   927  		},
   928  	)
   929  	require.NoError(t, err)
   930  
   931  	// send invite
   932  	didMsg, err := service.ParseDIDCommMsgMap(invite)
   933  	require.NoError(t, err)
   934  
   935  	_, err = svc.HandleInbound(didMsg, service.EmptyDIDCommContext())
   936  	require.NoError(t, err)
   937  
   938  	select {
   939  	case <-done:
   940  	case <-time.After(5 * time.Second):
   941  		require.Fail(t, "tests are not validated")
   942  	}
   943  }
   944  
   945  func TestContinueWithPublicDID(t *testing.T) {
   946  	sp := mockstorage.NewMockStoreProvider()
   947  	k := newKMS(t, sp)
   948  	ctx := &context{
   949  		kms:              k,
   950  		keyType:          kms.ED25519Type,
   951  		keyAgreementType: kms.X25519ECDHKWType,
   952  	}
   953  	didDoc := mockdiddoc.GetMockDIDDoc(t, false)
   954  	svc, err := New(&protocol.MockProvider{
   955  		ServiceMap: map[string]interface{}{
   956  			mediator.Coordination: &mockroute.MockMediatorSvc{},
   957  		},
   958  		KeyTypeValue:          ctx.keyType,
   959  		KeyAgreementTypeValue: ctx.keyAgreementType,
   960  	})
   961  	require.NoError(t, err)
   962  
   963  	actionCh := make(chan service.DIDCommAction, 10)
   964  	err = svc.RegisterActionEvent(actionCh)
   965  	require.NoError(t, err)
   966  
   967  	go func() { continueWithPublicDID(actionCh, didDoc.ID) }()
   968  
   969  	_, pubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
   970  	require.NoError(t, err)
   971  
   972  	id := randomString()
   973  	invite, err := json.Marshal(
   974  		&Invitation{
   975  			Type:          InvitationMsgType,
   976  			ID:            id,
   977  			Label:         "test",
   978  			RecipientKeys: []string{base58.Encode(pubKey)},
   979  		},
   980  	)
   981  	require.NoError(t, err)
   982  
   983  	// send invite
   984  	didMsg, err := service.ParseDIDCommMsgMap(invite)
   985  	require.NoError(t, err)
   986  
   987  	_, err = svc.HandleInbound(didMsg, service.EmptyDIDCommContext())
   988  	require.NoError(t, err)
   989  }
   990  
   991  func continueWithPublicDID(ch chan service.DIDCommAction, pubDID string) {
   992  	for msg := range ch {
   993  		msg.Continue(&testOptions{publicDID: pubDID})
   994  	}
   995  }
   996  
   997  type testOptions struct {
   998  	publicDID         string
   999  	label             string
  1000  	routerConnections []string
  1001  }
  1002  
  1003  func (to *testOptions) PublicDID() string {
  1004  	return to.publicDID
  1005  }
  1006  
  1007  func (to *testOptions) Label() string {
  1008  	return to.label
  1009  }
  1010  
  1011  func (to *testOptions) RouterConnections() []string {
  1012  	return to.routerConnections
  1013  }
  1014  
  1015  func TestEventsUserError(t *testing.T) {
  1016  	svc, err := New(&protocol.MockProvider{
  1017  		ServiceMap: map[string]interface{}{
  1018  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1019  		},
  1020  	})
  1021  	require.NoError(t, err)
  1022  
  1023  	actionCh := make(chan service.DIDCommAction, 10)
  1024  	err = svc.RegisterActionEvent(actionCh)
  1025  	require.NoError(t, err)
  1026  
  1027  	statusCh := make(chan service.StateMsg, 10)
  1028  	err = svc.RegisterMsgEvent(statusCh)
  1029  	require.NoError(t, err)
  1030  
  1031  	done := make(chan struct{})
  1032  
  1033  	go func() {
  1034  		for {
  1035  			select {
  1036  			case e := <-actionCh:
  1037  				e.Stop(errors.New("invalid id"))
  1038  			case e := <-statusCh:
  1039  				if e.Type == service.PostState {
  1040  					done <- struct{}{}
  1041  				}
  1042  			}
  1043  		}
  1044  	}()
  1045  
  1046  	id := randomString()
  1047  	connRec := &connection.Record{
  1048  		ConnectionID: randomString(), ThreadID: id,
  1049  		Namespace: findNamespace(RequestMsgType), State: (&null{}).Name(),
  1050  	}
  1051  
  1052  	err = svc.connectionRecorder.SaveConnectionRecordWithMappings(connRec)
  1053  	require.NoError(t, err)
  1054  
  1055  	_, err = svc.HandleInbound(
  1056  		generateRequestMsgPayload(t, &protocol.MockProvider{}, id, randomString()),
  1057  		service.EmptyDIDCommContext())
  1058  	require.NoError(t, err)
  1059  
  1060  	select {
  1061  	case <-done:
  1062  	case <-time.After(5 * time.Second):
  1063  		require.Fail(t, "tests are not validated")
  1064  	}
  1065  }
  1066  
  1067  func TestEventStoreError(t *testing.T) {
  1068  	svc, err := New(&protocol.MockProvider{
  1069  		ServiceMap: map[string]interface{}{
  1070  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1071  		},
  1072  	})
  1073  	require.NoError(t, err)
  1074  
  1075  	actionCh := make(chan service.DIDCommAction, 10)
  1076  	err = svc.RegisterActionEvent(actionCh)
  1077  	require.NoError(t, err)
  1078  
  1079  	go func() {
  1080  		for e := range actionCh {
  1081  			e.Continue = func(args interface{}) {
  1082  				svc.processCallback(&message{Msg: service.NewDIDCommMsgMap(struct{}{})})
  1083  			}
  1084  			e.Continue(&service.Empty{})
  1085  		}
  1086  	}()
  1087  
  1088  	_, err = svc.HandleInbound(
  1089  		generateRequestMsgPayload(t, &protocol.MockProvider{}, randomString(), randomString()),
  1090  		service.EmptyDIDCommContext())
  1091  	require.NoError(t, err)
  1092  }
  1093  
  1094  func TestEventProcessCallback(t *testing.T) {
  1095  	svc, err := New(&protocol.MockProvider{
  1096  		ServiceMap: map[string]interface{}{
  1097  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1098  		},
  1099  	})
  1100  	require.NoError(t, err)
  1101  
  1102  	msg := &message{
  1103  		ThreadID: threadIDValue,
  1104  		Msg:      service.NewDIDCommMsgMap(model.Ack{Type: AckMsgType}),
  1105  	}
  1106  
  1107  	err = svc.handleWithoutAction(msg)
  1108  	require.Error(t, err)
  1109  	require.Contains(t, err.Error(), "invalid state name: invalid state name ")
  1110  }
  1111  
  1112  func validateState(t *testing.T, svc *Service, id, namespace, expected string) {
  1113  	nsThid, err := connection.CreateNamespaceKey(namespace, id)
  1114  	require.NoError(t, err)
  1115  	s, err := svc.currentState(nsThid)
  1116  	require.NoError(t, err)
  1117  	require.Equal(t, expected, s.Name())
  1118  }
  1119  
  1120  func TestServiceErrors(t *testing.T) {
  1121  	requestBytes, err := json.Marshal(
  1122  		&Request{
  1123  			Type:  ResponseMsgType,
  1124  			ID:    randomString(),
  1125  			Label: "test",
  1126  		},
  1127  	)
  1128  	require.NoError(t, err)
  1129  
  1130  	msg, err := service.ParseDIDCommMsgMap(requestBytes)
  1131  	require.NoError(t, err)
  1132  
  1133  	svc, err := New(&protocol.MockProvider{
  1134  		ServiceMap: map[string]interface{}{
  1135  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1136  		},
  1137  	})
  1138  	require.NoError(t, err)
  1139  
  1140  	actionCh := make(chan service.DIDCommAction, 10)
  1141  	err = svc.RegisterActionEvent(actionCh)
  1142  	require.NoError(t, err)
  1143  
  1144  	// fetch current state error
  1145  	mockStore := &mockStore{get: func(s string) (bytes []byte, e error) {
  1146  		return nil, errors.New("error")
  1147  	}}
  1148  
  1149  	prov := &protocol.MockProvider{
  1150  		ProtocolStateStoreProvider: mockstorage.NewCustomMockStoreProvider(
  1151  			mockStore,
  1152  		),
  1153  		ServiceMap: map[string]interface{}{
  1154  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1155  		},
  1156  	}
  1157  	svc, err = New(prov)
  1158  	require.NoError(t, err)
  1159  
  1160  	payload := generateRequestMsgPayload(t, prov, randomString(), "")
  1161  	_, err = svc.HandleInbound(payload, service.EmptyDIDCommContext())
  1162  	require.Error(t, err)
  1163  	require.Contains(t, err.Error(), "cannot fetch state from store")
  1164  
  1165  	svc, err = New(&protocol.MockProvider{
  1166  		ServiceMap: map[string]interface{}{
  1167  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1168  		},
  1169  	})
  1170  	require.NoError(t, err)
  1171  
  1172  	// invalid message type
  1173  	msg["@type"] = "invalid"
  1174  	svc.connectionRecorder, err = connection.NewRecorder(&protocol.MockProvider{})
  1175  	require.NoError(t, err)
  1176  
  1177  	_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
  1178  	require.Error(t, err)
  1179  	require.Contains(t, err.Error(), "unrecognized msgType: invalid")
  1180  
  1181  	// test handle - invalid state name
  1182  	msg["@type"] = ResponseMsgType
  1183  	m := &message{Msg: msg, ThreadID: randomString()}
  1184  	err = svc.handleWithoutAction(m)
  1185  	require.Error(t, err)
  1186  	require.Contains(t, err.Error(), "invalid state name:")
  1187  
  1188  	// invalid state name
  1189  	m.NextStateName = StateIDInvited
  1190  	m.ConnRecord = &connection.Record{ConnectionID: "abc"}
  1191  	err = svc.handleWithoutAction(m)
  1192  	require.Error(t, err)
  1193  	require.Contains(t, err.Error(), "failed to execute state 'invited':")
  1194  }
  1195  
  1196  func TestHandleOutbound(t *testing.T) {
  1197  	svc, err := New(&protocol.MockProvider{
  1198  		ServiceMap: map[string]interface{}{
  1199  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1200  		},
  1201  	})
  1202  	require.NoError(t, err)
  1203  
  1204  	_, err = svc.HandleOutbound(service.DIDCommMsgMap{}, "", "")
  1205  	require.Error(t, err)
  1206  	require.Contains(t, err.Error(), "not implemented")
  1207  }
  1208  
  1209  func TestConnectionRecord(t *testing.T) {
  1210  	svc, err := New(&protocol.MockProvider{
  1211  		ServiceMap: map[string]interface{}{
  1212  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1213  		},
  1214  	})
  1215  	require.NoError(t, err)
  1216  
  1217  	conn, err := svc.connectionRecord(generateRequestMsgPayload(t, &protocol.MockProvider{},
  1218  		randomString(), randomString()), service.EmptyDIDCommContext())
  1219  	require.NoError(t, err)
  1220  	require.NotNil(t, conn)
  1221  
  1222  	// invalid type
  1223  	requestBytes, err := json.Marshal(&Request{
  1224  		Type: "invalid-type",
  1225  	})
  1226  	require.NoError(t, err)
  1227  	msg, err := service.ParseDIDCommMsgMap(requestBytes)
  1228  	require.NoError(t, err)
  1229  
  1230  	_, err = svc.connectionRecord(msg, service.EmptyDIDCommContext())
  1231  	require.Error(t, err)
  1232  	require.Contains(t, err.Error(), "invalid message type")
  1233  }
  1234  
  1235  func TestInvitationRecord(t *testing.T) {
  1236  	sp := mockstorage.NewMockStoreProvider()
  1237  	k := newKMS(t, sp)
  1238  	ctx := &context{
  1239  		kms:              k,
  1240  		keyType:          kms.ED25519Type,
  1241  		keyAgreementType: kms.X25519ECDHKWType,
  1242  	}
  1243  	svc, err := New(&protocol.MockProvider{
  1244  		ServiceMap: map[string]interface{}{
  1245  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1246  		},
  1247  		KeyTypeValue:          ctx.keyType,
  1248  		KeyAgreementTypeValue: ctx.keyAgreementType,
  1249  	})
  1250  	require.NoError(t, err)
  1251  
  1252  	_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  1253  	require.NoError(t, err)
  1254  	invitationBytes, err := json.Marshal(&Invitation{
  1255  		Type:          InvitationMsgType,
  1256  		ID:            "id",
  1257  		RecipientKeys: []string{base58.Encode(verPubKey)},
  1258  	})
  1259  	require.NoError(t, err)
  1260  
  1261  	msg, err := service.ParseDIDCommMsgMap(invitationBytes)
  1262  	require.NoError(t, err)
  1263  
  1264  	conn, err := svc.invitationMsgRecord(msg)
  1265  	require.NoError(t, err)
  1266  	require.NotNil(t, conn)
  1267  
  1268  	// invalid thread id
  1269  	invitationBytes, err = json.Marshal(&Invitation{
  1270  		Type: "invalid-type",
  1271  	})
  1272  	require.NoError(t, err)
  1273  	msg, err = service.ParseDIDCommMsgMap(invitationBytes)
  1274  	require.NoError(t, err)
  1275  
  1276  	_, err = svc.invitationMsgRecord(msg)
  1277  	require.Error(t, err)
  1278  	require.Contains(t, err.Error(), "threadID not found")
  1279  
  1280  	// db error
  1281  	svc, err = New(&protocol.MockProvider{
  1282  		ProtocolStateStoreProvider: mockstorage.NewCustomMockStoreProvider(&mockstorage.MockStore{
  1283  			Store: make(map[string]mockstorage.DBEntry), ErrPut: errors.New("db error"),
  1284  		}),
  1285  		ServiceMap: map[string]interface{}{
  1286  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1287  		},
  1288  	})
  1289  	require.NotNil(t, svc.connectionRecorder)
  1290  	require.NoError(t, err)
  1291  
  1292  	invitationBytes, err = json.Marshal(&Invitation{
  1293  		Type:          InvitationMsgType,
  1294  		ID:            "id",
  1295  		RecipientKeys: []string{base58.Encode(verPubKey)},
  1296  	})
  1297  	require.NoError(t, err)
  1298  
  1299  	msg, err = service.ParseDIDCommMsgMap(invitationBytes)
  1300  	require.NoError(t, err)
  1301  
  1302  	_, err = svc.invitationMsgRecord(msg)
  1303  	require.Error(t, err)
  1304  	require.Contains(t, err.Error(), "save connection record")
  1305  }
  1306  
  1307  func TestRequestRecord(t *testing.T) {
  1308  	t.Run("returns connection record", func(t *testing.T) {
  1309  		svc, err := New(&protocol.MockProvider{
  1310  			ServiceMap: map[string]interface{}{
  1311  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1312  			},
  1313  		})
  1314  		require.NoError(t, err)
  1315  
  1316  		didcommMsg := generateRequestMsgPayload(t, &protocol.MockProvider{}, randomString(), uuid.New().String())
  1317  		require.NotEmpty(t, didcommMsg.ParentThreadID())
  1318  		conn, err := svc.requestMsgRecord(didcommMsg, service.EmptyDIDCommContext())
  1319  		require.NoError(t, err)
  1320  		require.NotNil(t, conn)
  1321  		require.Equal(t, didcommMsg.ParentThreadID(), conn.InvitationID)
  1322  	})
  1323  
  1324  	t.Run("returns connection record from request without connection DIDDoc field", func(t *testing.T) {
  1325  		svc, err := New(&protocol.MockProvider{
  1326  			ServiceMap: map[string]interface{}{
  1327  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1328  			},
  1329  		})
  1330  		require.NoError(t, err)
  1331  
  1332  		didcommMsg := generateRequestMsgPayload(t, &protocol.MockProvider{}, randomString(), uuid.New().String())
  1333  		require.NotEmpty(t, didcommMsg.ParentThreadID())
  1334  		delete(didcommMsg, "connection")
  1335  
  1336  		_, err = svc.requestMsgRecord(didcommMsg, service.EmptyDIDCommContext())
  1337  		require.Error(t, err)
  1338  		require.Contains(t, err.Error(), "missing connection field")
  1339  	})
  1340  
  1341  	t.Run("fails on db error", func(t *testing.T) {
  1342  		svc, err := New(&protocol.MockProvider{
  1343  			ProtocolStateStoreProvider: mockstorage.NewCustomMockStoreProvider(
  1344  				&mockstorage.MockStore{Store: make(map[string]mockstorage.DBEntry), ErrPut: errors.New("db error")},
  1345  			),
  1346  			ServiceMap: map[string]interface{}{
  1347  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1348  			},
  1349  		})
  1350  		require.NotNil(t, svc.connectionRecorder)
  1351  		require.NoError(t, err)
  1352  
  1353  		_, err = svc.requestMsgRecord(generateRequestMsgPayload(t, &protocol.MockProvider{},
  1354  			randomString(), uuid.New().String()), service.EmptyDIDCommContext())
  1355  		require.Error(t, err)
  1356  		require.Contains(t, err.Error(), "save connection record")
  1357  	})
  1358  
  1359  	t.Run("fails if parent thread ID is missing", func(t *testing.T) {
  1360  		svc, err := New(&protocol.MockProvider{
  1361  			ServiceMap: map[string]interface{}{
  1362  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1363  			},
  1364  		})
  1365  		require.NoError(t, err)
  1366  
  1367  		parentThreadID := ""
  1368  		didcommMsg := generateRequestMsgPayload(t, &protocol.MockProvider{}, randomString(), parentThreadID)
  1369  		require.Empty(t, didcommMsg.ParentThreadID())
  1370  		_, err = svc.requestMsgRecord(didcommMsg, service.EmptyDIDCommContext())
  1371  		require.Error(t, err)
  1372  	})
  1373  }
  1374  
  1375  func TestAcceptConnectionRequest(t *testing.T) {
  1376  	sp := mockstorage.NewMockStoreProvider()
  1377  	k := newKMS(t, sp)
  1378  	ctx := &context{
  1379  		kms:              k,
  1380  		keyType:          kms.ED25519Type,
  1381  		keyAgreementType: kms.X25519ECDHKWType,
  1382  	}
  1383  
  1384  	svc, err := New(&protocol.MockProvider{
  1385  		StoreProvider: sp,
  1386  		ServiceMap: map[string]interface{}{
  1387  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1388  		},
  1389  		CustomKMS:             k,
  1390  		KeyTypeValue:          ctx.keyType,
  1391  		KeyAgreementTypeValue: ctx.keyAgreementType,
  1392  	})
  1393  	require.NoError(t, err)
  1394  
  1395  	actionCh := make(chan service.DIDCommAction, 10)
  1396  	err = svc.RegisterActionEvent(actionCh)
  1397  	require.NoError(t, err)
  1398  
  1399  	_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  1400  	require.NoError(t, err)
  1401  
  1402  	invitation := &Invitation{
  1403  		Type:            InvitationMsgType,
  1404  		ID:              randomString(),
  1405  		Label:           "Bob",
  1406  		RecipientKeys:   []string{base58.Encode(verPubKey)},
  1407  		ServiceEndpoint: "http://alice.agent.example.com:8081",
  1408  	}
  1409  
  1410  	err = svc.connectionRecorder.SaveInvitation(invitation.ID, invitation)
  1411  	require.NoError(t, err)
  1412  
  1413  	go func() {
  1414  		for e := range actionCh {
  1415  			prop, ok := e.Properties.(event)
  1416  			require.True(t, ok, "Failed to cast the event properties to service.Event")
  1417  			require.NoError(t, svc.AcceptConnectionRequest(prop.ConnectionID(), "", "", nil))
  1418  		}
  1419  	}()
  1420  
  1421  	statusCh := make(chan service.StateMsg, 10)
  1422  	err = svc.RegisterMsgEvent(statusCh)
  1423  	require.NoError(t, err)
  1424  
  1425  	done := make(chan struct{})
  1426  
  1427  	go func() {
  1428  		for e := range statusCh {
  1429  			if e.Type == service.PostState && e.StateID == StateIDResponded {
  1430  				done <- struct{}{}
  1431  			}
  1432  		}
  1433  	}()
  1434  
  1435  	_, err = svc.HandleInbound(generateRequestMsgPayload(t, &protocol.MockProvider{
  1436  		StoreProvider: mockstorage.NewMockStoreProvider(),
  1437  	}, randomString(), invitation.ID), service.EmptyDIDCommContext())
  1438  	require.NoError(t, err)
  1439  
  1440  	select {
  1441  	case <-done:
  1442  	case <-time.After(5 * time.Second):
  1443  		require.Fail(t, "tests are not validated")
  1444  	}
  1445  }
  1446  
  1447  func TestAcceptConnectionRequestWithoutParentThreadID(t *testing.T) {
  1448  	sp := mockstorage.NewMockStoreProvider()
  1449  	k := newKMS(t, sp)
  1450  	ctx := &context{
  1451  		kms:              k,
  1452  		keyType:          kms.ED25519Type,
  1453  		keyAgreementType: kms.X25519ECDHKWType,
  1454  	}
  1455  
  1456  	svc, err := New(&protocol.MockProvider{
  1457  		StoreProvider: sp,
  1458  		ServiceMap: map[string]interface{}{
  1459  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1460  		},
  1461  		CustomKMS:             k,
  1462  		KeyTypeValue:          ctx.keyType,
  1463  		KeyAgreementTypeValue: ctx.keyAgreementType,
  1464  	})
  1465  	require.NoError(t, err)
  1466  
  1467  	actionCh := make(chan service.DIDCommAction, 10)
  1468  	err = svc.RegisterActionEvent(actionCh)
  1469  	require.NoError(t, err)
  1470  
  1471  	_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  1472  	require.NoError(t, err)
  1473  
  1474  	invitation := &Invitation{
  1475  		Type:            InvitationMsgType,
  1476  		ID:              randomString(),
  1477  		Label:           "Bob",
  1478  		RecipientKeys:   []string{base58.Encode(verPubKey)},
  1479  		ServiceEndpoint: "http://alice.agent.example.com:8081",
  1480  	}
  1481  
  1482  	err = svc.connectionRecorder.SaveInvitation(invitation.ID, invitation)
  1483  	require.NoError(t, err)
  1484  
  1485  	go func() {
  1486  		for e := range actionCh {
  1487  			prop, ok := e.Properties.(event)
  1488  			require.True(t, ok, "Failed to cast the event properties to service.Event")
  1489  			require.NoError(t, svc.AcceptConnectionRequest(prop.ConnectionID(), "", "", nil))
  1490  		}
  1491  	}()
  1492  
  1493  	statusCh := make(chan service.StateMsg, 10)
  1494  	err = svc.RegisterMsgEvent(statusCh)
  1495  	require.NoError(t, err)
  1496  
  1497  	done := make(chan struct{})
  1498  
  1499  	go func() {
  1500  		for e := range statusCh {
  1501  			if e.Type == service.PostState && e.StateID == StateIDResponded {
  1502  				done <- struct{}{}
  1503  			}
  1504  		}
  1505  	}()
  1506  
  1507  	props := map[string]interface{}{}
  1508  	props[InvitationRecipientKey] = invitation.RecipientKeys[0]
  1509  	c := service.NewDIDCommContext("", "", props)
  1510  
  1511  	_, err = svc.HandleInbound(generateRequestMsgPayload(t, &protocol.MockProvider{
  1512  		StoreProvider: mockstorage.NewMockStoreProvider(),
  1513  	}, randomString(), ""), c)
  1514  	require.NoError(t, err, "missing parent thread ID and invitation recipient key on connection request")
  1515  	select {
  1516  	case <-done:
  1517  	case <-time.After(5 * time.Second):
  1518  		require.Fail(t, "tests are not validated")
  1519  	}
  1520  }
  1521  
  1522  func TestAcceptConnectionRequestWithPublicDID(t *testing.T) {
  1523  	sp := mockstorage.NewMockStoreProvider()
  1524  	k := newKMS(t, sp)
  1525  	ctx := &context{
  1526  		kms:              k,
  1527  		keyType:          kms.ED25519Type,
  1528  		keyAgreementType: kms.X25519ECDHKWType,
  1529  	}
  1530  	svc, err := New(&protocol.MockProvider{
  1531  		StoreProvider: sp,
  1532  		ServiceMap: map[string]interface{}{
  1533  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1534  		},
  1535  		KeyTypeValue:          ctx.keyType,
  1536  		KeyAgreementTypeValue: ctx.keyAgreementType,
  1537  	})
  1538  	require.NoError(t, err)
  1539  
  1540  	const publicDIDMethod = "sidetree"
  1541  	publicDID := fmt.Sprintf("did:%s:123456", publicDIDMethod)
  1542  	doc, err := svc.ctx.vdRegistry.Create(publicDIDMethod, nil)
  1543  	require.NoError(t, err)
  1544  
  1545  	svc.ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: doc.DIDDocument}
  1546  
  1547  	actionCh := make(chan service.DIDCommAction, 10)
  1548  	err = svc.RegisterActionEvent(actionCh)
  1549  	require.NoError(t, err)
  1550  
  1551  	_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  1552  	require.NoError(t, err)
  1553  
  1554  	invitation := &Invitation{
  1555  		Type:            InvitationMsgType,
  1556  		ID:              randomString(),
  1557  		Label:           "Bob",
  1558  		RecipientKeys:   []string{base58.Encode(verPubKey)},
  1559  		ServiceEndpoint: "http://alice.agent.example.com:8081",
  1560  	}
  1561  
  1562  	err = svc.connectionRecorder.SaveInvitation(invitation.ID, invitation)
  1563  	require.NoError(t, err)
  1564  
  1565  	go func() {
  1566  		for e := range actionCh {
  1567  			prop, ok := e.Properties.(event)
  1568  			require.True(t, ok, "Failed to cast the event properties to service.Event")
  1569  			require.NoError(t, svc.AcceptConnectionRequest(prop.ConnectionID(), publicDID, "sample-label", nil))
  1570  		}
  1571  	}()
  1572  
  1573  	statusCh := make(chan service.StateMsg, 10)
  1574  	err = svc.RegisterMsgEvent(statusCh)
  1575  	require.NoError(t, err)
  1576  
  1577  	done := make(chan struct{})
  1578  
  1579  	go func() {
  1580  		for e := range statusCh {
  1581  			if e.Type == service.PostState && e.StateID == StateIDResponded {
  1582  				done <- struct{}{}
  1583  			}
  1584  		}
  1585  	}()
  1586  
  1587  	_, err = svc.HandleInbound(generateRequestMsgPayload(t, &protocol.MockProvider{
  1588  		StoreProvider: mockstorage.NewMockStoreProvider(),
  1589  	}, randomString(), invitation.ID), service.EmptyDIDCommContext())
  1590  	require.NoError(t, err)
  1591  
  1592  	select {
  1593  	case <-done:
  1594  	case <-time.After(5 * time.Second):
  1595  		require.Fail(t, "tests are not validated")
  1596  	}
  1597  }
  1598  
  1599  func TestAcceptInvitation(t *testing.T) {
  1600  	t.Run("accept invitation - success", func(t *testing.T) {
  1601  		sp := mockstorage.NewMockStoreProvider()
  1602  		k := newKMS(t, sp)
  1603  		ctx := &context{
  1604  			kms:              k,
  1605  			keyType:          kms.ED25519Type,
  1606  			keyAgreementType: kms.X25519ECDHKWType,
  1607  		}
  1608  		svc, err := New(&protocol.MockProvider{
  1609  			StoreProvider: sp,
  1610  			ServiceMap: map[string]interface{}{
  1611  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1612  			},
  1613  			CustomKMS:             k,
  1614  			KeyTypeValue:          ctx.keyType,
  1615  			KeyAgreementTypeValue: ctx.keyAgreementType,
  1616  		})
  1617  		require.NoError(t, err)
  1618  
  1619  		actionCh := make(chan service.DIDCommAction, 10)
  1620  		err = svc.RegisterActionEvent(actionCh)
  1621  		require.NoError(t, err)
  1622  
  1623  		go func() {
  1624  			for e := range actionCh {
  1625  				_, ok := e.Properties.(event)
  1626  				require.True(t, ok, "Failed to cast the event properties to service.Event")
  1627  
  1628  				// ignore action event
  1629  			}
  1630  		}()
  1631  
  1632  		statusCh := make(chan service.StateMsg, 10)
  1633  		err = svc.RegisterMsgEvent(statusCh)
  1634  		require.NoError(t, err)
  1635  
  1636  		done := make(chan struct{})
  1637  
  1638  		go func() {
  1639  			for e := range statusCh {
  1640  				prop, ok := e.Properties.(event)
  1641  				if !ok {
  1642  					require.Fail(t, "Failed to cast the event properties to service.Event")
  1643  				}
  1644  
  1645  				if e.Type == service.PostState && e.StateID == StateIDInvited {
  1646  					require.NoError(t, svc.AcceptInvitation(prop.ConnectionID(), "", "", nil))
  1647  				}
  1648  
  1649  				if e.Type == service.PostState && e.StateID == StateIDRequested {
  1650  					done <- struct{}{}
  1651  				}
  1652  			}
  1653  		}()
  1654  		_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  1655  		require.NoError(t, err)
  1656  
  1657  		invitationBytes, err := json.Marshal(&Invitation{
  1658  			Type:          InvitationMsgType,
  1659  			ID:            generateRandomID(),
  1660  			RecipientKeys: []string{base58.Encode(verPubKey)},
  1661  		})
  1662  		require.NoError(t, err)
  1663  
  1664  		didMsg, err := service.ParseDIDCommMsgMap(invitationBytes)
  1665  		require.NoError(t, err)
  1666  
  1667  		_, err = svc.HandleInbound(didMsg, service.EmptyDIDCommContext())
  1668  		require.NoError(t, err)
  1669  
  1670  		select {
  1671  		case <-done:
  1672  		case <-time.After(5 * time.Second):
  1673  			require.Fail(t, "tests are not validated")
  1674  		}
  1675  	})
  1676  
  1677  	t.Run("accept invitation - error", func(t *testing.T) {
  1678  		svc, err := New(&protocol.MockProvider{
  1679  			ServiceMap: map[string]interface{}{
  1680  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1681  			},
  1682  		})
  1683  		require.NoError(t, err)
  1684  
  1685  		err = svc.AcceptInvitation(generateRandomID(), "", "", nil)
  1686  		require.Error(t, err)
  1687  		require.Contains(t, err.Error(), "accept connection invitation : get protocol state data : data not found")
  1688  	})
  1689  
  1690  	t.Run("accept invitation - state error", func(t *testing.T) {
  1691  		svc, err := New(&protocol.MockProvider{
  1692  			ServiceMap: map[string]interface{}{
  1693  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1694  			},
  1695  		})
  1696  		require.NoError(t, err)
  1697  
  1698  		id := generateRandomID()
  1699  		connRecord := &connection.Record{
  1700  			ConnectionID: id,
  1701  			State:        StateIDRequested,
  1702  		}
  1703  		err = svc.connectionRecorder.SaveConnectionRecord(connRecord)
  1704  		require.NoError(t, err)
  1705  
  1706  		err = svc.storeEventProtocolStateData(&message{ConnRecord: connRecord})
  1707  		require.NoError(t, err)
  1708  
  1709  		err = svc.AcceptInvitation(id, "", "", nil)
  1710  		require.Error(t, err)
  1711  		require.Contains(t, err.Error(), "current state (requested) is different from expected state (invited)")
  1712  	})
  1713  
  1714  	t.Run("accept invitation - no connection record error", func(t *testing.T) {
  1715  		svc, err := New(&protocol.MockProvider{
  1716  			ServiceMap: map[string]interface{}{
  1717  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1718  			},
  1719  		})
  1720  		require.NoError(t, err)
  1721  
  1722  		id := generateRandomID()
  1723  		connRecord := &connection.Record{
  1724  			ConnectionID: id,
  1725  			State:        StateIDRequested,
  1726  		}
  1727  
  1728  		err = svc.storeEventProtocolStateData(&message{ConnRecord: connRecord})
  1729  		require.NoError(t, err)
  1730  
  1731  		err = svc.AcceptInvitation(id, "", "", nil)
  1732  		require.Error(t, err)
  1733  		require.Contains(t, err.Error(), "accept connection invitation : data not found")
  1734  	})
  1735  }
  1736  
  1737  func TestAcceptInvitationWithPublicDID(t *testing.T) {
  1738  	t.Run("accept invitation with public DID - success", func(t *testing.T) {
  1739  		sp := mockstorage.NewMockStoreProvider()
  1740  		k := newKMS(t, sp)
  1741  		ctx := &context{
  1742  			kms:              k,
  1743  			keyType:          kms.ED25519Type,
  1744  			keyAgreementType: kms.X25519ECDHKWType,
  1745  		}
  1746  		svc, err := New(&protocol.MockProvider{
  1747  			StoreProvider: sp,
  1748  			ServiceMap: map[string]interface{}{
  1749  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1750  			},
  1751  			KeyTypeValue:          ctx.keyType,
  1752  			KeyAgreementTypeValue: ctx.keyAgreementType,
  1753  		})
  1754  		require.NoError(t, err)
  1755  
  1756  		const publicDIDMethod = "sidetree"
  1757  		publicDID := fmt.Sprintf("did:%s:123456", publicDIDMethod)
  1758  		doc, err := svc.ctx.vdRegistry.Create(publicDIDMethod, nil)
  1759  		require.NoError(t, err)
  1760  		svc.ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: doc.DIDDocument}
  1761  
  1762  		actionCh := make(chan service.DIDCommAction, 10)
  1763  		err = svc.RegisterActionEvent(actionCh)
  1764  		require.NoError(t, err)
  1765  
  1766  		go func() {
  1767  			for e := range actionCh {
  1768  				_, ok := e.Properties.(event)
  1769  				require.True(t, ok, "Failed to cast the event properties to service.Event")
  1770  
  1771  				// ignore action event
  1772  			}
  1773  		}()
  1774  
  1775  		statusCh := make(chan service.StateMsg, 10)
  1776  		err = svc.RegisterMsgEvent(statusCh)
  1777  		require.NoError(t, err)
  1778  
  1779  		done := make(chan struct{})
  1780  
  1781  		go func() {
  1782  			for e := range statusCh {
  1783  				prop, ok := e.Properties.(event)
  1784  				if !ok {
  1785  					require.Fail(t, "Failed to cast the event properties to service.Event")
  1786  				}
  1787  
  1788  				if e.Type == service.PostState && e.StateID == StateIDInvited {
  1789  					require.NoError(t, svc.AcceptInvitation(prop.ConnectionID(), publicDID, "sample-label", nil))
  1790  				}
  1791  
  1792  				if e.Type == service.PostState && e.StateID == StateIDRequested {
  1793  					done <- struct{}{}
  1794  				}
  1795  			}
  1796  		}()
  1797  
  1798  		_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  1799  		require.NoError(t, err)
  1800  
  1801  		invitationBytes, err := json.Marshal(&Invitation{
  1802  			Type:          InvitationMsgType,
  1803  			ID:            generateRandomID(),
  1804  			RecipientKeys: []string{base58.Encode(verPubKey)},
  1805  		})
  1806  		require.NoError(t, err)
  1807  
  1808  		didMsg, err := service.ParseDIDCommMsgMap(invitationBytes)
  1809  		require.NoError(t, err)
  1810  
  1811  		_, err = svc.HandleInbound(didMsg, service.EmptyDIDCommContext())
  1812  		require.NoError(t, err)
  1813  
  1814  		select {
  1815  		case <-done:
  1816  		case <-time.After(5 * time.Second):
  1817  			require.Fail(t, "tests are not validated")
  1818  		}
  1819  	})
  1820  
  1821  	t.Run("accept invitation - error", func(t *testing.T) {
  1822  		svc, err := New(&protocol.MockProvider{
  1823  			ServiceMap: map[string]interface{}{
  1824  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1825  			},
  1826  		})
  1827  		require.NoError(t, err)
  1828  
  1829  		err = svc.AcceptInvitation(generateRandomID(), "sample-public-did", "sample-label", nil)
  1830  		require.Error(t, err)
  1831  		require.Contains(t, err.Error(), "accept connection invitation : get protocol state data : data not found")
  1832  	})
  1833  
  1834  	t.Run("accept invitation - state error", func(t *testing.T) {
  1835  		svc, err := New(&protocol.MockProvider{
  1836  			ServiceMap: map[string]interface{}{
  1837  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1838  			},
  1839  		})
  1840  		require.NoError(t, err)
  1841  
  1842  		id := generateRandomID()
  1843  		connRecord := &connection.Record{
  1844  			ConnectionID: id,
  1845  			State:        StateIDRequested,
  1846  		}
  1847  		err = svc.connectionRecorder.SaveConnectionRecord(connRecord)
  1848  		require.NoError(t, err)
  1849  
  1850  		err = svc.storeEventProtocolStateData(&message{ConnRecord: connRecord})
  1851  		require.NoError(t, err)
  1852  
  1853  		err = svc.AcceptInvitation(id, "sample-public-did", "sample-label", nil)
  1854  		require.Error(t, err)
  1855  		require.Contains(t, err.Error(), "current state (requested) is different from expected state (invited)")
  1856  	})
  1857  
  1858  	t.Run("accept invitation - no connection record error", func(t *testing.T) {
  1859  		svc, err := New(&protocol.MockProvider{
  1860  			ServiceMap: map[string]interface{}{
  1861  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1862  			},
  1863  		})
  1864  		require.NoError(t, err)
  1865  
  1866  		id := generateRandomID()
  1867  		connRecord := &connection.Record{
  1868  			ConnectionID: id,
  1869  			State:        StateIDRequested,
  1870  		}
  1871  
  1872  		err = svc.storeEventProtocolStateData(&message{ConnRecord: connRecord})
  1873  		require.NoError(t, err)
  1874  
  1875  		err = svc.AcceptInvitation(id, "sample-public-did", "sample-label", nil)
  1876  		require.Error(t, err)
  1877  		require.Contains(t, err.Error(), "accept connection invitation : data not found")
  1878  	})
  1879  }
  1880  
  1881  func TestEventProtocolStateData(t *testing.T) {
  1882  	t.Run("event protocol state data - success", func(t *testing.T) {
  1883  		svc, err := New(&protocol.MockProvider{
  1884  			ServiceMap: map[string]interface{}{
  1885  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1886  			},
  1887  		})
  1888  		require.NoError(t, err)
  1889  
  1890  		connID := generateRandomID()
  1891  
  1892  		msg := &message{
  1893  			ConnRecord: &connection.Record{ConnectionID: connID},
  1894  		}
  1895  		err = svc.storeEventProtocolStateData(msg)
  1896  		require.NoError(t, err)
  1897  
  1898  		retrievedMsg, err := svc.getEventProtocolStateData(connID)
  1899  		require.NoError(t, err)
  1900  		require.Equal(t, msg, retrievedMsg)
  1901  	})
  1902  
  1903  	t.Run("event protocol state data - data not found", func(t *testing.T) {
  1904  		svc, err := New(&protocol.MockProvider{
  1905  			ServiceMap: map[string]interface{}{
  1906  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1907  			},
  1908  		})
  1909  		require.NoError(t, err)
  1910  
  1911  		err = svc.AcceptConnectionRequest(generateRandomID(), "", "", nil)
  1912  		require.Error(t, err)
  1913  		require.Contains(t, err.Error(), "accept exchange request : get protocol state data : data not found")
  1914  
  1915  		err = svc.AcceptConnectionRequest(generateRandomID(), "sample-public-did", "sample-label", nil)
  1916  		require.Error(t, err)
  1917  		require.Contains(t, err.Error(), "accept exchange request : get protocol state data : data not found")
  1918  	})
  1919  
  1920  	t.Run("event protocol state data - invalid data", func(t *testing.T) {
  1921  		svc, err := New(&protocol.MockProvider{
  1922  			ServiceMap: map[string]interface{}{
  1923  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1924  			},
  1925  		})
  1926  		require.NoError(t, err)
  1927  
  1928  		connID := generateRandomID()
  1929  
  1930  		err = svc.connectionRecorder.SaveEvent(connID, []byte("invalid data"))
  1931  		require.NoError(t, err)
  1932  
  1933  		_, err = svc.getEventProtocolStateData(connID)
  1934  		require.Error(t, err)
  1935  		require.Contains(t, err.Error(), "get protocol state data : invalid character")
  1936  	})
  1937  }
  1938  
  1939  func TestNextState(t *testing.T) {
  1940  	t.Run("empty thread ID", func(t *testing.T) {
  1941  		svc, err := New(&protocol.MockProvider{
  1942  			ServiceMap: map[string]interface{}{
  1943  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1944  			},
  1945  		})
  1946  		require.NoError(t, err)
  1947  
  1948  		_, err = svc.nextState(RequestMsgType, "")
  1949  		require.EqualError(t, err, "unable to compute hash, empty bytes")
  1950  	})
  1951  
  1952  	t.Run("valid inputs", func(t *testing.T) {
  1953  		svc, err := New(&protocol.MockProvider{
  1954  			ServiceMap: map[string]interface{}{
  1955  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1956  			},
  1957  		})
  1958  		require.NoError(t, err)
  1959  
  1960  		s, errState := svc.nextState(RequestMsgType, generateRandomID())
  1961  		require.NoError(t, errState)
  1962  		require.Equal(t, StateIDRequested, s.Name())
  1963  	})
  1964  }
  1965  
  1966  func TestFetchConnectionRecord(t *testing.T) {
  1967  	t.Run("fetch connection record - invalid payload", func(t *testing.T) {
  1968  		svc, err := New(&protocol.MockProvider{
  1969  			ServiceMap: map[string]interface{}{
  1970  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1971  			},
  1972  		})
  1973  		require.NoError(t, err)
  1974  
  1975  		_, err = svc.fetchConnectionRecord("", service.DIDCommMsgMap{"~thread": map[int]int{1: 1}})
  1976  		require.Contains(t, fmt.Sprintf("%v", err), `'~thread' needs a map with string keys`)
  1977  	})
  1978  
  1979  	t.Run("fetch connection record - no thread id", func(t *testing.T) {
  1980  		svc, err := New(&protocol.MockProvider{
  1981  			ServiceMap: map[string]interface{}{
  1982  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1983  			},
  1984  		})
  1985  		require.NoError(t, err)
  1986  
  1987  		_, err = svc.fetchConnectionRecord(theirNSPrefix, toDIDCommMsg(t, &Request{
  1988  			Type: ResponseMsgType,
  1989  			ID:   generateRandomID(),
  1990  		}))
  1991  		require.Error(t, err)
  1992  		require.Contains(t, err.Error(), "unable to compute hash, empty bytes")
  1993  	})
  1994  
  1995  	t.Run("fetch connection record - valid input", func(t *testing.T) {
  1996  		svc, err := New(&protocol.MockProvider{
  1997  			ServiceMap: map[string]interface{}{
  1998  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1999  			},
  2000  		})
  2001  		require.NoError(t, err)
  2002  
  2003  		_, err = svc.fetchConnectionRecord(theirNSPrefix, toDIDCommMsg(t, &Response{
  2004  			Type:   ResponseMsgType,
  2005  			ID:     generateRandomID(),
  2006  			Thread: &decorator.Thread{ID: generateRandomID()},
  2007  		}))
  2008  		require.Error(t, err)
  2009  		require.Contains(t, err.Error(), "get connectionID by namespaced threadID: data not found")
  2010  	})
  2011  }
  2012  
  2013  func generateRequestMsgPayload(t *testing.T, prov provider, id, invitationID string) service.DIDCommMsgMap {
  2014  	connRec, err := connection.NewRecorder(prov)
  2015  	require.NoError(t, err)
  2016  	require.NotNil(t, connRec)
  2017  
  2018  	ctx := context{
  2019  		outboundDispatcher: prov.OutboundDispatcher(),
  2020  		vdRegistry:         &mockvdr.MockVDRegistry{CreateValue: mockdiddoc.GetMockDIDDoc(t, false)},
  2021  		connectionRecorder: connRec,
  2022  	}
  2023  	doc, err := ctx.vdRegistry.Create(testMethod, nil)
  2024  	require.NoError(t, err)
  2025  
  2026  	requestBytes, err := json.Marshal(&Request{
  2027  		Type: RequestMsgType,
  2028  		ID:   id,
  2029  		Thread: &decorator.Thread{
  2030  			PID: invitationID,
  2031  		},
  2032  		Connection: &Connection{
  2033  			DID:    doc.DIDDocument.ID,
  2034  			DIDDoc: doc.DIDDocument,
  2035  		},
  2036  	})
  2037  	require.NoError(t, err)
  2038  
  2039  	didMsg, err := service.ParseDIDCommMsgMap(requestBytes)
  2040  	require.NoError(t, err)
  2041  
  2042  	return didMsg
  2043  }
  2044  
  2045  func TestService_CreateImplicitInvitation(t *testing.T) {
  2046  	t.Run("success", func(t *testing.T) {
  2047  		routeSvc := &mockroute.MockMediatorSvc{}
  2048  		prov := &protocol.MockProvider{
  2049  			ServiceMap: map[string]interface{}{
  2050  				mediator.Coordination: routeSvc,
  2051  			},
  2052  		}
  2053  		sp := mockstorage.NewMockStoreProvider()
  2054  		k := newKMS(t, sp)
  2055  		ctx := &context{
  2056  			kms:                k,
  2057  			outboundDispatcher: prov.OutboundDispatcher(),
  2058  			routeSvc:           routeSvc,
  2059  			keyType:            kms.ED25519Type,
  2060  			keyAgreementType:   kms.X25519ECDHKWType,
  2061  			mediaTypeProfiles:  []string{transport.MediaTypeRFC0019EncryptedEnvelope},
  2062  		}
  2063  
  2064  		_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  2065  		require.NoError(t, err)
  2066  
  2067  		newDIDDoc := createDIDDocWithKey(verPubKey)
  2068  
  2069  		connRec, err := connection.NewRecorder(prov)
  2070  		require.NoError(t, err)
  2071  		require.NotNil(t, connRec)
  2072  
  2073  		didConnStore, err := didstore.NewConnectionStore(prov)
  2074  		require.NoError(t, err)
  2075  		require.NotNil(t, didConnStore)
  2076  
  2077  		ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: newDIDDoc}
  2078  		ctx.connectionRecorder = connRec
  2079  		ctx.connectionStore = didConnStore
  2080  
  2081  		s, err := New(prov)
  2082  		require.NoError(t, err)
  2083  
  2084  		s.ctx = ctx
  2085  		connID, err := s.CreateImplicitInvitation("label", newDIDDoc.ID, "", "", nil)
  2086  		require.NoError(t, err)
  2087  		require.NotEmpty(t, connID)
  2088  	})
  2089  
  2090  	t.Run("error during did resolution", func(t *testing.T) {
  2091  		routeSvc := &mockroute.MockMediatorSvc{}
  2092  		prov := &protocol.MockProvider{
  2093  			ServiceMap: map[string]interface{}{
  2094  				mediator.Coordination: routeSvc,
  2095  			},
  2096  		}
  2097  		sp := mockstorage.NewMockStoreProvider()
  2098  		k := newKMS(t, sp)
  2099  		ctx := &context{
  2100  			kms:                k,
  2101  			outboundDispatcher: prov.OutboundDispatcher(),
  2102  			routeSvc:           routeSvc,
  2103  			keyType:            kms.ED25519Type,
  2104  			keyAgreementType:   kms.X25519ECDHKWType,
  2105  			mediaTypeProfiles:  []string{transport.MediaTypeRFC0019EncryptedEnvelope},
  2106  		}
  2107  
  2108  		_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  2109  		require.NoError(t, err)
  2110  
  2111  		newDIDDoc := createDIDDocWithKey(verPubKey)
  2112  
  2113  		connRec, err := connection.NewRecorder(prov)
  2114  		require.NoError(t, err)
  2115  		require.NotNil(t, connRec)
  2116  
  2117  		didConnStore, err := didstore.NewConnectionStore(prov)
  2118  		require.NoError(t, err)
  2119  		require.NotNil(t, didConnStore)
  2120  
  2121  		ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveErr: errors.New("resolve error")}
  2122  		ctx.connectionRecorder = connRec
  2123  		ctx.connectionStore = didConnStore
  2124  
  2125  		s, err := New(prov)
  2126  		require.NoError(t, err)
  2127  		s.ctx = ctx
  2128  
  2129  		connID, err := s.CreateImplicitInvitation("label", newDIDDoc.ID, "", "", nil)
  2130  		require.Error(t, err)
  2131  		require.Contains(t, err.Error(), "resolve error")
  2132  		require.Empty(t, connID)
  2133  	})
  2134  
  2135  	t.Run("error during saving connection", func(t *testing.T) {
  2136  		sp := mockstorage.NewMockStoreProvider()
  2137  		k := newKMS(t, sp)
  2138  		ctx := &context{
  2139  			kms:               k,
  2140  			keyType:           kms.ED25519Type,
  2141  			keyAgreementType:  kms.X25519ECDHKWType,
  2142  			mediaTypeProfiles: []string{transport.MediaTypeRFC0019EncryptedEnvelope},
  2143  		}
  2144  		routeSvc := &mockroute.MockMediatorSvc{}
  2145  		protocolStateStore := mockstorage.NewMockStoreProvider()
  2146  		protocolStateStore.Store.ErrPut = errors.New("store put error")
  2147  		prov := &protocol.MockProvider{
  2148  			ProtocolStateStoreProvider: protocolStateStore,
  2149  			ServiceMap: map[string]interface{}{
  2150  				mediator.Coordination: routeSvc,
  2151  			},
  2152  			KeyTypeValue:          ctx.keyType,
  2153  			KeyAgreementTypeValue: ctx.keyAgreementType,
  2154  		}
  2155  
  2156  		ctx.outboundDispatcher = prov.OutboundDispatcher()
  2157  		ctx.routeSvc = routeSvc
  2158  
  2159  		_, verPubKey, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type)
  2160  		require.NoError(t, err)
  2161  
  2162  		newDIDDoc := createDIDDocWithKey(verPubKey)
  2163  
  2164  		connRec, err := connection.NewRecorder(prov)
  2165  		require.NoError(t, err)
  2166  		require.NotNil(t, connRec)
  2167  
  2168  		didConnStore, err := didstore.NewConnectionStore(prov)
  2169  		require.NoError(t, err)
  2170  		require.NotNil(t, didConnStore)
  2171  
  2172  		ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: newDIDDoc}
  2173  		ctx.connectionRecorder = connRec
  2174  		ctx.connectionStore = didConnStore
  2175  
  2176  		s, err := New(prov)
  2177  		require.NoError(t, err)
  2178  		s.ctx = ctx
  2179  
  2180  		connID, err := s.CreateImplicitInvitation("label", newDIDDoc.ID, "", "", nil)
  2181  		require.Error(t, err)
  2182  		require.Contains(t, err.Error(), "store put error")
  2183  		require.Empty(t, connID)
  2184  	})
  2185  }
  2186  
  2187  func testProvider() *protocol.MockProvider {
  2188  	return &protocol.MockProvider{
  2189  		StoreProvider: mockstorage.NewMockStoreProvider(),
  2190  		ServiceMap: map[string]interface{}{
  2191  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  2192  		},
  2193  		KeyTypeValue:          kms.ED25519Type,
  2194  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
  2195  	}
  2196  }
  2197  
  2198  func newPeerDID(t *testing.T, k kms.KeyManager) *did.Doc {
  2199  	kid, pubKey, err := k.CreateAndExportPubKeyBytes(kms.ED25519)
  2200  	require.NoError(t, err)
  2201  
  2202  	key := did.VerificationMethod{
  2203  		ID:         kid,
  2204  		Type:       "Ed25519VerificationKey2018",
  2205  		Controller: "",
  2206  		Value:      pubKey,
  2207  	}
  2208  	doc, err := peer.NewDoc(
  2209  		[]did.VerificationMethod{key},
  2210  		did.WithAuthentication([]did.Verification{{
  2211  			VerificationMethod: key,
  2212  			Relationship:       0,
  2213  			Embedded:           true,
  2214  		}}),
  2215  		did.WithService([]did.Service{{
  2216  			ID:              "didcomm",
  2217  			Type:            "did-communication",
  2218  			Priority:        0,
  2219  			RecipientKeys:   []string{base58.Encode(pubKey)},
  2220  			ServiceEndpoint: commonmodel.NewDIDCommV1Endpoint("http://example.com"),
  2221  		}}),
  2222  	)
  2223  	require.NoError(t, err)
  2224  
  2225  	return doc
  2226  }
  2227  
  2228  type mockConnectionStore struct {
  2229  	saveDIDByResolvingErr error
  2230  	saveDIDFromDocErr     error
  2231  }
  2232  
  2233  // GetDID returns DID associated with key.
  2234  func (m *mockConnectionStore) GetDID(string) (string, error) {
  2235  	return "", nil
  2236  }
  2237  
  2238  // SaveDID saves DID to the underlying storage.
  2239  func (m *mockConnectionStore) SaveDID(string, ...string) error {
  2240  	return nil
  2241  }
  2242  
  2243  // SaveDIDFromDoc saves DID from did.Doc to the underlying storage.
  2244  func (m *mockConnectionStore) SaveDIDFromDoc(*did.Doc) error {
  2245  	return m.saveDIDFromDocErr
  2246  }
  2247  
  2248  // SaveDIDByResolving saves DID resolved by VDR to the underlying storage.
  2249  func (m *mockConnectionStore) SaveDIDByResolving(string, ...string) error {
  2250  	return m.saveDIDByResolvingErr
  2251  }
  2252  
  2253  func randomString() string {
  2254  	u := uuid.New()
  2255  	return u.String()
  2256  }