github.com/hyperledger/aries-framework-go@v0.3.2/pkg/client/didexchange/client_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package didexchange
     8  
     9  import (
    10  	"crypto/ed25519"
    11  	"crypto/rand"
    12  	"encoding/base64"
    13  	"encoding/json"
    14  	"errors"
    15  	"fmt"
    16  	"strconv"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/google/uuid"
    21  	"github.com/stretchr/testify/require"
    22  
    23  	"github.com/hyperledger/aries-framework-go/component/storageutil/mem"
    24  	"github.com/hyperledger/aries-framework-go/pkg/common/model"
    25  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
    26  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator"
    27  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange"
    28  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator"
    29  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/transport"
    30  	"github.com/hyperledger/aries-framework-go/pkg/doc/did"
    31  	"github.com/hyperledger/aries-framework-go/pkg/framework/aries"
    32  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    33  	"github.com/hyperledger/aries-framework-go/pkg/kms/localkms"
    34  	mockprotocol "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol"
    35  	mocksvc "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange"
    36  	mockroute "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator"
    37  	mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
    38  	mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider"
    39  	mockstore "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    40  	mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr"
    41  	"github.com/hyperledger/aries-framework-go/pkg/secretlock"
    42  	"github.com/hyperledger/aries-framework-go/pkg/secretlock/noop"
    43  	"github.com/hyperledger/aries-framework-go/pkg/store/connection"
    44  	"github.com/hyperledger/aries-framework-go/pkg/vdr/peer"
    45  	spi "github.com/hyperledger/aries-framework-go/spi/storage"
    46  )
    47  
    48  func TestNew(t *testing.T) {
    49  	t.Run("test new client", func(t *testing.T) {
    50  		svc, err := didexchange.New(&mockprotocol.MockProvider{
    51  			ServiceMap: map[string]interface{}{
    52  				mediator.Coordination: &mockroute.MockMediatorSvc{},
    53  			},
    54  		})
    55  		require.NoError(t, err)
    56  		require.NotNil(t, svc)
    57  
    58  		_, err = New(&mockprovider.Provider{
    59  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
    60  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
    61  			ServiceMap: map[string]interface{}{
    62  				didexchange.DIDExchange: svc,
    63  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
    64  			},
    65  		})
    66  		require.NoError(t, err)
    67  	})
    68  
    69  	t.Run("test error from get service from context", func(t *testing.T) {
    70  		_, err := New(&mockprovider.Provider{ServiceErr: fmt.Errorf("service error")})
    71  		require.Error(t, err)
    72  		require.Contains(t, err.Error(), "service error")
    73  	})
    74  
    75  	t.Run("test error from cast service", func(t *testing.T) {
    76  		_, err := New(&mockprovider.Provider{ServiceValue: nil})
    77  		require.Error(t, err)
    78  		require.Contains(t, err.Error(), "cast service to DIDExchange Service failed")
    79  	})
    80  
    81  	t.Run("test route service cast error", func(t *testing.T) {
    82  		_, err := New(&mockprovider.Provider{
    83  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
    84  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
    85  			ServiceMap: map[string]interface{}{
    86  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{},
    87  				mediator.Coordination:   &mocksvc.MockDIDExchangeSvc{},
    88  			},
    89  		})
    90  		require.Error(t, err)
    91  		require.Contains(t, err.Error(), "cast service to Route Service failed")
    92  	})
    93  
    94  	t.Run("test error from open store", func(t *testing.T) {
    95  		svc, err := didexchange.New(&mockprotocol.MockProvider{
    96  			ServiceMap: map[string]interface{}{
    97  				mediator.Coordination: &mockroute.MockMediatorSvc{},
    98  			},
    99  		})
   100  		require.NoError(t, err)
   101  		require.NotNil(t, svc)
   102  
   103  		_, err = New(&mockprovider.Provider{
   104  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   105  			StorageProviderValue: &mockstore.MockStoreProvider{
   106  				ErrOpenStoreHandle: fmt.Errorf("failed to open store"),
   107  			},
   108  			ServiceMap: map[string]interface{}{
   109  				didexchange.DIDExchange: svc,
   110  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   111  			},
   112  			ServiceEndpointValue: "endpoint",
   113  		})
   114  		require.Error(t, err)
   115  		require.Contains(t, err.Error(), "failed to open store")
   116  	})
   117  
   118  	t.Run("test error from open protocol state store", func(t *testing.T) {
   119  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   120  			ServiceMap: map[string]interface{}{
   121  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   122  			},
   123  		})
   124  		require.NoError(t, err)
   125  		require.NotNil(t, svc)
   126  
   127  		_, err = New(&mockprovider.Provider{
   128  			StorageProviderValue: mockstore.NewMockStoreProvider(),
   129  			ProtocolStateStorageProviderValue: &mockstore.MockStoreProvider{
   130  				ErrOpenStoreHandle: fmt.Errorf("failed to open protocol state store"),
   131  			},
   132  			ServiceMap: map[string]interface{}{
   133  				didexchange.DIDExchange: svc,
   134  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   135  			},
   136  			ServiceEndpointValue: "endpoint",
   137  		})
   138  		require.Error(t, err)
   139  		require.Contains(t, err.Error(), "failed to open protocol state store")
   140  	})
   141  }
   142  
   143  func TestClient_CreateInvitation(t *testing.T) {
   144  	t.Run("test success", func(t *testing.T) {
   145  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   146  			ServiceMap: map[string]interface{}{
   147  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   148  			},
   149  		})
   150  		require.NoError(t, err)
   151  		require.NotNil(t, svc)
   152  
   153  		ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   154  		require.NoError(t, err)
   155  
   156  		c, err := New(&mockprovider.Provider{
   157  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   158  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   159  			ServiceMap: map[string]interface{}{
   160  				didexchange.DIDExchange: svc,
   161  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   162  			},
   163  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   164  			ServiceEndpointValue: "endpoint",
   165  		})
   166  
   167  		require.NoError(t, err)
   168  		inviteReq, err := c.CreateInvitation("agent")
   169  		require.NoError(t, err)
   170  		require.NotNil(t, inviteReq)
   171  		require.NotEmpty(t, inviteReq.Label)
   172  		require.NotEmpty(t, inviteReq.ID)
   173  		require.Nil(t, inviteReq.RoutingKeys)
   174  		require.Equal(t, "endpoint", inviteReq.ServiceEndpoint)
   175  	})
   176  
   177  	t.Run("test success with DIDCommV2 media profile", func(t *testing.T) {
   178  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   179  			ServiceMap: map[string]interface{}{
   180  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   181  			},
   182  		})
   183  		require.NoError(t, err)
   184  		require.NotNil(t, svc)
   185  
   186  		store, err := kms.NewAriesProviderWrapper(mockstore.NewMockStoreProvider())
   187  		require.NoError(t, err)
   188  
   189  		km := newKMS(t, store)
   190  
   191  		c, err := New(&mockprovider.Provider{
   192  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   193  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   194  			ServiceMap: map[string]interface{}{
   195  				didexchange.DIDExchange: svc,
   196  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   197  			},
   198  			KMSValue:               km,
   199  			ServiceEndpointValue:   "endpoint",
   200  			KeyAgreementTypeValue:  kms.NISTP521ECDHKWType,
   201  			MediaTypeProfilesValue: []string{transport.MediaTypeDIDCommV2Profile},
   202  		})
   203  
   204  		require.NoError(t, err)
   205  		inviteReq, err := c.CreateInvitation("agent")
   206  		require.NoError(t, err)
   207  		require.NotNil(t, inviteReq)
   208  		require.NotEmpty(t, inviteReq.Label)
   209  		require.NotEmpty(t, inviteReq.ID)
   210  		require.Nil(t, inviteReq.RoutingKeys)
   211  		require.Equal(t, "endpoint", inviteReq.ServiceEndpoint)
   212  	})
   213  
   214  	t.Run("test success with DIDCommV2 media profile and KeyType option", func(t *testing.T) {
   215  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   216  			ServiceMap: map[string]interface{}{
   217  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   218  			},
   219  		})
   220  		require.NoError(t, err)
   221  		require.NotNil(t, svc)
   222  
   223  		store, err := kms.NewAriesProviderWrapper(mockstore.NewMockStoreProvider())
   224  		require.NoError(t, err)
   225  
   226  		km := newKMS(t, store)
   227  
   228  		c, err := New(&mockprovider.Provider{
   229  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   230  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   231  			ServiceMap: map[string]interface{}{
   232  				didexchange.DIDExchange: svc,
   233  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   234  			},
   235  			KMSValue:               km,
   236  			ServiceEndpointValue:   "endpoint",
   237  			KeyAgreementTypeValue:  kms.NISTP521ECDHKWType,
   238  			MediaTypeProfilesValue: []string{transport.MediaTypeDIDCommV2Profile},
   239  		})
   240  
   241  		require.NoError(t, err)
   242  		inviteReq, err := c.CreateInvitation("agent", WithKeyType(kms.X25519ECDHKWType))
   243  		require.NoError(t, err)
   244  		require.NotNil(t, inviteReq)
   245  		require.NotEmpty(t, inviteReq.Label)
   246  		require.NotEmpty(t, inviteReq.ID)
   247  		require.Nil(t, inviteReq.RoutingKeys)
   248  		x25519DIDKeyPrefix := "did:key:z6L"
   249  		require.Equal(t, x25519DIDKeyPrefix, inviteReq.RecipientKeys[0][:len(x25519DIDKeyPrefix)])
   250  		require.Equal(t, "endpoint", inviteReq.ServiceEndpoint)
   251  	})
   252  
   253  	t.Run("test failure with DIDCommV2 media profile with empty kms key for calling "+
   254  		"kmsdidkey.BuildDIDKeyByKeyType()", func(t *testing.T) {
   255  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   256  			ServiceMap: map[string]interface{}{
   257  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   258  			},
   259  		})
   260  		require.NoError(t, err)
   261  		require.NotNil(t, svc)
   262  
   263  		c, err := New(&mockprovider.Provider{
   264  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   265  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   266  			ServiceMap: map[string]interface{}{
   267  				didexchange.DIDExchange: svc,
   268  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   269  			},
   270  			KMSValue:               &mockkms.KeyManager{},
   271  			ServiceEndpointValue:   "endpoint",
   272  			KeyAgreementTypeValue:  kms.NISTP521ECDHKWType,
   273  			MediaTypeProfilesValue: []string{transport.MediaTypeDIDCommV2Profile},
   274  		})
   275  		require.NoError(t, err)
   276  
   277  		_, err = c.CreateInvitation("agent")
   278  		require.EqualError(t, err, "createInvitation: failed to build did:key by key type: buildDIDkeyByKMSKeyType"+
   279  			" failed to unmarshal key type NISTP521ECDHKW: unexpected end of JSON input")
   280  	})
   281  
   282  	t.Run("test error from createSigningKey", func(t *testing.T) {
   283  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   284  			ServiceMap: map[string]interface{}{
   285  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   286  			},
   287  		})
   288  		require.NoError(t, err)
   289  		require.NotNil(t, svc)
   290  
   291  		c, err := New(&mockprovider.Provider{
   292  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   293  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   294  			ServiceMap: map[string]interface{}{
   295  				didexchange.DIDExchange: svc,
   296  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   297  			},
   298  			KMSValue: &mockkms.KeyManager{CrAndExportPubKeyErr: fmt.Errorf("createKeyErr")},
   299  		})
   300  		require.NoError(t, err)
   301  		_, err = c.CreateInvitation("agent")
   302  		require.Error(t, err)
   303  		require.Contains(t, err.Error(), "createKeyErr")
   304  	})
   305  
   306  	t.Run("test error from save record", func(t *testing.T) {
   307  		store := &mockstore.MockStore{
   308  			Store:  make(map[string]mockstore.DBEntry),
   309  			ErrPut: fmt.Errorf("store error"),
   310  		}
   311  
   312  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   313  			StoreProvider: mockstore.NewCustomMockStoreProvider(store),
   314  			ServiceMap: map[string]interface{}{
   315  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   316  			},
   317  		})
   318  		require.NoError(t, err)
   319  		require.NotNil(t, svc)
   320  
   321  		c, err := New(&mockprovider.Provider{
   322  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   323  			StorageProviderValue:              mockstore.NewCustomMockStoreProvider(store),
   324  			ServiceMap: map[string]interface{}{
   325  				didexchange.DIDExchange: svc,
   326  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   327  			},
   328  			KMSValue: &mockkms.KeyManager{},
   329  		})
   330  		require.NoError(t, err)
   331  		_, err = c.CreateInvitation("agent")
   332  		require.Error(t, err)
   333  		require.Contains(t, err.Error(), "failed to save invitation")
   334  	})
   335  
   336  	t.Run("test success with router registered", func(t *testing.T) {
   337  		endpoint := "http://router.example.com"
   338  		routingKeys := []string{"abc", "xyz"}
   339  
   340  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   341  			ServiceMap: map[string]interface{}{
   342  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   343  			},
   344  		})
   345  		require.NoError(t, err)
   346  		require.NotNil(t, svc)
   347  
   348  		ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   349  		require.NoError(t, err)
   350  
   351  		c, err := New(&mockprovider.Provider{
   352  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   353  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   354  			ServiceMap: map[string]interface{}{
   355  				didexchange.DIDExchange: svc,
   356  				mediator.Coordination: &mockroute.MockMediatorSvc{
   357  					Connections:    []string{"xyz"},
   358  					RoutingKeys:    routingKeys,
   359  					RouterEndpoint: endpoint,
   360  				},
   361  			},
   362  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   363  			ServiceEndpointValue: "endpoint",
   364  		})
   365  		require.NoError(t, err)
   366  
   367  		inviteReq, err := c.CreateInvitation("agent", WithRouterConnectionID("xyz"))
   368  		require.NoError(t, err)
   369  		require.NotNil(t, inviteReq)
   370  		require.NotEmpty(t, inviteReq.Label)
   371  		require.NotEmpty(t, inviteReq.ID)
   372  		require.Equal(t, endpoint, inviteReq.ServiceEndpoint)
   373  		require.Equal(t, routingKeys, inviteReq.RoutingKeys)
   374  	})
   375  
   376  	t.Run("test create invitation with router config error", func(t *testing.T) {
   377  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   378  			ServiceMap: map[string]interface{}{
   379  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   380  			},
   381  		})
   382  		require.NoError(t, err)
   383  		require.NotNil(t, svc)
   384  
   385  		ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   386  		require.NoError(t, err)
   387  
   388  		c, err := New(&mockprovider.Provider{
   389  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   390  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   391  			ServiceMap: map[string]interface{}{
   392  				didexchange.DIDExchange: svc,
   393  				mediator.Coordination: &mockroute.MockMediatorSvc{
   394  					Connections: []string{"xyz"},
   395  					ConfigErr:   errors.New("router config error"),
   396  				},
   397  			},
   398  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   399  			ServiceEndpointValue: "endpoint",
   400  		})
   401  		require.NoError(t, err)
   402  
   403  		inviteReq, err := c.CreateInvitation("agent", WithRouterConnectionID("xyz"))
   404  		require.EqualError(t, err, "createInvitation: getRouterConfig: fetch router config: router config error")
   405  		require.Nil(t, inviteReq)
   406  	})
   407  
   408  	t.Run("test create invitation with adding key to router error", func(t *testing.T) {
   409  		endpoint := "http://router.example.com"
   410  		routingKeys := []string{"abc", "xyz"}
   411  
   412  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   413  			ServiceMap: map[string]interface{}{
   414  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   415  			},
   416  		})
   417  		require.NoError(t, err)
   418  		require.NotNil(t, svc)
   419  
   420  		ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   421  		require.NoError(t, err)
   422  
   423  		c, err := New(&mockprovider.Provider{
   424  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   425  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   426  			ServiceMap: map[string]interface{}{
   427  				didexchange.DIDExchange: svc,
   428  				mediator.Coordination: &mockroute.MockMediatorSvc{
   429  					Connections:    []string{"xyz"},
   430  					RoutingKeys:    routingKeys,
   431  					RouterEndpoint: endpoint,
   432  					AddKeyErr:      errors.New("failed to add key to the router"),
   433  				},
   434  			},
   435  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   436  			ServiceEndpointValue: "endpoint",
   437  		})
   438  		require.NoError(t, err)
   439  
   440  		inviteReq, err := c.CreateInvitation("agent", WithRouterConnectionID("xyz"))
   441  		require.EqualError(t, err, "createInvitation: AddKeyToRouter: addKey: failed to add key to the router")
   442  		require.Nil(t, inviteReq)
   443  	})
   444  }
   445  
   446  func TestClient_CreateInvitationWithDID(t *testing.T) {
   447  	t.Run("test success", func(t *testing.T) {
   448  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   449  			ServiceMap: map[string]interface{}{
   450  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   451  			},
   452  		})
   453  		require.NoError(t, err)
   454  		require.NotNil(t, svc)
   455  
   456  		ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   457  		require.NoError(t, err)
   458  
   459  		c, err := New(&mockprovider.Provider{
   460  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   461  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   462  			ServiceMap: map[string]interface{}{
   463  				didexchange.DIDExchange: svc,
   464  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   465  			},
   466  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   467  			ServiceEndpointValue: "endpoint",
   468  		})
   469  		require.NoError(t, err)
   470  
   471  		const label = "agent"
   472  		const id = "did:sidetree:123"
   473  		inviteReq, err := c.CreateInvitationWithDID(label, id)
   474  		require.NoError(t, err)
   475  		require.NotNil(t, inviteReq)
   476  		require.Equal(t, label, inviteReq.Label)
   477  		require.NotEmpty(t, inviteReq.ID)
   478  		require.Equal(t, id, inviteReq.DID)
   479  	})
   480  
   481  	t.Run("test error from save invitation", func(t *testing.T) {
   482  		store := &mockstore.MockStore{
   483  			Store:  make(map[string]mockstore.DBEntry),
   484  			ErrPut: fmt.Errorf("store error"),
   485  		}
   486  
   487  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   488  			StoreProvider: mockstore.NewCustomMockStoreProvider(store),
   489  			ServiceMap: map[string]interface{}{
   490  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   491  			},
   492  		})
   493  		require.NoError(t, err)
   494  		require.NotNil(t, svc)
   495  
   496  		c, err := New(&mockprovider.Provider{
   497  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   498  			StorageProviderValue:              mockstore.NewCustomMockStoreProvider(store),
   499  			ServiceMap: map[string]interface{}{
   500  				didexchange.DIDExchange: svc,
   501  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   502  			},
   503  			KMSValue: &mockkms.KeyManager{},
   504  		})
   505  		require.NoError(t, err)
   506  
   507  		_, err = c.CreateInvitationWithDID("agent", "did:sidetree:123")
   508  		require.Error(t, err)
   509  		require.Contains(t, err.Error(), "failed to save invitation")
   510  	})
   511  }
   512  
   513  func TestClient_QueryConnectionByID(t *testing.T) {
   514  	const (
   515  		connID   = "id1"
   516  		threadID = "thid1"
   517  	)
   518  
   519  	ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   520  	require.NoError(t, err)
   521  
   522  	t.Run("test success", func(t *testing.T) {
   523  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   524  			ServiceMap: map[string]interface{}{
   525  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   526  			},
   527  		})
   528  		require.NoError(t, err)
   529  		require.NotNil(t, svc)
   530  
   531  		c, err := New(&mockprovider.Provider{
   532  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   533  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   534  			ServiceMap: map[string]interface{}{
   535  				didexchange.DIDExchange: svc,
   536  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   537  			},
   538  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   539  			ServiceEndpointValue: "endpoint",
   540  		})
   541  		require.NoError(t, err)
   542  
   543  		connRec := &connection.Record{ConnectionID: connID, ThreadID: threadID, State: "complete"}
   544  
   545  		require.NoError(t, err)
   546  		require.NoError(t, c.connectionStore.SaveConnectionRecord(connRec))
   547  		result, err := c.GetConnection(connID)
   548  		require.NoError(t, err)
   549  		require.Equal(t, "complete", result.State)
   550  		require.Equal(t, "id1", result.ConnectionID)
   551  	})
   552  
   553  	t.Run("test error", func(t *testing.T) {
   554  		const errMsg = "query connection error"
   555  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   556  			ServiceMap: map[string]interface{}{
   557  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   558  			},
   559  		})
   560  		require.NoError(t, err)
   561  		require.NotNil(t, svc)
   562  
   563  		store := &mockstore.MockStore{
   564  			Store:  make(map[string]mockstore.DBEntry),
   565  			ErrGet: fmt.Errorf(errMsg),
   566  		}
   567  
   568  		c, err := New(&mockprovider.Provider{
   569  			ProtocolStateStorageProviderValue: mockstore.NewCustomMockStoreProvider(store),
   570  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   571  			ServiceMap: map[string]interface{}{
   572  				didexchange.DIDExchange: svc,
   573  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   574  			},
   575  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   576  			ServiceEndpointValue: "endpoint",
   577  		})
   578  		require.NoError(t, err)
   579  
   580  		connRec := &connection.Record{ConnectionID: connID, ThreadID: threadID, State: "complete"}
   581  
   582  		require.NoError(t, err)
   583  		require.NoError(t, c.connectionStore.SaveConnectionRecord(connRec))
   584  		_, err = c.GetConnection(connID)
   585  		require.Error(t, err)
   586  		require.Contains(t, err.Error(), errMsg)
   587  	})
   588  
   589  	t.Run("test data not found", func(t *testing.T) {
   590  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   591  			ServiceMap: map[string]interface{}{
   592  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   593  			},
   594  		})
   595  		require.NoError(t, err)
   596  		require.NotNil(t, svc)
   597  
   598  		c, err := New(&mockprovider.Provider{
   599  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   600  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   601  			ServiceMap: map[string]interface{}{
   602  				didexchange.DIDExchange: svc,
   603  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   604  			},
   605  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   606  			ServiceEndpointValue: "endpoint",
   607  		})
   608  		require.NoError(t, err)
   609  
   610  		result, err := c.GetConnection(connID)
   611  		require.Error(t, err)
   612  		require.True(t, errors.Is(err, ErrConnectionNotFound))
   613  		require.Nil(t, result)
   614  	})
   615  }
   616  
   617  func TestClient_GetConnection(t *testing.T) {
   618  	connID := "id1"
   619  	threadID := "thid1"
   620  
   621  	t.Run("test failure", func(t *testing.T) {
   622  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   623  			ServiceMap: map[string]interface{}{
   624  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   625  			},
   626  		})
   627  		require.NoError(t, err)
   628  		require.NotNil(t, svc)
   629  		s := &mockstore.MockStore{Store: make(map[string]mockstore.DBEntry), ErrGet: ErrConnectionNotFound}
   630  		c, err := New(&mockprovider.Provider{
   631  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   632  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   633  			ServiceMap: map[string]interface{}{
   634  				didexchange.DIDExchange: svc,
   635  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   636  			},
   637  		})
   638  		require.NoError(t, err)
   639  		connRec := &connection.Record{ConnectionID: connID, ThreadID: threadID, State: "complete"}
   640  		connBytes, err := json.Marshal(connRec)
   641  		require.NoError(t, err)
   642  		require.NoError(t, s.Put("conn_id1", connBytes))
   643  		result, err := c.GetConnection(connID)
   644  		require.Equal(t, err.Error(), ErrConnectionNotFound.Error())
   645  		require.Nil(t, result)
   646  	})
   647  }
   648  
   649  func TestClientGetConnectionAtState(t *testing.T) {
   650  	// create service
   651  	svc, err := didexchange.New(&mockprotocol.MockProvider{
   652  		ServiceMap: map[string]interface{}{
   653  			mediator.Coordination: &mockroute.MockMediatorSvc{},
   654  		},
   655  	})
   656  	require.NoError(t, err)
   657  	require.NotNil(t, svc)
   658  
   659  	// create client
   660  	c, err := New(&mockprovider.Provider{
   661  		ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   662  		StorageProviderValue:              mockstore.NewMockStoreProvider(),
   663  		ServiceMap: map[string]interface{}{
   664  			didexchange.DIDExchange: svc,
   665  			mediator.Coordination:   &mockroute.MockMediatorSvc{},
   666  		},
   667  	})
   668  	require.NoError(t, err)
   669  
   670  	// not found
   671  	result, err := c.GetConnectionAtState("id1", "complete")
   672  	require.Equal(t, err.Error(), ErrConnectionNotFound.Error())
   673  	require.Nil(t, result)
   674  }
   675  
   676  func TestClient_CreateConnection(t *testing.T) {
   677  	t.Run("test create connection - success", func(t *testing.T) {
   678  		theirDID := newPeerDID(t)
   679  		myDID := newPeerDID(t)
   680  		threadID := uuid.New().String()
   681  		parentThreadID := uuid.New().String()
   682  		label := uuid.New().String()
   683  		invitationID := uuid.New().String()
   684  		invitationDID := newPeerDID(t).ID
   685  		implicit := true
   686  		storageProvider := &mockprovider.Provider{
   687  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   688  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   689  		}
   690  		c, err := New(&mockprovider.Provider{
   691  			ProtocolStateStorageProviderValue: storageProvider.ProtocolStateStorageProvider(),
   692  			StorageProviderValue:              storageProvider.StorageProvider(),
   693  			ServiceMap: map[string]interface{}{
   694  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{
   695  					CreateConnRecordFunc: func(r *connection.Record, td *did.Doc) error {
   696  						recorder, err := connection.NewRecorder(storageProvider)
   697  						require.NoError(t, err)
   698  						err = recorder.SaveConnectionRecord(r)
   699  						require.NoError(t, err)
   700  
   701  						return nil
   702  					},
   703  				},
   704  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   705  			},
   706  		})
   707  		require.NoError(t, err)
   708  
   709  		id, err := c.CreateConnection(myDID.ID, theirDID,
   710  			WithTheirLabel(label), WithThreadID(threadID), WithParentThreadID(parentThreadID),
   711  			WithInvitationID(invitationID), WithInvitationDID(invitationDID), WithImplicit(implicit))
   712  		require.NoError(t, err)
   713  
   714  		conn, err := c.GetConnection(id)
   715  		require.NoError(t, err)
   716  		require.Equal(t, connection.StateNameCompleted, conn.State)
   717  		require.Equal(t, threadID, conn.ThreadID)
   718  		require.Equal(t, parentThreadID, conn.ParentThreadID)
   719  		require.Equal(t, label, conn.TheirLabel)
   720  		require.Equal(t, theirDID.ID, conn.TheirDID)
   721  		require.Equal(t, myDID.ID, conn.MyDID)
   722  		require.Equal(t, invitationID, conn.InvitationID)
   723  		require.Equal(t, invitationDID, conn.InvitationDID)
   724  		require.Equal(t, theirDID.Service[0].ServiceEndpoint, conn.ServiceEndPoint)
   725  		require.Equal(t, implicit, conn.Implicit)
   726  	})
   727  
   728  	t.Run("test create connection - error", func(t *testing.T) {
   729  		c, err := New(&mockprovider.Provider{
   730  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   731  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   732  			ServiceMap: map[string]interface{}{
   733  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{
   734  					CreateConnRecordFunc: func(*connection.Record, *did.Doc) error {
   735  						return errors.New("save connection")
   736  					},
   737  				},
   738  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   739  			},
   740  		})
   741  		require.NoError(t, err)
   742  
   743  		id, err := c.CreateConnection(newPeerDID(t).ID, newPeerDID(t))
   744  		require.EqualError(t, err, "createConnection: err: save connection")
   745  		require.Empty(t, id)
   746  	})
   747  
   748  	t.Run("test create connection - error from CreateDestination", func(t *testing.T) {
   749  		theirDID := newPeerDID(t)
   750  		myDID := newPeerDID(t)
   751  		threadID := uuid.New().String()
   752  		parentThreadID := uuid.New().String()
   753  		label := uuid.New().String()
   754  		invitationID := uuid.New().String()
   755  		invitationDID := newPeerDID(t).ID
   756  		implicit := true
   757  		storageProvider := &mockprovider.Provider{
   758  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   759  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   760  		}
   761  		c, err := New(&mockprovider.Provider{
   762  			ProtocolStateStorageProviderValue: storageProvider.ProtocolStateStorageProvider(),
   763  			StorageProviderValue:              storageProvider.StorageProvider(),
   764  			ServiceMap: map[string]interface{}{
   765  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{
   766  					CreateConnRecordFunc: func(r *connection.Record, td *did.Doc) error {
   767  						recorder, err := connection.NewRecorder(storageProvider)
   768  						require.NoError(t, err)
   769  						err = recorder.SaveConnectionRecord(r)
   770  						require.NoError(t, err)
   771  
   772  						return nil
   773  					},
   774  				},
   775  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   776  			},
   777  		})
   778  		require.NoError(t, err)
   779  
   780  		// empty ServiceEndpoint to trigger CreateDestination error
   781  		theirDID.Service[0].ServiceEndpoint = model.NewDIDCommV1Endpoint("")
   782  
   783  		_, err = c.CreateConnection(myDID.ID, theirDID,
   784  			WithTheirLabel(label), WithThreadID(threadID), WithParentThreadID(parentThreadID),
   785  			WithInvitationID(invitationID), WithInvitationDID(invitationDID), WithImplicit(implicit))
   786  		require.Contains(t, err.Error(), "createConnection: failed to create destination: "+
   787  			"create destination: service endpoint URI on didcomm v1 service block in diddoc error:")
   788  	})
   789  }
   790  
   791  func TestClient_RemoveConnection(t *testing.T) {
   792  	t.Run("test success", func(t *testing.T) {
   793  		connID := "id1"
   794  		threadID := "thid1"
   795  
   796  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   797  			ServiceMap: map[string]interface{}{
   798  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   799  			},
   800  		})
   801  		require.NoError(t, err)
   802  		require.NotNil(t, svc)
   803  
   804  		c, err := New(&mockprovider.Provider{
   805  			ProtocolStateStorageProviderValue: mem.NewProvider(),
   806  			StorageProviderValue:              mem.NewProvider(),
   807  			ServiceMap: map[string]interface{}{
   808  				didexchange.DIDExchange: svc,
   809  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   810  			},
   811  		})
   812  		require.NoError(t, err)
   813  
   814  		connRec := &connection.Record{ConnectionID: connID, ThreadID: threadID, State: "complete"}
   815  
   816  		require.NoError(t, err)
   817  		require.NoError(t, c.connectionStore.SaveConnectionRecord(connRec))
   818  
   819  		_, err = c.GetConnection(connID)
   820  		require.NoError(t, err)
   821  
   822  		err = c.RemoveConnection(connID)
   823  		require.NoError(t, err)
   824  
   825  		_, err = c.GetConnection(connID)
   826  		require.Error(t, err)
   827  		require.Equal(t, err.Error(), ErrConnectionNotFound.Error())
   828  	})
   829  	t.Run("test error data not found", func(t *testing.T) {
   830  		svc, err := didexchange.New(&mockprotocol.MockProvider{
   831  			ServiceMap: map[string]interface{}{
   832  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   833  			},
   834  		})
   835  		require.NoError(t, err)
   836  		require.NotNil(t, svc)
   837  		c, err := New(&mockprovider.Provider{
   838  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   839  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   840  			ServiceMap: map[string]interface{}{
   841  				didexchange.DIDExchange: svc,
   842  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   843  			},
   844  		})
   845  		require.NoError(t, err)
   846  
   847  		err = c.RemoveConnection("sample-id")
   848  		require.Error(t, err)
   849  		require.Contains(t, err.Error(), "data not found")
   850  	})
   851  }
   852  
   853  func TestClient_HandleInvitation(t *testing.T) {
   854  	ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   855  	require.NoError(t, err)
   856  
   857  	t.Run("test success", func(t *testing.T) {
   858  		c, err := New(&mockprovider.Provider{
   859  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   860  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   861  			ServiceMap: map[string]interface{}{
   862  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{},
   863  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   864  			},
   865  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   866  			ServiceEndpointValue: "endpoint",
   867  		})
   868  
   869  		require.NoError(t, err)
   870  		inviteReq, err := c.CreateInvitation("agent")
   871  		require.NoError(t, err)
   872  
   873  		connectionID, err := c.HandleInvitation(inviteReq)
   874  		require.NoError(t, err)
   875  		require.NotEmpty(t, connectionID)
   876  	})
   877  
   878  	t.Run("test error from handle msg", func(t *testing.T) {
   879  		c, err := New(&mockprovider.Provider{
   880  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   881  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   882  			ServiceMap: map[string]interface{}{
   883  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{HandleFunc: func(msg service.DIDCommMsg) (string, error) {
   884  					return "", fmt.Errorf("handle error")
   885  				}},
   886  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   887  			},
   888  
   889  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   890  			ServiceEndpointValue: "endpoint",
   891  		})
   892  		require.NoError(t, err)
   893  		inviteReq, err := c.CreateInvitation("agent")
   894  		require.NoError(t, err)
   895  
   896  		_, err = c.HandleInvitation(inviteReq)
   897  		require.Error(t, err)
   898  		require.Contains(t, err.Error(), "handle error")
   899  	})
   900  }
   901  
   902  func TestClient_CreateImplicitInvitation(t *testing.T) {
   903  	ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   904  	require.NoError(t, err)
   905  
   906  	t.Run("test success", func(t *testing.T) {
   907  		c, err := New(&mockprovider.Provider{
   908  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   909  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   910  			ServiceMap: map[string]interface{}{
   911  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{},
   912  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   913  			},
   914  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   915  			ServiceEndpointValue: "endpoint",
   916  		})
   917  		require.NoError(t, err)
   918  
   919  		connectionID, err := c.CreateImplicitInvitation("alice", "did:example:123")
   920  		require.NoError(t, err)
   921  		require.NotEmpty(t, connectionID)
   922  	})
   923  
   924  	t.Run("test error from service", func(t *testing.T) {
   925  		c, err := New(&mockprovider.Provider{
   926  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   927  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   928  			ServiceMap: map[string]interface{}{
   929  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{
   930  					ImplicitInvitationErr: errors.New("implicit error"),
   931  				},
   932  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   933  			},
   934  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   935  			ServiceEndpointValue: "endpoint",
   936  		})
   937  		require.NoError(t, err)
   938  
   939  		connectionID, err := c.CreateImplicitInvitation("Alice", "did:example:123")
   940  		require.Error(t, err)
   941  		require.Contains(t, err.Error(), "implicit error")
   942  		require.Empty(t, connectionID)
   943  	})
   944  }
   945  
   946  func TestClient_CreateImplicitInvitationWithDID(t *testing.T) {
   947  	inviter := &DIDInfo{Label: "alice", DID: "did:example:alice"}
   948  	invitee := &DIDInfo{Label: "bob", DID: "did:example:bob"}
   949  
   950  	ed25519KH, err := mockkms.CreateMockED25519KeyHandle()
   951  	require.NoError(t, err)
   952  
   953  	t.Run("test success", func(t *testing.T) {
   954  		c, err := New(&mockprovider.Provider{
   955  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   956  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   957  			ServiceMap: map[string]interface{}{
   958  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{},
   959  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   960  			},
   961  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   962  			ServiceEndpointValue: "endpoint",
   963  		})
   964  		require.NoError(t, err)
   965  
   966  		connectionID, err := c.CreateImplicitInvitationWithDID(inviter, invitee)
   967  		require.NoError(t, err)
   968  		require.NotEmpty(t, connectionID)
   969  	})
   970  
   971  	t.Run("test error from service", func(t *testing.T) {
   972  		c, err := New(&mockprovider.Provider{
   973  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   974  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   975  			ServiceMap: map[string]interface{}{
   976  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{
   977  					ImplicitInvitationErr: errors.New("implicit with DID error"),
   978  				},
   979  				mediator.Coordination: &mockroute.MockMediatorSvc{},
   980  			},
   981  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
   982  			ServiceEndpointValue: "endpoint",
   983  		})
   984  		require.NoError(t, err)
   985  
   986  		connectionID, err := c.CreateImplicitInvitationWithDID(inviter, invitee)
   987  		require.Error(t, err)
   988  		require.Contains(t, err.Error(), "implicit with DID error")
   989  		require.Empty(t, connectionID)
   990  	})
   991  
   992  	t.Run("test missing required DID info", func(t *testing.T) {
   993  		c, err := New(&mockprovider.Provider{
   994  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   995  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   996  			ServiceMap: map[string]interface{}{
   997  				didexchange.DIDExchange: &mocksvc.MockDIDExchangeSvc{},
   998  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
   999  			},
  1000  			KMSValue:             &mockkms.KeyManager{CreateKeyValue: ed25519KH},
  1001  			ServiceEndpointValue: "endpoint",
  1002  		})
  1003  		require.NoError(t, err)
  1004  
  1005  		connectionID, err := c.CreateImplicitInvitationWithDID(inviter, nil)
  1006  		require.Error(t, err)
  1007  		require.Contains(t, err.Error(), "missing inviter and/or invitee public DID(s)")
  1008  		require.Empty(t, connectionID)
  1009  
  1010  		connectionID, err = c.CreateImplicitInvitationWithDID(nil, invitee)
  1011  		require.Error(t, err)
  1012  		require.Contains(t, err.Error(), "missing inviter and/or invitee public DID(s)")
  1013  		require.Empty(t, connectionID)
  1014  	})
  1015  }
  1016  
  1017  func TestClient_QueryConnectionsByParams(t *testing.T) { // nolint: gocyclo
  1018  	t.Run("test get all connections", func(t *testing.T) {
  1019  		svc, err := didexchange.New(&mockprotocol.MockProvider{
  1020  			ServiceMap: map[string]interface{}{
  1021  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1022  			},
  1023  		})
  1024  		require.NoError(t, err)
  1025  		require.NotNil(t, svc)
  1026  
  1027  		storageProvider := mem.NewProvider()
  1028  		c, err := New(&mockprovider.Provider{
  1029  			ProtocolStateStorageProviderValue: mem.NewProvider(),
  1030  			StorageProviderValue:              storageProvider,
  1031  			ServiceMap: map[string]interface{}{
  1032  				didexchange.DIDExchange: svc,
  1033  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
  1034  			},
  1035  		})
  1036  		require.NoError(t, err)
  1037  
  1038  		didExchangeStore, err := storageProvider.OpenStore("didexchange")
  1039  		require.NoError(t, err)
  1040  
  1041  		const count = 10
  1042  		const keyPrefix = "conn_"
  1043  		const state = "completed"
  1044  		for i := 0; i < count; i++ {
  1045  			val, e := json.Marshal(&connection.Record{
  1046  				ConnectionID: fmt.Sprint(i),
  1047  				State:        state,
  1048  			})
  1049  			require.NoError(t, e)
  1050  			require.NoError(t,
  1051  				didExchangeStore.Put(fmt.Sprintf("%sabc%d", keyPrefix, i), val, spi.Tag{Name: keyPrefix}))
  1052  		}
  1053  
  1054  		results, err := c.QueryConnections(&QueryConnectionsParams{})
  1055  		require.NoError(t, err)
  1056  		require.Len(t, results, count)
  1057  		for _, result := range results {
  1058  			require.NotEmpty(t, result.ConnectionID)
  1059  		}
  1060  	})
  1061  
  1062  	t.Run("test get connections with params", func(t *testing.T) {
  1063  		svc, err := didexchange.New(&mockprotocol.MockProvider{
  1064  			ServiceMap: map[string]interface{}{
  1065  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1066  			},
  1067  		})
  1068  		require.NoError(t, err)
  1069  		require.NotNil(t, svc)
  1070  
  1071  		storageProvider := mem.NewProvider()
  1072  		c, err := New(&mockprovider.Provider{
  1073  			ProtocolStateStorageProviderValue: mem.NewProvider(),
  1074  			StorageProviderValue:              storageProvider,
  1075  			ServiceMap: map[string]interface{}{
  1076  				didexchange.DIDExchange: svc,
  1077  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
  1078  			},
  1079  		})
  1080  		require.NoError(t, err)
  1081  
  1082  		didExchangeStore, err := storageProvider.OpenStore("didexchange")
  1083  		require.NoError(t, err)
  1084  
  1085  		const count = 10
  1086  		const countWithState = 5
  1087  		const keyPrefix = "conn_"
  1088  		const state = "completed"
  1089  		const myDID = "my_did"
  1090  		const theirDID = "their_did"
  1091  		for i := 0; i < count; i++ {
  1092  			var queryState string
  1093  			if i < countWithState {
  1094  				queryState = state
  1095  			}
  1096  
  1097  			val, e := json.Marshal(&connection.Record{
  1098  				ConnectionID:   fmt.Sprint(i),
  1099  				InvitationID:   fmt.Sprintf("inv-%d", i),
  1100  				ParentThreadID: fmt.Sprintf("ptid-%d", i),
  1101  				State:          queryState,
  1102  				MyDID:          myDID + strconv.Itoa(i),
  1103  				TheirDID:       theirDID + strconv.Itoa(i),
  1104  			})
  1105  			require.NoError(t, e)
  1106  			require.NoError(t,
  1107  				didExchangeStore.Put(fmt.Sprintf("%sabc%d", keyPrefix, i), val, spi.Tag{Name: keyPrefix}))
  1108  		}
  1109  
  1110  		results, err := c.QueryConnections(&QueryConnectionsParams{})
  1111  		require.NoError(t, err)
  1112  		require.Len(t, results, count)
  1113  		for _, result := range results {
  1114  			require.NotEmpty(t, result.ConnectionID)
  1115  		}
  1116  
  1117  		results, err = c.QueryConnections(&QueryConnectionsParams{State: state})
  1118  		require.NoError(t, err)
  1119  		require.Len(t, results, countWithState)
  1120  		for _, result := range results {
  1121  			require.NotEmpty(t, result.ConnectionID)
  1122  			require.Equal(t, result.State, state)
  1123  		}
  1124  
  1125  		params := &QueryConnectionsParams{MyDID: myDID + strconv.Itoa(count-1)}
  1126  		results, err = c.QueryConnections(params)
  1127  		require.NoError(t, err)
  1128  		require.Len(t, results, 1)
  1129  		for _, result := range results {
  1130  			require.NotEmpty(t, result.ConnectionID)
  1131  			require.Equal(t, result.MyDID, params.MyDID)
  1132  		}
  1133  
  1134  		params = &QueryConnectionsParams{TheirDID: theirDID + strconv.Itoa(count-1)}
  1135  		results, err = c.QueryConnections(params)
  1136  		require.NoError(t, err)
  1137  		require.Len(t, results, 1)
  1138  		for _, result := range results {
  1139  			require.NotEmpty(t, result.ConnectionID)
  1140  			require.Equal(t, result.TheirDID, params.TheirDID)
  1141  		}
  1142  
  1143  		params = &QueryConnectionsParams{
  1144  			MyDID:    myDID + strconv.Itoa(count-1),
  1145  			TheirDID: theirDID + strconv.Itoa(count-1),
  1146  		}
  1147  		results, err = c.QueryConnections(params)
  1148  		require.NoError(t, err)
  1149  		require.Len(t, results, 1)
  1150  		for _, result := range results {
  1151  			require.NotEmpty(t, result.ConnectionID)
  1152  			require.Equal(t, result.MyDID, params.MyDID)
  1153  			require.Equal(t, result.TheirDID, params.TheirDID)
  1154  		}
  1155  
  1156  		params = &QueryConnectionsParams{
  1157  			InvitationID: fmt.Sprintf("inv-%d", count-1),
  1158  		}
  1159  		results, err = c.QueryConnections(params)
  1160  		require.NoError(t, err)
  1161  		require.Len(t, results, 1)
  1162  		for _, result := range results {
  1163  			require.NotEmpty(t, result.ConnectionID)
  1164  			require.Equal(t, result.InvitationID, params.InvitationID)
  1165  		}
  1166  
  1167  		params = &QueryConnectionsParams{
  1168  			ParentThreadID: fmt.Sprintf("ptid-%d", count-1),
  1169  		}
  1170  		results, err = c.QueryConnections(params)
  1171  		require.NoError(t, err)
  1172  		require.Len(t, results, 1)
  1173  		for _, result := range results {
  1174  			require.NotEmpty(t, result.ConnectionID)
  1175  			require.Equal(t, result.ParentThreadID, params.ParentThreadID)
  1176  		}
  1177  	})
  1178  
  1179  	t.Run("test get connections error", func(t *testing.T) {
  1180  		svc, err := didexchange.New(&mockprotocol.MockProvider{
  1181  			ServiceMap: map[string]interface{}{
  1182  				mediator.Coordination: &mockroute.MockMediatorSvc{},
  1183  			},
  1184  		})
  1185  		require.NoError(t, err)
  1186  		require.NotNil(t, svc)
  1187  		const keyPrefix = "conn_"
  1188  
  1189  		storageProvider := mem.NewProvider()
  1190  		c, err := New(&mockprovider.Provider{
  1191  			ProtocolStateStorageProviderValue: mem.NewProvider(),
  1192  			StorageProviderValue:              storageProvider,
  1193  			ServiceMap: map[string]interface{}{
  1194  				didexchange.DIDExchange: svc,
  1195  				mediator.Coordination:   &mockroute.MockMediatorSvc{},
  1196  			},
  1197  		})
  1198  		require.NoError(t, err)
  1199  
  1200  		didExchangeStore, err := storageProvider.OpenStore("didexchange")
  1201  		require.NoError(t, err)
  1202  
  1203  		require.NoError(t,
  1204  			didExchangeStore.Put(fmt.Sprintf("%sabc", keyPrefix), []byte("----"), spi.Tag{Name: keyPrefix}))
  1205  
  1206  		results, err := c.QueryConnections(&QueryConnectionsParams{})
  1207  		require.Error(t, err)
  1208  		require.Empty(t, results)
  1209  	})
  1210  }
  1211  
  1212  func TestServiceEvents(t *testing.T) {
  1213  	protocolStateStore := mockstore.NewMockStoreProvider()
  1214  	ariesStore := mockstore.NewMockStoreProvider()
  1215  	kmsStore, err := kms.NewAriesProviderWrapper(ariesStore)
  1216  	require.NoError(t, err)
  1217  
  1218  	km := newKMS(t, kmsStore)
  1219  
  1220  	didExSvc, err := didexchange.New(&mockprotocol.MockProvider{
  1221  		ProtocolStateStoreProvider: protocolStateStore,
  1222  		StoreProvider:              ariesStore,
  1223  		KMSStore:                   kmsStore,
  1224  		ServiceMap: map[string]interface{}{
  1225  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1226  		},
  1227  		CustomKMS:             km,
  1228  		KeyTypeValue:          kms.ED25519Type,
  1229  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
  1230  	})
  1231  	require.NoError(t, err)
  1232  
  1233  	// create the client
  1234  	c, err := New(&mockprovider.Provider{
  1235  		ProtocolStateStorageProviderValue: protocolStateStore,
  1236  		StorageProviderValue:              ariesStore,
  1237  		ServiceMap: map[string]interface{}{
  1238  			didexchange.DIDExchange: didExSvc,
  1239  			mediator.Coordination:   &mockroute.MockMediatorSvc{},
  1240  		},
  1241  		KMSValue:              km,
  1242  		KeyTypeValue:          kms.ED25519Type,
  1243  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
  1244  	})
  1245  	require.NoError(t, err)
  1246  	require.NotNil(t, c)
  1247  
  1248  	// register action event channel
  1249  	aCh := make(chan service.DIDCommAction, 10)
  1250  	err = c.RegisterActionEvent(aCh)
  1251  	require.NoError(t, err)
  1252  
  1253  	go func() {
  1254  		service.AutoExecuteActionEvent(aCh)
  1255  	}()
  1256  
  1257  	// register message event channel
  1258  	mCh := make(chan service.StateMsg, 10)
  1259  	err = c.RegisterMsgEvent(mCh)
  1260  	require.NoError(t, err)
  1261  
  1262  	stateMsg := make(chan service.StateMsg)
  1263  
  1264  	go func() {
  1265  		for e := range mCh {
  1266  			if e.Type == service.PostState && e.StateID == "responded" {
  1267  				stateMsg <- e
  1268  			}
  1269  		}
  1270  	}()
  1271  
  1272  	// send connection request message
  1273  	id := "valid-thread-id"
  1274  	doc, err := (&mockvdr.MockVDRegistry{}).Create("test", nil)
  1275  	require.NoError(t, err)
  1276  
  1277  	invitation, err := c.CreateInvitation("alice")
  1278  	require.NoError(t, err)
  1279  
  1280  	request, err := json.Marshal(
  1281  		&didexchange.Request{
  1282  			Type:  didexchange.RequestMsgType,
  1283  			ID:    id,
  1284  			Label: "test",
  1285  			Thread: &decorator.Thread{
  1286  				PID: invitation.ID,
  1287  			},
  1288  			DID:       doc.DIDDocument.ID,
  1289  			DocAttach: unsignedDocAttach(t, doc.DIDDocument),
  1290  		},
  1291  	)
  1292  	require.NoError(t, err)
  1293  
  1294  	msg, err := service.ParseDIDCommMsgMap(request)
  1295  	require.NoError(t, err)
  1296  	_, err = didExSvc.HandleInbound(msg, service.EmptyDIDCommContext())
  1297  	require.NoError(t, err)
  1298  
  1299  	select {
  1300  	case e := <-stateMsg:
  1301  		switch v := e.Properties.(type) {
  1302  		case Event:
  1303  			props := v
  1304  			conn, err := c.GetConnectionAtState(props.ConnectionID(), e.StateID)
  1305  			require.NoError(t, err)
  1306  			require.Equal(t, e.StateID, conn.State)
  1307  		default:
  1308  			require.Fail(t, "unable to cast to did exchange event")
  1309  		}
  1310  	case <-time.After(5 * time.Second):
  1311  		require.Fail(t, "tests are not validated due to timeout")
  1312  	}
  1313  }
  1314  
  1315  func TestAcceptExchangeRequest(t *testing.T) {
  1316  	ariesStore := mockstore.NewMockStoreProvider()
  1317  	kmsStore, err := kms.NewAriesProviderWrapper(ariesStore)
  1318  	require.NoError(t, err)
  1319  
  1320  	km := newKMS(t, kmsStore)
  1321  	didExSvc, err := didexchange.New(&mockprotocol.MockProvider{
  1322  		StoreProvider: ariesStore,
  1323  		KMSStore:      kmsStore,
  1324  		ServiceMap: map[string]interface{}{
  1325  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1326  		},
  1327  		CustomKMS:             km,
  1328  		KeyTypeValue:          kms.ED25519Type,
  1329  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
  1330  	})
  1331  	require.NoError(t, err)
  1332  
  1333  	// create the client
  1334  	c, err := New(&mockprovider.Provider{
  1335  		ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
  1336  		StorageProviderValue:              ariesStore,
  1337  		ServiceMap: map[string]interface{}{
  1338  			didexchange.DIDExchange: didExSvc,
  1339  			mediator.Coordination:   &mockroute.MockMediatorSvc{},
  1340  		},
  1341  		KMSValue:              km,
  1342  		KeyTypeValue:          kms.ED25519Type,
  1343  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
  1344  	},
  1345  	)
  1346  	require.NoError(t, err)
  1347  	require.NotNil(t, c)
  1348  
  1349  	// register action event channel
  1350  	aCh := make(chan service.DIDCommAction, 10)
  1351  	err = c.RegisterActionEvent(aCh)
  1352  	require.NoError(t, err)
  1353  
  1354  	go func() {
  1355  		for e := range aCh {
  1356  			prop, ok := e.Properties.(Event)
  1357  			if !ok {
  1358  				require.Fail(t, "Failed to cast the event properties to service.Event")
  1359  			}
  1360  
  1361  			require.NoError(t, c.AcceptExchangeRequest(prop.ConnectionID(), "", ""))
  1362  		}
  1363  	}()
  1364  
  1365  	// register message event channel
  1366  	mCh := make(chan service.StateMsg, 10)
  1367  	err = c.RegisterMsgEvent(mCh)
  1368  	require.NoError(t, err)
  1369  
  1370  	done := make(chan struct{})
  1371  
  1372  	go func() {
  1373  		for e := range mCh {
  1374  			if e.Type == service.PostState && e.StateID == "responded" {
  1375  				close(done)
  1376  			}
  1377  		}
  1378  	}()
  1379  
  1380  	invitation, err := c.CreateInvitation("alice")
  1381  	require.NoError(t, err)
  1382  	// send connection request message
  1383  	id := "valid-thread-id"
  1384  	doc, err := (&mockvdr.MockVDRegistry{}).Create("test", nil)
  1385  	require.NoError(t, err)
  1386  
  1387  	request, err := json.Marshal(
  1388  		&didexchange.Request{
  1389  			Type:  didexchange.RequestMsgType,
  1390  			ID:    id,
  1391  			Label: "test",
  1392  			Thread: &decorator.Thread{
  1393  				PID: invitation.ID,
  1394  			},
  1395  			DocAttach: unsignedDocAttach(t, doc.DIDDocument),
  1396  			DID:       doc.DIDDocument.ID,
  1397  		},
  1398  	)
  1399  	require.NoError(t, err)
  1400  
  1401  	msg, err := service.ParseDIDCommMsgMap(request)
  1402  	require.NoError(t, err)
  1403  	_, err = didExSvc.HandleInbound(msg, service.EmptyDIDCommContext())
  1404  	require.NoError(t, err)
  1405  
  1406  	select {
  1407  	case <-done:
  1408  	case <-time.After(5 * time.Second):
  1409  		require.Fail(t, "tests are not validated due to timeout")
  1410  	}
  1411  
  1412  	err = c.AcceptExchangeRequest("invalid-id", "", "")
  1413  	require.Error(t, err)
  1414  	require.Contains(t, err.Error(), "did exchange client - accept exchange request:")
  1415  }
  1416  
  1417  func TestAcceptInvitation(t *testing.T) {
  1418  	ariesStore := mockstore.NewMockStoreProvider()
  1419  	kmsStore, err := kms.NewAriesProviderWrapper(ariesStore)
  1420  	require.NoError(t, err)
  1421  
  1422  	km := newKMS(t, kmsStore)
  1423  	didExSvc, err := didexchange.New(&mockprotocol.MockProvider{
  1424  		StoreProvider: ariesStore,
  1425  		KMSStore:      kmsStore,
  1426  		ServiceMap: map[string]interface{}{
  1427  			mediator.Coordination: &mockroute.MockMediatorSvc{},
  1428  		},
  1429  		CustomKMS:             km,
  1430  		KeyTypeValue:          kms.ED25519Type,
  1431  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
  1432  	})
  1433  	require.NoError(t, err)
  1434  
  1435  	// create the client
  1436  	c, err := New(&mockprovider.Provider{
  1437  		ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
  1438  		StorageProviderValue:              ariesStore,
  1439  		ServiceMap: map[string]interface{}{
  1440  			didexchange.DIDExchange: didExSvc,
  1441  			mediator.Coordination:   &mockroute.MockMediatorSvc{},
  1442  		},
  1443  		KMSValue:              km,
  1444  		KeyTypeValue:          kms.ED25519Type,
  1445  		KeyAgreementTypeValue: kms.X25519ECDHKWType,
  1446  	})
  1447  	require.NoError(t, err)
  1448  	require.NotNil(t, c)
  1449  
  1450  	t.Run("accept invitation - success", func(t *testing.T) {
  1451  		// register action event channel
  1452  		aCh := make(chan service.DIDCommAction, 10)
  1453  		err = c.RegisterActionEvent(aCh)
  1454  		require.NoError(t, err)
  1455  
  1456  		go func() {
  1457  			for e := range aCh {
  1458  				_, ok := e.Properties.(Event)
  1459  				require.True(t, ok, "Failed to cast the event properties to service.Event")
  1460  
  1461  				// ignore action event
  1462  			}
  1463  		}()
  1464  
  1465  		// register message event channel
  1466  		mCh := make(chan service.StateMsg, 10)
  1467  		err = c.RegisterMsgEvent(mCh)
  1468  		require.NoError(t, err)
  1469  
  1470  		done := make(chan struct{})
  1471  
  1472  		go func() {
  1473  			for e := range mCh {
  1474  				prop, ok := e.Properties.(Event)
  1475  				if !ok {
  1476  					require.Fail(t, "Failed to cast the event properties to service.Event")
  1477  				}
  1478  
  1479  				if e.Type == service.PostState && e.StateID == "invited" {
  1480  					require.NoError(t, c.AcceptInvitation(prop.ConnectionID(), "", ""))
  1481  				}
  1482  
  1483  				if e.Type == service.PostState && e.StateID == "requested" {
  1484  					close(done)
  1485  				}
  1486  			}
  1487  		}()
  1488  
  1489  		_, pubKey, e := km.CreateAndExportPubKeyBytes(kms.ED25519Type)
  1490  		require.NoError(t, e)
  1491  
  1492  		// send connection invitation message
  1493  		invitation, jsonErr := json.Marshal(
  1494  			&didexchange.Invitation{
  1495  				Type:          InvitationMsgType,
  1496  				ID:            "abc",
  1497  				Label:         "test",
  1498  				RecipientKeys: []string{string(pubKey)},
  1499  			},
  1500  		)
  1501  		require.NoError(t, jsonErr)
  1502  
  1503  		msg, svcErr := service.ParseDIDCommMsgMap(invitation)
  1504  		require.NoError(t, svcErr)
  1505  		_, err = didExSvc.HandleInbound(msg, service.EmptyDIDCommContext())
  1506  		require.NoError(t, err)
  1507  
  1508  		select {
  1509  		case <-done:
  1510  		case <-time.After(5 * time.Second):
  1511  			require.Fail(t, "tests are not validated due to timeout")
  1512  		}
  1513  	})
  1514  
  1515  	t.Run("accept invitation - error", func(t *testing.T) {
  1516  		err = c.AcceptInvitation("invalid-id", "", "")
  1517  		require.Error(t, err)
  1518  		require.Contains(t, err.Error(), "did exchange client - accept exchange invitation")
  1519  	})
  1520  }
  1521  
  1522  func newPeerDID(t *testing.T) *did.Doc {
  1523  	t.Helper()
  1524  
  1525  	a, err := aries.New(
  1526  		aries.WithStoreProvider(mem.NewProvider()),
  1527  		aries.WithProtocolStateStoreProvider(mem.NewProvider()),
  1528  	)
  1529  	require.NoError(t, err)
  1530  
  1531  	ctx, err := a.Context()
  1532  	require.NoError(t, err)
  1533  
  1534  	d, err := ctx.VDRegistry().Create(
  1535  		peer.DIDMethod, &did.Doc{Service: []did.Service{{
  1536  			Type:            "did-communication",
  1537  			ServiceEndpoint: model.NewDIDCommV1Endpoint("http://agent.example.com/didcomm"),
  1538  		}}, VerificationMethod: []did.VerificationMethod{getSigningKey()}})
  1539  	require.NoError(t, err)
  1540  
  1541  	return d.DIDDocument
  1542  }
  1543  
  1544  func getSigningKey() did.VerificationMethod {
  1545  	pub, _, err := ed25519.GenerateKey(rand.Reader)
  1546  	if err != nil {
  1547  		panic(err)
  1548  	}
  1549  
  1550  	return did.VerificationMethod{Value: pub[:], Type: "Ed25519VerificationKey2018"}
  1551  }
  1552  
  1553  type mockKMSProvider struct {
  1554  	kmsStore          kms.Store
  1555  	secretLockService secretlock.Service
  1556  }
  1557  
  1558  func (m *mockKMSProvider) StorageProvider() kms.Store {
  1559  	return m.kmsStore
  1560  }
  1561  
  1562  func (m *mockKMSProvider) SecretLock() secretlock.Service {
  1563  	return m.secretLockService
  1564  }
  1565  
  1566  func newKMS(t *testing.T, store kms.Store) kms.KeyManager {
  1567  	t.Helper()
  1568  
  1569  	kmsProv := &mockKMSProvider{
  1570  		kmsStore:          store,
  1571  		secretLockService: &noop.NoLock{},
  1572  	}
  1573  
  1574  	customKMS, err := localkms.New("local-lock://primary/test/", kmsProv)
  1575  	require.NoError(t, err)
  1576  
  1577  	return customKMS
  1578  }
  1579  
  1580  func unsignedDocAttach(t *testing.T, doc *did.Doc) *decorator.Attachment {
  1581  	t.Helper()
  1582  
  1583  	docBytes, err := doc.JSONBytes()
  1584  	require.NoError(t, err)
  1585  
  1586  	att := &decorator.Attachment{
  1587  		Data: decorator.AttachmentData{
  1588  			Base64: base64.StdEncoding.EncodeToString(docBytes),
  1589  		},
  1590  	}
  1591  
  1592  	return att
  1593  }