routing/tests: move lock acquisition after state driving channels

In our payment lifecycle tests, we have two goroutines that
compete for the lock in our mock control tower: the resumePayment
loop which tries to call RegisterAttempt, and the collectResult
handler which is launched in a goroutine by collectResultAsync
and is responsible for various settle/fail calls.

The order that the lock is acquired by these goroutines is
arbitrary, and can lead to flakes in our tests if the step
that we do not intend to execute first gets the lock (eg,
we want to fail a payment in collectResult, but RegisterAttempt
gets there first). This commit moves contention for this lock
after our mock's various "state driving" channels, so that the
lock will be acquired in the order that the test intends it.
This commit is contained in:
carla 2021-04-23 08:39:39 +02:00
parent b2d941ebfb
commit 9a78e9da73
No known key found for this signature in database
GPG Key ID: 4CA7FE54A6213C91

View File

@ -248,13 +248,13 @@ func makeMockControlTower() *mockControlTower {
func (m *mockControlTower) InitPayment(phash lntypes.Hash, func (m *mockControlTower) InitPayment(phash lntypes.Hash,
c *channeldb.PaymentCreationInfo) error { c *channeldb.PaymentCreationInfo) error {
m.Lock()
defer m.Unlock()
if m.init != nil { if m.init != nil {
m.init <- initArgs{c} m.init <- initArgs{c}
} }
m.Lock()
defer m.Unlock()
// Don't allow re-init a successful payment. // Don't allow re-init a successful payment.
if _, ok := m.successful[phash]; ok { if _, ok := m.successful[phash]; ok {
return channeldb.ErrAlreadyPaid return channeldb.ErrAlreadyPaid
@ -279,13 +279,13 @@ func (m *mockControlTower) InitPayment(phash lntypes.Hash,
func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash, func (m *mockControlTower) RegisterAttempt(phash lntypes.Hash,
a *channeldb.HTLCAttemptInfo) error { a *channeldb.HTLCAttemptInfo) error {
m.Lock()
defer m.Unlock()
if m.registerAttempt != nil { if m.registerAttempt != nil {
m.registerAttempt <- registerAttemptArgs{a} m.registerAttempt <- registerAttemptArgs{a}
} }
m.Lock()
defer m.Unlock()
// Cannot register attempts for successful or failed payments. // Cannot register attempts for successful or failed payments.
if _, ok := m.successful[phash]; ok { if _, ok := m.successful[phash]; ok {
return channeldb.ErrPaymentAlreadySucceeded return channeldb.ErrPaymentAlreadySucceeded
@ -312,13 +312,13 @@ func (m *mockControlTower) SettleAttempt(phash lntypes.Hash,
pid uint64, settleInfo *channeldb.HTLCSettleInfo) ( pid uint64, settleInfo *channeldb.HTLCSettleInfo) (
*channeldb.HTLCAttempt, error) { *channeldb.HTLCAttempt, error) {
m.Lock()
defer m.Unlock()
if m.settleAttempt != nil { if m.settleAttempt != nil {
m.settleAttempt <- settleAttemptArgs{settleInfo.Preimage} m.settleAttempt <- settleAttemptArgs{settleInfo.Preimage}
} }
m.Lock()
defer m.Unlock()
// Only allow setting attempts if the payment is known. // Only allow setting attempts if the payment is known.
p, ok := m.payments[phash] p, ok := m.payments[phash]
if !ok { if !ok {
@ -353,13 +353,13 @@ func (m *mockControlTower) SettleAttempt(phash lntypes.Hash,
func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64, func (m *mockControlTower) FailAttempt(phash lntypes.Hash, pid uint64,
failInfo *channeldb.HTLCFailInfo) (*channeldb.HTLCAttempt, error) { failInfo *channeldb.HTLCFailInfo) (*channeldb.HTLCAttempt, error) {
m.Lock()
defer m.Unlock()
if m.failAttempt != nil { if m.failAttempt != nil {
m.failAttempt <- failAttemptArgs{failInfo} m.failAttempt <- failAttemptArgs{failInfo}
} }
m.Lock()
defer m.Unlock()
// 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 {
@ -437,13 +437,13 @@ func (m *mockControlTower) FetchPayment(phash lntypes.Hash) (
func (m *mockControlTower) FetchInFlightPayments() ( func (m *mockControlTower) FetchInFlightPayments() (
[]*channeldb.InFlightPayment, error) { []*channeldb.InFlightPayment, error) {
m.Lock()
defer m.Unlock()
if m.fetchInFlight != nil { if m.fetchInFlight != nil {
m.fetchInFlight <- struct{}{} m.fetchInFlight <- struct{}{}
} }
m.Lock()
defer m.Unlock()
// In flight are all payments not successful or failed. // In flight are all payments not successful or failed.
var fl []*channeldb.InFlightPayment var fl []*channeldb.InFlightPayment
for hash, p := range m.payments { for hash, p := range m.payments {