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

     1  /*
     2  Copyright Scoir Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package messagepickup
     8  
     9  import (
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/stretchr/testify/require"
    17  
    18  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
    19  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/transport"
    20  	mockdispatcher "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/dispatcher"
    21  	mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider"
    22  	mockstore "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    23  	"github.com/hyperledger/aries-framework-go/pkg/store/connection"
    24  	"github.com/hyperledger/aries-framework-go/spi/storage"
    25  )
    26  
    27  const (
    28  	MYDID    = "sample-my-did"
    29  	THEIRDID = "sample-their-did"
    30  )
    31  
    32  func TestServiceNew(t *testing.T) {
    33  	t.Run("test new service - success", func(t *testing.T) {
    34  		svc, err := getService()
    35  		require.NoError(t, err)
    36  		require.Equal(t, MessagePickup, svc.Name())
    37  	})
    38  
    39  	t.Run("test new service name - store error", func(t *testing.T) {
    40  		svc, err := New(&mockprovider.Provider{
    41  			StorageProviderValue: &mockstore.MockStoreProvider{
    42  				ErrOpenStoreHandle: fmt.Errorf("error opening the store"),
    43  			},
    44  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
    45  			OutboundDispatcherValue:           nil,
    46  			PackagerValue:                     &mockPackager{},
    47  		})
    48  
    49  		require.Error(t, err)
    50  		require.Contains(t, err.Error(), "open mailbox store")
    51  		require.Nil(t, svc)
    52  	})
    53  }
    54  
    55  func TestService_Initialize(t *testing.T) {
    56  	t.Run("success", func(t *testing.T) {
    57  		prov := &mockprovider.Provider{
    58  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
    59  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
    60  			OutboundDispatcherValue:           nil,
    61  			PackagerValue:                     &mockPackager{},
    62  		}
    63  
    64  		svc := Service{}
    65  
    66  		err := svc.Initialize(prov)
    67  		require.NoError(t, err)
    68  
    69  		// second init is no-op
    70  		err = svc.Initialize(prov)
    71  		require.NoError(t, err)
    72  	})
    73  
    74  	t.Run("failure, not given a valid provider", func(t *testing.T) {
    75  		svc := Service{}
    76  
    77  		err := svc.Initialize("not a provider")
    78  		require.Error(t, err)
    79  		require.Contains(t, err.Error(), "expected provider of type")
    80  	})
    81  }
    82  
    83  func TestHandleInbound(t *testing.T) {
    84  	t.Run("test MessagePickupService.HandleInbound() - Status", func(t *testing.T) {
    85  		const jsonStr = `{
    86  			"@id": "123456781",
    87  			"@type": "https://didcomm.org/messagepickup/1.0/status",
    88  			"message_count": 7,
    89  			"duration_waited": 3600,
    90  			"last_added_time": "2019-05-01T12:00:00Z",
    91  			"last_delivered_time": "2019-05-01T12:00:00Z",
    92  			"last_removed_time": "2019-05-01T12:00:00Z",
    93  			"total_size": 8096
    94  		}`
    95  
    96  		svc, err := getService()
    97  		require.NoError(t, err)
    98  
    99  		msg, err := service.ParseDIDCommMsgMap([]byte(jsonStr))
   100  		require.NoError(t, err)
   101  
   102  		statusCh := make(chan Status)
   103  		svc.setStatusCh(msg.ID(), statusCh)
   104  
   105  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(MYDID, THEIRDID, nil))
   106  		require.NoError(t, err)
   107  
   108  		tyme, err := time.Parse(time.RFC3339, "2019-05-01T12:00:00Z")
   109  		require.NoError(t, err)
   110  
   111  		select {
   112  		case x := <-svc.statusMap[msg.ID()]:
   113  			require.NotNil(t, x)
   114  			require.Equal(t, "123456781", x.ID)
   115  			require.Equal(t, 3600, x.DurationWaited)
   116  			require.Equal(t, tyme, x.LastAddedTime)
   117  			require.Equal(t, tyme, x.LastDeliveredTime)
   118  			require.Equal(t, tyme, x.LastRemovedTime)
   119  			require.Equal(t, 7, x.MessageCount)
   120  			require.Equal(t, 8096, x.TotalSize)
   121  
   122  		case <-time.After(2 * time.Second):
   123  			require.Fail(t, "didn't receive message to handle")
   124  		}
   125  	})
   126  
   127  	t.Run("test MessagePickupService.HandleInbound() - unknown type", func(t *testing.T) {
   128  		const jsonStr = `{
   129  			"@id": "123456781",
   130  			"@type": "unknown"
   131  		}`
   132  
   133  		svc, err := getService()
   134  		require.NoError(t, err)
   135  
   136  		msg, err := service.ParseDIDCommMsgMap([]byte(jsonStr))
   137  		require.NoError(t, err)
   138  
   139  		statusCh := make(chan Status)
   140  		svc.setStatusCh(msg.ID(), statusCh)
   141  
   142  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(MYDID, THEIRDID, nil))
   143  		require.NoError(t, err)
   144  	})
   145  
   146  	t.Run("test MessagePickupService.HandleInbound() - Status - msg error", func(t *testing.T) {
   147  		svc, err := getService()
   148  		require.NoError(t, err)
   149  
   150  		msg := &service.DIDCommMsgMap{"@id": map[int]int{}}
   151  		err = svc.handleStatus(msg)
   152  		require.Error(t, err)
   153  		require.Contains(t, err.Error(), "status message unmarshal")
   154  	})
   155  
   156  	t.Run("test MessagePickupService.HandleInbound() - StatusRequest success", func(t *testing.T) {
   157  		const jsonStr = `{
   158  			"@id": "123456781",
   159  			"@type": "https://didcomm.org/messagepickup/1.0/status-request",
   160  			"~thread" : {"thid": "2d798168-8abf-4410-8535-bc1e8406a5ff"}
   161  		}`
   162  		msgID := make(chan string)
   163  
   164  		tyme, err := time.Parse(time.RFC3339, "2019-05-01T12:00:00Z")
   165  		require.NoError(t, err)
   166  
   167  		svc, err := New(&mockprovider.Provider{
   168  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   169  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   170  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   171  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   172  					require.Equal(t, myDID, MYDID)
   173  					require.Equal(t, theirDID, THEIRDID)
   174  
   175  					reqMsgMap, ok := msg.(service.DIDCommMsgMap)
   176  					require.True(t, ok)
   177  
   178  					request := &Status{}
   179  
   180  					err = reqMsgMap.Decode(request)
   181  					require.NoError(t, err)
   182  
   183  					require.Equal(t, 1, request.MessageCount)
   184  					require.Equal(t, tyme, request.LastAddedTime)
   185  					require.Equal(t, tyme, request.LastDeliveredTime)
   186  					require.Equal(t, tyme, request.LastRemovedTime)
   187  					require.Equal(t, 3096, request.TotalSize)
   188  					require.Equal(t, "2d798168-8abf-4410-8535-bc1e8406a5ff", request.Thread.PID)
   189  
   190  					msgID <- request.ID
   191  
   192  					return nil
   193  				},
   194  			},
   195  			PackagerValue: &mockPackager{},
   196  		})
   197  		require.NoError(t, err)
   198  
   199  		b, err := json.Marshal(inbox{
   200  			DID:               "sample-their-did",
   201  			MessageCount:      1,
   202  			LastAddedTime:     tyme,
   203  			LastDeliveredTime: tyme,
   204  			LastRemovedTime:   tyme,
   205  			TotalSize:         3096,
   206  			Messages:          []byte(`[{"test": "message"}]`),
   207  		})
   208  		require.NoError(t, err)
   209  
   210  		err = svc.msgStore.Put(THEIRDID, b)
   211  		require.NoError(t, err)
   212  
   213  		msg, err := service.ParseDIDCommMsgMap([]byte(jsonStr))
   214  		require.NoError(t, err)
   215  
   216  		go func() {
   217  			_, err = svc.HandleInbound(msg, service.NewDIDCommContext(MYDID, THEIRDID, nil))
   218  			require.NoError(t, err)
   219  		}()
   220  
   221  		select {
   222  		case id := <-msgID:
   223  			require.NotNil(t, id)
   224  			require.Equal(t, "123456781", id)
   225  
   226  		case <-time.After(2 * time.Second):
   227  			require.Fail(t, "didn't receive message to handle")
   228  		}
   229  	})
   230  
   231  	t.Run("test MessagePickupService.HandleInbound() - StatusRequest - msg error", func(t *testing.T) {
   232  		svc, err := getService()
   233  		require.NoError(t, err)
   234  
   235  		msg := &service.DIDCommMsgMap{"@id": map[int]int{}}
   236  		err = svc.handleStatusRequest(msg, MYDID, THEIRDID)
   237  		require.Error(t, err)
   238  		require.Contains(t, err.Error(), "status request message unmarshal")
   239  	})
   240  
   241  	t.Run("test MessagePickupService.HandleInbound() - StatusRequest - get error", func(t *testing.T) {
   242  		const jsonStr = `{
   243  			"@id": "123456781",
   244  			"@type": "https://didcomm.org/messagepickup/1.0/status-request",
   245  			"~thread" : {"thid": "2d798168-8abf-4410-8535-bc1e8406a5ff"}
   246  		}`
   247  
   248  		svc, err := getService()
   249  		require.NoError(t, err)
   250  
   251  		msg, err := service.ParseDIDCommMsgMap([]byte(jsonStr))
   252  		require.NoError(t, err)
   253  
   254  		err = svc.handleStatusRequest(msg, MYDID, "not found")
   255  		require.Error(t, err)
   256  		require.Contains(t, err.Error(), "error in status request getting inbox")
   257  	})
   258  
   259  	t.Run("test MessagePickupService.HandleInbound() - BatchPickup", func(t *testing.T) {
   260  		msgID := make(chan string)
   261  
   262  		tyme, err := time.Parse(time.RFC3339, "2019-05-01T12:00:00Z")
   263  		require.NoError(t, err)
   264  
   265  		svc, err := New(&mockprovider.Provider{
   266  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   267  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   268  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   269  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   270  					require.Equal(t, myDID, MYDID)
   271  					require.Equal(t, theirDID, THEIRDID)
   272  
   273  					reqMsgMap, ok := msg.(service.DIDCommMsgMap)
   274  					require.True(t, ok)
   275  
   276  					request := &Batch{}
   277  
   278  					err = reqMsgMap.Decode(request)
   279  					require.NoError(t, err)
   280  
   281  					require.Equal(t, 2, len(request.Messages))
   282  
   283  					msgID <- request.ID
   284  
   285  					return nil
   286  				},
   287  			},
   288  			PackagerValue: &mockPackager{},
   289  		})
   290  		require.NoError(t, err)
   291  
   292  		b, err := json.Marshal(inbox{
   293  			DID:               "sample-their-did",
   294  			MessageCount:      2,
   295  			LastAddedTime:     tyme,
   296  			LastDeliveredTime: tyme,
   297  			LastRemovedTime:   tyme,
   298  			TotalSize:         3096,
   299  			Messages:          []byte(`[{"id": "8910"}, {"id": "8911"}, {"id": "8912"}]`),
   300  		})
   301  		require.NoError(t, err)
   302  
   303  		err = svc.msgStore.Put(THEIRDID, b)
   304  		require.NoError(t, err)
   305  
   306  		msg, err := service.ParseDIDCommMsgMap([]byte(`{
   307  			"@id": "123456781",
   308  			"@type": "https://didcomm.org/messagepickup/1.0/batch-pickup",
   309  			"batch_size": 2,
   310  			"~thread" : {"thid": "2d798168-8abf-4410-8535-bc1e8406a5ff"}
   311  		}`))
   312  		require.NoError(t, err)
   313  
   314  		go func() {
   315  			_, err = svc.HandleInbound(msg, service.NewDIDCommContext(MYDID, THEIRDID, nil))
   316  			require.NoError(t, err)
   317  		}()
   318  
   319  		select {
   320  		case id := <-msgID:
   321  			require.NotNil(t, id)
   322  			require.Equal(t, id, "123456781")
   323  
   324  		case <-time.After(2 * time.Second):
   325  			require.Fail(t, "didn't receive message to handle")
   326  		}
   327  	})
   328  
   329  	t.Run("test MessagePickupService.HandleInbound() - BatchPickup - msg error", func(t *testing.T) {
   330  		svc, err := getService()
   331  		require.NoError(t, err)
   332  
   333  		msg := &service.DIDCommMsgMap{"@id": map[int]int{}}
   334  		err = svc.handleBatchPickup(msg, MYDID, THEIRDID)
   335  		require.Error(t, err)
   336  		require.Contains(t, err.Error(), "batch pickup message unmarshal")
   337  	})
   338  
   339  	t.Run("test MessagePickupService.HandleInbound() - BatchPickup - get error", func(t *testing.T) {
   340  		mockStore := mockstore.NewMockStoreProvider()
   341  		svc, err := New(&mockprovider.Provider{
   342  			StorageProviderValue:              mockStore,
   343  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   344  			OutboundDispatcherValue:           nil,
   345  			PackagerValue:                     &mockPackager{},
   346  		})
   347  		require.NoError(t, err)
   348  
   349  		mockStore.Store.ErrGet = errors.New("error get inbox")
   350  
   351  		msg, err := service.ParseDIDCommMsgMap([]byte(`{
   352  			"@id": "123456781",
   353  			"@type": "https://didcomm.org/messagepickup/1.0/batch-pickup",
   354  			"batch_size": 2,
   355  			"~thread" : {"thid": "2d798168-8abf-4410-8535-bc1e8406a5ff"}
   356  		}`))
   357  		require.NoError(t, err)
   358  
   359  		err = svc.handleBatchPickup(msg, MYDID, THEIRDID)
   360  		require.Error(t, err)
   361  		require.Contains(t, err.Error(), "error get inbox")
   362  	})
   363  
   364  	t.Run("test MessagePickupService.pullMessages() - put inbox error", func(t *testing.T) {
   365  		mockStore := mockstore.NewMockStoreProvider()
   366  		svc, err := New(&mockprovider.Provider{
   367  			StorageProviderValue:              mockStore,
   368  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   369  			OutboundDispatcherValue:           nil,
   370  			PackagerValue:                     &mockPackager{},
   371  		})
   372  		require.NoError(t, err)
   373  
   374  		b, err := json.Marshal(&inbox{DID: THEIRDID})
   375  		require.NoError(t, err)
   376  
   377  		err = mockStore.Store.Put(THEIRDID, b)
   378  		require.NoError(t, err)
   379  
   380  		mockStore.Store.ErrPut = errors.New("error put inbox")
   381  
   382  		msg, err := service.ParseDIDCommMsgMap([]byte(`{
   383  			"@id": "123456781",
   384  			"@type": "https://didcomm.org/messagepickup/1.0/batch-pickup",
   385  			"batch_size": 2,
   386  			"~thread" : {"thid": "2d798168-8abf-4410-8535-bc1e8406a5ff"}
   387  		}`))
   388  		require.NoError(t, err)
   389  
   390  		err = svc.handleBatchPickup(msg, MYDID, THEIRDID)
   391  		require.Error(t, err)
   392  		require.Contains(t, err.Error(), "error put inbox")
   393  	})
   394  
   395  	t.Run("test MessagePickupService.HandleInbound() - Batch", func(t *testing.T) {
   396  		const jsonStr = `{ 
   397  			"@id": "123456781", 
   398  			"@type": "https://didcomm.org/messagepickup/1.0/batch", 
   399  			"messages~attach": [ 
   400  				{ 
   401  					"@id" : "06ca25f6-d3c5-48ac-8eee-1a9e29120c31", 
   402  					"message" : "{\"id\": \"8910\"}"
   403  				}, 
   404  				{ 	
   405  					"@id" : "344a51cf-379f-40ab-ab2c-711dab3f53a9a", 
   406  					"message" : "{\"id\": \"8910\"}"
   407  				} 
   408  			] 
   409  		}`
   410  
   411  		svc, err := getService()
   412  		require.NoError(t, err)
   413  
   414  		msg, err := service.ParseDIDCommMsgMap([]byte(jsonStr))
   415  		require.NoError(t, err)
   416  
   417  		batchCh := make(chan Batch)
   418  		svc.setBatchCh(msg.ID(), batchCh)
   419  
   420  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(MYDID, THEIRDID, nil))
   421  		require.NoError(t, err)
   422  
   423  		select {
   424  		case x := <-svc.batchMap[msg.ID()]:
   425  			require.NotNil(t, x)
   426  			require.Equal(t, "123456781", x.ID)
   427  			require.Equal(t, 2, len(x.Messages))
   428  
   429  		case <-time.After(2 * time.Second):
   430  			require.Fail(t, "didn't receive message to handle")
   431  		}
   432  	})
   433  
   434  	t.Run("test MessagePickupService.HandleInbound() - Batch - msg error", func(t *testing.T) {
   435  		svc, err := getService()
   436  		require.NoError(t, err)
   437  
   438  		msg := &service.DIDCommMsgMap{"@id": map[int]int{}}
   439  		err = svc.handleBatch(msg)
   440  		require.Error(t, err)
   441  		require.Contains(t, err.Error(), "batch message unmarshal")
   442  	})
   443  
   444  	t.Run("test MessagePickupService.HandleInbound() - Noop", func(t *testing.T) {
   445  		const jsonStr = `{ 
   446  			"@id": "123456781", 
   447  			"@type": "https://didcomm.org/messagepickup/1.0/noop"
   448  		}`
   449  
   450  		svc, err := getService()
   451  		require.NoError(t, err)
   452  
   453  		msg, err := service.ParseDIDCommMsgMap([]byte(jsonStr))
   454  		require.NoError(t, err)
   455  
   456  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(MYDID, THEIRDID, nil))
   457  		require.NoError(t, err)
   458  	})
   459  
   460  	t.Run("test MessagePickupService.HandleInbound() - Noop - msg error", func(t *testing.T) {
   461  		svc, err := getService()
   462  		require.NoError(t, err)
   463  
   464  		msg := &service.DIDCommMsgMap{"@id": map[int]int{}}
   465  		err = svc.handleNoop(msg)
   466  		require.Error(t, err)
   467  		require.Contains(t, err.Error(), "noop message unmarshal")
   468  	})
   469  }
   470  
   471  func TestAccept(t *testing.T) {
   472  	t.Run("test MessagePickupService.Accept() - Status", func(t *testing.T) {
   473  		svc, err := getService()
   474  		require.NoError(t, err)
   475  
   476  		require.True(t, svc.Accept(StatusMsgType))
   477  		require.True(t, svc.Accept(StatusRequestMsgType))
   478  		require.True(t, svc.Accept(NoopMsgType))
   479  		require.True(t, svc.Accept(BatchMsgType))
   480  		require.True(t, svc.Accept(BatchPickupMsgType))
   481  		require.False(t, svc.Accept("random-msg-type"))
   482  	})
   483  }
   484  
   485  func TestAddMessage(t *testing.T) {
   486  	t.Run("test MessagePickupService.AddMessage() to new inbox - success", func(t *testing.T) {
   487  		mockStore := mockstore.NewMockStoreProvider()
   488  		svc, err := New(&mockprovider.Provider{
   489  			StorageProviderValue:              mockStore,
   490  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   491  			OutboundDispatcherValue:           nil,
   492  			PackagerValue:                     &mockPackager{},
   493  		})
   494  		require.NoError(t, err)
   495  
   496  		message := []byte(`{
   497  			Protected: "eyJ0eXAiOiJwcnMuaHlwZXJsZWRnZXIuYXJpZXMtYXV0aC1t" +
   498  				"ZXNzYWdlIiwiYWxnIjoiRUNESC1TUytYQzIwUEtXIiwiZW5jIjoiWEMyMFAifQ",
   499  			IV:         "JS2FxjEKdndnt-J7QX5pEnVwyBTu0_3d",
   500  			CipherText: "qQyzvajdvCDJbwxM",
   501  			Tag:        "2FqZMMQuNPYfL0JsSkj8LQ",
   502  		}`)
   503  
   504  		err = svc.AddMessage(message, THEIRDID)
   505  		require.NoError(t, err)
   506  
   507  		b, err := mockStore.Store.Get(THEIRDID)
   508  		require.NoError(t, err)
   509  
   510  		ibx := &inbox{}
   511  		err = json.Unmarshal(b, ibx)
   512  		require.NoError(t, err)
   513  
   514  		require.Equal(t, 1, ibx.MessageCount)
   515  	})
   516  
   517  	t.Run("test MessagePickupService.AddMessage() to existing inbox - success", func(t *testing.T) {
   518  		mockStore := mockstore.NewMockStoreProvider()
   519  		svc, err := New(&mockprovider.Provider{
   520  			StorageProviderValue:              mockStore,
   521  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   522  			OutboundDispatcherValue:           nil,
   523  			PackagerValue:                     &mockPackager{},
   524  		})
   525  		require.NoError(t, err)
   526  
   527  		message := []byte(`{
   528  			Protected: "eyJ0eXAiOiJwcnMuaHlwZXJsZWRnZXIuYXJpZXMtYXV0aC1t" +
   529  				"ZXNzYWdlIiwiYWxnIjoiRUNESC1TUytYQzIwUEtXIiwiZW5jIjoiWEMyMFAifQ",
   530  			IV:         "JS2FxjEKdndnt-J7QX5pEnVwyBTu0_3d",
   531  			CipherText: "qQyzvajdvCDJbwxM",
   532  			Tag:        "2FqZMMQuNPYfL0JsSkj8LQ",
   533  		}`)
   534  
   535  		tyme, err := time.Parse(time.RFC3339, "2019-05-01T12:00:00Z")
   536  		require.NoError(t, err)
   537  
   538  		b, err := json.Marshal(inbox{
   539  			DID:               "sample-their-did",
   540  			MessageCount:      3,
   541  			LastAddedTime:     tyme,
   542  			LastDeliveredTime: tyme,
   543  			LastRemovedTime:   tyme,
   544  			TotalSize:         3096,
   545  			Messages:          []byte(`[{"id": "8910"}, {"id": "8911"}, {"id": "8912"}]`),
   546  		})
   547  		require.NoError(t, err)
   548  
   549  		err = svc.msgStore.Put(THEIRDID, b)
   550  		require.NoError(t, err)
   551  
   552  		err = svc.AddMessage(message, THEIRDID)
   553  		require.NoError(t, err)
   554  
   555  		b, err = mockStore.Store.Get(THEIRDID)
   556  		require.NoError(t, err)
   557  
   558  		ibx := &inbox{}
   559  		err = json.Unmarshal(b, ibx)
   560  		require.NoError(t, err)
   561  
   562  		require.Equal(t, 4, ibx.MessageCount)
   563  	})
   564  
   565  	t.Run("test MessagePickupService.AddMessage() - put error", func(t *testing.T) {
   566  		mockStore := mockstore.NewMockStoreProvider()
   567  		svc, err := New(&mockprovider.Provider{
   568  			StorageProviderValue:              mockStore,
   569  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   570  			OutboundDispatcherValue:           nil,
   571  			PackagerValue:                     &mockPackager{},
   572  		})
   573  		require.NoError(t, err)
   574  
   575  		b, err := json.Marshal(inbox{
   576  			DID: "sample-their-did",
   577  		})
   578  		require.NoError(t, err)
   579  
   580  		// seed data for initial get in AddMessage
   581  		err = mockStore.Store.Put(THEIRDID, b)
   582  		require.NoError(t, err)
   583  
   584  		mockStore.Store.ErrPut = errors.New("error put")
   585  
   586  		message := []byte("")
   587  
   588  		err = svc.AddMessage(message, THEIRDID)
   589  		require.Error(t, err)
   590  		require.Contains(t, err.Error(), "error put")
   591  	})
   592  
   593  	t.Run("test MessagePickupService.AddMessage() - get error", func(t *testing.T) {
   594  		mockStore := mockstore.NewMockStoreProvider()
   595  		svc, err := New(&mockprovider.Provider{
   596  			StorageProviderValue:              mockStore,
   597  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   598  			OutboundDispatcherValue:           nil,
   599  			PackagerValue:                     &mockPackager{},
   600  		})
   601  		require.NoError(t, err)
   602  
   603  		message := []byte("")
   604  
   605  		mockStore.Store.ErrGet = errors.New("error get")
   606  
   607  		err = svc.AddMessage(message, "not found")
   608  		require.Error(t, err)
   609  		require.Contains(t, err.Error(), "error get")
   610  	})
   611  }
   612  
   613  func TestStatusRequest(t *testing.T) {
   614  	t.Run("test MessagePickupService.StatusRequest() - success", func(t *testing.T) {
   615  		msgID := make(chan string)
   616  		s := make(map[string][]byte)
   617  
   618  		provider := &mockprovider.Provider{
   619  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   620  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   621  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   622  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   623  					require.Equal(t, myDID, MYDID)
   624  					require.Equal(t, theirDID, THEIRDID)
   625  
   626  					request, ok := msg.(*StatusRequest)
   627  					require.True(t, ok)
   628  
   629  					msgID <- request.ID
   630  
   631  					return nil
   632  				},
   633  			},
   634  			PackagerValue: &mockPackager{},
   635  		}
   636  
   637  		connRec := &connection.Record{
   638  			ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "completed",
   639  		}
   640  		connBytes, err := json.Marshal(connRec)
   641  		require.NoError(t, err)
   642  
   643  		s["conn_conn1"] = connBytes
   644  
   645  		r, err := connection.NewRecorder(provider)
   646  		require.NoError(t, err)
   647  		err = r.SaveConnectionRecord(connRec)
   648  		require.NoError(t, err)
   649  
   650  		svc, err := New(provider)
   651  		require.NoError(t, err)
   652  
   653  		go func() {
   654  			status, err := svc.StatusRequest("conn")
   655  			require.NoError(t, err)
   656  
   657  			require.Equal(t, 6, status.MessageCount)
   658  		}()
   659  
   660  		select {
   661  		case id := <-msgID:
   662  			require.NotNil(t, id)
   663  			s := Status{
   664  				MessageCount: 6,
   665  			}
   666  
   667  			// outbound has been handled, simulate a callback to finish the trip
   668  			ch := svc.getStatusCh(id)
   669  			ch <- s
   670  
   671  		case <-time.After(2 * time.Second):
   672  			require.Fail(t, "didn't receive message to handle")
   673  		}
   674  	})
   675  
   676  	t.Run("test MessagePickupService.StatusRequest() - connection error", func(t *testing.T) {
   677  		svc, err := getService()
   678  		require.NoError(t, err)
   679  
   680  		expected := errors.New("get error")
   681  		svc.connectionLookup = &connectionsStub{
   682  			getConnRecord: func(string) (*connection.Record, error) {
   683  				return nil, expected
   684  			},
   685  		}
   686  
   687  		_, err = svc.StatusRequest("conn")
   688  		require.Error(t, err)
   689  		require.True(t, errors.Is(err, expected))
   690  	})
   691  
   692  	t.Run("test MessagePickupService.StatusRequest() - send to DID error", func(t *testing.T) {
   693  		s := make(map[string][]byte)
   694  
   695  		provider := &mockprovider.Provider{
   696  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   697  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   698  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   699  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   700  					return errors.New("send error")
   701  				},
   702  			},
   703  			PackagerValue: &mockPackager{},
   704  		}
   705  
   706  		connRec := &connection.Record{
   707  			ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "completed",
   708  		}
   709  		connBytes, err := json.Marshal(connRec)
   710  		require.NoError(t, err)
   711  
   712  		s["conn_conn1"] = connBytes
   713  
   714  		r, err := connection.NewRecorder(provider)
   715  		require.NoError(t, err)
   716  		err = r.SaveConnectionRecord(connRec)
   717  		require.NoError(t, err)
   718  
   719  		svc, err := New(provider)
   720  		require.NoError(t, err)
   721  
   722  		_, err = svc.StatusRequest("conn")
   723  		require.Error(t, err)
   724  		require.Contains(t, err.Error(), "send route request")
   725  	})
   726  }
   727  
   728  func TestBatchPickup(t *testing.T) {
   729  	t.Run("test MessagePickupService.BatchPickup() - success", func(t *testing.T) {
   730  		msgID := make(chan string)
   731  		s := make(map[string][]byte)
   732  
   733  		provider := &mockprovider.Provider{
   734  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   735  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   736  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   737  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   738  					require.Equal(t, myDID, MYDID)
   739  					require.Equal(t, theirDID, THEIRDID)
   740  
   741  					reqMsgMap, ok := msg.(service.DIDCommMsgMap)
   742  					require.True(t, ok)
   743  
   744  					batchpickup := &BatchPickup{}
   745  
   746  					err := reqMsgMap.Decode(batchpickup)
   747  					require.NoError(t, err)
   748  
   749  					require.True(t, ok)
   750  
   751  					require.Equal(t, 1, batchpickup.BatchSize)
   752  					msgID <- batchpickup.ID
   753  
   754  					return nil
   755  				},
   756  			},
   757  			PackagerValue:              &mockPackager{},
   758  			InboundMessageHandlerValue: (&mockTransportProvider{}).InboundMessageHandler(),
   759  		}
   760  
   761  		connRec := &connection.Record{
   762  			ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "completed",
   763  		}
   764  		connBytes, err := json.Marshal(connRec)
   765  		require.NoError(t, err)
   766  
   767  		s["conn_conn1"] = connBytes
   768  
   769  		r, err := connection.NewRecorder(provider)
   770  		require.NoError(t, err)
   771  		err = r.SaveConnectionRecord(connRec)
   772  		require.NoError(t, err)
   773  
   774  		svc, err := New(provider)
   775  		require.NoError(t, err)
   776  
   777  		go func() {
   778  			id := <-msgID
   779  			require.NotNil(t, id)
   780  
   781  			s := Batch{
   782  				Messages: []*Message{{Message: []byte(`{
   783  					Protected: "eyJ0eXAiOiJwcnMuaHlwZXJsZWRnZXIuYXJpZXMtYXV0aC1t" +
   784  						"ZXNzYWdlIiwiYWxnIjoiRUNESC1TUytYQzIwUEtXIiwiZW5jIjoiWEMyMFAifQ",
   785  					IV:         "JS2FxjEKdndnt-J7QX5pEnVwyBTu0_3d",
   786  					CipherText: "qQyzvajdvCDJbwxM",
   787  					Tag:        "2FqZMMQuNPYfL0JsSkj8LQ",
   788  				}`)}},
   789  			}
   790  
   791  			// outbound has been handled, simulate a callback to finish the trip
   792  			ch := svc.getBatchCh(id)
   793  			ch <- s
   794  		}()
   795  
   796  		p, err := svc.BatchPickup("conn", 1)
   797  		require.NoError(t, err)
   798  
   799  		require.Equal(t, 1, p)
   800  	})
   801  
   802  	t.Run("test MessagePickupService.BatchPickup() - connection error", func(t *testing.T) {
   803  		svc, err := getService()
   804  		require.NoError(t, err)
   805  
   806  		expected := errors.New("get error")
   807  		svc.connectionLookup = &connectionsStub{
   808  			getConnRecord: func(string) (*connection.Record, error) {
   809  				return nil, expected
   810  			},
   811  		}
   812  
   813  		p, err := svc.BatchPickup("conn", 4)
   814  		require.Error(t, err)
   815  		require.True(t, errors.Is(err, expected))
   816  		require.Equal(t, -1, p)
   817  	})
   818  
   819  	t.Run("test MessagePickupService.BatchPickup() - send to DID error", func(t *testing.T) {
   820  		s := make(map[string][]byte)
   821  
   822  		provider := &mockprovider.Provider{
   823  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   824  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   825  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   826  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   827  					return errors.New("send error")
   828  				},
   829  			},
   830  			PackagerValue: &mockPackager{},
   831  		}
   832  
   833  		connRec := &connection.Record{
   834  			ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "completed",
   835  		}
   836  		connBytes, err := json.Marshal(connRec)
   837  		require.NoError(t, err)
   838  
   839  		s["conn_conn1"] = connBytes
   840  
   841  		r, err := connection.NewRecorder(provider)
   842  		require.NoError(t, err)
   843  		err = r.SaveConnectionRecord(connRec)
   844  		require.NoError(t, err)
   845  
   846  		svc, err := New(provider)
   847  		require.NoError(t, err)
   848  
   849  		_, err = svc.BatchPickup("conn", 4)
   850  		require.Error(t, err)
   851  		require.Contains(t, err.Error(), "send batch pickup request")
   852  	})
   853  }
   854  
   855  func TestDecodeMessages(t *testing.T) {
   856  	t.Run("test inbox.DecodeMessages() - success", func(t *testing.T) {
   857  		ibx := &inbox{}
   858  
   859  		msgs, err := ibx.DecodeMessages()
   860  		require.NoError(t, err)
   861  		require.Empty(t, msgs)
   862  	})
   863  
   864  	t.Run("test inbox.DecodeMessages() - error", func(t *testing.T) {
   865  		b, err := json.Marshal([]*Message{})
   866  		require.NoError(t, err)
   867  
   868  		ibx := &inbox{
   869  			Messages: b,
   870  		}
   871  
   872  		_, err = ibx.DecodeMessages()
   873  		require.NoError(t, err)
   874  	})
   875  }
   876  
   877  func TestHandleOutbound(t *testing.T) {
   878  	t.Run("test MessagePickupService.HandleOutbound() - not implemented", func(t *testing.T) {
   879  		svc, err := getService()
   880  		require.NoError(t, err)
   881  
   882  		svc.connectionLookup = &connectionsStub{
   883  			getConnRecord: func(string) (*connection.Record, error) {
   884  				return nil, storage.ErrDataNotFound
   885  			},
   886  		}
   887  
   888  		_, err = svc.HandleOutbound(nil, "not", "implemented")
   889  		require.Error(t, err)
   890  		require.Contains(t, err.Error(), "not implemented")
   891  	})
   892  }
   893  
   894  func TestNoop(t *testing.T) {
   895  	t.Run("test MessagePickupService.Noop() - success", func(t *testing.T) {
   896  		s := make(map[string][]byte)
   897  
   898  		provider := &mockprovider.Provider{
   899  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   900  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   901  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   902  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   903  					require.Equal(t, myDID, MYDID)
   904  					require.Equal(t, theirDID, THEIRDID)
   905  
   906  					reqMsgMap, ok := msg.(service.DIDCommMsgMap)
   907  					require.True(t, ok)
   908  
   909  					request := &Noop{}
   910  
   911  					err := reqMsgMap.Decode(request)
   912  					require.NoError(t, err)
   913  
   914  					return nil
   915  				},
   916  			},
   917  			PackagerValue: &mockPackager{},
   918  		}
   919  
   920  		connRec := &connection.Record{
   921  			ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "completed",
   922  		}
   923  		connBytes, err := json.Marshal(connRec)
   924  		require.NoError(t, err)
   925  
   926  		s["conn_conn1"] = connBytes
   927  
   928  		r, err := connection.NewRecorder(provider)
   929  		require.NoError(t, err)
   930  		err = r.SaveConnectionRecord(connRec)
   931  		require.NoError(t, err)
   932  
   933  		svc, err := New(provider)
   934  		require.NoError(t, err)
   935  
   936  		err = svc.Noop("conn")
   937  		require.NoError(t, err)
   938  	})
   939  
   940  	t.Run("test MessagePickupService.Noop() - send to DID error", func(t *testing.T) {
   941  		s := make(map[string][]byte)
   942  
   943  		provider := &mockprovider.Provider{
   944  			StorageProviderValue:              mockstore.NewMockStoreProvider(),
   945  			ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
   946  			OutboundDispatcherValue: &mockdispatcher.MockOutbound{
   947  				ValidateSendToDID: func(msg interface{}, myDID, theirDID string) error {
   948  					return errors.New("send error")
   949  				},
   950  			},
   951  			PackagerValue: &mockPackager{},
   952  		}
   953  
   954  		connRec := &connection.Record{
   955  			ConnectionID: "conn", MyDID: MYDID, TheirDID: THEIRDID, State: "completed",
   956  		}
   957  		connBytes, err := json.Marshal(connRec)
   958  		require.NoError(t, err)
   959  
   960  		s["conn_conn1"] = connBytes
   961  
   962  		r, err := connection.NewRecorder(provider)
   963  		require.NoError(t, err)
   964  		err = r.SaveConnectionRecord(connRec)
   965  		require.NoError(t, err)
   966  
   967  		svc, err := New(provider)
   968  		require.NoError(t, err)
   969  
   970  		err = svc.Noop("conn")
   971  		require.Error(t, err)
   972  		require.Contains(t, err.Error(), "send noop request")
   973  	})
   974  
   975  	t.Run("test MessagePickupService.Noop() - connection error", func(t *testing.T) {
   976  		svc, err := getService()
   977  		require.NoError(t, err)
   978  
   979  		expected := errors.New("get error")
   980  		svc.connectionLookup = &connectionsStub{
   981  			getConnRecord: func(string) (*connection.Record, error) {
   982  				return nil, expected
   983  			},
   984  		}
   985  
   986  		err = svc.Noop("conn")
   987  		require.Error(t, err)
   988  		require.True(t, errors.Is(err, expected))
   989  	})
   990  }
   991  
   992  func TestGetConnection(t *testing.T) {
   993  	t.Run("test MessagePickupService.getConnection() - error", func(t *testing.T) {
   994  		svc, err := getService()
   995  		require.NoError(t, err)
   996  
   997  		svc.connectionLookup = &connectionsStub{
   998  			getConnRecord: func(string) (*connection.Record, error) {
   999  				return nil, storage.ErrDataNotFound
  1000  			},
  1001  		}
  1002  
  1003  		_, err = svc.getConnection("test")
  1004  		require.Error(t, err)
  1005  		require.True(t, errors.Is(err, ErrConnectionNotFound))
  1006  	})
  1007  }
  1008  
  1009  func getService() (*Service, error) {
  1010  	svc, err := New(&mockprovider.Provider{
  1011  		StorageProviderValue:              mockstore.NewMockStoreProvider(),
  1012  		ProtocolStateStorageProviderValue: mockstore.NewMockStoreProvider(),
  1013  		OutboundDispatcherValue:           nil,
  1014  		PackagerValue:                     &mockPackager{},
  1015  	})
  1016  
  1017  	return svc, err
  1018  }
  1019  
  1020  // mockProvider mock provider.
  1021  type mockTransportProvider struct {
  1022  	packagerValue transport.Packager
  1023  }
  1024  
  1025  func (p *mockTransportProvider) Packager() transport.Packager {
  1026  	return p.packagerValue
  1027  }
  1028  
  1029  func (p *mockTransportProvider) InboundMessageHandler() transport.InboundMessageHandler {
  1030  	return func(envelope *transport.Envelope) error {
  1031  		logger.Debugf("message received is %s", envelope.Message)
  1032  		return nil
  1033  	}
  1034  }
  1035  
  1036  func (p *mockTransportProvider) AriesFrameworkID() string {
  1037  	return "aries-framework-instance-1"
  1038  }
  1039  
  1040  // mockPackager mock packager.
  1041  type mockPackager struct{}
  1042  
  1043  func (m *mockPackager) PackMessage(e *transport.Envelope) ([]byte, error) {
  1044  	return e.Message, nil
  1045  }
  1046  
  1047  func (m *mockPackager) UnpackMessage(encMessage []byte) (*transport.Envelope, error) {
  1048  	return &transport.Envelope{
  1049  		Message: []byte(`{
  1050  			"id": "8910",     
  1051  			"~transport": {
  1052  				"return_route": "all"
  1053  			}
  1054  		}`),
  1055  	}, nil
  1056  }
  1057  
  1058  type connectionsStub struct {
  1059  	getConnIDByDIDs func(string, string) (string, error)
  1060  	getConnRecord   func(string) (*connection.Record, error)
  1061  }
  1062  
  1063  func (c *connectionsStub) GetConnectionIDByDIDs(myDID, theirDID string) (string, error) {
  1064  	if c.getConnIDByDIDs != nil {
  1065  		return c.getConnIDByDIDs(myDID, theirDID)
  1066  	}
  1067  
  1068  	return "", nil
  1069  }
  1070  
  1071  func (c *connectionsStub) GetConnectionRecord(id string) (*connection.Record, error) {
  1072  	if c.getConnRecord != nil {
  1073  		return c.getConnRecord(id)
  1074  	}
  1075  
  1076  	return nil, nil
  1077  }