channeldb+invoices: fix what pending invoice means in ChannelDB

This commits builds on top of PR #3694 to further clarify invoice
state by defining pending invoices as the ones which are not
settled or canceled. Automatic cancellation of expired invoices
makes this possbile. While this change only directly affects
ChannelDB, users of the listinvoices RPC will receive actual
pending invoices when pending_only flag is set.
This commit is contained in:
Andras Banki-Horvath committed 2019-12-19 17:44:32 +01:00
1 parent 9b60685961
commit fa14ff67ad
5 files changed
+113 -25

No files matched your search

+87 -1
View File
@@ -52,6 +52,29 @@ func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) {
return i, nil
}
// Tests that pending invoices are those which are either in ContractOpen or
// in ContractAccepted state.
func TestInvoiceIsPending(t *testing.T) {
contractStates := []ContractState{
ContractOpen, ContractSettled, ContractCanceled, ContractAccepted,
}
for _, state := range contractStates {
invoice := Invoice{
State: state,
}
// We expect that an invoice is pending if it's either in ContractOpen
// or ContractAccepted state.
pending := (state == ContractOpen || state == ContractAccepted)
if invoice.IsPending() != pending {
t.Fatalf("expected pending: %v, got: %v, invoice: %v",
pending, invoice.IsPending(), invoice)
}
}
}
func TestInvoiceWorkflow(t *testing.T) {
t.Parallel()
@@ -436,7 +459,7 @@ func TestFetchAllInvoicesWithPaymentHash(t *testing.T) {
invoice.State = states[i%len(states)]
paymentHash := invoice.Terms.PaymentPreimage.Hash()
if invoice.State != ContractSettled && invoice.State != ContractCanceled {
if invoice.IsPending() {
testPendingInvoices[paymentHash] = invoice
}
@@ -579,6 +602,69 @@ func TestDuplicateSettleInvoice(t *testing.T) {
}
}
// TestFetchAllInvoices tests that FetchAllInvoices works as expected.
func TestFetchAllInvoices(t *testing.T) {
t.Parallel()
db, cleanUp, err := makeTestDB()
defer cleanUp()
if err != nil {
t.Fatalf("unable to make test db: %v", err)
}
contractStates := []ContractState{
ContractOpen, ContractSettled, ContractCanceled, ContractAccepted,
}
numInvoices := len(contractStates) * 2
var expectedPendingInvoices []Invoice
var expectedAllInvoices []Invoice
for i := 1; i <= numInvoices; i++ {
invoice, err := randInvoice(lnwire.MilliSatoshi(i))
if err != nil {
t.Fatalf("unable to create invoice: %v", err)
}
invoice.AddIndex = uint64(i)
// Set the contract state of the next invoice such that there's an equal
// number for all possbile states.
invoice.State = contractStates[i%len(contractStates)]
paymentHash := invoice.Terms.PaymentPreimage.Hash()
if invoice.IsPending() {
expectedPendingInvoices = append(expectedPendingInvoices, *invoice)
}
expectedAllInvoices = append(expectedAllInvoices, *invoice)
if _, err := db.AddInvoice(invoice, paymentHash); err != nil {
t.Fatalf("unable to add invoice: %v", err)
}
}
pendingInvoices, err := db.FetchAllInvoices(true)
if err != nil {
t.Fatalf("unable to fetch all pending invoices: %v", err)
}
allInvoices, err := db.FetchAllInvoices(false)
if err != nil {
t.Fatalf("unable to fetch all non pending invoices: %v", err)
}
if !reflect.DeepEqual(pendingInvoices, expectedPendingInvoices) {
t.Fatalf("pending invoices: %v\n != \n expected einvoices: %v",
spew.Sdump(pendingInvoices), spew.Sdump(expectedPendingInvoices))
}
if !reflect.DeepEqual(allInvoices, expectedAllInvoices) {
t.Fatalf("pending + non pending: %v\n != \n expected: %v",
spew.Sdump(allInvoices), spew.Sdump(expectedAllInvoices))
}
}
// TestQueryInvoices ensures that we can properly query the invoice database for
// invoices using different types of queries.
func TestQueryInvoices(t *testing.T) {