routing/test: block on pathfinding in tests

This commit adds a step to our payment lifecycle test to add
control over when we find a path for our payment, This is
required for testing race conditions around pathfinding
completing and payment failures being reported.
This commit is contained in:
carla 2021-04-23 08:39:43 +02:00
parent a68155545c
commit 125980afb7
No known key found for this signature in database
GPG Key ID: 4CA7FE54A6213C91
2 changed files with 66 additions and 3 deletions

@ -84,6 +84,7 @@ func (m *mockPaymentAttemptDispatcher) setPaymentResult(
type mockPaymentSessionSource struct {
routes []*route.Route
routeRelease chan struct{}
}
var _ PaymentSessionSource = (*mockPaymentSessionSource)(nil)
@ -91,7 +92,10 @@ var _ PaymentSessionSource = (*mockPaymentSessionSource)(nil)
func (m *mockPaymentSessionSource) NewPaymentSession(
_ *LightningPayment) (PaymentSession, error) {
return &mockPaymentSession{m.routes}, nil
return &mockPaymentSession{
routes: m.routes,
release: m.routeRelease,
}, nil
}
func (m *mockPaymentSessionSource) NewPaymentSessionForRoute(
@ -137,6 +141,11 @@ func (m *mockMissionControl) GetProbability(fromNode, toNode route.Vertex,
type mockPaymentSession struct {
routes []*route.Route
// release is a channel that optionally blocks requesting a route
// from our mock payment channel. If this value is nil, we will just
// release the route automatically.
release chan struct{}
}
var _ PaymentSession = (*mockPaymentSession)(nil)
@ -144,6 +153,10 @@ var _ PaymentSession = (*mockPaymentSession)(nil)
func (m *mockPaymentSession) RequestRoute(_, _ lnwire.MilliSatoshi,
_, height uint32) (*route.Route, error) {
if m.release != nil {
m.release <- struct{}{}
}
if len(m.routes) == 0 {
return nil, errNoPathFound
}

@ -89,6 +89,10 @@ const (
// to call the Fail method on the control tower.
routerFailPayment = "Router:fail-payment"
// routeRelease is a test step where we unblock pathfinding and
// allow it to respond to our test with a route.
routeRelease = "PaymentSession:release"
// sendToSwitchSuccess is a step where we expect the router to
// call send the payment attempt to the switch, and we will
// respond with a non-error, indicating that the payment
@ -205,6 +209,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
getPaymentResultSuccess,
@ -220,6 +225,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -228,6 +234,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerFailAttempt,
// The router should retry.
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -246,6 +253,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerRegisterAttempt,
// Make the first sent attempt fail.
@ -253,6 +261,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerFailAttempt,
// The router should retry.
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -271,6 +280,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -278,6 +288,8 @@ func TestRouterPaymentStateMachine(t *testing.T) {
getPaymentResultTempFailure,
routerFailAttempt,
routeRelease,
// Since there are no more routes to try, the
// payment should fail.
routerFailPayment,
@ -293,6 +305,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerFailPayment,
paymentError,
},
@ -308,6 +321,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerRegisterAttempt,
// Manually resend the payment, the router
@ -350,6 +364,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -375,6 +390,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
steps: []string{
routerInitPayment,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -390,6 +406,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// Since we have no more routes to try, the
// original payment should fail.
routeRelease,
routerFailPayment,
paymentError,
@ -397,6 +414,7 @@ func TestRouterPaymentStateMachine(t *testing.T) {
// allowed, since the payment has failed.
resendPayment,
routerInitPayment,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
getPaymentResultSuccess,
@ -418,18 +436,22 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerInitPayment,
// shard 0
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 1
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 2
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 3
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -460,18 +482,22 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerInitPayment,
// shard 0
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 1
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 2
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 3
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -481,8 +507,10 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerFailAttempt,
routerFailAttempt,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -512,10 +540,12 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerInitPayment,
// shard 0
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 1
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -524,6 +554,10 @@ func TestRouterPaymentStateMachine(t *testing.T) {
getPaymentResultTempFailure,
routerFailAttempt,
// We will try one more shard because we haven't
// sent the full payment amount.
routeRelease,
// The second shard succeed against all odds,
// making the overall payment succeed.
getPaymentResultSuccess,
@ -541,18 +575,22 @@ func TestRouterPaymentStateMachine(t *testing.T) {
routerInitPayment,
// shard 0
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 1
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 2
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
// shard 3
routeRelease,
routerRegisterAttempt,
sendToSwitchSuccess,
@ -697,8 +735,12 @@ func testPaymentLifecycle(t *testing.T, test paymentLifecycleTestCase,
PaymentHash: payHash,
}
// Setup our payment session source to block on release of
// routes.
routeChan := make(chan struct{})
router.cfg.SessionSource = &mockPaymentSessionSource{
routes: test.routes,
routeRelease: routeChan,
}
router.cfg.MissionControl = &mockMissionControl{}
@ -729,6 +771,14 @@ func testPaymentLifecycle(t *testing.T, test paymentLifecycleTestCase,
t.Fatalf("expected non-nil CreationInfo")
}
case routeRelease:
select {
case <-routeChan:
case <-time.After(stepTimeout):
t.Fatalf("no route requested")
}
// In this step we expect the router to make a call to
// register a new attempt with the ControlTower.
case routerRegisterAttempt: