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

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package presentproof
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/base64"
    12  	"encoding/json"
    13  	"errors"
    14  	"fmt"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/golang/mock/gomock"
    19  	"github.com/google/uuid"
    20  	"github.com/stretchr/testify/require"
    21  
    22  	"github.com/hyperledger/aries-framework-go/component/storageutil/mem"
    23  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model"
    24  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
    25  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator"
    26  	serviceMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/common/service"
    27  	presentproofMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/protocol/presentproof"
    28  	storageMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/spi/storage"
    29  	"github.com/hyperledger/aries-framework-go/spi/storage"
    30  )
    31  
    32  const (
    33  	Alice = "Alice"
    34  	Bob   = "Bob"
    35  )
    36  
    37  func TestNew(t *testing.T) {
    38  	ctrl := gomock.NewController(t)
    39  	defer ctrl.Finish()
    40  
    41  	t.Run("Success", func(t *testing.T) {
    42  		storeProvider := storageMocks.NewMockProvider(ctrl)
    43  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil)
    44  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
    45  
    46  		provider := presentproofMocks.NewMockProvider(ctrl)
    47  		provider.EXPECT().Messenger().Return(nil)
    48  		provider.EXPECT().StorageProvider().Return(storeProvider).Times(2)
    49  
    50  		svc, err := New(provider)
    51  		require.NoError(t, err)
    52  		require.NotNil(t, svc)
    53  	})
    54  
    55  	t.Run("Error open store", func(t *testing.T) {
    56  		const errMsg = "error"
    57  
    58  		storeProvider := storageMocks.NewMockProvider(ctrl)
    59  		storeProvider.EXPECT().OpenStore(Name).Return(nil, errors.New(errMsg))
    60  
    61  		provider := presentproofMocks.NewMockProvider(ctrl)
    62  		provider.EXPECT().StorageProvider().Return(storeProvider)
    63  
    64  		svc, err := New(provider)
    65  		require.Contains(t, fmt.Sprintf("%v", err), errMsg)
    66  		require.Nil(t, svc)
    67  	})
    68  }
    69  
    70  func TestService_Initialize(t *testing.T) {
    71  	ctrl := gomock.NewController(t)
    72  	defer ctrl.Finish()
    73  
    74  	t.Run("success", func(t *testing.T) {
    75  		storeProvider := storageMocks.NewMockProvider(ctrl)
    76  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil)
    77  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
    78  
    79  		provider := presentproofMocks.NewMockProvider(ctrl)
    80  		provider.EXPECT().Messenger().Return(nil)
    81  		provider.EXPECT().StorageProvider().Return(storeProvider).Times(2)
    82  
    83  		svc := Service{}
    84  
    85  		err := svc.Initialize(provider)
    86  		require.NoError(t, err)
    87  
    88  		// second init is no-op
    89  		err = svc.Initialize(provider)
    90  		require.NoError(t, err)
    91  	})
    92  
    93  	t.Run("failure, not given a valid provider", func(t *testing.T) {
    94  		svc := Service{}
    95  
    96  		err := svc.Initialize("not a provider")
    97  		require.Error(t, err)
    98  		require.Contains(t, err.Error(), "expected provider of type")
    99  	})
   100  }
   101  
   102  func TestService_Use(t *testing.T) {
   103  	ctrl := gomock.NewController(t)
   104  	defer ctrl.Finish()
   105  
   106  	t.Run("Success (one function)", func(t *testing.T) {
   107  		storeProvider := storageMocks.NewMockProvider(ctrl)
   108  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil).Times(1)
   109  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
   110  
   111  		provider := presentproofMocks.NewMockProvider(ctrl)
   112  		provider.EXPECT().Messenger().Return(nil)
   113  		provider.EXPECT().StorageProvider().Return(storeProvider).Times(2)
   114  
   115  		svc, err := New(provider)
   116  		require.NoError(t, err)
   117  		require.NotNil(t, svc)
   118  
   119  		meta := &metaData{
   120  			state: &done{},
   121  			msgClone: service.NewDIDCommMsgMap(struct {
   122  				Type string `json:"@type"`
   123  			}{
   124  				Type: PresentationMsgTypeV2,
   125  			}),
   126  			presentation:          &PresentationV2{Type: PresentationMsgTypeV2},
   127  			presentationV3:        &PresentationV3{Type: PresentationMsgTypeV3},
   128  			proposePresentation:   &ProposePresentationV2{Type: ProposePresentationMsgTypeV2},
   129  			proposePresentationV3: &ProposePresentationV3{Type: ProposePresentationMsgTypeV3},
   130  			request:               &RequestPresentationV2{Type: RequestPresentationMsgTypeV2},
   131  			requestV3:             &RequestPresentationV3{Type: RequestPresentationMsgTypeV3},
   132  			presentationNames:     []string{"name"},
   133  		}
   134  		var executed bool
   135  		svc.Use(func(next Handler) Handler {
   136  			return HandlerFunc(func(metadata Metadata) error {
   137  				require.Equal(t, meta.msgClone, metadata.Message())
   138  				require.Equal(t, metadata.Message().Type(), PresentationMsgTypeV2)
   139  				require.Equal(t, meta.presentation, metadata.Presentation())
   140  				require.Equal(t, meta.presentationV3, metadata.PresentationV3())
   141  				require.Equal(t, meta.proposePresentation, metadata.ProposePresentation())
   142  				require.Equal(t, meta.proposePresentationV3, metadata.ProposePresentationV3())
   143  				require.Equal(t, meta.request, metadata.RequestPresentation())
   144  				require.Equal(t, meta.requestV3, metadata.RequestPresentationV3())
   145  				require.Equal(t, meta.presentationNames, metadata.PresentationNames())
   146  				require.Equal(t, meta.state.Name(), metadata.StateName())
   147  				require.Nil(t, metadata.GetAddProofFn())
   148  
   149  				executed = true
   150  				return next.Handle(metadata)
   151  			})
   152  		})
   153  
   154  		_, _, err = svc.execute(meta.state, meta)
   155  		require.NoError(t, err)
   156  		require.True(t, executed)
   157  	})
   158  
   159  	t.Run("Success (two function)", func(t *testing.T) {
   160  		storeProvider := storageMocks.NewMockProvider(ctrl)
   161  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil).Times(1)
   162  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
   163  
   164  		provider := presentproofMocks.NewMockProvider(ctrl)
   165  		provider.EXPECT().Messenger().Return(nil)
   166  		provider.EXPECT().StorageProvider().Return(storeProvider).Times(2)
   167  
   168  		svc, err := New(provider)
   169  		require.NoError(t, err)
   170  		require.NotNil(t, svc)
   171  
   172  		var executed bool
   173  		svc.Use(func(next Handler) Handler {
   174  			return HandlerFunc(func(metadata Metadata) error {
   175  				executed = true
   176  				return next.Handle(metadata)
   177  			})
   178  		}, func(next Handler) Handler {
   179  			return HandlerFunc(func(metadata Metadata) error {
   180  				require.True(t, executed)
   181  				return next.Handle(metadata)
   182  			})
   183  		})
   184  
   185  		_, _, err = svc.execute(&done{}, &metaData{})
   186  		require.NoError(t, err)
   187  	})
   188  
   189  	t.Run("Failed", func(t *testing.T) {
   190  		storeProvider := storageMocks.NewMockProvider(ctrl)
   191  		storeProvider.EXPECT().OpenStore(gomock.Any()).Return(nil, nil).Times(1)
   192  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
   193  
   194  		provider := presentproofMocks.NewMockProvider(ctrl)
   195  		provider.EXPECT().Messenger().Return(nil)
   196  		provider.EXPECT().StorageProvider().Return(storeProvider).Times(2)
   197  
   198  		svc, err := New(provider)
   199  		require.NoError(t, err)
   200  		require.NotNil(t, svc)
   201  
   202  		const msgErr = "error message"
   203  		svc.Use(func(next Handler) Handler {
   204  			return HandlerFunc(func(metadata Metadata) error {
   205  				return errors.New(msgErr)
   206  			})
   207  		})
   208  
   209  		_, _, err = svc.execute(&done{}, &metaData{})
   210  		require.EqualError(t, err, "middleware: "+msgErr)
   211  	})
   212  }
   213  
   214  func TestService_ActionContinue(t *testing.T) {
   215  	ctrl := gomock.NewController(t)
   216  	defer ctrl.Finish()
   217  
   218  	const errMsg = "error"
   219  
   220  	store := storageMocks.NewMockStore(ctrl)
   221  	storeProvider := storageMocks.NewMockProvider(ctrl)
   222  	storeProvider.EXPECT().OpenStore(gomock.Any()).Return(store, nil).AnyTimes()
   223  	storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil).AnyTimes()
   224  
   225  	provider := presentproofMocks.NewMockProvider(ctrl)
   226  	provider.EXPECT().Messenger().Return(nil).AnyTimes()
   227  	provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
   228  
   229  	t.Run("Error transitional payload (get)", func(t *testing.T) {
   230  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
   231  
   232  		svc, err := New(provider)
   233  		require.NoError(t, err)
   234  
   235  		err = svc.ActionContinue("piID", nil)
   236  		require.Contains(t, fmt.Sprintf("%v", err), "get transitional payload: store get: "+errMsg)
   237  	})
   238  
   239  	t.Run("Error transitional payload (delete)", func(t *testing.T) {
   240  		store.EXPECT().Get(gomock.Any()).Return([]byte(`{}`), nil)
   241  		store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg))
   242  
   243  		svc, err := New(provider)
   244  		require.NoError(t, err)
   245  
   246  		err = svc.ActionContinue("piID")
   247  		require.Contains(t, fmt.Sprintf("%v", err), "delete transitional payload: "+errMsg)
   248  	})
   249  }
   250  
   251  func TestService_ActionStop(t *testing.T) {
   252  	t.Run("Error transitional payload (get)", func(t *testing.T) {
   253  		ctrl := gomock.NewController(t)
   254  		defer ctrl.Finish()
   255  
   256  		const errMsg = "error"
   257  
   258  		store := storageMocks.NewMockStore(ctrl)
   259  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg))
   260  
   261  		storeProvider := storageMocks.NewMockProvider(ctrl)
   262  		storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes()
   263  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
   264  
   265  		provider := presentproofMocks.NewMockProvider(ctrl)
   266  		provider.EXPECT().Messenger().Return(nil)
   267  		provider.EXPECT().StorageProvider().Return(storeProvider).Times(2)
   268  
   269  		svc, err := New(provider)
   270  		require.NoError(t, err)
   271  
   272  		err = svc.ActionStop("piID", nil)
   273  		require.Contains(t, fmt.Sprintf("%v", err), "get transitional payload: store get: "+errMsg)
   274  	})
   275  
   276  	t.Run("Error transitional payload (delete)", func(t *testing.T) {
   277  		ctrl := gomock.NewController(t)
   278  		defer ctrl.Finish()
   279  
   280  		const errMsg = "error"
   281  
   282  		store := storageMocks.NewMockStore(ctrl)
   283  		store.EXPECT().Get(gomock.Any()).Return([]byte(`{}`), nil)
   284  		store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg))
   285  
   286  		storeProvider := storageMocks.NewMockProvider(ctrl)
   287  		storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes()
   288  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
   289  
   290  		provider := presentproofMocks.NewMockProvider(ctrl)
   291  		provider.EXPECT().Messenger().Return(nil)
   292  		provider.EXPECT().StorageProvider().Return(storeProvider).Times(2)
   293  
   294  		svc, err := New(provider)
   295  		require.NoError(t, err)
   296  
   297  		err = svc.ActionStop("piID", nil)
   298  		require.Contains(t, fmt.Sprintf("%v", err), "delete transitional payload: "+errMsg)
   299  	})
   300  }
   301  
   302  // nolint: gocyclo,gocognit
   303  func TestService_HandleInboundOutbound(t *testing.T) {
   304  	ctrl := gomock.NewController(t)
   305  	defer ctrl.Finish()
   306  
   307  	const errMsg = "error"
   308  
   309  	initMocks := func(controller *gomock.Controller) (
   310  		store *storageMocks.MockStore,
   311  		messenger *serviceMocks.MockMessenger,
   312  		provider *presentproofMocks.MockProvider,
   313  	) {
   314  		store = storageMocks.NewMockStore(controller)
   315  
   316  		storeProvider := storageMocks.NewMockProvider(controller)
   317  		storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes()
   318  		storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil).AnyTimes()
   319  
   320  		messenger = serviceMocks.NewMockMessenger(controller)
   321  
   322  		provider = presentproofMocks.NewMockProvider(controller)
   323  		provider.EXPECT().Messenger().Return(messenger).AnyTimes()
   324  		provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
   325  
   326  		return store, messenger, provider
   327  	}
   328  
   329  	t.Run("No clients", func(t *testing.T) {
   330  		_, _, provider := initMocks(ctrl)
   331  
   332  		svc, err := New(provider)
   333  		require.NoError(t, err)
   334  
   335  		_, err = svc.HandleInbound(randomInboundMessage(""), service.EmptyDIDCommContext())
   336  		require.Contains(t, fmt.Sprintf("%v", err), "no clients")
   337  	})
   338  
   339  	t.Run("DB error", func(t *testing.T) {
   340  		store, _, provider := initMocks(ctrl)
   341  
   342  		store.EXPECT().Get(gomock.Any()).Return(nil, errors.New(errMsg)).AnyTimes()
   343  
   344  		svc, err := New(provider)
   345  		require.NoError(t, err)
   346  
   347  		require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction)))
   348  
   349  		msg := service.NewDIDCommMsgMap(struct {
   350  			ID     string           `json:"@id"`
   351  			Type   string           `json:"@type"`
   352  			Thread decorator.Thread `json:"~thread"`
   353  		}{ID: "ID", Type: "type", Thread: decorator.Thread{PID: "PID"}})
   354  		msg.SetID(uuid.New().String())
   355  
   356  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
   357  		require.Contains(t, fmt.Sprintf("%v", err),
   358  			"buildMetaData: current internal data and PIID: current internal data: "+errMsg)
   359  	})
   360  
   361  	t.Run("DB error (saveTransitionalPayload)", func(t *testing.T) {
   362  		store, _, provider := initMocks(ctrl)
   363  
   364  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   365  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New(errMsg))
   366  
   367  		svc, err := New(provider)
   368  		require.NoError(t, err)
   369  
   370  		require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction)))
   371  
   372  		_, err = svc.HandleInbound(randomInboundMessage(RequestPresentationMsgTypeV2), service.EmptyDIDCommContext())
   373  		require.Contains(t, fmt.Sprintf("%v", err), "save transitional payload: "+errMsg)
   374  	})
   375  
   376  	t.Run("Unrecognized msgType", func(t *testing.T) {
   377  		store, _, provider := initMocks(ctrl)
   378  
   379  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   380  
   381  		svc, err := New(provider)
   382  		require.NoError(t, err)
   383  
   384  		require.NoError(t, svc.RegisterActionEvent(make(chan<- service.DIDCommAction)))
   385  
   386  		msg := service.NewDIDCommMsgMap(struct{}{})
   387  		msg.SetID(uuid.New().String())
   388  		msg["@type"] = "type"
   389  
   390  		_, err = svc.HandleInbound(msg, service.EmptyDIDCommContext())
   391  		require.Contains(t, fmt.Sprintf("%v", err), "buildMetaData: nextState: unrecognized msgType: ")
   392  	})
   393  
   394  	t.Run("Invalid state transition", func(t *testing.T) {
   395  		_, _, provider := initMocks(ctrl)
   396  
   397  		svc, err := New(provider)
   398  		require.NoError(t, err)
   399  
   400  		ch := make(chan service.DIDCommAction, 1)
   401  		require.NoError(t, svc.RegisterActionEvent(ch))
   402  
   403  		chState := make(chan service.StateMsg, 2)
   404  		require.NoError(t, svc.RegisterMsgEvent(chState))
   405  
   406  		_, err = svc.HandleInbound(service.NewDIDCommMsgMap(model.ProblemReport{
   407  			Type: ProblemReportMsgTypeV2,
   408  		}), service.EmptyDIDCommContext())
   409  		require.Contains(t, fmt.Sprintf("%v", err), "buildMetaData: invalid state transition")
   410  	})
   411  
   412  	t.Run("Receive Invitation Presentation (Stop)", func(t *testing.T) {
   413  		store, messenger, provider := initMocks(ctrl)
   414  
   415  		done := make(chan struct{})
   416  		errChan := make(chan error)
   417  
   418  		messenger.EXPECT().
   419  			ReplyToNested(gomock.Any(), gomock.Any()).
   420  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   421  				defer close(done)
   422  
   423  				r := &model.ProblemReport{}
   424  				require.NoError(t, msg.Decode(r))
   425  				require.Equal(t, codeRejectedError, r.Description.Code)
   426  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
   427  
   428  				return nil
   429  			})
   430  
   431  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   432  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   433  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   434  			src, err := json.Marshal(&internalData{StateName: "abandoned", ProtocolVersion: version2})
   435  			require.NoError(t, err)
   436  			require.True(t, bytes.Equal(src, data))
   437  
   438  			if !bytes.Equal(src, data) {
   439  				errChan <- fmt.Errorf("data: %s\nsrc: %s", string(data), string(src))
   440  			}
   441  			return nil
   442  		})
   443  		store.EXPECT().Delete(gomock.Any()).Return(errors.New(errMsg))
   444  
   445  		svc, err := New(provider)
   446  		require.NoError(t, err)
   447  
   448  		ch := make(chan service.DIDCommAction, 1)
   449  		require.NoError(t, svc.RegisterActionEvent(ch))
   450  
   451  		_, err = svc.HandleInbound(
   452  			randomInboundMessage(RequestPresentationMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil))
   453  		require.NoError(t, err)
   454  
   455  		action := <-ch
   456  
   457  		properties, ok := action.Properties.(*eventProps)
   458  		require.True(t, ok)
   459  		require.NotEmpty(t, properties.PIID())
   460  		require.Equal(t, properties.MyDID(), Alice)
   461  		require.Equal(t, properties.TheirDID(), Bob)
   462  		require.Equal(t, properties.All()["myDID"], Alice)
   463  		require.Equal(t, properties.All()["theirDID"], Bob)
   464  
   465  		action.Stop(nil)
   466  
   467  		select {
   468  		case e := <-errChan:
   469  			t.Error(e)
   470  		case <-done:
   471  			return
   472  		case <-time.After(time.Second):
   473  			t.Error("timeout")
   474  		}
   475  	})
   476  
   477  	t.Run("Receive Invitation Presentation (continue with presentation)", func(t *testing.T) {
   478  		store, messenger, provider := initMocks(ctrl)
   479  
   480  		done := make(chan struct{})
   481  
   482  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   483  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   484  				defer close(done)
   485  
   486  				r := &PresentationV2{}
   487  				require.NoError(t, msg.Decode(r))
   488  				require.Equal(t, PresentationMsgTypeV2, r.Type)
   489  
   490  				return nil
   491  			})
   492  
   493  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   494  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   495  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   496  			src, err := json.Marshal(&internalData{StateName: "request-received", ProtocolVersion: version2})
   497  			require.NoError(t, err)
   498  			require.Equal(t, string(src), string(data))
   499  
   500  			return nil
   501  		})
   502  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   503  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   504  			src, err := json.Marshal(&internalData{StateName: "presentation-sent", ProtocolVersion: version2})
   505  			require.NoError(t, err)
   506  			require.Equal(t, string(src), string(data))
   507  
   508  			return nil
   509  		})
   510  
   511  		svc, err := New(provider)
   512  		require.NoError(t, err)
   513  
   514  		ch := make(chan service.DIDCommAction, 1)
   515  		require.NoError(t, svc.RegisterActionEvent(ch))
   516  
   517  		msg := randomInboundMessage(RequestPresentationMsgTypeV2)
   518  		msg["will_confirm"] = true
   519  
   520  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   521  		require.NoError(t, err)
   522  
   523  		action := <-ch
   524  
   525  		properties, ok := action.Properties.(*eventProps)
   526  		require.True(t, ok)
   527  		require.NotEmpty(t, properties.PIID())
   528  		require.Equal(t, properties.MyDID(), Alice)
   529  		require.Equal(t, properties.TheirDID(), Bob)
   530  
   531  		action.Continue(WithMultiOptions(WithPresentation(&PresentationParams{}), WithAddProofFn(nil)))
   532  
   533  		select {
   534  		case <-done:
   535  			return
   536  		case <-time.After(time.Second):
   537  			t.Error("timeout")
   538  		}
   539  	})
   540  
   541  	t.Run("Receive Invitation Presentation (continue with presentation) async", func(t *testing.T) {
   542  		_, messenger, _ := initMocks(ctrl)
   543  
   544  		done := make(chan struct{})
   545  
   546  		memProvider := mem.NewProvider()
   547  
   548  		newProvider := presentproofMocks.NewMockProvider(ctrl)
   549  		newProvider.EXPECT().Messenger().Return(messenger)
   550  		newProvider.EXPECT().StorageProvider().Return(memProvider).Times(2)
   551  
   552  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   553  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   554  				defer close(done)
   555  
   556  				r := &PresentationV2{}
   557  				require.NoError(t, msg.Decode(r))
   558  				require.Equal(t, PresentationMsgTypeV2, r.Type)
   559  
   560  				return nil
   561  			})
   562  
   563  		svc, err := New(newProvider)
   564  		require.NoError(t, err)
   565  
   566  		ch := make(chan service.DIDCommAction, 1)
   567  		require.NoError(t, svc.RegisterActionEvent(ch))
   568  
   569  		msg := randomInboundMessage(RequestPresentationMsgTypeV2)
   570  		msg["will_confirm"] = true
   571  
   572  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   573  		require.NoError(t, err)
   574  
   575  		actions, err := svc.Actions()
   576  		require.NoError(t, err)
   577  		for _, action := range actions {
   578  			require.Equal(t, action.MyDID, Alice)
   579  			require.Equal(t, action.TheirDID, Bob)
   580  			require.NoError(t, svc.ActionContinue(action.PIID, WithPresentation(&PresentationParams{})))
   581  		}
   582  
   583  		select {
   584  		case <-done:
   585  			return
   586  		case <-time.After(time.Second):
   587  			t.Error("timeout")
   588  		}
   589  	})
   590  
   591  	t.Run("Receive Invitation Presentation (continue with presentation) async v3", func(t *testing.T) {
   592  		_, messenger, _ := initMocks(ctrl)
   593  
   594  		done := make(chan struct{})
   595  
   596  		memProvider := mem.NewProvider()
   597  
   598  		newProvider := presentproofMocks.NewMockProvider(ctrl)
   599  		newProvider.EXPECT().Messenger().Return(messenger)
   600  		newProvider.EXPECT().StorageProvider().Return(memProvider).Times(2)
   601  
   602  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   603  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   604  				defer close(done)
   605  
   606  				r := &PresentationV3{}
   607  				require.NoError(t, msg.Decode(r))
   608  				require.Equal(t, PresentationMsgTypeV3, r.Type)
   609  
   610  				return nil
   611  			})
   612  
   613  		svc, err := New(newProvider)
   614  		require.NoError(t, err)
   615  
   616  		ch := make(chan service.DIDCommAction, 1)
   617  		require.NoError(t, svc.RegisterActionEvent(ch))
   618  
   619  		msg := randomInboundMessageV3(RequestPresentationMsgTypeV3)
   620  
   621  		msg["data"] = map[string]interface{}{
   622  			"will_confirm": true,
   623  		}
   624  
   625  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
   626  		require.NoError(t, err)
   627  
   628  		actions, err := svc.Actions()
   629  		require.NoError(t, err)
   630  		for _, action := range actions {
   631  			require.Equal(t, action.MyDID, Alice)
   632  			require.Equal(t, action.TheirDID, Bob)
   633  			require.NoError(t, svc.ActionContinue(action.PIID, WithPresentation(&PresentationParams{})))
   634  		}
   635  
   636  		select {
   637  		case <-done:
   638  			return
   639  		case <-time.After(time.Second):
   640  			t.Error("timeout")
   641  		}
   642  	})
   643  
   644  	t.Run("Receive Invitation Presentation (Stop) async", func(t *testing.T) {
   645  		_, messenger, _ := initMocks(ctrl)
   646  
   647  		done := make(chan struct{})
   648  
   649  		memProvider := mem.NewProvider()
   650  
   651  		newProvider := presentproofMocks.NewMockProvider(ctrl)
   652  		newProvider.EXPECT().Messenger().Return(messenger)
   653  		newProvider.EXPECT().StorageProvider().Return(memProvider).Times(2)
   654  
   655  		messenger.EXPECT().
   656  			ReplyToNested(gomock.Any(), gomock.Any()).
   657  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   658  				defer close(done)
   659  
   660  				r := &model.ProblemReport{}
   661  				require.NoError(t, msg.Decode(r))
   662  				require.Equal(t, codeRejectedError, r.Description.Code)
   663  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
   664  
   665  				return nil
   666  			})
   667  
   668  		svc, err := New(newProvider)
   669  		require.NoError(t, err)
   670  
   671  		ch := make(chan service.DIDCommAction, 1)
   672  		require.NoError(t, svc.RegisterActionEvent(ch))
   673  
   674  		_, err = svc.HandleInbound(
   675  			randomInboundMessage(RequestPresentationMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil))
   676  		require.NoError(t, err)
   677  
   678  		actions, err := svc.Actions()
   679  		require.NoError(t, err)
   680  		for _, action := range actions {
   681  			require.Equal(t, action.MyDID, Alice)
   682  			require.Equal(t, action.TheirDID, Bob)
   683  			require.NoError(t, svc.ActionStop(action.PIID, nil))
   684  		}
   685  
   686  		select {
   687  		case <-done:
   688  			return
   689  		case <-time.After(time.Second):
   690  			t.Error("timeout")
   691  		}
   692  	})
   693  
   694  	t.Run("Receive Invitation Presentation (continue with proposal)", func(t *testing.T) {
   695  		store, messenger, provider := initMocks(ctrl)
   696  
   697  		done := make(chan struct{})
   698  
   699  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   700  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   701  				defer close(done)
   702  
   703  				r := &ProposePresentationV2{}
   704  				require.NoError(t, msg.Decode(r))
   705  				require.Equal(t, ProposePresentationMsgTypeV2, r.Type)
   706  
   707  				return nil
   708  			})
   709  
   710  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   711  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   712  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   713  			src, err := json.Marshal(&internalData{StateName: "request-received", ProtocolVersion: version2})
   714  			require.NoError(t, err)
   715  			require.Equal(t, string(src), string(data))
   716  
   717  			return nil
   718  		})
   719  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   720  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   721  			src, err := json.Marshal(&internalData{StateName: "proposal-sent", ProtocolVersion: version2})
   722  			require.NoError(t, err)
   723  			require.Equal(t, string(src), string(data))
   724  
   725  			return nil
   726  		})
   727  
   728  		svc, err := New(provider)
   729  		require.NoError(t, err)
   730  
   731  		ch := make(chan service.DIDCommAction, 1)
   732  		require.NoError(t, svc.RegisterActionEvent(ch))
   733  
   734  		_, err = svc.HandleInbound(
   735  			randomInboundMessage(RequestPresentationMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil))
   736  		require.NoError(t, err)
   737  
   738  		action := <-ch
   739  
   740  		properties, ok := action.Properties.(*eventProps)
   741  		require.True(t, ok)
   742  		require.NotEmpty(t, properties.PIID())
   743  		require.Equal(t, properties.MyDID(), Alice)
   744  		require.Equal(t, properties.TheirDID(), Bob)
   745  
   746  		action.Continue(WithProposePresentation(&ProposePresentationParams{}))
   747  
   748  		select {
   749  		case <-done:
   750  			return
   751  		case <-time.After(time.Second):
   752  			t.Error("timeout")
   753  		}
   754  	})
   755  
   756  	t.Run("Receive Invitation Presentation (continue with proposal) v3", func(t *testing.T) {
   757  		store, messenger, provider := initMocks(ctrl)
   758  
   759  		done := make(chan struct{})
   760  
   761  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   762  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   763  				defer close(done)
   764  
   765  				r := &ProposePresentationV3{}
   766  				require.NoError(t, msg.Decode(r))
   767  				require.Equal(t, ProposePresentationMsgTypeV3, r.Type)
   768  
   769  				return nil
   770  			})
   771  
   772  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   773  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   774  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   775  			src, err := json.Marshal(&internalData{StateName: "request-received", ProtocolVersion: version3})
   776  			require.NoError(t, err)
   777  			require.Equal(t, string(src), string(data))
   778  
   779  			return nil
   780  		})
   781  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   782  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   783  			src, err := json.Marshal(&internalData{StateName: "proposal-sent", ProtocolVersion: version3})
   784  			require.NoError(t, err)
   785  			require.Equal(t, string(src), string(data))
   786  
   787  			return nil
   788  		})
   789  
   790  		svc, err := New(provider)
   791  		require.NoError(t, err)
   792  
   793  		ch := make(chan service.DIDCommAction, 1)
   794  		require.NoError(t, svc.RegisterActionEvent(ch))
   795  
   796  		_, err = svc.HandleInbound(
   797  			randomInboundMessageV3(RequestPresentationMsgTypeV3), service.NewDIDCommContext(Alice, Bob, nil))
   798  		require.NoError(t, err)
   799  
   800  		action := <-ch
   801  
   802  		properties, ok := action.Properties.(*eventProps)
   803  		require.True(t, ok)
   804  		require.NotEmpty(t, properties.PIID())
   805  		require.Equal(t, properties.MyDID(), Alice)
   806  		require.Equal(t, properties.TheirDID(), Bob)
   807  
   808  		action.Continue(WithProposePresentation(&ProposePresentationParams{}))
   809  
   810  		select {
   811  		case <-done:
   812  			return
   813  		case <-time.After(time.Second):
   814  			t.Error("timeout")
   815  		}
   816  	})
   817  
   818  	t.Run("Receive Propose Presentation (continue)", func(t *testing.T) {
   819  		store, messenger, provider := initMocks(ctrl)
   820  
   821  		done := make(chan struct{})
   822  
   823  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   824  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   825  				defer close(done)
   826  
   827  				r := &RequestPresentationV2{}
   828  				require.NoError(t, msg.Decode(r))
   829  				require.Equal(t, RequestPresentationMsgTypeV2, r.Type)
   830  
   831  				return nil
   832  			})
   833  
   834  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   835  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   836  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   837  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   838  			src, err := json.Marshal(&internalData{StateName: "proposal-received", ProtocolVersion: version2})
   839  			require.NoError(t, err)
   840  			require.Equal(t, string(src), string(data))
   841  
   842  			return nil
   843  		})
   844  
   845  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   846  			src, err := json.Marshal(&internalData{StateName: "request-sent", ProtocolVersion: version2})
   847  			require.NoError(t, err)
   848  			require.Equal(t, string(src), string(data))
   849  
   850  			return nil
   851  		})
   852  
   853  		svc, err := New(provider)
   854  		require.NoError(t, err)
   855  
   856  		ch := make(chan service.DIDCommAction, 1)
   857  		require.NoError(t, svc.RegisterActionEvent(ch))
   858  
   859  		_, err = svc.HandleInbound(
   860  			randomInboundMessage(ProposePresentationMsgTypeV2),
   861  			service.NewDIDCommContext(Alice, Bob, nil))
   862  		require.NoError(t, err)
   863  
   864  		action := <-ch
   865  
   866  		properties, ok := action.Properties.(*eventProps)
   867  		require.True(t, ok)
   868  		require.NotEmpty(t, properties.PIID())
   869  		require.Equal(t, properties.MyDID(), Alice)
   870  		require.Equal(t, properties.TheirDID(), Bob)
   871  
   872  		action.Continue(WithRequestPresentation(&RequestPresentationParams{}))
   873  
   874  		select {
   875  		case <-done:
   876  			return
   877  		case <-time.After(time.Second):
   878  			t.Error("timeout")
   879  		}
   880  	})
   881  
   882  	t.Run("Receive Propose Presentation (continue) v3", func(t *testing.T) {
   883  		store, messenger, provider := initMocks(ctrl)
   884  
   885  		done := make(chan struct{})
   886  
   887  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
   888  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
   889  				defer close(done)
   890  
   891  				r := &RequestPresentationV3{}
   892  				require.NoError(t, msg.Decode(r))
   893  				require.Equal(t, RequestPresentationMsgTypeV3, r.Type)
   894  
   895  				return nil
   896  			})
   897  
   898  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
   899  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   900  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   901  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   902  			src, err := json.Marshal(&internalData{StateName: "proposal-received", ProtocolVersion: version3})
   903  			require.NoError(t, err)
   904  			require.Equal(t, string(src), string(data))
   905  
   906  			return nil
   907  		})
   908  
   909  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   910  			src, err := json.Marshal(&internalData{StateName: "request-sent", ProtocolVersion: version3})
   911  			require.NoError(t, err)
   912  			require.Equal(t, string(src), string(data))
   913  
   914  			return nil
   915  		})
   916  
   917  		svc, err := New(provider)
   918  		require.NoError(t, err)
   919  
   920  		ch := make(chan service.DIDCommAction, 1)
   921  		require.NoError(t, svc.RegisterActionEvent(ch))
   922  
   923  		_, err = svc.HandleInbound(
   924  			randomInboundMessageV3(ProposePresentationMsgTypeV3),
   925  			service.NewDIDCommContext(Alice, Bob, nil))
   926  		require.NoError(t, err)
   927  
   928  		action := <-ch
   929  
   930  		properties, ok := action.Properties.(*eventProps)
   931  		require.True(t, ok)
   932  		require.NotEmpty(t, properties.PIID())
   933  		require.Equal(t, properties.MyDID(), Alice)
   934  		require.Equal(t, properties.TheirDID(), Bob)
   935  
   936  		action.Continue(WithRequestPresentation(&RequestPresentationParams{}))
   937  
   938  		select {
   939  		case <-done:
   940  			return
   941  		case <-time.After(time.Second):
   942  			t.Error("timeout")
   943  		}
   944  	})
   945  
   946  	t.Run("Receive Problem Report (continue)", func(t *testing.T) {
   947  		store, _, provider := initMocks(ctrl)
   948  
   949  		done := make(chan struct{})
   950  
   951  		src, err := json.Marshal(&internalData{StateName: "request-sent", ProtocolVersion: version2})
   952  		require.NoError(t, err)
   953  
   954  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
   955  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
   956  		store.EXPECT().Delete(gomock.Any()).Return(nil)
   957  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
   958  			defer close(done)
   959  
   960  			src, err = json.Marshal(&internalData{StateName: "abandoned", ProtocolVersion: version2})
   961  			require.NoError(t, err)
   962  			require.Equal(t, string(src), string(data))
   963  
   964  			return nil
   965  		})
   966  
   967  		svc, err := New(provider)
   968  		require.NoError(t, err)
   969  
   970  		ch := make(chan service.DIDCommAction, 1)
   971  		require.NoError(t, svc.RegisterActionEvent(ch))
   972  
   973  		_, err = svc.HandleInbound(randomInboundMessage(ProblemReportMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil))
   974  		require.NoError(t, err)
   975  
   976  		action := <-ch
   977  
   978  		properties, ok := action.Properties.(*eventProps)
   979  		require.True(t, ok)
   980  		require.NotEmpty(t, properties.PIID())
   981  		require.Equal(t, properties.MyDID(), Alice)
   982  		require.Equal(t, properties.TheirDID(), Bob)
   983  
   984  		action.Continue(WithRequestPresentation(&RequestPresentationParams{}))
   985  
   986  		select {
   987  		case <-done:
   988  			return
   989  		case <-time.After(time.Second):
   990  			t.Error("timeout")
   991  		}
   992  	})
   993  
   994  	t.Run("Receive Problem Report (stop)", func(t *testing.T) {
   995  		store, _, provider := initMocks(ctrl)
   996  
   997  		done := make(chan struct{})
   998  
   999  		src, err := json.Marshal(&internalData{StateName: "request-sent"})
  1000  		require.NoError(t, err)
  1001  
  1002  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1003  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1004  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1005  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1006  			defer close(done)
  1007  
  1008  			src, err = json.Marshal(&internalData{StateName: "abandoned"})
  1009  			require.NoError(t, err)
  1010  			require.Equal(t, src, data)
  1011  
  1012  			return nil
  1013  		})
  1014  
  1015  		svc, err := New(provider)
  1016  		require.NoError(t, err)
  1017  
  1018  		ch := make(chan service.DIDCommAction, 1)
  1019  		require.NoError(t, svc.RegisterActionEvent(ch))
  1020  
  1021  		_, err = svc.HandleInbound(randomInboundMessage(ProblemReportMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil))
  1022  		require.NoError(t, err)
  1023  
  1024  		action := <-ch
  1025  
  1026  		properties, ok := action.Properties.(*eventProps)
  1027  		require.True(t, ok)
  1028  		require.NotEmpty(t, properties.PIID())
  1029  		require.Equal(t, properties.MyDID(), Alice)
  1030  		require.Equal(t, properties.TheirDID(), Bob)
  1031  
  1032  		action.Stop(nil)
  1033  
  1034  		select {
  1035  		case <-done:
  1036  			return
  1037  		case <-time.After(time.Second):
  1038  			t.Error("timeout")
  1039  		}
  1040  	})
  1041  
  1042  	t.Run("Receive Propose Presentation (continue without request)", func(t *testing.T) {
  1043  		store, messenger, provider := initMocks(ctrl)
  1044  
  1045  		done := make(chan struct{})
  1046  
  1047  		messenger.EXPECT().
  1048  			ReplyToNested(gomock.Any(), gomock.Any()).
  1049  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
  1050  				defer close(done)
  1051  
  1052  				r := &model.ProblemReport{}
  1053  				require.NoError(t, msg.Decode(r))
  1054  				require.Equal(t, codeInternalError, r.Description.Code)
  1055  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
  1056  
  1057  				return nil
  1058  			})
  1059  
  1060  		store.EXPECT().Get(gomock.Any()).Return(nil, storage.ErrDataNotFound).AnyTimes()
  1061  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1062  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1063  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1064  			src, err := json.Marshal(&internalData{StateName: "proposal-received", ProtocolVersion: version2})
  1065  			require.NoError(t, err)
  1066  			require.Equal(t, string(src), string(data))
  1067  
  1068  			return nil
  1069  		})
  1070  
  1071  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1072  			src, err := json.Marshal(&internalData{StateName: "abandoned", ProtocolVersion: version2})
  1073  			require.NoError(t, err)
  1074  			require.Equal(t, string(src), string(data))
  1075  
  1076  			return nil
  1077  		})
  1078  
  1079  		svc, err := New(provider)
  1080  		require.NoError(t, err)
  1081  
  1082  		ch := make(chan service.DIDCommAction, 1)
  1083  		require.NoError(t, svc.RegisterActionEvent(ch))
  1084  
  1085  		_, err = svc.HandleInbound(
  1086  			randomInboundMessage(ProposePresentationMsgTypeV2),
  1087  			service.NewDIDCommContext(Alice, Bob, nil))
  1088  		require.NoError(t, err)
  1089  
  1090  		action := <-ch
  1091  
  1092  		properties, ok := action.Properties.(*eventProps)
  1093  		require.True(t, ok)
  1094  		require.NotEmpty(t, properties.PIID())
  1095  		require.Equal(t, properties.MyDID(), Alice)
  1096  		require.Equal(t, properties.TheirDID(), Bob)
  1097  
  1098  		action.Continue(nil)
  1099  
  1100  		select {
  1101  		case <-done:
  1102  			return
  1103  		case <-time.After(time.Second):
  1104  			t.Error("timeout")
  1105  		}
  1106  	})
  1107  
  1108  	t.Run("Receive Presentation (continue)", func(t *testing.T) {
  1109  		store, messenger, provider := initMocks(ctrl)
  1110  
  1111  		done := make(chan struct{})
  1112  
  1113  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1114  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1115  				r := &model.Ack{}
  1116  				require.NoError(t, msg.Decode(r))
  1117  				require.Equal(t, AckMsgTypeV2, r.Type)
  1118  
  1119  				return nil
  1120  			})
  1121  
  1122  		src, err := json.Marshal(&internalData{AckRequired: true, StateName: "request-sent"})
  1123  		require.NoError(t, err)
  1124  
  1125  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1126  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1127  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1128  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1129  			src, err = json.Marshal(&internalData{AckRequired: true, StateName: "presentation-received"})
  1130  			require.NoError(t, err)
  1131  			require.Equal(t, src, data)
  1132  
  1133  			return nil
  1134  		})
  1135  
  1136  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1137  			defer close(done)
  1138  
  1139  			src, err = json.Marshal(&internalData{AckRequired: true, StateName: "done"})
  1140  			require.NoError(t, err)
  1141  			require.Equal(t, src, data)
  1142  
  1143  			return nil
  1144  		})
  1145  
  1146  		svc, err := New(provider)
  1147  		require.NoError(t, err)
  1148  
  1149  		ch := make(chan service.DIDCommAction, 1)
  1150  		require.NoError(t, svc.RegisterActionEvent(ch))
  1151  
  1152  		msg := service.NewDIDCommMsgMap(PresentationV2{
  1153  			Type: PresentationMsgTypeV2,
  1154  			PresentationsAttach: []decorator.Attachment{{
  1155  				Data: decorator.AttachmentData{
  1156  					Base64: base64.StdEncoding.EncodeToString([]byte(`{}`)),
  1157  				},
  1158  			}},
  1159  		})
  1160  		msg.SetID(uuid.New().String())
  1161  
  1162  		msg["~thread"] = decorator.Thread{ID: uuid.New().String()}
  1163  
  1164  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1165  		require.NoError(t, err)
  1166  
  1167  		action := <-ch
  1168  
  1169  		properties, ok := action.Properties.(*eventProps)
  1170  		require.True(t, ok)
  1171  		require.NotEmpty(t, properties.PIID())
  1172  		require.Equal(t, properties.MyDID(), Alice)
  1173  		require.Equal(t, properties.TheirDID(), Bob)
  1174  
  1175  		action.Continue(nil)
  1176  
  1177  		select {
  1178  		case <-done:
  1179  			return
  1180  		case <-time.After(time.Second * 10):
  1181  			t.Error("timeout")
  1182  		}
  1183  	})
  1184  
  1185  	t.Run("Receive Presentation (continue) v3", func(t *testing.T) {
  1186  		store, messenger, provider := initMocks(ctrl)
  1187  
  1188  		done := make(chan struct{})
  1189  
  1190  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
  1191  			Do(func(_, msg service.DIDCommMsgMap, _, _ string, opts ...service.Opt) error {
  1192  				r := &model.AckV2{}
  1193  				require.NoError(t, msg.Decode(r))
  1194  				require.Equal(t, AckMsgTypeV3, r.Type)
  1195  
  1196  				return nil
  1197  			})
  1198  
  1199  		src, err := json.Marshal(&internalData{AckRequired: true, StateName: "request-sent"})
  1200  		require.NoError(t, err)
  1201  
  1202  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1203  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1204  		store.EXPECT().Delete(gomock.Any()).Return(nil)
  1205  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1206  			src, err = json.Marshal(&internalData{AckRequired: true, StateName: "presentation-received"})
  1207  			require.NoError(t, err)
  1208  			require.Equal(t, src, data)
  1209  
  1210  			return nil
  1211  		})
  1212  
  1213  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1214  			defer close(done)
  1215  
  1216  			src, err = json.Marshal(&internalData{AckRequired: true, StateName: "done"})
  1217  			require.NoError(t, err)
  1218  			require.Equal(t, src, data)
  1219  
  1220  			return nil
  1221  		})
  1222  
  1223  		svc, err := New(provider)
  1224  		require.NoError(t, err)
  1225  
  1226  		ch := make(chan service.DIDCommAction, 1)
  1227  		require.NoError(t, svc.RegisterActionEvent(ch))
  1228  
  1229  		msg := service.NewDIDCommMsgMap(PresentationV3{
  1230  			Type: PresentationMsgTypeV3,
  1231  			Attachments: []decorator.AttachmentV2{{
  1232  				Data: decorator.AttachmentData{
  1233  					Base64: base64.StdEncoding.EncodeToString([]byte(`{}`)),
  1234  				},
  1235  			}},
  1236  		})
  1237  		msg.SetID(uuid.New().String())
  1238  		msg.SetThread(uuid.New().String(), "", service.WithVersion(service.V2))
  1239  
  1240  		_, err = svc.HandleInbound(msg, service.NewDIDCommContext(Alice, Bob, nil))
  1241  		require.NoError(t, err)
  1242  
  1243  		action := <-ch
  1244  
  1245  		properties, ok := action.Properties.(*eventProps)
  1246  		require.True(t, ok)
  1247  		require.NotEmpty(t, properties.PIID())
  1248  		require.Equal(t, properties.MyDID(), Alice)
  1249  		require.Equal(t, properties.TheirDID(), Bob)
  1250  
  1251  		action.Continue(nil)
  1252  
  1253  		select {
  1254  		case <-done:
  1255  			return
  1256  		case <-time.After(time.Second * 10):
  1257  			t.Error("timeout")
  1258  		}
  1259  	})
  1260  
  1261  	t.Run("Receive Ack", func(t *testing.T) {
  1262  		store, _, provider := initMocks(ctrl)
  1263  
  1264  		done := make(chan struct{})
  1265  
  1266  		src, err := json.Marshal(&internalData{StateName: "presentation-sent"})
  1267  		require.NoError(t, err)
  1268  
  1269  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1270  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1271  			defer close(done)
  1272  
  1273  			src, err = json.Marshal(&internalData{StateName: "done"})
  1274  			require.NoError(t, err)
  1275  			require.Equal(t, src, data)
  1276  
  1277  			return nil
  1278  		})
  1279  
  1280  		svc, err := New(provider)
  1281  		require.NoError(t, err)
  1282  
  1283  		ch := make(chan service.DIDCommAction, 1)
  1284  		require.NoError(t, svc.RegisterActionEvent(ch))
  1285  
  1286  		_, err = svc.HandleInbound(randomInboundMessage(AckMsgTypeV2), service.NewDIDCommContext(Alice, Bob, nil))
  1287  		require.NoError(t, err)
  1288  
  1289  		select {
  1290  		case <-done:
  1291  			return
  1292  		case <-time.After(time.Second):
  1293  			t.Error("timeout")
  1294  		}
  1295  	})
  1296  
  1297  	t.Run("Send Invitation Presentation", func(t *testing.T) {
  1298  		store, messenger, provider := initMocks(ctrl)
  1299  
  1300  		done := make(chan struct{})
  1301  
  1302  		src, err := json.Marshal(&internalData{StateName: "proposal-received"})
  1303  		require.NoError(t, err)
  1304  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1305  
  1306  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1307  			src, e := json.Marshal(&internalData{StateName: "request-sent"})
  1308  			require.NoError(t, e)
  1309  			require.Equal(t, src, data)
  1310  
  1311  			return nil
  1312  		})
  1313  
  1314  		svc, err := New(provider)
  1315  		require.NoError(t, err)
  1316  
  1317  		msg := service.NewDIDCommMsgMap(RequestPresentationV2{
  1318  			Type: RequestPresentationMsgTypeV2,
  1319  		})
  1320  
  1321  		messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()).
  1322  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  1323  				require.NotEmpty(t, msg.ID())
  1324  				require.Equal(t, RequestPresentationMsgTypeV2, msg.Type())
  1325  
  1326  				defer close(done)
  1327  
  1328  				return nil
  1329  			})
  1330  
  1331  		_, err = svc.HandleOutbound(msg, Alice, Bob)
  1332  		require.NoError(t, err)
  1333  
  1334  		select {
  1335  		case <-done:
  1336  			return
  1337  		case <-time.After(time.Second):
  1338  			t.Error("timeout")
  1339  		}
  1340  	})
  1341  
  1342  	t.Run("Send Invitation Presentation with error", func(t *testing.T) {
  1343  		store, messenger, provider := initMocks(ctrl)
  1344  
  1345  		src, err := json.Marshal(&internalData{StateName: "proposal-received"})
  1346  		require.NoError(t, err)
  1347  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1348  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
  1349  
  1350  		svc, err := New(provider)
  1351  		require.NoError(t, err)
  1352  
  1353  		msg := service.NewDIDCommMsgMap(RequestPresentationV2{
  1354  			Type: RequestPresentationMsgTypeV2,
  1355  		})
  1356  
  1357  		messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  1358  
  1359  		_, err = svc.HandleOutbound(msg, Alice, Bob)
  1360  		require.Contains(t, fmt.Sprintf("%v", err), "action request-sent: "+errMsg)
  1361  	})
  1362  
  1363  	t.Run("Send Proposal", func(t *testing.T) {
  1364  		store, messenger, provider := initMocks(ctrl)
  1365  
  1366  		done := make(chan struct{})
  1367  
  1368  		src, err := json.Marshal(&internalData{StateName: "request-received"})
  1369  		require.NoError(t, err)
  1370  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1371  		store.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ string, data []byte) error {
  1372  			s, e := json.Marshal(&internalData{StateName: "proposal-sent"})
  1373  			require.NoError(t, e)
  1374  			require.Equal(t, s, data)
  1375  
  1376  			return nil
  1377  		})
  1378  
  1379  		svc, err := New(provider)
  1380  		require.NoError(t, err)
  1381  
  1382  		msg := service.NewDIDCommMsgMap(ProposePresentationV2{
  1383  			Type: ProposePresentationMsgTypeV2,
  1384  		})
  1385  
  1386  		messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()).
  1387  			Do(func(msg service.DIDCommMsgMap, myDID, theirDID string, opts ...service.Opt) error {
  1388  				defer close(done)
  1389  
  1390  				require.NotEmpty(t, msg.ID())
  1391  				require.Equal(t, ProposePresentationMsgTypeV2, msg.Type())
  1392  
  1393  				return nil
  1394  			})
  1395  
  1396  		_, err = svc.HandleOutbound(msg, Alice, Bob)
  1397  		require.NoError(t, err)
  1398  
  1399  		select {
  1400  		case <-done:
  1401  			return
  1402  		case <-time.After(time.Second):
  1403  			t.Error("timeout")
  1404  		}
  1405  	})
  1406  
  1407  	t.Run("Send Proposal with error", func(t *testing.T) {
  1408  		store, messenger, provider := initMocks(ctrl)
  1409  
  1410  		src, err := json.Marshal(&internalData{StateName: "request-received"})
  1411  		require.NoError(t, err)
  1412  		store.EXPECT().Get(gomock.Any()).Return(src, nil).AnyTimes()
  1413  		store.EXPECT().Put(gomock.Any(), gomock.Any()).Return(nil)
  1414  
  1415  		svc, err := New(provider)
  1416  		require.NoError(t, err)
  1417  
  1418  		msg := service.NewDIDCommMsgMap(ProposePresentationV2{
  1419  			Type: ProposePresentationMsgTypeV2,
  1420  		})
  1421  
  1422  		messenger.EXPECT().Send(gomock.Any(), Alice, Bob, gomock.Any()).Return(errors.New(errMsg))
  1423  
  1424  		_, err = svc.HandleOutbound(msg, Alice, Bob)
  1425  		require.Contains(t, fmt.Sprintf("%v", err), "action proposal-sent: "+errMsg)
  1426  	})
  1427  }
  1428  
  1429  func Test_stateFromName(t *testing.T) {
  1430  	require.Equal(t, stateFromName(stateNameStart, SpecV2), &start{})
  1431  	require.Equal(t, stateFromName(StateNameAbandoned, SpecV2), &abandoned{V: SpecV2})
  1432  	require.Equal(t, stateFromName(StateNameDone, SpecV2), &done{V: SpecV2})
  1433  	require.Equal(t, stateFromName(stateNameRequestSent, SpecV2), &requestSent{V: SpecV2})
  1434  	require.Equal(t, stateFromName(stateNamePresentationReceived, SpecV2), &presentationReceived{V: SpecV2})
  1435  	require.Equal(t, stateFromName(stateNameProposalReceived, SpecV2), &proposalReceived{V: SpecV2})
  1436  	require.Equal(t, stateFromName(stateNameRequestReceived, SpecV2), &requestReceived{V: SpecV2})
  1437  	require.Equal(t, stateFromName(stateNamePresentationSent, SpecV2), &presentationSent{V: SpecV2})
  1438  	require.Equal(t, stateFromName(stateNameProposalSent, SpecV2), &proposalSent{V: SpecV2})
  1439  	require.Equal(t, stateFromName("unknown", SpecV2), &noOp{})
  1440  }
  1441  
  1442  func TestService_Name(t *testing.T) {
  1443  	require.Equal(t, (*Service).Name(nil), Name)
  1444  }
  1445  
  1446  func TestService_Accept(t *testing.T) {
  1447  	require.True(t, (*Service).Accept(nil, ProposePresentationMsgTypeV2))
  1448  	require.True(t, (*Service).Accept(nil, RequestPresentationMsgTypeV2))
  1449  	require.True(t, (*Service).Accept(nil, PresentationMsgTypeV2))
  1450  	require.True(t, (*Service).Accept(nil, AckMsgTypeV2))
  1451  	require.True(t, (*Service).Accept(nil, ProblemReportMsgTypeV2))
  1452  	require.False(t, (*Service).Accept(nil, "unknown"))
  1453  }
  1454  
  1455  func TestService_canTriggerActionEvents(t *testing.T) {
  1456  	require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(ProposePresentationV2{
  1457  		Type: ProposePresentationMsgTypeV2,
  1458  	})))
  1459  
  1460  	require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(RequestPresentationV2{
  1461  		Type: RequestPresentationMsgTypeV2,
  1462  	})))
  1463  
  1464  	require.True(t, canTriggerActionEvents(service.NewDIDCommMsgMap(PresentationV2{
  1465  		Type: PresentationMsgTypeV2,
  1466  	})))
  1467  
  1468  	require.False(t, canTriggerActionEvents(service.NewDIDCommMsgMap(struct{}{})))
  1469  }
  1470  
  1471  func Test_getTransitionalPayload(t *testing.T) {
  1472  	ctrl := gomock.NewController(t)
  1473  	defer ctrl.Finish()
  1474  
  1475  	store := storageMocks.NewMockStore(ctrl)
  1476  
  1477  	storeProvider := storageMocks.NewMockProvider(ctrl)
  1478  	storeProvider.EXPECT().OpenStore(Name).Return(store, nil).AnyTimes()
  1479  	storeProvider.EXPECT().SetStoreConfig(Name, gomock.Any()).Return(nil)
  1480  
  1481  	provider := presentproofMocks.NewMockProvider(ctrl)
  1482  	provider.EXPECT().Messenger().Return(nil).AnyTimes()
  1483  	provider.EXPECT().StorageProvider().Return(storeProvider).AnyTimes()
  1484  
  1485  	store.EXPECT().Get(fmt.Sprintf(transitionalPayloadKey, "ID")).Return([]byte(`[]`), nil)
  1486  
  1487  	svc, err := New(provider)
  1488  	require.NoError(t, err)
  1489  
  1490  	res, err := svc.getTransitionalPayload("ID")
  1491  	require.Nil(t, res)
  1492  	require.Contains(t, fmt.Sprintf("%v", err), "unmarshal transitional payload")
  1493  }
  1494  
  1495  func Test_nextState(t *testing.T) {
  1496  	next, err := nextState(service.NewDIDCommMsgMap(RequestPresentationV2{
  1497  		Type: RequestPresentationMsgTypeV2,
  1498  	}), outboundMessage)
  1499  	require.NoError(t, err)
  1500  	require.Equal(t, next, &requestSent{V: SpecV2})
  1501  
  1502  	next, err = nextState(randomInboundMessage(RequestPresentationMsgTypeV2), inboundMessage)
  1503  	require.NoError(t, err)
  1504  	require.Equal(t, next, &requestReceived{V: SpecV2})
  1505  
  1506  	next, err = nextState(service.NewDIDCommMsgMap(ProposePresentationV2{
  1507  		Type: ProposePresentationMsgTypeV2,
  1508  	}), outboundMessage)
  1509  	require.NoError(t, err)
  1510  	require.Equal(t, next, &proposalSent{V: SpecV2})
  1511  
  1512  	next, err = nextState(randomInboundMessage(ProposePresentationMsgTypeV2), inboundMessage)
  1513  	require.NoError(t, err)
  1514  	require.Equal(t, next, &proposalReceived{V: SpecV2})
  1515  
  1516  	next, err = nextState(randomInboundMessage(PresentationMsgTypeV2), inboundMessage)
  1517  	require.NoError(t, err)
  1518  	require.Equal(t, next, &presentationReceived{V: SpecV2})
  1519  
  1520  	next, err = nextState(randomInboundMessage(AckMsgTypeV2), inboundMessage)
  1521  	require.NoError(t, err)
  1522  	require.Equal(t, next, &done{V: SpecV2, properties: map[string]interface{}{}})
  1523  
  1524  	next, err = nextState(randomInboundMessage(ProblemReportMsgTypeV2), inboundMessage)
  1525  	require.NoError(t, err)
  1526  	require.Equal(t, next, &abandoned{V: SpecV2, properties: map[string]interface{}{}})
  1527  
  1528  	next, err = nextState(service.NewDIDCommMsgMap(struct{}{}), outboundMessage)
  1529  	require.Error(t, err)
  1530  	require.Nil(t, next)
  1531  }