routing/payment_lifecycle_test+mock: set up listener for FailAttempt

Also rename Success to SettleAttempt in the tests.
This commit is contained in:
Johan T. Halseth 2020-04-01 00:13:26 +02:00
parent aa9c971dc0
commit 2e63b518b7
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26
2 changed files with 77 additions and 43 deletions

@ -176,15 +176,19 @@ type initArgs struct {
c *channeldb.PaymentCreationInfo c *channeldb.PaymentCreationInfo
} }
type registerArgs struct { type registerAttemptArgs struct {
a *channeldb.HTLCAttemptInfo a *channeldb.HTLCAttemptInfo
} }
type successArgs struct { type settleAttemptArgs struct {
preimg lntypes.Preimage preimg lntypes.Preimage
} }
type failArgs struct { type failAttemptArgs struct {
reason *channeldb.HTLCFailInfo
}
type failPaymentArgs struct {
reason channeldb.FailureReason reason channeldb.FailureReason
} }
@ -198,11 +202,12 @@ type mockControlTower struct {
successful map[lntypes.Hash]struct{} successful map[lntypes.Hash]struct{}
failed map[lntypes.Hash]channeldb.FailureReason failed map[lntypes.Hash]channeldb.FailureReason
init chan initArgs init chan initArgs
register chan registerArgs registerAttempt chan registerAttemptArgs
success chan successArgs settleAttempt chan settleAttemptArgs
fail chan failArgs failAttempt chan failAttemptArgs
fetchInFlight chan struct{} failPayment chan failPaymentArgs
fetchInFlight chan struct{}
sync.Mutex sync.Mutex
} }
@ -254,8 +259,8 @@ func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash,
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
if m.register != nil { if m.registerAttempt != nil {
m.register <- registerArgs{a} m.registerAttempt <- registerAttemptArgs{a}
} }
// Cannot register attempts for successful or failed payments. // Cannot register attempts for successful or failed payments.
@ -286,8 +291,8 @@ func (m *mockControlTower) SettleAttempt(phash lntypes.Hash,
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
if m.success != nil { if m.settleAttempt != nil {
m.success <- successArgs{settleInfo.Preimage} m.settleAttempt <- settleAttemptArgs{settleInfo.Preimage}
} }
// Only allow setting attempts if the payment is known. // Only allow setting attempts if the payment is known.
@ -325,6 +330,10 @@ func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64,
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
if m.failAttempt != nil {
m.failAttempt <- failAttemptArgs{failInfo}
}
// Only allow failing attempts if the payment is known. // Only allow failing attempts if the payment is known.
p, ok := m.payments[phash] p, ok := m.payments[phash]
if !ok { if !ok {
@ -357,8 +366,8 @@ func (m *mockControlTower) Fail(phash lntypes.Hash,
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
if m.fail != nil { if m.failPayment != nil {
m.fail <- failArgs{reason} m.failPayment <- failPaymentArgs{reason}
} }
// Payment must be known. // Payment must be known.

@ -109,13 +109,18 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// tower. // tower.
routerRegisterAttempt = "Router:register-attempt" routerRegisterAttempt = "Router:register-attempt"
// routerSuccess is a test step where we expect the router to // routerSettleAttempt is a test step where we expect the
// call the Success method on the control tower. // router to call the SettleAttempt method on the control
routerSuccess = "Router:success" // tower.
routerSettleAttempt = "Router:settle-attempt"
// routerFail is a test step where we expect the router to call // routerFailAttempt is a test step where we expect the router
// the Fail method on the control tower. // to call the FailAttempt method on the control tower.
routerFail = "Router:fail" routerFailAttempt = "Router:fail-attempt"
// routerFailPayment is a test step where we expect the router
// to call the Fail method on the control tower.
routerFailPayment = "Router:fail-payment"
// sendToSwitchSuccess is a step where we expect the router to // sendToSwitchSuccess is a step where we expect the router to
// call send the payment attempt to the switch, and we will // call send the payment attempt to the switch, and we will
@ -178,7 +183,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerRegisterAttempt, routerRegisterAttempt,
sendToSwitchSuccess, sendToSwitchSuccess,
getPaymentResultSuccess, getPaymentResultSuccess,
routerSuccess, routerSettleAttempt,
paymentSuccess, paymentSuccess,
}, },
routes: []*route.Route{rt}, routes: []*route.Route{rt},
@ -193,6 +198,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Make the first sent attempt fail. // Make the first sent attempt fail.
getPaymentResultFailure, getPaymentResultFailure,
routerFailAttempt,
// The router should retry. // The router should retry.
routerRegisterAttempt, routerRegisterAttempt,
@ -200,7 +206,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Make the second sent attempt succeed. // Make the second sent attempt succeed.
getPaymentResultSuccess, getPaymentResultSuccess,
routerSuccess, routerSettleAttempt,
paymentSuccess, paymentSuccess,
}, },
routes: []*route.Route{rt, rt}, routes: []*route.Route{rt, rt},
@ -215,6 +221,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Make the first sent attempt fail. // Make the first sent attempt fail.
sendToSwitchResultFailure, sendToSwitchResultFailure,
routerFailAttempt,
// The router should retry. // The router should retry.
routerRegisterAttempt, routerRegisterAttempt,
@ -222,7 +229,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Make the second sent attempt succeed. // Make the second sent attempt succeed.
getPaymentResultSuccess, getPaymentResultSuccess,
routerSuccess, routerSettleAttempt,
paymentSuccess, paymentSuccess,
}, },
routes: []*route.Route{rt, rt}, routes: []*route.Route{rt, rt},
@ -238,10 +245,11 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Make the first sent attempt fail. // Make the first sent attempt fail.
getPaymentResultFailure, getPaymentResultFailure,
routerFailAttempt,
// Since there are no more routes to try, the // Since there are no more routes to try, the
// payment should fail. // payment should fail.
routerFail, routerFailPayment,
paymentError, paymentError,
}, },
routes: []*route.Route{rt}, routes: []*route.Route{rt},
@ -251,7 +259,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// no routes to try. // no routes to try.
steps: []string{ steps: []string{
routerInitPayment, routerInitPayment,
routerFail, routerFailPayment,
paymentError, paymentError,
}, },
routes: []*route.Route{}, routes: []*route.Route{},
@ -286,7 +294,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Notify about a success for the original // Notify about a success for the original
// payment. // payment.
getPaymentResultSuccess, getPaymentResultSuccess,
routerSuccess, routerSettleAttempt,
// Now that the original payment finished, // Now that the original payment finished,
// resend it again to ensure this is not // resend it again to ensure this is not
@ -316,7 +324,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// control tower. // control tower.
startRouter, startRouter,
getPaymentResultSuccess, getPaymentResultSuccess,
routerSuccess, routerSettleAttempt,
}, },
routes: []*route.Route{rt}, routes: []*route.Route{rt},
}, },
@ -336,10 +344,11 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Make the first attempt fail. // Make the first attempt fail.
getPaymentResultFailure, getPaymentResultFailure,
routerFail, routerFailAttempt,
// Since we have no more routes to try, the // Since we have no more routes to try, the
// original payment should fail. // original payment should fail.
routerFailPayment,
paymentError, paymentError,
// Now resend the payment again. This should be // Now resend the payment again. This should be
@ -349,7 +358,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerRegisterAttempt, routerRegisterAttempt,
sendToSwitchSuccess, sendToSwitchSuccess,
getPaymentResultSuccess, getPaymentResultSuccess,
routerSuccess, routerSettleAttempt,
resentPaymentSuccess, resentPaymentSuccess,
}, },
routes: []*route.Route{rt}, routes: []*route.Route{rt},
@ -360,9 +369,10 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// synchronize and listen for events. // synchronize and listen for events.
control := makeMockControlTower() control := makeMockControlTower()
control.init = make(chan initArgs) control.init = make(chan initArgs)
control.register = make(chan registerArgs) control.registerAttempt = make(chan registerAttemptArgs)
control.success = make(chan successArgs) control.settleAttempt = make(chan settleAttemptArgs)
control.fail = make(chan failArgs) control.failAttempt = make(chan failAttemptArgs)
control.failPayment = make(chan failPaymentArgs)
control.fetchInFlight = make(chan struct{}) control.fetchInFlight = make(chan struct{})
quit := make(chan struct{}) quit := make(chan struct{})
@ -497,11 +507,12 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// In this step we expect the router to make a call to // In this step we expect the router to make a call to
// register a new attempt with the ControlTower. // register a new attempt with the ControlTower.
case routerRegisterAttempt: case routerRegisterAttempt:
var args registerArgs var args registerAttemptArgs
select { select {
case args = <-control.register: case args = <-control.registerAttempt:
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
t.Fatalf("not registered with control") t.Fatalf("attempt not registered " +
"with control")
} }
if args.a == nil { if args.a == nil {
@ -509,22 +520,35 @@ func TestRouterPaymentStateMachine(t *testing.T) {
} }
// In this step we expect the router to call the // In this step we expect the router to call the
// ControlTower's Succcess method with the preimage. // ControlTower's SettleAttempt method with the preimage.
case routerSuccess: case routerSettleAttempt:
select { select {
case <-control.success: case <-control.settleAttempt:
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
t.Fatalf("not registered with control") t.Fatalf("attempt settle not " +
"registered with control")
}
// In this step we expect the router to call the
// ControlTower's FailAttempt method with a HTLC fail
// info.
case routerFailAttempt:
select {
case <-control.failAttempt:
case <-time.After(1 * time.Second):
t.Fatalf("attempt fail not " +
"registered with control")
} }
// In this step we expect the router to call the // In this step we expect the router to call the
// ControlTower's Fail method, to indicate that the // ControlTower's Fail method, to indicate that the
// payment failed. // payment failed.
case routerFail: case routerFailPayment:
select { select {
case <-control.fail: case <-control.failPayment:
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
t.Fatalf("not registered with control") t.Fatalf("payment fail not " +
"registered with control")
} }
// In this step we expect the SendToSwitch method to be // In this step we expect the SendToSwitch method to be
@ -625,7 +649,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
select { select {
case err := <-paymentResult: case err := <-paymentResult:
if err != nil { if err != nil {
t.Fatalf("did not expecte error %v", err) t.Fatalf("did not expect "+
"error %v", err)
} }
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):