mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-27 22:21:18 +02:00
We introduce a new package paymentsDB and start by moving the payment specifc errors from the channeldb package to the paymentsDB package. We also fix linter issues which showed up due to changing this code part.
250 lines
6.4 KiB
Go
250 lines
6.4 KiB
Go
package channeldb
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestDecidePaymentStatus checks that given a set of HTLC and a failure
|
|
// reason, the payment's current status is returned as expected.
|
|
func TestDecidePaymentStatus(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Create two attempts used for testing.
|
|
inflight := HTLCAttempt{}
|
|
settled := HTLCAttempt{
|
|
Settle: &HTLCSettleInfo{Preimage: lntypes.Preimage{}},
|
|
}
|
|
failed := HTLCAttempt{
|
|
Failure: &HTLCFailInfo{FailureSourceIndex: 1},
|
|
}
|
|
|
|
// Create a test failure reason and get the pointer.
|
|
reason := FailureReasonNoRoute
|
|
failure := &reason
|
|
|
|
testCases := []struct {
|
|
name string
|
|
htlcs []HTLCAttempt
|
|
reason *FailureReason
|
|
expectedStatus PaymentStatus
|
|
expectedErr error
|
|
}{
|
|
{
|
|
// Test when inflight=true, settled=true, failed=true,
|
|
// reason=yes.
|
|
name: "state 1111",
|
|
htlcs: []HTLCAttempt{
|
|
inflight, settled, failed,
|
|
},
|
|
reason: failure,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=true, settled=true, failed=true,
|
|
// reason=no.
|
|
name: "state 1110",
|
|
htlcs: []HTLCAttempt{
|
|
inflight, settled, failed,
|
|
},
|
|
reason: nil,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=true, settled=true, failed=false,
|
|
// reason=yes.
|
|
name: "state 1101",
|
|
htlcs: []HTLCAttempt{inflight, settled},
|
|
reason: failure,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=true, settled=true, failed=false,
|
|
// reason=no.
|
|
name: "state 1100",
|
|
htlcs: []HTLCAttempt{inflight, settled},
|
|
reason: nil,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=true, settled=false, failed=true,
|
|
// reason=yes.
|
|
name: "state 1011",
|
|
htlcs: []HTLCAttempt{inflight, failed},
|
|
reason: failure,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=true, settled=false, failed=true,
|
|
// reason=no.
|
|
name: "state 1010",
|
|
htlcs: []HTLCAttempt{inflight, failed},
|
|
reason: nil,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=true, settled=false, failed=false,
|
|
// reason=yes.
|
|
name: "state 1001",
|
|
htlcs: []HTLCAttempt{inflight},
|
|
reason: failure,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=true, settled=false, failed=false,
|
|
// reason=no.
|
|
name: "state 1000",
|
|
htlcs: []HTLCAttempt{inflight},
|
|
reason: nil,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=true, failed=true,
|
|
// reason=yes.
|
|
name: "state 0111",
|
|
htlcs: []HTLCAttempt{settled, failed},
|
|
reason: failure,
|
|
expectedStatus: StatusSucceeded,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=true, failed=true,
|
|
// reason=no.
|
|
name: "state 0110",
|
|
htlcs: []HTLCAttempt{settled, failed},
|
|
reason: nil,
|
|
expectedStatus: StatusSucceeded,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=true,
|
|
// failed=false, reason=yes.
|
|
name: "state 0101",
|
|
htlcs: []HTLCAttempt{settled},
|
|
reason: failure,
|
|
expectedStatus: StatusSucceeded,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=true,
|
|
// failed=false, reason=no.
|
|
name: "state 0100",
|
|
htlcs: []HTLCAttempt{settled},
|
|
reason: nil,
|
|
expectedStatus: StatusSucceeded,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=false,
|
|
// failed=true, reason=yes.
|
|
name: "state 0011",
|
|
htlcs: []HTLCAttempt{failed},
|
|
reason: failure,
|
|
expectedStatus: StatusFailed,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=false,
|
|
// failed=true, reason=no.
|
|
name: "state 0010",
|
|
htlcs: []HTLCAttempt{failed},
|
|
reason: nil,
|
|
expectedStatus: StatusInFlight,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=false,
|
|
// failed=false, reason=yes.
|
|
name: "state 0001",
|
|
htlcs: []HTLCAttempt{},
|
|
reason: failure,
|
|
expectedStatus: StatusFailed,
|
|
},
|
|
{
|
|
// Test when inflight=false, settled=false,
|
|
// failed=false, reason=no.
|
|
name: "state 0000",
|
|
htlcs: []HTLCAttempt{},
|
|
reason: nil,
|
|
expectedStatus: StatusInitiated,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
status, err := decidePaymentStatus(tc.htlcs, tc.reason)
|
|
require.Equalf(t, tc.expectedStatus, status,
|
|
"got %s, want %s", status, tc.expectedStatus)
|
|
require.ErrorIs(t, err, tc.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestPaymentStatusActions checks whether a list of actions can be applied
|
|
// against ALL possible payment statuses. Unlike normal unit tests where we
|
|
// check against a single function, all the actions including `removable`,
|
|
// `initable`, and `updatable` are tested together so this test can be used as
|
|
// a reference of state transition.
|
|
func TestPaymentStatusActions(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := []struct {
|
|
status PaymentStatus
|
|
initErr error
|
|
updateErr error
|
|
removeErr error
|
|
}{
|
|
{
|
|
status: StatusInitiated,
|
|
initErr: paymentsdb.ErrPaymentExists,
|
|
updateErr: nil,
|
|
removeErr: nil,
|
|
},
|
|
{
|
|
status: StatusInFlight,
|
|
initErr: paymentsdb.ErrPaymentInFlight,
|
|
updateErr: nil,
|
|
removeErr: paymentsdb.ErrPaymentInFlight,
|
|
},
|
|
{
|
|
status: StatusSucceeded,
|
|
initErr: paymentsdb.ErrAlreadyPaid,
|
|
updateErr: paymentsdb.ErrPaymentAlreadySucceeded,
|
|
removeErr: nil,
|
|
},
|
|
{
|
|
status: StatusFailed,
|
|
initErr: nil,
|
|
updateErr: paymentsdb.ErrPaymentAlreadyFailed,
|
|
removeErr: nil,
|
|
},
|
|
{
|
|
status: 0,
|
|
initErr: paymentsdb.ErrUnknownPaymentStatus,
|
|
updateErr: paymentsdb.ErrUnknownPaymentStatus,
|
|
removeErr: paymentsdb.ErrUnknownPaymentStatus,
|
|
},
|
|
}
|
|
|
|
for i, tc := range testCases {
|
|
i, tc := i, tc
|
|
|
|
ps := tc.status
|
|
name := fmt.Sprintf("test_%d_%s", i, ps.String())
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
require.ErrorIs(t, ps.initializable(), tc.initErr,
|
|
"initable under state %v", tc.status)
|
|
|
|
require.ErrorIs(t, ps.updatable(), tc.updateErr,
|
|
"updatable under state %v", tc.status)
|
|
|
|
require.ErrorIs(t, ps.removable(), tc.removeErr,
|
|
"removable under state %v", tc.status)
|
|
})
|
|
}
|
|
}
|