github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/presentproof/states_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  	"errors"
    11  	"fmt"
    12  	"testing"
    13  
    14  	"github.com/golang/mock/gomock"
    15  	"github.com/google/uuid"
    16  	"github.com/stretchr/testify/require"
    17  
    18  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model"
    19  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
    20  	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator"
    21  	serviceMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/common/service"
    22  )
    23  
    24  func TestStart_CanTransitionTo(t *testing.T) {
    25  	st := &start{}
    26  	require.Equal(t, stateNameStart, st.Name())
    27  	// common states
    28  	require.False(t, st.CanTransitionTo(&start{}))
    29  	require.False(t, st.CanTransitionTo(&abandoned{}))
    30  	require.False(t, st.CanTransitionTo(&done{}))
    31  	require.False(t, st.CanTransitionTo(&noOp{}))
    32  	// states for Verifier
    33  	require.True(t, st.CanTransitionTo(&requestSent{}))
    34  	require.False(t, st.CanTransitionTo(&presentationReceived{}))
    35  	require.True(t, st.CanTransitionTo(&proposalReceived{}))
    36  	// states for Prover
    37  	require.True(t, st.CanTransitionTo(&requestReceived{}))
    38  	require.False(t, st.CanTransitionTo(&presentationSent{}))
    39  	require.True(t, st.CanTransitionTo(&proposalSent{}))
    40  }
    41  
    42  func TestStart_Execute(t *testing.T) {
    43  	followup, action, err := (&start{}).Execute(&metaData{})
    44  	require.Contains(t, fmt.Sprintf("%v", err), "is not implemented yet")
    45  	require.Nil(t, followup)
    46  	require.Nil(t, action)
    47  }
    48  
    49  func TestAbandoning_CanTransitionTo(t *testing.T) {
    50  	st := &abandoned{}
    51  	require.Equal(t, StateNameAbandoned, st.Name())
    52  	// common states
    53  	require.False(t, st.CanTransitionTo(&start{}))
    54  	require.False(t, st.CanTransitionTo(&abandoned{}))
    55  	require.False(t, st.CanTransitionTo(&done{}))
    56  	require.False(t, st.CanTransitionTo(&noOp{}))
    57  	// states for Verifier
    58  	require.False(t, st.CanTransitionTo(&requestSent{}))
    59  	require.False(t, st.CanTransitionTo(&presentationReceived{}))
    60  	require.False(t, st.CanTransitionTo(&proposalReceived{}))
    61  	// states for Prover
    62  	require.False(t, st.CanTransitionTo(&requestReceived{}))
    63  	require.False(t, st.CanTransitionTo(&presentationSent{}))
    64  	require.False(t, st.CanTransitionTo(&proposalSent{}))
    65  }
    66  
    67  func TestAbandoning_Execute(t *testing.T) {
    68  	t.Run("Internal Error", func(t *testing.T) {
    69  		md := &metaData{}
    70  		md.Msg = service.NewDIDCommMsgMap(struct{}{})
    71  		md.Msg.SetID(uuid.New().String())
    72  
    73  		followup, action, err := (&abandoned{V: SpecV2, Code: codeInternalError}).Execute(md)
    74  		require.NoError(t, err)
    75  		require.Equal(t, &noOp{}, followup)
    76  		require.NotNil(t, action)
    77  
    78  		ctrl := gomock.NewController(t)
    79  		defer ctrl.Finish()
    80  
    81  		messenger := serviceMocks.NewMockMessenger(ctrl)
    82  		messenger.EXPECT().
    83  			ReplyToNested(gomock.Any(), gomock.Any()).
    84  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
    85  				r := &model.ProblemReport{}
    86  				require.NoError(t, msg.Decode(r))
    87  				require.Equal(t, codeInternalError, r.Description.Code)
    88  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
    89  
    90  				return nil
    91  			})
    92  
    93  		require.NoError(t, action(messenger))
    94  	})
    95  
    96  	t.Run("Internal Error (v3)", func(t *testing.T) {
    97  		md := &metaData{}
    98  		md.Msg = service.NewDIDCommMsgMap(struct{}{})
    99  		md.Msg.SetID(uuid.New().String())
   100  
   101  		followup, action, err := (&abandoned{V: SpecV3, Code: codeInternalError}).Execute(md)
   102  		require.NoError(t, err)
   103  		require.Equal(t, &noOp{}, followup)
   104  		require.NotNil(t, action)
   105  
   106  		ctrl := gomock.NewController(t)
   107  		defer ctrl.Finish()
   108  
   109  		messenger := serviceMocks.NewMockMessenger(ctrl)
   110  		messenger.EXPECT().
   111  			ReplyToNested(gomock.Any(), gomock.Any()).
   112  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   113  				r := &model.ProblemReportV2{}
   114  				require.NoError(t, msg.Decode(r))
   115  				require.Equal(t, codeInternalError, r.Body.Code)
   116  				require.Equal(t, ProblemReportMsgTypeV3, r.Type)
   117  
   118  				return nil
   119  			})
   120  
   121  		require.NoError(t, action(messenger))
   122  	})
   123  
   124  	t.Run("Invalid message", func(t *testing.T) {
   125  		followup, action, err := (&abandoned{Code: codeInternalError}).Execute(&metaData{})
   126  		require.EqualError(t, errors.Unwrap(err), service.ErrInvalidMessage.Error())
   127  		require.Nil(t, followup)
   128  		require.Nil(t, action)
   129  	})
   130  
   131  	t.Run("Custom Error", func(t *testing.T) {
   132  		md := &metaData{err: customError{error: errors.New("error")}}
   133  		md.Msg = service.NewDIDCommMsgMap(struct{}{})
   134  		md.Msg.SetID(uuid.New().String())
   135  
   136  		followup, action, err := (&abandoned{V: SpecV2, Code: codeInternalError}).Execute(md)
   137  		require.NoError(t, err)
   138  		require.Equal(t, &noOp{}, followup)
   139  		require.NotNil(t, action)
   140  
   141  		ctrl := gomock.NewController(t)
   142  		defer ctrl.Finish()
   143  
   144  		messenger := serviceMocks.NewMockMessenger(ctrl)
   145  		messenger.EXPECT().
   146  			ReplyToNested(gomock.Any(), gomock.Any()).
   147  			Do(func(msg service.DIDCommMsgMap, opts *service.NestedReplyOpts) error {
   148  				r := &model.ProblemReport{}
   149  				require.NoError(t, msg.Decode(r))
   150  				require.Equal(t, codeRejectedError, r.Description.Code)
   151  				require.Equal(t, ProblemReportMsgTypeV2, r.Type)
   152  
   153  				return nil
   154  			})
   155  
   156  		require.NoError(t, action(messenger))
   157  	})
   158  
   159  	t.Run("No error code", func(t *testing.T) {
   160  		md := &metaData{}
   161  		md.Msg = service.NewDIDCommMsgMap(struct{}{})
   162  		md.Msg.SetID(uuid.New().String())
   163  
   164  		followup, action, err := (&abandoned{}).Execute(md)
   165  		require.NoError(t, err)
   166  		require.Equal(t, &noOp{}, followup)
   167  		require.NotNil(t, action)
   168  
   169  		require.NoError(t, action(nil))
   170  	})
   171  }
   172  
   173  func TestDone_CanTransitionTo(t *testing.T) {
   174  	st := &done{}
   175  	require.Equal(t, StateNameDone, st.Name())
   176  	notTransition(t, st)
   177  }
   178  
   179  func TestDone_Execute(t *testing.T) {
   180  	followup, action, err := (&done{}).Execute(&metaData{})
   181  	require.NoError(t, err)
   182  	require.Equal(t, &noOp{}, followup)
   183  	require.NoError(t, action(nil))
   184  }
   185  
   186  func TestNoOp_CanTransitionTo(t *testing.T) {
   187  	st := &noOp{}
   188  	require.Equal(t, stateNameNoop, st.Name())
   189  	notTransition(t, st)
   190  }
   191  
   192  func TestNoOp_Execute(t *testing.T) {
   193  	followup, action, err := (&noOp{}).Execute(&metaData{})
   194  	require.Contains(t, fmt.Sprintf("%v", err), "cannot execute no-op")
   195  	require.Nil(t, followup)
   196  	require.Nil(t, action)
   197  }
   198  
   199  func TestRequestReceived_CanTransitionTo(t *testing.T) {
   200  	st := &requestReceived{}
   201  	require.Equal(t, stateNameRequestReceived, st.Name())
   202  	// common states
   203  	require.False(t, st.CanTransitionTo(&start{}))
   204  	require.True(t, st.CanTransitionTo(&abandoned{}))
   205  	require.False(t, st.CanTransitionTo(&done{}))
   206  	require.False(t, st.CanTransitionTo(&noOp{}))
   207  	// states for Verifier
   208  	require.False(t, st.CanTransitionTo(&requestSent{}))
   209  	require.False(t, st.CanTransitionTo(&presentationReceived{}))
   210  	require.False(t, st.CanTransitionTo(&proposalReceived{}))
   211  	// states for Prover
   212  	require.False(t, st.CanTransitionTo(&requestReceived{}))
   213  	require.True(t, st.CanTransitionTo(&presentationSent{}))
   214  	require.True(t, st.CanTransitionTo(&proposalSent{}))
   215  }
   216  
   217  func TestRequestReceived_Execute(t *testing.T) {
   218  	t.Run("With presentation", func(t *testing.T) {
   219  		msg := randomInboundMessage(RequestPresentationMsgTypeV2)
   220  		msg["will_confirm"] = true
   221  
   222  		followup, action, err := (&requestReceived{V: SpecV2}).Execute(&metaData{
   223  			presentation:        &PresentationV2{},
   224  			transitionalPayload: transitionalPayload{Action: Action{Msg: msg}},
   225  		})
   226  		require.NoError(t, err)
   227  		require.Equal(t, &presentationSent{V: SpecV2, WillConfirm: true}, followup)
   228  		require.NoError(t, action(nil))
   229  	})
   230  
   231  	t.Run("With presentation - Ack is not required", func(t *testing.T) {
   232  		followup, action, err := (&requestReceived{}).Execute(&metaData{
   233  			presentation: &PresentationV2{},
   234  			transitionalPayload: transitionalPayload{Action: Action{
   235  				Msg: randomInboundMessage(RequestPresentationMsgTypeV2),
   236  			}},
   237  		})
   238  		require.NoError(t, err)
   239  		require.Equal(t, &presentationSent{}, followup)
   240  		require.NoError(t, action(nil))
   241  	})
   242  
   243  	t.Run("Without presentation", func(t *testing.T) {
   244  		followup, action, err := (&requestReceived{}).Execute(&metaData{})
   245  		require.NoError(t, err)
   246  		require.Equal(t, &proposalSent{}, followup)
   247  		require.NoError(t, action(nil))
   248  	})
   249  
   250  	t.Run("Message decode error", func(t *testing.T) {
   251  		followup, action, err := (&requestReceived{V: SpecV2}).Execute(&metaData{
   252  			presentation: &PresentationV2{},
   253  			transitionalPayload: transitionalPayload{Action: Action{
   254  				Msg: service.DIDCommMsgMap{"@type": []int{1}},
   255  			}},
   256  		})
   257  		require.Error(t, err)
   258  		require.Nil(t, followup)
   259  		require.Nil(t, action)
   260  	})
   261  }
   262  
   263  func TestRequestSent_CanTransitionTo(t *testing.T) {
   264  	st := &requestSent{}
   265  	require.Equal(t, stateNameRequestSent, st.Name())
   266  	// common states
   267  	require.False(t, st.CanTransitionTo(&start{}))
   268  	require.True(t, st.CanTransitionTo(&abandoned{}))
   269  	require.False(t, st.CanTransitionTo(&done{}))
   270  	require.False(t, st.CanTransitionTo(&noOp{}))
   271  	// states for Verifier
   272  	require.False(t, st.CanTransitionTo(&requestSent{}))
   273  	require.True(t, st.CanTransitionTo(&presentationReceived{}))
   274  	require.True(t, st.CanTransitionTo(&proposalReceived{}))
   275  	// states for Prover
   276  	require.False(t, st.CanTransitionTo(&requestReceived{}))
   277  	require.False(t, st.CanTransitionTo(&presentationSent{}))
   278  	require.False(t, st.CanTransitionTo(&proposalSent{}))
   279  }
   280  
   281  func randomInboundMessage(t string) service.DIDCommMsgMap {
   282  	return service.NewDIDCommMsgMap(struct {
   283  		ID     string           `json:"@id"`
   284  		Thread decorator.Thread `json:"~thread"`
   285  		Type   string           `json:"@type"`
   286  	}{
   287  		ID:     uuid.New().String(),
   288  		Thread: decorator.Thread{ID: uuid.New().String()},
   289  		Type:   t,
   290  	})
   291  }
   292  
   293  func randomInboundMessageV3(t string) service.DIDCommMsgMap {
   294  	return service.DIDCommMsgMap{
   295  		"id":   uuid.New().String(),
   296  		"type": t,
   297  		"thid": uuid.New().String(),
   298  	}
   299  }
   300  
   301  func TestRequestSent_Execute(t *testing.T) {
   302  	t.Run("Success", func(t *testing.T) {
   303  		followup, action, err := (&requestSent{V: SpecV2}).Execute(&metaData{
   304  			transitionalPayload: transitionalPayload{Action: Action{Msg: randomInboundMessage("")}},
   305  			request:             &RequestPresentationV2{},
   306  		})
   307  		require.NoError(t, err)
   308  		require.Equal(t, &noOp{}, followup)
   309  		require.NotNil(t, action)
   310  
   311  		ctrl := gomock.NewController(t)
   312  		defer ctrl.Finish()
   313  
   314  		messenger := serviceMocks.NewMockMessenger(ctrl)
   315  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
   316  
   317  		require.NoError(t, action(messenger))
   318  	})
   319  
   320  	t.Run("Invitation presentation is absent", func(t *testing.T) {
   321  		followup, action, err := (&requestSent{}).Execute(&metaData{
   322  			transitionalPayload: transitionalPayload{Action: Action{Msg: randomInboundMessage("")}},
   323  		})
   324  		require.EqualError(t, err, "request was not provided")
   325  		require.Nil(t, followup)
   326  		require.Nil(t, action)
   327  	})
   328  
   329  	t.Run("Success (outbound)", func(t *testing.T) {
   330  		followup, action, err := (&requestSent{}).Execute(&metaData{transitionalPayload: transitionalPayload{
   331  			Action: Action{Msg: service.NewDIDCommMsgMap(struct {
   332  				WillConfirm bool `json:"will_confirm"`
   333  			}{WillConfirm: true})},
   334  			Direction: outboundMessage,
   335  		}})
   336  		require.NoError(t, err)
   337  		require.Equal(t, &noOp{}, followup)
   338  		require.NotNil(t, action)
   339  
   340  		ctrl := gomock.NewController(t)
   341  		defer ctrl.Finish()
   342  
   343  		messenger := serviceMocks.NewMockMessenger(ctrl)
   344  		messenger.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
   345  
   346  		require.NoError(t, action(messenger))
   347  	})
   348  
   349  	t.Run("Message decode error", func(t *testing.T) {
   350  		followup, action, err := (&requestSent{V: SpecV2}).Execute(&metaData{transitionalPayload: transitionalPayload{
   351  			Action: Action{Msg: service.DIDCommMsgMap{"@type": []int{1}}},
   352  		}})
   353  		require.Error(t, err)
   354  		require.Nil(t, followup)
   355  		require.Nil(t, action)
   356  	})
   357  }
   358  
   359  func TestPresentationSent_CanTransitionTo(t *testing.T) {
   360  	st := &presentationSent{}
   361  	require.Equal(t, stateNamePresentationSent, st.Name())
   362  	// common states
   363  	require.False(t, st.CanTransitionTo(&start{}))
   364  	require.True(t, st.CanTransitionTo(&abandoned{}))
   365  	require.True(t, st.CanTransitionTo(&done{}))
   366  	require.False(t, st.CanTransitionTo(&noOp{}))
   367  	// states for Verifier
   368  	require.False(t, st.CanTransitionTo(&requestSent{}))
   369  	require.False(t, st.CanTransitionTo(&presentationReceived{}))
   370  	require.False(t, st.CanTransitionTo(&proposalReceived{}))
   371  	// states for Prover
   372  	require.False(t, st.CanTransitionTo(&requestReceived{}))
   373  	require.False(t, st.CanTransitionTo(&presentationSent{}))
   374  	require.False(t, st.CanTransitionTo(&proposalSent{}))
   375  }
   376  
   377  func TestPresentationSent_Execute(t *testing.T) {
   378  	t.Run("Success", func(t *testing.T) {
   379  		followup, action, err := (&presentationSent{}).
   380  			Execute(&metaData{presentation: &PresentationV2{}})
   381  		require.NoError(t, err)
   382  		require.Equal(t, &done{}, followup)
   383  		require.NotNil(t, action)
   384  
   385  		ctrl := gomock.NewController(t)
   386  		defer ctrl.Finish()
   387  
   388  		messenger := serviceMocks.NewMockMessenger(ctrl)
   389  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
   390  
   391  		require.NoError(t, action(messenger))
   392  	})
   393  
   394  	t.Run("Success (WillConfirm)", func(t *testing.T) {
   395  		followup, action, err := (&presentationSent{WillConfirm: true}).
   396  			Execute(&metaData{presentation: &PresentationV2{}})
   397  		require.NoError(t, err)
   398  		require.Equal(t, &noOp{}, followup)
   399  		require.NotNil(t, action)
   400  
   401  		ctrl := gomock.NewController(t)
   402  		defer ctrl.Finish()
   403  
   404  		messenger := serviceMocks.NewMockMessenger(ctrl)
   405  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
   406  
   407  		require.NoError(t, action(messenger))
   408  	})
   409  
   410  	t.Run("Presentation is absent", func(t *testing.T) {
   411  		followup, action, err := (&presentationSent{}).Execute(&metaData{})
   412  		require.EqualError(t, err, "presentation was not provided")
   413  		require.Nil(t, followup)
   414  		require.Nil(t, action)
   415  	})
   416  }
   417  
   418  func TestPresentationReceived_CanTransitionTo(t *testing.T) {
   419  	st := &presentationReceived{}
   420  	require.Equal(t, stateNamePresentationReceived, st.Name())
   421  	// common states
   422  	require.False(t, st.CanTransitionTo(&start{}))
   423  	require.True(t, st.CanTransitionTo(&abandoned{}))
   424  	require.True(t, st.CanTransitionTo(&done{}))
   425  	require.False(t, st.CanTransitionTo(&noOp{}))
   426  	// states for Verifier
   427  	require.False(t, st.CanTransitionTo(&requestSent{}))
   428  	require.False(t, st.CanTransitionTo(&presentationReceived{}))
   429  	require.False(t, st.CanTransitionTo(&proposalReceived{}))
   430  	// states for Prover
   431  	require.False(t, st.CanTransitionTo(&requestReceived{}))
   432  	require.False(t, st.CanTransitionTo(&presentationSent{}))
   433  	require.False(t, st.CanTransitionTo(&proposalSent{}))
   434  }
   435  
   436  func TestPresentationReceived_Execute(t *testing.T) {
   437  	t.Run("Success", func(t *testing.T) {
   438  		followup, action, err := (&presentationReceived{}).Execute(&metaData{
   439  			transitionalPayload: transitionalPayload{AckRequired: true},
   440  			presentation:        &PresentationV2{},
   441  		})
   442  		require.NoError(t, err)
   443  		require.Equal(t, &done{}, followup)
   444  		require.NotNil(t, action)
   445  
   446  		ctrl := gomock.NewController(t)
   447  		defer ctrl.Finish()
   448  
   449  		messenger := serviceMocks.NewMockMessenger(ctrl)
   450  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
   451  
   452  		require.NoError(t, action(messenger))
   453  	})
   454  
   455  	t.Run("Ack is not required", func(t *testing.T) {
   456  		followup, action, err := (&presentationReceived{}).Execute(&metaData{
   457  			request:      &RequestPresentationV2{WillConfirm: true},
   458  			presentation: &PresentationV2{},
   459  		})
   460  		require.NoError(t, err)
   461  		require.Equal(t, &done{}, followup)
   462  		require.NotNil(t, action)
   463  		require.NoError(t, action(nil))
   464  	})
   465  }
   466  
   467  func TestProposePresentationSent_CanTransitionTo(t *testing.T) {
   468  	st := &proposalSent{}
   469  	require.Equal(t, stateNameProposalSent, st.Name())
   470  	// common states
   471  	require.False(t, st.CanTransitionTo(&start{}))
   472  	require.True(t, st.CanTransitionTo(&abandoned{}))
   473  	require.False(t, st.CanTransitionTo(&done{}))
   474  	require.False(t, st.CanTransitionTo(&noOp{}))
   475  	// states for Verifier
   476  	require.False(t, st.CanTransitionTo(&requestSent{}))
   477  	require.False(t, st.CanTransitionTo(&presentationReceived{}))
   478  	require.False(t, st.CanTransitionTo(&proposalReceived{}))
   479  	// states for Prover
   480  	require.True(t, st.CanTransitionTo(&requestReceived{}))
   481  	require.False(t, st.CanTransitionTo(&presentationSent{}))
   482  	require.False(t, st.CanTransitionTo(&proposalSent{}))
   483  }
   484  
   485  func TestProposePresentationSent_Execute(t *testing.T) {
   486  	t.Run("Success", func(t *testing.T) {
   487  		followup, action, err := (&proposalSent{}).Execute(&metaData{
   488  			transitionalPayload: transitionalPayload{Action: Action{Msg: randomInboundMessage("")}},
   489  			proposePresentation: &ProposePresentationV2{},
   490  		})
   491  		require.NoError(t, err)
   492  		require.Equal(t, &noOp{}, followup)
   493  		require.NotNil(t, action)
   494  
   495  		ctrl := gomock.NewController(t)
   496  		defer ctrl.Finish()
   497  
   498  		messenger := serviceMocks.NewMockMessenger(ctrl)
   499  		messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
   500  
   501  		require.NoError(t, action(messenger))
   502  	})
   503  
   504  	t.Run("Propose presentation is absent", func(t *testing.T) {
   505  		followup, action, err := (&proposalSent{}).Execute(&metaData{
   506  			transitionalPayload: transitionalPayload{Action: Action{Msg: randomInboundMessage("")}},
   507  		})
   508  		require.EqualError(t, err, "propose-presentation was not provided")
   509  		require.Nil(t, followup)
   510  		require.Nil(t, action)
   511  	})
   512  
   513  	t.Run("Success (outbound)", func(t *testing.T) {
   514  		followup, action, err := (&proposalSent{}).Execute(&metaData{
   515  			transitionalPayload: transitionalPayload{Direction: outboundMessage},
   516  		})
   517  		require.NoError(t, err)
   518  		require.Equal(t, &noOp{}, followup)
   519  		require.NotNil(t, action)
   520  
   521  		ctrl := gomock.NewController(t)
   522  		defer ctrl.Finish()
   523  
   524  		messenger := serviceMocks.NewMockMessenger(ctrl)
   525  		messenger.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
   526  
   527  		require.NoError(t, action(messenger))
   528  	})
   529  }
   530  
   531  func TestProposePresentationReceived_CanTransitionTo(t *testing.T) {
   532  	st := &proposalReceived{}
   533  	require.Equal(t, stateNameProposalReceived, st.Name())
   534  	// common states
   535  	require.False(t, st.CanTransitionTo(&start{}))
   536  	require.True(t, st.CanTransitionTo(&abandoned{}))
   537  	require.False(t, st.CanTransitionTo(&done{}))
   538  	require.False(t, st.CanTransitionTo(&noOp{}))
   539  	// states for Verifier
   540  	require.True(t, st.CanTransitionTo(&requestSent{}))
   541  	require.False(t, st.CanTransitionTo(&presentationReceived{}))
   542  	require.False(t, st.CanTransitionTo(&proposalReceived{}))
   543  	// states for Prover
   544  	require.False(t, st.CanTransitionTo(&requestReceived{}))
   545  	require.False(t, st.CanTransitionTo(&presentationSent{}))
   546  	require.False(t, st.CanTransitionTo(&proposalSent{}))
   547  }
   548  
   549  func TestProposePresentationReceived_Execute(t *testing.T) {
   550  	followup, action, err := (&proposalReceived{}).Execute(&metaData{})
   551  	require.NoError(t, err)
   552  	require.Equal(t, &requestSent{}, followup)
   553  	require.NoError(t, action(nil))
   554  }
   555  
   556  func notTransition(t *testing.T, st state) {
   557  	t.Helper()
   558  
   559  	allState := [...]state{
   560  		// common states
   561  		&start{}, &abandoned{}, &done{}, &noOp{},
   562  		// states for Verifier
   563  		&requestSent{}, &presentationReceived{}, &proposalReceived{},
   564  		// states for Prover
   565  		&requestReceived{}, &presentationSent{}, &proposalSent{},
   566  	}
   567  
   568  	for _, s := range allState {
   569  		require.False(t, st.CanTransitionTo(s))
   570  	}
   571  }