package watcher import ( "context" "testing" "github.com/wormhole-foundation/wormhole-explorer/common/domain" "github.com/wormhole-foundation/wormhole-explorer/contract-watcher/storage" ) // TestCheckTxShouldBeUpdated tests the checkTxShouldBeUpdated function. func TestCheckTxShouldBeUpdated(t *testing.T) { testCase := []struct { name string inputTx storage.TransactionUpdate inputGetGlobalTransactionByIDFunc FuncGetGlobalTransactionById expectedUpdate bool expectedError error }{ { name: "tx with status completed and does not exist transaction with the same vaa ID", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusConfirmed, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{}, storage.ErrDocNotFound }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status completed and already exists a transaction with the same vaa ID with status completed", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusConfirmed, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusConfirmed, }}, nil }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status completed and already exist a transaction with the same vaa ID with status failed", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusConfirmed, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusFailedToProcess, }}, nil }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status completed and already exist a transaction with the same vaa ID with status unknown", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusConfirmed, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusUnkonwn, }}, nil }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status failed and does not exist transaction with the same vaa ID", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusFailedToProcess, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{}, storage.ErrDocNotFound }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status failed and already exists a transaction with the same vaa ID with status completed", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusFailedToProcess, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusConfirmed, }}, nil }, expectedUpdate: false, expectedError: ErrTxfailedCannotBeUpdated, }, { name: "tx with status failed and already exist a transaction with the same vaa ID with status failed", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusFailedToProcess, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusFailedToProcess, }}, nil }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status failed and already exist a transaction with the same vaa ID with status unknown", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusFailedToProcess, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusUnkonwn, }}, nil }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status unknown and does not exist transaction with the same vaa ID", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusUnkonwn, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{}, storage.ErrDocNotFound }, expectedUpdate: true, expectedError: nil, }, { name: "tx with status unknown and already exists a transaction with the same vaa ID with status completed", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusUnkonwn, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusConfirmed, }}, nil }, expectedUpdate: false, expectedError: ErrTxUnknowCannotBeUpdated, }, { name: "tx with status unknown and already exist a transaction with the same vaa ID with status failed", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusUnkonwn, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusFailedToProcess, }}, nil }, expectedUpdate: false, expectedError: ErrTxUnknowCannotBeUpdated, }, { name: "tx with status unknown and already exist a transaction with the same vaa ID with status unknown", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusUnkonwn, }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: domain.DstTxStatusUnkonwn, }}, nil }, expectedUpdate: true, expectedError: nil, }, { name: "tx with invalid status", inputTx: storage.TransactionUpdate{ Destination: storage.DestinationTx{ Status: "invalid_status", }}, inputGetGlobalTransactionByIDFunc: func(ctx context.Context, id string) (storage.TransactionUpdate, error) { return storage.TransactionUpdate{}, storage.ErrDocNotFound }, expectedUpdate: false, expectedError: ErrInvalidTxStatus, }, } // iterate over the test cases for _, tc := range testCase { t.Run(tc.name, func(t *testing.T) { update, err := checkTxShouldBeUpdated(context.Background(), tc.inputTx, tc.inputGetGlobalTransactionByIDFunc) if update != tc.expectedUpdate { t.Errorf("%s - expected update %v, got %v", tc.name, tc.expectedUpdate, update) } if err != tc.expectedError { t.Errorf("expected error %v, got %v", tc.expectedError, err) } }) } }