github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/events/batch_pin_complete_test.go (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package events 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/json" 23 "fmt" 24 "io/ioutil" 25 "testing" 26 27 "github.com/kaleido-io/firefly/mocks/blockchainmocks" 28 "github.com/kaleido-io/firefly/mocks/databasemocks" 29 "github.com/kaleido-io/firefly/mocks/identitymocks" 30 "github.com/kaleido-io/firefly/mocks/publicstoragemocks" 31 "github.com/kaleido-io/firefly/pkg/blockchain" 32 "github.com/kaleido-io/firefly/pkg/database" 33 "github.com/kaleido-io/firefly/pkg/fftypes" 34 "github.com/stretchr/testify/assert" 35 "github.com/stretchr/testify/mock" 36 ) 37 38 func TestBatchPinCompleteOkBroadcast(t *testing.T) { 39 em, cancel := newTestEventManager(t) 40 defer cancel() 41 42 batch := &blockchain.BatchPin{ 43 Namespace: "ns1", 44 TransactionID: fftypes.NewUUID(), 45 BatchID: fftypes.NewUUID(), 46 BatchPaylodRef: fftypes.NewRandB32(), 47 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 48 } 49 batchData := &fftypes.Batch{ 50 ID: batch.BatchID, 51 Namespace: "ns1", 52 Author: "0x12345", 53 PayloadRef: batch.BatchPaylodRef, 54 Payload: fftypes.BatchPayload{ 55 TX: fftypes.TransactionRef{ 56 Type: fftypes.TransactionTypeBatchPin, 57 ID: batch.TransactionID, 58 }, 59 Messages: []*fftypes.Message{}, 60 Data: []*fftypes.Data{}, 61 }, 62 } 63 batchDataBytes, err := json.Marshal(&batchData) 64 assert.NoError(t, err) 65 batchReadCloser := ioutil.NopCloser(bytes.NewReader(batchDataBytes)) 66 67 mpi := em.publicstorage.(*publicstoragemocks.Plugin) 68 mpi.On("RetrieveData", mock.Anything, mock. 69 MatchedBy(func(pr *fftypes.Bytes32) bool { return *pr == *batch.BatchPaylodRef })). 70 Return(batchReadCloser, nil) 71 72 mdi := em.database.(*databasemocks.Plugin) 73 rag := mdi.On("RunAsGroup", mock.Anything, mock.Anything).Return(nil) 74 rag.RunFn = func(a mock.Arguments) { 75 // Call through to persistBatch - the hash of our batch will be invalid, 76 // which is swallowed without error as we cannot retry (it is logged of course) 77 rag.ReturnArguments = mock.Arguments{ 78 a[1].(func(ctx context.Context) error)(a[0].(context.Context)), 79 } 80 } 81 mdi.On("GetTransactionByID", mock.Anything, uuidMatches(batchData.Payload.TX.ID)).Return(nil, nil) 82 mdi.On("UpsertTransaction", mock.Anything, mock.Anything, true, false).Return(nil) 83 mdi.On("UpsertPin", mock.Anything, mock.Anything).Return(nil) 84 mbi := &blockchainmocks.Plugin{} 85 86 mii := em.identity.(*identitymocks.Plugin) 87 mii.On("Resolve", mock.Anything, "0x12345").Return(&fftypes.Identity{OnChain: "0x12345"}, nil) 88 89 err = em.BatchPinComplete(mbi, batch, "0x12345", "tx1", nil) 90 assert.NoError(t, err) 91 92 mdi.AssertExpectations(t) 93 } 94 95 func TestBatchPinCompleteOkPrivate(t *testing.T) { 96 em, cancel := newTestEventManager(t) 97 defer cancel() 98 99 batch := &blockchain.BatchPin{ 100 Namespace: "ns1", 101 TransactionID: fftypes.NewUUID(), 102 BatchID: fftypes.NewUUID(), 103 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 104 } 105 batchData := &fftypes.Batch{ 106 ID: batch.BatchID, 107 Namespace: "ns1", 108 PayloadRef: batch.BatchPaylodRef, 109 Payload: fftypes.BatchPayload{ 110 TX: fftypes.TransactionRef{ 111 Type: fftypes.TransactionTypeBatchPin, 112 ID: batch.TransactionID, 113 }, 114 Messages: []*fftypes.Message{}, 115 Data: []*fftypes.Data{}, 116 }, 117 } 118 batchDataBytes, err := json.Marshal(&batchData) 119 assert.NoError(t, err) 120 batchReadCloser := ioutil.NopCloser(bytes.NewReader(batchDataBytes)) 121 122 mpi := em.publicstorage.(*publicstoragemocks.Plugin) 123 mpi.On("RetrieveData", mock.Anything, mock. 124 MatchedBy(func(pr *fftypes.Bytes32) bool { return *pr == *batch.BatchPaylodRef })). 125 Return(batchReadCloser, nil) 126 127 mdi := em.database.(*databasemocks.Plugin) 128 mdi.On("RunAsGroup", mock.Anything, mock.Anything).Return(nil) 129 mdi.On("GetTransactionByID", mock.Anything, uuidMatches(batchData.Payload.TX.ID)).Return(nil, nil) 130 mdi.On("UpsertTransaction", mock.Anything, mock.Anything, true, false).Return(nil) 131 mdi.On("UpsertPin", mock.Anything, mock.Anything).Return(nil) 132 mbi := &blockchainmocks.Plugin{} 133 134 err = em.BatchPinComplete(mbi, batch, "0x12345", "tx1", nil) 135 assert.NoError(t, err) 136 137 // Call through to persistBatch - the hash of our batch will be invalid, 138 // which is swallowed without error as we cannot retry (it is logged of course) 139 fn := mdi.Calls[0].Arguments[1].(func(ctx context.Context) error) 140 err = fn(context.Background()) 141 assert.NoError(t, err) 142 143 mdi.AssertExpectations(t) 144 } 145 146 func TestSequencedBroadcastRetrieveIPFSFail(t *testing.T) { 147 em, cancel := newTestEventManager(t) 148 149 batch := &blockchain.BatchPin{ 150 TransactionID: fftypes.NewUUID(), 151 BatchID: fftypes.NewUUID(), 152 BatchPaylodRef: fftypes.NewRandB32(), 153 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 154 } 155 156 cancel() // to avoid retry 157 mpi := em.publicstorage.(*publicstoragemocks.Plugin) 158 mpi.On("RetrieveData", mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop")) 159 mbi := &blockchainmocks.Plugin{} 160 161 err := em.BatchPinComplete(mbi, batch, "0x12345", "tx1", nil) 162 mpi.AssertExpectations(t) 163 assert.Regexp(t, "FF10158", err) 164 } 165 166 func TestBatchPinCompleteBadData(t *testing.T) { 167 em, cancel := newTestEventManager(t) 168 defer cancel() 169 170 batch := &blockchain.BatchPin{ 171 TransactionID: fftypes.NewUUID(), 172 BatchID: fftypes.NewUUID(), 173 BatchPaylodRef: fftypes.NewRandB32(), 174 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 175 } 176 batchReadCloser := ioutil.NopCloser(bytes.NewReader([]byte(`!json`))) 177 178 mpi := em.publicstorage.(*publicstoragemocks.Plugin) 179 mpi.On("RetrieveData", mock.Anything, mock.Anything).Return(batchReadCloser, nil) 180 mbi := &blockchainmocks.Plugin{} 181 182 err := em.BatchPinComplete(mbi, batch, "0x12345", "tx1", nil) 183 assert.NoError(t, err) // We do not return a blocking error in the case of bad data stored in IPFS 184 } 185 186 func TestPersistBatchMissingID(t *testing.T) { 187 em, cancel := newTestEventManager(t) 188 defer cancel() 189 err := em.persistBatch(context.Background(), &fftypes.Batch{}) 190 assert.NoError(t, err) 191 } 192 193 func TestPersistBatchAuthorResolveFail(t *testing.T) { 194 em, cancel := newTestEventManager(t) 195 defer cancel() 196 batchHash := fftypes.NewRandB32() 197 batch := &fftypes.Batch{ 198 ID: fftypes.NewUUID(), 199 Author: "0x23456", 200 Payload: fftypes.BatchPayload{ 201 TX: fftypes.TransactionRef{ 202 Type: fftypes.TransactionTypeBatchPin, 203 ID: fftypes.NewUUID(), 204 }, 205 }, 206 Hash: batchHash, 207 } 208 mii := em.identity.(*identitymocks.Plugin) 209 mii.On("Resolve", mock.Anything, "0x23456").Return(nil, fmt.Errorf("pop")) 210 batch.Hash = batch.Payload.Hash() 211 err := em.persistBatchFromBroadcast(context.Background(), batch, batchHash, "0x12345") 212 assert.NoError(t, err) 213 } 214 215 func TestPersistBatchBadAuthor(t *testing.T) { 216 em, cancel := newTestEventManager(t) 217 defer cancel() 218 batchHash := fftypes.NewRandB32() 219 batch := &fftypes.Batch{ 220 ID: fftypes.NewUUID(), 221 Author: "0x23456", 222 Payload: fftypes.BatchPayload{ 223 TX: fftypes.TransactionRef{ 224 Type: fftypes.TransactionTypeBatchPin, 225 ID: fftypes.NewUUID(), 226 }, 227 }, 228 Hash: batchHash, 229 } 230 mii := em.identity.(*identitymocks.Plugin) 231 mii.On("Resolve", mock.Anything, "0x23456").Return(&fftypes.Identity{OnChain: "0x23456"}, nil) 232 batch.Hash = batch.Payload.Hash() 233 err := em.persistBatchFromBroadcast(context.Background(), batch, batchHash, "0x12345") 234 assert.NoError(t, err) 235 } 236 237 func TestPersistBatchMismatchChainHash(t *testing.T) { 238 em, cancel := newTestEventManager(t) 239 defer cancel() 240 batch := &fftypes.Batch{ 241 ID: fftypes.NewUUID(), 242 Author: "0x12345", 243 Payload: fftypes.BatchPayload{ 244 TX: fftypes.TransactionRef{ 245 Type: fftypes.TransactionTypeBatchPin, 246 ID: fftypes.NewUUID(), 247 }, 248 }, 249 Hash: fftypes.NewRandB32(), 250 } 251 mii := em.identity.(*identitymocks.Plugin) 252 mii.On("Resolve", mock.Anything, "0x12345").Return(&fftypes.Identity{OnChain: "0x12345"}, nil) 253 batch.Hash = batch.Payload.Hash() 254 err := em.persistBatchFromBroadcast(context.Background(), batch, fftypes.NewRandB32(), "0x12345") 255 assert.NoError(t, err) 256 } 257 258 func TestPersistBatchUpsertBatchMismatchHash(t *testing.T) { 259 em, cancel := newTestEventManager(t) 260 defer cancel() 261 batch := &fftypes.Batch{ 262 ID: fftypes.NewUUID(), 263 Author: "0x12345", 264 Payload: fftypes.BatchPayload{ 265 TX: fftypes.TransactionRef{ 266 Type: fftypes.TransactionTypeBatchPin, 267 ID: fftypes.NewUUID(), 268 }, 269 }, 270 } 271 batch.Hash = batch.Payload.Hash() 272 273 mdi := em.database.(*databasemocks.Plugin) 274 mdi.On("UpsertBatch", mock.Anything, mock.Anything, true, false).Return(database.HashMismatch) 275 276 err := em.persistBatch(context.Background(), batch) 277 assert.NoError(t, err) 278 mdi.AssertExpectations(t) 279 } 280 281 func TestPersistBatchUpsertBatchFail(t *testing.T) { 282 em, cancel := newTestEventManager(t) 283 defer cancel() 284 batch := &fftypes.Batch{ 285 ID: fftypes.NewUUID(), 286 Author: "0x12345", 287 Payload: fftypes.BatchPayload{ 288 TX: fftypes.TransactionRef{ 289 Type: fftypes.TransactionTypeBatchPin, 290 ID: fftypes.NewUUID(), 291 }, 292 }, 293 } 294 batch.Hash = batch.Payload.Hash() 295 296 mdi := em.database.(*databasemocks.Plugin) 297 mdi.On("UpsertBatch", mock.Anything, mock.Anything, true, false).Return(fmt.Errorf("pop")) 298 299 err := em.persistBatch(context.Background(), batch) 300 assert.EqualError(t, err, "pop") 301 } 302 303 func TestPersistBatchGetTransactionBadNamespace(t *testing.T) { 304 em, cancel := newTestEventManager(t) 305 defer cancel() 306 batchPin := &blockchain.BatchPin{ 307 TransactionID: fftypes.NewUUID(), 308 BatchID: fftypes.NewUUID(), 309 BatchHash: fftypes.NewRandB32(), 310 BatchPaylodRef: nil, 311 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 312 } 313 314 mdi := em.database.(*databasemocks.Plugin) 315 mdi.On("GetTransactionByID", mock.Anything, mock.Anything).Return(nil, nil) 316 317 err := em.persistBatchTransaction(context.Background(), batchPin, "0x12345", "txid1", fftypes.JSONObject{}) 318 assert.NoError(t, err) 319 mdi.AssertExpectations(t) 320 } 321 322 func TestPersistBatchGetTransactionFail(t *testing.T) { 323 em, cancel := newTestEventManager(t) 324 defer cancel() 325 batchPin := &blockchain.BatchPin{ 326 Namespace: "ns1", 327 TransactionID: fftypes.NewUUID(), 328 BatchID: fftypes.NewUUID(), 329 BatchHash: fftypes.NewRandB32(), 330 BatchPaylodRef: nil, 331 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 332 } 333 334 mdi := em.database.(*databasemocks.Plugin) 335 mdi.On("GetTransactionByID", mock.Anything, mock.Anything).Return(nil, fmt.Errorf("pop")) 336 337 err := em.persistBatchTransaction(context.Background(), batchPin, "0x12345", "txid1", fftypes.JSONObject{}) 338 assert.EqualError(t, err, "pop") 339 mdi.AssertExpectations(t) 340 } 341 342 func TestPersistBatchGetTransactionInvalidMatch(t *testing.T) { 343 em, cancel := newTestEventManager(t) 344 defer cancel() 345 batchPin := &blockchain.BatchPin{ 346 Namespace: "ns1", 347 TransactionID: fftypes.NewUUID(), 348 BatchID: fftypes.NewUUID(), 349 BatchHash: fftypes.NewRandB32(), 350 BatchPaylodRef: nil, 351 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 352 } 353 354 mdi := em.database.(*databasemocks.Plugin) 355 mdi.On("GetTransactionByID", mock.Anything, mock.Anything).Return(&fftypes.Transaction{ 356 ID: fftypes.NewUUID(), // wrong 357 }, nil) 358 359 err := em.persistBatchTransaction(context.Background(), batchPin, "0x12345", "txid1", fftypes.JSONObject{}) 360 assert.NoError(t, err) 361 mdi.AssertExpectations(t) 362 } 363 364 func TestPersistBatcNewTXUpsertFail(t *testing.T) { 365 em, cancel := newTestEventManager(t) 366 defer cancel() 367 batchPin := &blockchain.BatchPin{ 368 Namespace: "ns1", 369 TransactionID: fftypes.NewUUID(), 370 BatchID: fftypes.NewUUID(), 371 BatchHash: fftypes.NewRandB32(), 372 BatchPaylodRef: nil, 373 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 374 } 375 376 mdi := em.database.(*databasemocks.Plugin) 377 mdi.On("GetTransactionByID", mock.Anything, mock.Anything).Return(nil, nil) 378 mdi.On("UpsertTransaction", mock.Anything, mock.Anything, true, false).Return(fmt.Errorf("pop")) 379 380 err := em.persistBatchTransaction(context.Background(), batchPin, "0x12345", "txid1", fftypes.JSONObject{}) 381 assert.EqualError(t, err, "pop") 382 mdi.AssertExpectations(t) 383 } 384 385 func TestPersistBatcExistingTXHashMismatch(t *testing.T) { 386 em, cancel := newTestEventManager(t) 387 defer cancel() 388 batchPin := &blockchain.BatchPin{ 389 Namespace: "ns1", 390 TransactionID: fftypes.NewUUID(), 391 BatchID: fftypes.NewUUID(), 392 BatchHash: fftypes.NewRandB32(), 393 BatchPaylodRef: nil, 394 Contexts: []*fftypes.Bytes32{fftypes.NewRandB32()}, 395 } 396 397 mdi := em.database.(*databasemocks.Plugin) 398 mdi.On("GetTransactionByID", mock.Anything, mock.Anything).Return(&fftypes.Transaction{ 399 Subject: fftypes.TransactionSubject{ 400 Type: fftypes.TransactionTypeBatchPin, 401 Namespace: "ns1", 402 Signer: "0x12345", 403 Reference: batchPin.BatchID, 404 }, 405 }, nil) 406 mdi.On("UpsertTransaction", mock.Anything, mock.Anything, true, false).Return(database.HashMismatch) 407 408 err := em.persistBatchTransaction(context.Background(), batchPin, "0x12345", "txid1", fftypes.JSONObject{}) 409 assert.NoError(t, err) 410 mdi.AssertExpectations(t) 411 } 412 413 func TestPersistBatchSwallowBadData(t *testing.T) { 414 em, cancel := newTestEventManager(t) 415 defer cancel() 416 batch := &fftypes.Batch{ 417 ID: fftypes.NewUUID(), 418 Author: "0x12345", 419 Namespace: "ns1", 420 Payload: fftypes.BatchPayload{ 421 TX: fftypes.TransactionRef{ 422 Type: fftypes.TransactionTypeBatchPin, 423 ID: fftypes.NewUUID(), 424 }, 425 Messages: []*fftypes.Message{nil}, 426 Data: []*fftypes.Data{nil}, 427 }, 428 } 429 batch.Hash = batch.Payload.Hash() 430 431 mdi := em.database.(*databasemocks.Plugin) 432 mdi.On("UpsertBatch", mock.Anything, mock.Anything, true, false).Return(nil) 433 434 err := em.persistBatch(context.Background(), batch) 435 assert.NoError(t, err) 436 mdi.AssertExpectations(t) 437 } 438 439 func TestPersistBatchGoodDataUpsertFail(t *testing.T) { 440 em, cancel := newTestEventManager(t) 441 defer cancel() 442 batch := &fftypes.Batch{ 443 ID: fftypes.NewUUID(), 444 Author: "0x12345", 445 Namespace: "ns1", 446 Payload: fftypes.BatchPayload{ 447 TX: fftypes.TransactionRef{ 448 Type: fftypes.TransactionTypeBatchPin, 449 ID: fftypes.NewUUID(), 450 }, 451 Data: []*fftypes.Data{ 452 {ID: fftypes.NewUUID()}, 453 }, 454 }, 455 } 456 batch.Payload.Data[0].Hash = batch.Payload.Data[0].Value.Hash() 457 batch.Hash = batch.Payload.Hash() 458 459 mdi := em.database.(*databasemocks.Plugin) 460 mdi.On("UpsertBatch", mock.Anything, mock.Anything, true, false).Return(nil) 461 mdi.On("UpsertData", mock.Anything, mock.Anything, true, false).Return(fmt.Errorf("pop")) 462 463 err := em.persistBatch(context.Background(), batch) 464 assert.EqualError(t, err, "pop") 465 } 466 467 func TestPersistBatchGoodDataMessageFail(t *testing.T) { 468 em, cancel := newTestEventManager(t) 469 defer cancel() 470 batch := &fftypes.Batch{ 471 ID: fftypes.NewUUID(), 472 Author: "0x12345", 473 Namespace: "ns1", 474 Payload: fftypes.BatchPayload{ 475 TX: fftypes.TransactionRef{ 476 Type: fftypes.TransactionTypeBatchPin, 477 ID: fftypes.NewUUID(), 478 }, 479 Messages: []*fftypes.Message{ 480 {Header: fftypes.MessageHeader{ 481 ID: fftypes.NewUUID(), 482 Author: "0x12345", 483 }}, 484 }, 485 }, 486 } 487 batch.Payload.Messages[0].Header.DataHash = batch.Payload.Messages[0].Data.Hash() 488 batch.Payload.Messages[0].Hash = batch.Payload.Messages[0].Header.Hash() 489 batch.Hash = batch.Payload.Hash() 490 491 mdi := em.database.(*databasemocks.Plugin) 492 mdi.On("UpsertBatch", mock.Anything, mock.Anything, true, false).Return(nil) 493 mdi.On("UpsertMessage", mock.Anything, mock.Anything, true, false).Return(fmt.Errorf("pop")) 494 495 err := em.persistBatch(context.Background(), batch) 496 assert.EqualError(t, err, "pop") 497 } 498 499 func TestPersistBatchGoodMessageAuthorMismatch(t *testing.T) { 500 em, cancel := newTestEventManager(t) 501 defer cancel() 502 batch := &fftypes.Batch{ 503 ID: fftypes.NewUUID(), 504 Author: "0x12345", 505 Namespace: "ns1", 506 Payload: fftypes.BatchPayload{ 507 TX: fftypes.TransactionRef{ 508 Type: fftypes.TransactionTypeBatchPin, 509 ID: fftypes.NewUUID(), 510 }, 511 Messages: []*fftypes.Message{ 512 {Header: fftypes.MessageHeader{ 513 ID: fftypes.NewUUID(), 514 Author: "0x9999999", 515 }}, 516 }, 517 }, 518 } 519 batch.Payload.Messages[0].Header.DataHash = batch.Payload.Messages[0].Data.Hash() 520 batch.Payload.Messages[0].Hash = batch.Payload.Messages[0].Header.Hash() 521 batch.Hash = batch.Payload.Hash() 522 523 mdi := em.database.(*databasemocks.Plugin) 524 mdi.On("UpsertBatch", mock.Anything, mock.Anything, true, false).Return(nil) 525 526 err := em.persistBatch(context.Background(), batch) 527 assert.NoError(t, err) 528 } 529 func TestPersistBatchDataBadHash(t *testing.T) { 530 em, cancel := newTestEventManager(t) 531 defer cancel() 532 batch := &fftypes.Batch{ 533 ID: fftypes.NewUUID(), 534 } 535 data := &fftypes.Data{ 536 ID: fftypes.NewUUID(), 537 } 538 err := em.persistBatchData(context.Background(), batch, 0, data) 539 assert.NoError(t, err) 540 } 541 542 func TestPersistBatchDataUpsertHashMismatch(t *testing.T) { 543 em, cancel := newTestEventManager(t) 544 defer cancel() 545 batch := &fftypes.Batch{ 546 ID: fftypes.NewUUID(), 547 } 548 549 data := &fftypes.Data{ 550 ID: fftypes.NewUUID(), 551 } 552 data.Hash = data.Value.Hash() 553 554 mdi := em.database.(*databasemocks.Plugin) 555 mdi.On("UpsertData", mock.Anything, mock.Anything, true, false).Return(database.HashMismatch) 556 557 err := em.persistBatchData(context.Background(), batch, 0, data) 558 assert.NoError(t, err) 559 mdi.AssertExpectations(t) 560 } 561 562 func TestPersistBatchDataUpsertDataError(t *testing.T) { 563 em, cancel := newTestEventManager(t) 564 defer cancel() 565 batch := &fftypes.Batch{ 566 ID: fftypes.NewUUID(), 567 } 568 569 data := &fftypes.Data{ 570 ID: fftypes.NewUUID(), 571 } 572 data.Hash = data.Value.Hash() 573 574 mdi := em.database.(*databasemocks.Plugin) 575 mdi.On("UpsertData", mock.Anything, mock.Anything, true, false).Return(fmt.Errorf("pop")) 576 577 err := em.persistBatchData(context.Background(), batch, 0, data) 578 assert.EqualError(t, err, "pop") 579 } 580 581 func TestPersistBatchDataOk(t *testing.T) { 582 em, cancel := newTestEventManager(t) 583 defer cancel() 584 batch := &fftypes.Batch{ 585 ID: fftypes.NewUUID(), 586 } 587 588 data := &fftypes.Data{ 589 ID: fftypes.NewUUID(), 590 } 591 data.Hash = data.Value.Hash() 592 593 mdi := em.database.(*databasemocks.Plugin) 594 mdi.On("UpsertData", mock.Anything, mock.Anything, true, false).Return(nil) 595 596 err := em.persistBatchData(context.Background(), batch, 0, data) 597 assert.NoError(t, err) 598 mdi.AssertExpectations(t) 599 } 600 601 func TestPersistBatchMessageBadHash(t *testing.T) { 602 em, cancel := newTestEventManager(t) 603 defer cancel() 604 batch := &fftypes.Batch{ 605 ID: fftypes.NewUUID(), 606 } 607 msg := &fftypes.Message{ 608 Header: fftypes.MessageHeader{ 609 ID: fftypes.NewUUID(), 610 }, 611 } 612 err := em.persistBatchMessage(context.Background(), batch, 0, msg) 613 assert.NoError(t, err) 614 } 615 616 func TestPersistBatchMessageUpsertHashMismatch(t *testing.T) { 617 em, cancel := newTestEventManager(t) 618 defer cancel() 619 batch := &fftypes.Batch{ 620 ID: fftypes.NewUUID(), 621 } 622 msg := &fftypes.Message{ 623 Header: fftypes.MessageHeader{ 624 ID: fftypes.NewUUID(), 625 }, 626 } 627 msg.Header.DataHash = msg.Data.Hash() 628 msg.Hash = msg.Header.Hash() 629 assert.NoError(t, msg.Verify(context.Background())) 630 631 mdi := em.database.(*databasemocks.Plugin) 632 mdi.On("UpsertMessage", mock.Anything, mock.Anything, true, false).Return(database.HashMismatch) 633 634 err := em.persistBatchMessage(context.Background(), batch, 0, msg) 635 assert.NoError(t, err) 636 mdi.AssertExpectations(t) 637 } 638 639 func TestPersistBatchMessageUpsertMessageFail(t *testing.T) { 640 em, cancel := newTestEventManager(t) 641 defer cancel() 642 batch := &fftypes.Batch{ 643 ID: fftypes.NewUUID(), 644 } 645 msg := &fftypes.Message{ 646 Header: fftypes.MessageHeader{ 647 ID: fftypes.NewUUID(), 648 }, 649 } 650 msg.Header.DataHash = msg.Data.Hash() 651 msg.Hash = msg.Header.Hash() 652 assert.NoError(t, msg.Verify(context.Background())) 653 654 mdi := em.database.(*databasemocks.Plugin) 655 mdi.On("UpsertMessage", mock.Anything, mock.Anything, true, false).Return(fmt.Errorf("pop")) 656 657 err := em.persistBatchMessage(context.Background(), batch, 0, msg) 658 assert.EqualError(t, err, "pop") 659 } 660 661 func TestPersistBatchMessageOK(t *testing.T) { 662 em, cancel := newTestEventManager(t) 663 defer cancel() 664 batch := &fftypes.Batch{ 665 ID: fftypes.NewUUID(), 666 } 667 msg := &fftypes.Message{ 668 Header: fftypes.MessageHeader{ 669 ID: fftypes.NewUUID(), 670 }, 671 } 672 msg.Header.DataHash = msg.Data.Hash() 673 msg.Hash = msg.Header.Hash() 674 assert.NoError(t, msg.Verify(context.Background())) 675 676 mdi := em.database.(*databasemocks.Plugin) 677 mdi.On("UpsertMessage", mock.Anything, mock.Anything, true, false).Return(nil) 678 679 err := em.persistBatchMessage(context.Background(), batch, 0, msg) 680 assert.NoError(t, err) 681 mdi.AssertExpectations(t) 682 } 683 684 func TestPersistContextsFail(t *testing.T) { 685 em, cancel := newTestEventManager(t) 686 defer cancel() 687 688 mdi := em.database.(*databasemocks.Plugin) 689 mdi.On("UpsertPin", mock.Anything, mock.Anything).Return(fmt.Errorf("pop")) 690 691 err := em.persistContexts(em.ctx, &blockchain.BatchPin{ 692 Contexts: []*fftypes.Bytes32{ 693 fftypes.NewRandB32(), 694 }, 695 }, false) 696 assert.EqualError(t, err, "pop") 697 mdi.AssertExpectations(t) 698 }