2019-12-09 19:50:11 +03:00
|
|
|
package invoices
|
|
|
|
|
|
|
|
import (
|
2020-04-09 10:58:22 +03:00
|
|
|
"sync"
|
2019-12-09 19:50:11 +03:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2020-01-23 02:21:12 +03:00
|
|
|
"github.com/lightningnetwork/lnd/channeldb"
|
2019-12-09 19:50:11 +03:00
|
|
|
"github.com/lightningnetwork/lnd/clock"
|
|
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
|
|
)
|
|
|
|
|
|
|
|
// invoiceExpiryWatcherTest holds a test fixture and implements checks
|
|
|
|
// for InvoiceExpiryWatcher tests.
|
|
|
|
type invoiceExpiryWatcherTest struct {
|
|
|
|
t *testing.T
|
2020-04-09 10:58:22 +03:00
|
|
|
wg sync.WaitGroup
|
2019-12-09 19:50:11 +03:00
|
|
|
watcher *InvoiceExpiryWatcher
|
|
|
|
testData invoiceExpiryTestData
|
|
|
|
canceledInvoices []lntypes.Hash
|
|
|
|
}
|
|
|
|
|
|
|
|
// newInvoiceExpiryWatcherTest creates a new InvoiceExpiryWatcher test fixture
|
|
|
|
// and sets up the test environment.
|
|
|
|
func newInvoiceExpiryWatcherTest(t *testing.T, now time.Time,
|
|
|
|
numExpiredInvoices, numPendingInvoices int) *invoiceExpiryWatcherTest {
|
|
|
|
|
|
|
|
test := &invoiceExpiryWatcherTest{
|
|
|
|
watcher: NewInvoiceExpiryWatcher(clock.NewTestClock(testTime)),
|
|
|
|
testData: generateInvoiceExpiryTestData(
|
|
|
|
t, now, 0, numExpiredInvoices, numPendingInvoices,
|
|
|
|
),
|
|
|
|
}
|
|
|
|
|
2020-04-09 10:58:22 +03:00
|
|
|
test.wg.Add(numExpiredInvoices)
|
|
|
|
|
2020-04-09 11:42:10 +03:00
|
|
|
err := test.watcher.Start(func(paymentHash lntypes.Hash,
|
|
|
|
force bool) error {
|
|
|
|
|
2020-07-17 15:24:54 +03:00
|
|
|
test.canceledInvoices = append(
|
|
|
|
test.canceledInvoices, paymentHash,
|
|
|
|
)
|
2020-04-09 10:58:22 +03:00
|
|
|
test.wg.Done()
|
2019-12-09 19:50:11 +03:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("cannot start InvoiceExpiryWatcher: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return test
|
|
|
|
}
|
|
|
|
|
2020-04-09 10:58:22 +03:00
|
|
|
func (t *invoiceExpiryWatcherTest) waitForFinish(timeout time.Duration) {
|
|
|
|
done := make(chan struct{})
|
|
|
|
|
|
|
|
// Wait for all cancels.
|
|
|
|
go func() {
|
|
|
|
t.wg.Wait()
|
|
|
|
close(done)
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-done:
|
|
|
|
case <-time.After(timeout):
|
|
|
|
t.t.Fatalf("test timeout")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-09 19:50:11 +03:00
|
|
|
func (t *invoiceExpiryWatcherTest) checkExpectations() {
|
|
|
|
// Check that invoices that got canceled during the test are the ones
|
|
|
|
// that expired.
|
|
|
|
if len(t.canceledInvoices) != len(t.testData.expiredInvoices) {
|
|
|
|
t.t.Fatalf("expected %v cancellations, got %v",
|
2020-07-17 15:24:54 +03:00
|
|
|
len(t.testData.expiredInvoices),
|
|
|
|
len(t.canceledInvoices))
|
2019-12-09 19:50:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := range t.canceledInvoices {
|
|
|
|
if _, ok := t.testData.expiredInvoices[t.canceledInvoices[i]]; !ok {
|
|
|
|
t.t.Fatalf("wrong invoice canceled")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that InvoiceExpiryWatcher can be started and stopped.
|
|
|
|
func TestInvoiceExpiryWatcherStartStop(t *testing.T) {
|
|
|
|
watcher := NewInvoiceExpiryWatcher(clock.NewTestClock(testTime))
|
2020-04-09 11:42:10 +03:00
|
|
|
cancel := func(lntypes.Hash, bool) error {
|
2019-12-09 19:50:11 +03:00
|
|
|
t.Fatalf("unexpected call")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := watcher.Start(cancel); err != nil {
|
|
|
|
t.Fatalf("unexpected error upon start: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := watcher.Start(cancel); err == nil {
|
|
|
|
t.Fatalf("expected error upon second start")
|
|
|
|
}
|
|
|
|
|
|
|
|
watcher.Stop()
|
|
|
|
|
|
|
|
if err := watcher.Start(cancel); err != nil {
|
|
|
|
t.Fatalf("unexpected error upon start: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that no invoices will expire from an empty InvoiceExpiryWatcher.
|
|
|
|
func TestInvoiceExpiryWithNoInvoices(t *testing.T) {
|
|
|
|
t.Parallel()
|
2020-04-09 10:58:22 +03:00
|
|
|
|
2019-12-09 19:50:11 +03:00
|
|
|
test := newInvoiceExpiryWatcherTest(t, testTime, 0, 0)
|
|
|
|
|
2020-04-09 10:58:22 +03:00
|
|
|
test.waitForFinish(testTimeout)
|
2019-12-09 19:50:11 +03:00
|
|
|
test.watcher.Stop()
|
|
|
|
test.checkExpectations()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that if all add invoices are expired, then all invoices
|
|
|
|
// will be canceled.
|
|
|
|
func TestInvoiceExpiryWithOnlyExpiredInvoices(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
test := newInvoiceExpiryWatcherTest(t, testTime, 0, 5)
|
|
|
|
|
|
|
|
for paymentHash, invoice := range test.testData.pendingInvoices {
|
|
|
|
test.watcher.AddInvoice(paymentHash, invoice)
|
|
|
|
}
|
|
|
|
|
2020-04-09 10:58:22 +03:00
|
|
|
test.waitForFinish(testTimeout)
|
2019-12-09 19:50:11 +03:00
|
|
|
test.watcher.Stop()
|
|
|
|
test.checkExpectations()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that if some invoices are expired, then those invoices
|
|
|
|
// will be canceled.
|
|
|
|
func TestInvoiceExpiryWithPendingAndExpiredInvoices(t *testing.T) {
|
|
|
|
t.Parallel()
|
2020-04-09 10:58:22 +03:00
|
|
|
|
2019-12-09 19:50:11 +03:00
|
|
|
test := newInvoiceExpiryWatcherTest(t, testTime, 5, 5)
|
|
|
|
|
|
|
|
for paymentHash, invoice := range test.testData.expiredInvoices {
|
|
|
|
test.watcher.AddInvoice(paymentHash, invoice)
|
|
|
|
}
|
|
|
|
|
|
|
|
for paymentHash, invoice := range test.testData.pendingInvoices {
|
|
|
|
test.watcher.AddInvoice(paymentHash, invoice)
|
|
|
|
}
|
|
|
|
|
2020-04-09 10:58:22 +03:00
|
|
|
test.waitForFinish(testTimeout)
|
2019-12-09 19:50:11 +03:00
|
|
|
test.watcher.Stop()
|
|
|
|
test.checkExpectations()
|
|
|
|
}
|
2020-01-23 02:21:12 +03:00
|
|
|
|
|
|
|
// Tests adding multiple invoices at once.
|
|
|
|
func TestInvoiceExpiryWhenAddingMultipleInvoices(t *testing.T) {
|
|
|
|
t.Parallel()
|
2020-04-09 10:58:22 +03:00
|
|
|
|
2020-01-23 02:21:12 +03:00
|
|
|
test := newInvoiceExpiryWatcherTest(t, testTime, 5, 5)
|
|
|
|
var invoices []channeldb.InvoiceWithPaymentHash
|
2020-04-09 10:58:22 +03:00
|
|
|
|
2020-01-23 02:21:12 +03:00
|
|
|
for hash, invoice := range test.testData.expiredInvoices {
|
|
|
|
invoices = append(invoices,
|
|
|
|
channeldb.InvoiceWithPaymentHash{
|
|
|
|
Invoice: *invoice,
|
|
|
|
PaymentHash: hash,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2020-04-09 10:58:22 +03:00
|
|
|
|
2020-01-23 02:21:12 +03:00
|
|
|
for hash, invoice := range test.testData.pendingInvoices {
|
|
|
|
invoices = append(invoices,
|
|
|
|
channeldb.InvoiceWithPaymentHash{
|
|
|
|
Invoice: *invoice,
|
|
|
|
PaymentHash: hash,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
test.watcher.AddInvoices(invoices)
|
2020-04-09 10:58:22 +03:00
|
|
|
test.waitForFinish(testTimeout)
|
2020-01-23 02:21:12 +03:00
|
|
|
test.watcher.Stop()
|
|
|
|
test.checkExpectations()
|
|
|
|
}
|