mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-07-28 13:52:55 +02:00
routing/test: run each test case individually, add names
Update our payment lifecycle test to run each test case with a fresh router. This prevents test cases from interacting with each other. Names are also added for easy debugging.
This commit is contained in:
@@ -48,56 +48,11 @@ func createTestRoute(amt lnwire.MilliSatoshi,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestRouterPaymentStateMachine tests that the router interacts as expected
|
// paymentLifecycleTestCase contains the steps that we expect for a payment
|
||||||
// with the ControlTower during a payment lifecycle, such that it payment
|
// lifecycle test, and the routes that pathfinding should deliver.
|
||||||
// attempts are not sent twice to the switch, and results are handled after a
|
type paymentLifecycleTestCase struct {
|
||||||
// restart.
|
name string
|
||||||
func TestRouterPaymentStateMachine(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
const startingBlockHeight = 101
|
|
||||||
|
|
||||||
// Setup two simple channels such that we can mock sending along this
|
|
||||||
// route.
|
|
||||||
chanCapSat := btcutil.Amount(100000)
|
|
||||||
testChannels := []*testChannel{
|
|
||||||
symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
|
|
||||||
Expiry: 144,
|
|
||||||
FeeRate: 400,
|
|
||||||
MinHTLC: 1,
|
|
||||||
MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat),
|
|
||||||
}, 1),
|
|
||||||
symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
|
|
||||||
Expiry: 144,
|
|
||||||
FeeRate: 400,
|
|
||||||
MinHTLC: 1,
|
|
||||||
MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat),
|
|
||||||
}, 2),
|
|
||||||
}
|
|
||||||
|
|
||||||
testGraph, err := createTestGraphFromChannels(testChannels, "a")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create graph: %v", err)
|
|
||||||
}
|
|
||||||
defer testGraph.cleanUp()
|
|
||||||
|
|
||||||
paymentAmt := lnwire.NewMSatFromSatoshis(1000)
|
|
||||||
|
|
||||||
// We create a simple route that we will supply every time the router
|
|
||||||
// requests one.
|
|
||||||
rt, err := createTestRoute(paymentAmt, testGraph.aliasMap)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create route: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
shard, err := createTestRoute(paymentAmt/4, testGraph.aliasMap)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create route: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A payment state machine test case consists of several ordered steps,
|
|
||||||
// that we use for driving the scenario.
|
|
||||||
type testCase struct {
|
|
||||||
// steps is a list of steps to perform during the testcase.
|
// steps is a list of steps to perform during the testcase.
|
||||||
steps []string
|
steps []string
|
||||||
|
|
||||||
@@ -188,9 +143,58 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
resentPaymentError = "ResentPaymentError"
|
resentPaymentError = "ResentPaymentError"
|
||||||
)
|
)
|
||||||
|
|
||||||
tests := []testCase{
|
// TestRouterPaymentStateMachine tests that the router interacts as expected
|
||||||
|
// with the ControlTower during a payment lifecycle, such that it payment
|
||||||
|
// attempts are not sent twice to the switch, and results are handled after a
|
||||||
|
// restart.
|
||||||
|
func TestRouterPaymentStateMachine(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
const startingBlockHeight = 101
|
||||||
|
|
||||||
|
// Setup two simple channels such that we can mock sending along this
|
||||||
|
// route.
|
||||||
|
chanCapSat := btcutil.Amount(100000)
|
||||||
|
testChannels := []*testChannel{
|
||||||
|
symmetricTestChannel("a", "b", chanCapSat, &testChannelPolicy{
|
||||||
|
Expiry: 144,
|
||||||
|
FeeRate: 400,
|
||||||
|
MinHTLC: 1,
|
||||||
|
MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat),
|
||||||
|
}, 1),
|
||||||
|
symmetricTestChannel("b", "c", chanCapSat, &testChannelPolicy{
|
||||||
|
Expiry: 144,
|
||||||
|
FeeRate: 400,
|
||||||
|
MinHTLC: 1,
|
||||||
|
MaxHTLC: lnwire.NewMSatFromSatoshis(chanCapSat),
|
||||||
|
}, 2),
|
||||||
|
}
|
||||||
|
|
||||||
|
testGraph, err := createTestGraphFromChannels(testChannels, "a")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create graph: %v", err)
|
||||||
|
}
|
||||||
|
defer testGraph.cleanUp()
|
||||||
|
|
||||||
|
paymentAmt := lnwire.NewMSatFromSatoshis(1000)
|
||||||
|
|
||||||
|
// We create a simple route that we will supply every time the router
|
||||||
|
// requests one.
|
||||||
|
rt, err := createTestRoute(paymentAmt, testGraph.aliasMap)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create route: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
shard, err := createTestRoute(paymentAmt/4, testGraph.aliasMap)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create route: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []paymentLifecycleTestCase{
|
||||||
{
|
{
|
||||||
// Tests a normal payment flow that succeeds.
|
// Tests a normal payment flow that succeeds.
|
||||||
|
name: "single shot success",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerRegisterAttempt,
|
routerRegisterAttempt,
|
||||||
@@ -204,6 +208,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// A payment flow with a failure on the first attempt,
|
// A payment flow with a failure on the first attempt,
|
||||||
// but that succeeds on the second attempt.
|
// but that succeeds on the second attempt.
|
||||||
|
name: "single shot retry",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerRegisterAttempt,
|
routerRegisterAttempt,
|
||||||
@@ -228,6 +234,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
// A payment flow with a forwarding failure first time
|
// A payment flow with a forwarding failure first time
|
||||||
// sending to the switch, but that succeeds on the
|
// sending to the switch, but that succeeds on the
|
||||||
// second attempt.
|
// second attempt.
|
||||||
|
name: "single shot switch failure",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerRegisterAttempt,
|
routerRegisterAttempt,
|
||||||
@@ -251,6 +259,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
// A payment that fails on the first attempt, and has
|
// A payment that fails on the first attempt, and has
|
||||||
// only one route available to try. It will therefore
|
// only one route available to try. It will therefore
|
||||||
// fail permanently.
|
// fail permanently.
|
||||||
|
name: "single shot route fails",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerRegisterAttempt,
|
routerRegisterAttempt,
|
||||||
@@ -270,6 +280,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// We expect the payment to fail immediately if we have
|
// We expect the payment to fail immediately if we have
|
||||||
// no routes to try.
|
// no routes to try.
|
||||||
|
name: "single shot no route",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerFailPayment,
|
routerFailPayment,
|
||||||
@@ -282,6 +294,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
// the same payment after each step. This ensures that
|
// the same payment after each step. This ensures that
|
||||||
// the router don't attempt to resend a payment already
|
// the router don't attempt to resend a payment already
|
||||||
// in flight.
|
// in flight.
|
||||||
|
name: "single shot resend",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerRegisterAttempt,
|
routerRegisterAttempt,
|
||||||
@@ -322,6 +336,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// Tests that the router is able to handle the
|
// Tests that the router is able to handle the
|
||||||
// receieved payment result after a restart.
|
// receieved payment result after a restart.
|
||||||
|
name: "single shot restart",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerRegisterAttempt,
|
routerRegisterAttempt,
|
||||||
@@ -344,6 +360,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// Tests that we are allowed to resend a payment after
|
// Tests that we are allowed to resend a payment after
|
||||||
// it has permanently failed.
|
// it has permanently failed.
|
||||||
|
name: "single shot resend fail",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
routerRegisterAttempt,
|
routerRegisterAttempt,
|
||||||
@@ -382,6 +400,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
// =====================================
|
// =====================================
|
||||||
{
|
{
|
||||||
// Tests a simple successful MP payment of 4 shards.
|
// Tests a simple successful MP payment of 4 shards.
|
||||||
|
name: "MP success",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
|
|
||||||
@@ -422,6 +442,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// An MP payment scenario where we need several extra
|
// An MP payment scenario where we need several extra
|
||||||
// attempts before the payment finally settle.
|
// attempts before the payment finally settle.
|
||||||
|
name: "MP failed shards",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
|
|
||||||
@@ -474,6 +496,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
// However the last shard settle, which means we get
|
// However the last shard settle, which means we get
|
||||||
// the preimage and should consider the overall payment
|
// the preimage and should consider the overall payment
|
||||||
// a success.
|
// a success.
|
||||||
|
name: "MP one shard success",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
|
|
||||||
@@ -513,6 +537,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// An MP payment scenario a shard fail with a terminal
|
// An MP payment scenario a shard fail with a terminal
|
||||||
// error, causing the router to stop attempting.
|
// error, causing the router to stop attempting.
|
||||||
|
name: "MP terminal",
|
||||||
|
|
||||||
steps: []string{
|
steps: []string{
|
||||||
routerInitPayment,
|
routerInitPayment,
|
||||||
|
|
||||||
@@ -554,6 +580,21 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
testPaymentLifecycle(
|
||||||
|
t, test, paymentAmt, startingBlockHeight,
|
||||||
|
testGraph,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPaymentLifecycle(t *testing.T, test paymentLifecycleTestCase,
|
||||||
|
paymentAmt lnwire.MilliSatoshi, startingBlockHeight uint32,
|
||||||
|
testGraph *testGraphInstance) {
|
||||||
|
|
||||||
// Create a mock control tower with channels set up, that we use to
|
// Create a mock control tower with channels set up, that we use to
|
||||||
// synchronize and listen for events.
|
// synchronize and listen for events.
|
||||||
control := makeMockControlTower()
|
control := makeMockControlTower()
|
||||||
@@ -644,7 +685,6 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
// Craft a LightningPayment struct.
|
// Craft a LightningPayment struct.
|
||||||
var preImage lntypes.Preimage
|
var preImage lntypes.Preimage
|
||||||
if _, err := rand.Read(preImage[:]); err != nil {
|
if _, err := rand.Read(preImage[:]); err != nil {
|
||||||
@@ -900,4 +940,3 @@ func TestRouterPaymentStateMachine(t *testing.T) {
|
|||||||
t.Fatalf("SendPayment didn't exit")
|
t.Fatalf("SendPayment didn't exit")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user