routing: patch unit tests for payment lifecycle

This commit adds unit tests for `resumePayment`. In addition, the
`resumePayment` has been split into two parts so it's easier to be
tested, 1) sending the htlc, and 2) collecting results. As seen in the
new tests, this split largely reduces the complexity involved and makes
the unit test flow sequential.

This commit also makes full use of `mock.Mock` in the unit tests to
provide a more clear testing flow.
This commit is contained in:
yyforyongyu 2023-03-08 02:50:33 +08:00
parent e46c689bf1
commit 10052ff4f5
No known key found for this signature in database
GPG Key ID: 9BCD95C4FF296868
2 changed files with 1156 additions and 24 deletions

View File

@ -41,6 +41,12 @@ type paymentLifecycle struct {
// or failed with temporary error. Otherwise, we should exit the
// lifecycle loop as a terminal error has occurred.
resultCollected chan error
// resultCollector is a function that is used to collect the result of
// an HTLC attempt, which is always mounted to `p.collectResultAsync`
// except in unit test, where we use a much simpler resultCollector to
// decouple the test flow for the payment lifecycle.
resultCollector func(attempt *channeldb.HTLCAttempt)
}
// newPaymentLifecycle initiates a new payment lifecycle and returns it.
@ -60,6 +66,9 @@ func newPaymentLifecycle(r *ChannelRouter, feeLimit lnwire.MilliSatoshi,
resultCollected: make(chan error, 1),
}
// Mount the result collector.
p.resultCollector = p.collectResultAsync
// If a timeout is specified, create a timeout channel. If no timeout is
// specified, the channel is left nil and will never abort the payment
// loop.
@ -178,7 +187,7 @@ func (p *paymentLifecycle) resumePayment() ([32]byte, *route.Route, error) {
log.Infof("Resuming payment shard %v for payment %v",
a.AttemptID, p.identifier)
p.collectResultAsync(&a)
p.resultCollector(&a)
}
// exitWithErr is a helper closure that logs and returns an error.
@ -280,7 +289,7 @@ lifecycle:
// Now that the shard was successfully sent, launch a go
// routine that will handle its result when its back.
if result.err == nil {
p.collectResultAsync(attempt)
p.resultCollector(attempt)
}
}
@ -416,6 +425,9 @@ type attemptResult struct {
// will send a nil error to channel `resultCollected` to indicate there's an
// result.
func (p *paymentLifecycle) collectResultAsync(attempt *channeldb.HTLCAttempt) {
log.Debugf("Collecting result for attempt %v in payment %v",
attempt.AttemptID, p.identifier)
go func() {
// Block until the result is available.
_, err := p.collectResult(attempt)

File diff suppressed because it is too large Load Diff