github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/introduce/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 introduce 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/service" 19 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 20 serviceMocks "github.com/hyperledger/aries-framework-go/pkg/internal/gomocks/didcomm/common/service" 21 ) 22 23 func notTransition(t *testing.T, st state) { 24 t.Helper() 25 26 allState := [...]state{ 27 &noOp{}, &start{}, &done{}, 28 &arranging{}, &delivering{}, 29 &confirming{}, &abandoning{}, 30 &deciding{}, &waiting{}, &requesting{}, 31 } 32 33 for _, s := range allState { 34 require.False(t, st.CanTransitionTo(s)) 35 } 36 } 37 38 func TestNoOp_CanTransitionTo(t *testing.T) { 39 noop := &noOp{} 40 require.Equal(t, stateNameNoop, noop.Name()) 41 notTransition(t, noop) 42 } 43 44 func TestNoOp_ExecuteInbound(t *testing.T) { 45 followup, _, err := (&noOp{}).ExecuteInbound(nil, &metaData{}) 46 require.Error(t, err) 47 require.Nil(t, followup) 48 } 49 50 func TestNoOp_saveMetadata(t *testing.T) { 51 require.NoError(t, (&Service{}).saveMetadata(nil, "")) 52 } 53 54 func TestNoOp_ExecuteOutbound(t *testing.T) { 55 followup, _, err := (&noOp{}).ExecuteOutbound(nil, &metaData{}) 56 require.Error(t, err) 57 require.Nil(t, followup) 58 } 59 60 func TestStart_CanTransitionTo(t *testing.T) { 61 st := &start{} 62 require.Equal(t, stateNameStart, st.Name()) 63 64 require.True(t, st.CanTransitionTo(&arranging{})) 65 require.True(t, st.CanTransitionTo(&deciding{})) 66 require.True(t, st.CanTransitionTo(&requesting{})) 67 require.True(t, st.CanTransitionTo(&abandoning{})) 68 69 require.False(t, st.CanTransitionTo(&delivering{})) 70 require.False(t, st.CanTransitionTo(&noOp{})) 71 require.False(t, st.CanTransitionTo(&start{})) 72 require.False(t, st.CanTransitionTo(&done{})) 73 require.False(t, st.CanTransitionTo(&confirming{})) 74 require.False(t, st.CanTransitionTo(&waiting{})) 75 } 76 77 func TestStart_ExecuteInbound(t *testing.T) { 78 followup, _, err := (&start{}).ExecuteInbound(nil, &metaData{}) 79 require.EqualError(t, err, "start: ExecuteInbound function is not supposed to be used") 80 require.Nil(t, followup) 81 } 82 83 func TestStart_ExecuteOutbound(t *testing.T) { 84 followup, _, err := (&start{}).ExecuteOutbound(nil, &metaData{}) 85 require.EqualError(t, err, "start: ExecuteOutbound function is not supposed to be used") 86 require.Nil(t, followup) 87 } 88 89 func TestDone_CanTransitionTo(t *testing.T) { 90 st := &done{} 91 require.Equal(t, stateNameDone, st.Name()) 92 notTransition(t, st) 93 } 94 95 func TestDone_ExecuteInbound(t *testing.T) { 96 followup, _, err := (&done{}).ExecuteInbound(nil, &metaData{}) 97 require.NoError(t, err) 98 require.Equal(t, &noOp{}, followup) 99 } 100 101 func TestDone_ExecuteOutbound(t *testing.T) { 102 followup, _, err := (&done{}).ExecuteOutbound(nil, &metaData{}) 103 require.Error(t, err) 104 require.Nil(t, followup) 105 } 106 107 func TestArranging_CanTransitionTo(t *testing.T) { 108 st := &arranging{} 109 require.Equal(t, stateNameArranging, st.Name()) 110 111 require.True(t, st.CanTransitionTo(&arranging{})) 112 require.True(t, st.CanTransitionTo(&abandoning{})) 113 require.True(t, st.CanTransitionTo(&done{})) 114 require.True(t, st.CanTransitionTo(&delivering{})) 115 116 require.False(t, st.CanTransitionTo(&noOp{})) 117 require.False(t, st.CanTransitionTo(&start{})) 118 require.False(t, st.CanTransitionTo(&confirming{})) 119 require.False(t, st.CanTransitionTo(&deciding{})) 120 require.False(t, st.CanTransitionTo(&waiting{})) 121 require.False(t, st.CanTransitionTo(&requesting{})) 122 } 123 124 func TestArranging_ExecuteOutbound(t *testing.T) { 125 const errMsg = "test error" 126 127 ctrl := gomock.NewController(t) 128 defer ctrl.Finish() 129 130 messenger := serviceMocks.NewMockMessenger(ctrl) 131 messenger.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 132 messenger.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New(errMsg)) 133 134 followup, action, err := (&arranging{}).ExecuteOutbound(messenger, &metaData{ 135 transitionalPayload: transitionalPayload{Action: Action{Msg: service.NewDIDCommMsgMap(struct{}{})}}, 136 saveMetadata: func(_ service.DIDCommMsgMap, _ string) error { return nil }, 137 }) 138 require.NoError(t, err) 139 require.NoError(t, action()) 140 require.Equal(t, &noOp{}, followup) 141 142 // Send an error 143 followup, action, err = (&arranging{}).ExecuteOutbound(messenger, &metaData{ 144 transitionalPayload: transitionalPayload{Action: Action{Msg: service.NewDIDCommMsgMap(struct{}{})}}, 145 saveMetadata: func(_ service.DIDCommMsgMap, _ string) error { return nil }, 146 }) 147 require.NoError(t, err) 148 require.Contains(t, fmt.Sprintf("%v", action()), errMsg) 149 require.Equal(t, &noOp{}, followup) 150 151 followup, action, err = (&arranging{}).ExecuteOutbound(messenger, &metaData{ 152 transitionalPayload: transitionalPayload{Action: Action{Msg: service.NewDIDCommMsgMap(struct{}{})}}, 153 saveMetadata: func(_ service.DIDCommMsgMap, _ string) error { return errors.New(errMsg) }, 154 }) 155 require.NoError(t, err) 156 require.Contains(t, fmt.Sprintf("%v", action()), errMsg) 157 require.Equal(t, &noOp{}, followup) 158 159 followup, action, err = (&arranging{}).ExecuteOutbound(messenger, &metaData{ 160 saveMetadata: func(msg service.DIDCommMsgMap, thID string) error { return errors.New("test error") }, 161 transitionalPayload: transitionalPayload{Action: Action{Msg: service.DIDCommMsgMap{}}}, 162 }) 163 require.NoError(t, err) 164 require.Contains(t, fmt.Sprintf("%v", action()), "test error") 165 require.Equal(t, &noOp{}, followup) 166 } 167 168 func TestDelivering_CanTransitionTo(t *testing.T) { 169 st := &delivering{} 170 require.Equal(t, stateNameDelivering, st.Name()) 171 172 require.True(t, st.CanTransitionTo(&confirming{})) 173 require.True(t, st.CanTransitionTo(&abandoning{})) 174 require.True(t, st.CanTransitionTo(&done{})) 175 176 require.False(t, st.CanTransitionTo(&noOp{})) 177 require.False(t, st.CanTransitionTo(&start{})) 178 require.False(t, st.CanTransitionTo(&delivering{})) 179 require.False(t, st.CanTransitionTo(&arranging{})) 180 require.False(t, st.CanTransitionTo(&deciding{})) 181 require.False(t, st.CanTransitionTo(&waiting{})) 182 require.False(t, st.CanTransitionTo(&requesting{})) 183 } 184 185 func TestDelivering_ExecuteOutbound(t *testing.T) { 186 followup, _, err := (&delivering{}).ExecuteOutbound(nil, &metaData{}) 187 require.Error(t, err) 188 require.Nil(t, followup) 189 } 190 191 func TestConfirming_CanTransitionTo(t *testing.T) { 192 st := &confirming{} 193 require.Equal(t, stateNameConfirming, st.Name()) 194 195 require.True(t, st.CanTransitionTo(&abandoning{})) 196 require.True(t, st.CanTransitionTo(&done{})) 197 198 require.False(t, st.CanTransitionTo(&noOp{})) 199 require.False(t, st.CanTransitionTo(&start{})) 200 require.False(t, st.CanTransitionTo(&delivering{})) 201 require.False(t, st.CanTransitionTo(&arranging{})) 202 require.False(t, st.CanTransitionTo(&confirming{})) 203 require.False(t, st.CanTransitionTo(&deciding{})) 204 require.False(t, st.CanTransitionTo(&waiting{})) 205 require.False(t, st.CanTransitionTo(&requesting{})) 206 } 207 208 func TestConfirming_ExecuteOutbound(t *testing.T) { 209 followup, _, err := (&confirming{}).ExecuteOutbound(nil, &metaData{}) 210 require.Error(t, err) 211 require.Nil(t, followup) 212 } 213 214 func TestAbandoning_CanTransitionTo(t *testing.T) { 215 st := &abandoning{} 216 require.Equal(t, stateNameAbandoning, st.Name()) 217 218 require.True(t, st.CanTransitionTo(&done{})) 219 220 require.False(t, st.CanTransitionTo(&noOp{})) 221 require.False(t, st.CanTransitionTo(&start{})) 222 require.False(t, st.CanTransitionTo(&delivering{})) 223 require.False(t, st.CanTransitionTo(&arranging{})) 224 require.False(t, st.CanTransitionTo(&confirming{})) 225 require.False(t, st.CanTransitionTo(&deciding{})) 226 require.False(t, st.CanTransitionTo(&abandoning{})) 227 require.False(t, st.CanTransitionTo(&waiting{})) 228 require.False(t, st.CanTransitionTo(&requesting{})) 229 } 230 231 func TestAbandoning_ExecuteOutbound(t *testing.T) { 232 followup, _, err := (&abandoning{}).ExecuteOutbound(nil, &metaData{}) 233 require.Error(t, err) 234 require.Nil(t, followup) 235 } 236 237 func TestDeciding_CanTransitionTo(t *testing.T) { 238 st := &deciding{} 239 require.Equal(t, stateNameDeciding, st.Name()) 240 241 require.True(t, st.CanTransitionTo(&waiting{})) 242 require.True(t, st.CanTransitionTo(&done{})) 243 require.True(t, st.CanTransitionTo(&abandoning{})) 244 245 require.False(t, st.CanTransitionTo(&noOp{})) 246 require.False(t, st.CanTransitionTo(&start{})) 247 require.False(t, st.CanTransitionTo(&delivering{})) 248 require.False(t, st.CanTransitionTo(&arranging{})) 249 require.False(t, st.CanTransitionTo(&confirming{})) 250 require.False(t, st.CanTransitionTo(&deciding{})) 251 require.False(t, st.CanTransitionTo(&requesting{})) 252 } 253 254 func TestDeciding_ExecuteInbound(t *testing.T) { 255 ctrl := gomock.NewController(t) 256 defer ctrl.Finish() 257 258 t.Run("handles inbound message", func(t *testing.T) { 259 messenger := serviceMocks.NewMockMessenger(ctrl) 260 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) 261 262 followup, action, err := (&deciding{}).ExecuteInbound(messenger, &metaData{ 263 transitionalPayload: transitionalPayload{Action: Action{Msg: service.NewDIDCommMsgMap(struct{}{})}}, 264 }) 265 266 require.NoError(t, err) 267 require.NoError(t, action()) 268 require.Equal(t, &waiting{}, followup) 269 }) 270 271 t.Run("adds attachment", func(t *testing.T) { 272 expected := &decorator.Attachment{ 273 ID: uuid.New().String(), 274 } 275 messenger := serviceMocks.NewMockMessenger(ctrl) 276 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( 277 func(_, msg service.DIDCommMsgMap, _, _ string) error { 278 result := &Response{} 279 err := msg.Decode(result) 280 require.NoError(t, err) 281 require.Len(t, result.Attachments, 1) 282 require.Equal(t, expected, result.Attachments[0]) 283 return nil 284 }, 285 ).Times(1) 286 msg := service.NewDIDCommMsgMap(struct{}{}) 287 msg.Metadata()[metaAttachment] = []*decorator.Attachment{expected} 288 _, action, err := (&deciding{}).ExecuteInbound(messenger, &metaData{ 289 transitionalPayload: transitionalPayload{Action: Action{Msg: msg}}, 290 }) 291 require.NoError(t, err) 292 err = action() 293 require.NoError(t, err) 294 }) 295 296 t.Run("fails if attachments used improperly", func(t *testing.T) { 297 messenger := serviceMocks.NewMockMessenger(ctrl) 298 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(0) 299 msg := service.NewDIDCommMsgMap(struct{}{}) 300 msg.Metadata()[metaAttachment] = []struct{}{} 301 _, action, err := (&deciding{}).ExecuteInbound(messenger, &metaData{ 302 transitionalPayload: transitionalPayload{Action: Action{Msg: msg}}, 303 }) 304 require.NoError(t, err) 305 err = action() 306 require.Error(t, err) 307 }) 308 } 309 310 func TestDeciding_ExecuteOutbound(t *testing.T) { 311 followup, _, err := (&deciding{}).ExecuteOutbound(nil, &metaData{}) 312 require.Error(t, err) 313 require.Nil(t, followup) 314 } 315 316 func TestWaiting_CanTransitionTo(t *testing.T) { 317 st := &waiting{} 318 require.Equal(t, stateNameWaiting, st.Name()) 319 320 require.True(t, st.CanTransitionTo(&done{})) 321 require.True(t, st.CanTransitionTo(&abandoning{})) 322 323 require.False(t, st.CanTransitionTo(&noOp{})) 324 require.False(t, st.CanTransitionTo(&start{})) 325 require.False(t, st.CanTransitionTo(&delivering{})) 326 require.False(t, st.CanTransitionTo(&arranging{})) 327 require.False(t, st.CanTransitionTo(&confirming{})) 328 require.False(t, st.CanTransitionTo(&deciding{})) 329 require.False(t, st.CanTransitionTo(&waiting{})) 330 require.False(t, st.CanTransitionTo(&requesting{})) 331 } 332 333 func TestWaiting_ExecuteInbound(t *testing.T) { 334 followup, _, err := (&waiting{}).ExecuteInbound(nil, &metaData{}) 335 require.NoError(t, err) 336 require.Equal(t, &noOp{}, followup) 337 } 338 339 func TestWaiting_ExecuteOutbound(t *testing.T) { 340 followup, _, err := (&waiting{}).ExecuteOutbound(nil, &metaData{}) 341 require.Error(t, err) 342 require.Nil(t, followup) 343 } 344 345 func TestRequesting_CanTransitionTo(t *testing.T) { 346 st := &requesting{} 347 require.Equal(t, stateNameRequesting, st.Name()) 348 349 require.True(t, st.CanTransitionTo(&deciding{})) 350 require.True(t, st.CanTransitionTo(&done{})) 351 require.True(t, st.CanTransitionTo(&abandoning{})) 352 353 require.False(t, st.CanTransitionTo(&noOp{})) 354 require.False(t, st.CanTransitionTo(&start{})) 355 require.False(t, st.CanTransitionTo(&delivering{})) 356 require.False(t, st.CanTransitionTo(&arranging{})) 357 require.False(t, st.CanTransitionTo(&confirming{})) 358 require.False(t, st.CanTransitionTo(&waiting{})) 359 require.False(t, st.CanTransitionTo(&requesting{})) 360 } 361 362 func TestRequesting_ExecuteInbound(t *testing.T) { 363 followup, _, err := (&requesting{}).ExecuteInbound(nil, &metaData{}) 364 require.Error(t, err) 365 require.Nil(t, followup) 366 } 367 368 func Test_stateFromName(t *testing.T) { 369 st := stateFromName(stateNameNoop) 370 require.Equal(t, &noOp{}, st) 371 372 st = stateFromName(stateNameStart) 373 require.Equal(t, &start{}, st) 374 375 st = stateFromName(stateNameDone) 376 require.Equal(t, &done{}, st) 377 378 st = stateFromName(stateNameArranging) 379 require.Equal(t, &arranging{}, st) 380 381 st = stateFromName(stateNameDelivering) 382 require.Equal(t, &delivering{}, st) 383 384 st = stateFromName(stateNameConfirming) 385 require.Equal(t, &confirming{}, st) 386 387 st = stateFromName(stateNameAbandoning) 388 require.Equal(t, &abandoning{}, st) 389 390 st = stateFromName(stateNameDeciding) 391 require.Equal(t, &deciding{}, st) 392 393 st = stateFromName(stateNameWaiting) 394 require.Equal(t, &waiting{}, st) 395 396 st = stateFromName(stateNameRequesting) 397 require.Equal(t, &requesting{}, st) 398 399 st = stateFromName("unknown") 400 require.Equal(t, &noOp{}, st) 401 } 402 403 func Test_sendProposals(t *testing.T) { 404 const errMsg = "test error" 405 406 ctrl := gomock.NewController(t) 407 defer ctrl.Finish() 408 409 messenger := serviceMocks.NewMockMessenger(ctrl) 410 messenger.EXPECT().ReplyToMsg(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New(errMsg)) 411 412 msg := service.NewDIDCommMsgMap(struct{}{}) 413 msg.SetID(uuid.New().String()) 414 415 msg.Metadata()[metaRecipients] = map[string]int{} 416 417 require.NoError(t, sendProposals(messenger, &metaData{ 418 transitionalPayload: transitionalPayload{Action: Action{Msg: msg}}, 419 })) 420 421 msg.Metadata()[metaRecipients] = []interface{}{&Recipient{}} 422 require.Contains(t, fmt.Sprintf("%v", sendProposals(messenger, &metaData{ 423 transitionalPayload: transitionalPayload{Action: Action{Msg: msg}}, 424 saveMetadata: func(_ service.DIDCommMsgMap, _ string) error { return nil }, 425 })), errMsg) 426 427 require.Contains(t, fmt.Sprintf("%v", sendProposals(messenger, &metaData{ 428 transitionalPayload: transitionalPayload{Action: Action{Msg: msg}}, 429 saveMetadata: func(_ service.DIDCommMsgMap, _ string) error { return errors.New(errMsg) }, 430 })), errMsg) 431 432 msg = service.NewDIDCommMsgMap(struct{}{}) 433 msg.Metadata()[metaRecipients] = []interface{}{&Recipient{}} 434 require.EqualError(t, sendProposals(messenger, &metaData{ 435 transitionalPayload: transitionalPayload{Action: Action{Msg: msg}}, 436 }), "get threadID: threadID not found") 437 438 msg = service.NewDIDCommMsgMap(struct{}{}) 439 msg.Metadata()[metaRecipients] = []interface{}{&Recipient{MyDID: "my_did"}} 440 require.EqualError(t, sendProposals(messenger, &metaData{ 441 transitionalPayload: transitionalPayload{Action: Action{Msg: msg}}, 442 saveMetadata: func(_ service.DIDCommMsgMap, _ string) error { return errors.New(errMsg) }, 443 }), "save metadata: test error") 444 }