Skip to content

Commit e9475e3

Browse files
committed
accounts: add service disabled unit tests
1 parent 09ac4d8 commit e9475e3

File tree

1 file changed

+235
-16
lines changed

1 file changed

+235
-16
lines changed

accounts/service_test.go

Lines changed: 235 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ type mockLnd struct {
3232
invoiceReq chan lndclient.InvoiceSubscriptionRequest
3333
paymentReq chan lntypes.Hash
3434

35-
callErr error
36-
errChan chan error
37-
invoiceChan chan *lndclient.Invoice
38-
paymentChans map[lntypes.Hash]chan lndclient.PaymentStatus
35+
invoiceSubscriptionErr error
36+
trackPaymentErr error
37+
invoiceErrChan chan error
38+
paymentErrChan chan error
39+
invoiceChan chan *lndclient.Invoice
40+
paymentChans map[lntypes.Hash]chan lndclient.PaymentStatus
3941
}
4042

4143
func newMockLnd() *mockLnd {
@@ -44,9 +46,10 @@ func newMockLnd() *mockLnd {
4446
invoiceReq: make(
4547
chan lndclient.InvoiceSubscriptionRequest, 10,
4648
),
47-
paymentReq: make(chan lntypes.Hash, 10),
48-
errChan: make(chan error, 10),
49-
invoiceChan: make(chan *lndclient.Invoice),
49+
paymentReq: make(chan lntypes.Hash, 10),
50+
invoiceErrChan: make(chan error, 10),
51+
paymentErrChan: make(chan error, 10),
52+
invoiceChan: make(chan *lndclient.Invoice),
5053
paymentChans: make(
5154
map[lntypes.Hash]chan lndclient.PaymentStatus,
5255
),
@@ -72,6 +75,16 @@ func (m *mockLnd) assertMainErr(t *testing.T, expectedErr error) {
7275
}
7376
}
7477

78+
func (m *mockLnd) assertMainErrContains(t *testing.T, expectedStr string) {
79+
select {
80+
case err := <-m.mainErrChan:
81+
require.ErrorContains(t, err, expectedStr)
82+
83+
case <-time.After(testTimeout):
84+
t.Fatalf("Did not get expected main err before timeout")
85+
}
86+
}
87+
7588
func (m *mockLnd) assertNoInvoiceRequest(t *testing.T) {
7689
select {
7790
case req := <-m.invoiceReq:
@@ -132,28 +145,28 @@ func (m *mockLnd) SubscribeInvoices(_ context.Context,
132145
req lndclient.InvoiceSubscriptionRequest) (<-chan *lndclient.Invoice,
133146
<-chan error, error) {
134147

135-
if m.callErr != nil {
136-
return nil, nil, m.callErr
148+
if m.invoiceSubscriptionErr != nil {
149+
return nil, nil, m.invoiceSubscriptionErr
137150
}
138151

139152
m.invoiceReq <- req
140153

141-
return m.invoiceChan, m.errChan, nil
154+
return m.invoiceChan, m.invoiceErrChan, nil
142155
}
143156

144157
// TrackPayment picks up a previously started payment and returns a payment
145158
// update stream and an error stream.
146159
func (m *mockLnd) TrackPayment(_ context.Context,
147160
hash lntypes.Hash) (chan lndclient.PaymentStatus, chan error, error) {
148161

149-
if m.callErr != nil {
150-
return nil, nil, m.callErr
162+
if m.trackPaymentErr != nil {
163+
return nil, nil, m.trackPaymentErr
151164
}
152165

153166
m.paymentReq <- hash
154167
m.paymentChans[hash] = make(chan lndclient.PaymentStatus, 1)
155168

156-
return m.paymentChans[hash], m.errChan, nil
169+
return m.paymentChans[hash], m.paymentErrChan, nil
157170
}
158171

159172
// TestAccountService tests that the account service can track payments and
@@ -169,15 +182,92 @@ func TestAccountService(t *testing.T) {
169182
validate func(t *testing.T, lnd *mockLnd,
170183
s *InterceptorService)
171184
}{{
172-
name: "startup err on tracking payment",
185+
name: "startup err on invoice subscription",
173186
setup: func(t *testing.T, lnd *mockLnd, s *InterceptorService) {
174-
lnd.callErr = testErr
187+
lnd.invoiceSubscriptionErr = testErr
175188
},
176189
startupErr: testErr.Error(),
177190
validate: func(t *testing.T, lnd *mockLnd,
178191
s *InterceptorService) {
179192

180193
lnd.assertNoInvoiceRequest(t)
194+
require.False(t, s.IsRunning())
195+
},
196+
}, {
197+
name: "err on invoice update",
198+
setup: func(t *testing.T, lnd *mockLnd, s *InterceptorService) {
199+
acct := &OffChainBalanceAccount{
200+
ID: testID,
201+
Type: TypeInitialBalance,
202+
CurrentBalance: 1234,
203+
Invoices: AccountInvoices{
204+
testHash: {},
205+
},
206+
}
207+
208+
err := s.store.UpdateAccount(acct)
209+
require.NoError(t, err)
210+
},
211+
validate: func(t *testing.T, lnd *mockLnd,
212+
s *InterceptorService) {
213+
214+
// Start by closing the store. This should cause an
215+
// error once we make an invoice update, as the service
216+
// will fail when persisting the invoice update.
217+
s.store.Close()
218+
219+
// Ensure that the service was started successfully and
220+
// still running though, despite the closing of the
221+
// db store.
222+
require.True(t, s.IsRunning())
223+
224+
// Now let's send the invoice update, which should fail.
225+
lnd.invoiceChan <- &lndclient.Invoice{
226+
AddIndex: 12,
227+
SettleIndex: 12,
228+
Hash: testHash,
229+
AmountPaid: 777,
230+
State: invpkg.ContractSettled,
231+
}
232+
233+
// Ensure that the service was eventually disabled.
234+
assertEventually(t, func() bool {
235+
isRunning := s.IsRunning()
236+
return isRunning == false
237+
})
238+
lnd.assertMainErrContains(t, "database not open")
239+
},
240+
}, {
241+
name: "err in invoice err channel",
242+
setup: func(t *testing.T, lnd *mockLnd, s *InterceptorService) {
243+
acct := &OffChainBalanceAccount{
244+
ID: testID,
245+
Type: TypeInitialBalance,
246+
CurrentBalance: 1234,
247+
Invoices: AccountInvoices{
248+
testHash: {},
249+
},
250+
}
251+
252+
err := s.store.UpdateAccount(acct)
253+
require.NoError(t, err)
254+
},
255+
validate: func(t *testing.T, lnd *mockLnd,
256+
s *InterceptorService) {
257+
// Ensure that the service was started successfully.
258+
require.True(t, s.IsRunning())
259+
260+
// Now let's send an error over the invoice error
261+
// channel. This should disable the service.
262+
lnd.invoiceErrChan <- testErr
263+
264+
// Ensure that the service was eventually disabled.
265+
assertEventually(t, func() bool {
266+
isRunning := s.IsRunning()
267+
return isRunning == false
268+
})
269+
270+
lnd.assertMainErrContains(t, testErr.Error())
181271
},
182272
}, {
183273
name: "goroutine err sent on main err chan",
@@ -195,7 +285,7 @@ func TestAccountService(t *testing.T) {
195285
err := s.store.UpdateAccount(acct)
196286
require.NoError(t, err)
197287

198-
lnd.errChan <- testErr
288+
lnd.mainErrChan <- testErr
199289
},
200290
validate: func(t *testing.T, lnd *mockLnd,
201291
s *InterceptorService) {
@@ -227,6 +317,135 @@ func TestAccountService(t *testing.T) {
227317
lnd.assertNoPaymentRequest(t)
228318
lnd.assertInvoiceRequest(t, 0, 0)
229319
lnd.assertNoMainErr(t)
320+
require.True(t, s.IsRunning())
321+
},
322+
}, {
323+
name: "startup err on payment tracking",
324+
setup: func(t *testing.T, lnd *mockLnd, s *InterceptorService) {
325+
acct := &OffChainBalanceAccount{
326+
ID: testID,
327+
Type: TypeInitialBalance,
328+
CurrentBalance: 1234,
329+
Invoices: AccountInvoices{
330+
testHash: {},
331+
},
332+
Payments: AccountPayments{
333+
testHash: {
334+
Status: lnrpc.Payment_IN_FLIGHT,
335+
FullAmount: 1234,
336+
},
337+
},
338+
}
339+
340+
err := s.store.UpdateAccount(acct)
341+
require.NoError(t, err)
342+
343+
lnd.trackPaymentErr = testErr
344+
},
345+
validate: func(t *testing.T, lnd *mockLnd,
346+
s *InterceptorService) {
347+
348+
// Assert that the invoice subscription succeeded.
349+
require.Contains(t, s.invoiceToAccount, testHash)
350+
351+
// But setting up the payment tracking should have failed.
352+
require.False(t, s.IsRunning())
353+
354+
// Finally let's assert that we didn't successfully add the
355+
// payment to pending payment, and that lnd isn't awaiting
356+
// the payment request.
357+
require.NotContains(t, s.pendingPayments, testHash)
358+
lnd.assertNoPaymentRequest(t)
359+
},
360+
}, {
361+
name: "err on payment update",
362+
setup: func(t *testing.T, lnd *mockLnd, s *InterceptorService) {
363+
acct := &OffChainBalanceAccount{
364+
ID: testID,
365+
Type: TypeInitialBalance,
366+
CurrentBalance: 1234,
367+
Payments: AccountPayments{
368+
testHash: {
369+
Status: lnrpc.Payment_IN_FLIGHT,
370+
FullAmount: 1234,
371+
},
372+
},
373+
}
374+
375+
err := s.store.UpdateAccount(acct)
376+
require.NoError(t, err)
377+
},
378+
validate: func(t *testing.T, lnd *mockLnd,
379+
s *InterceptorService) {
380+
// Ensure that the service was started successfully,
381+
// and lnd contains the payment request.
382+
require.True(t, s.IsRunning())
383+
lnd.assertPaymentRequests(t, map[lntypes.Hash]struct{}{
384+
testHash: {},
385+
})
386+
387+
// Now let's wipe the service's pending payments.
388+
// This will cause an error send an update over
389+
// the payment channel, which should disable the
390+
// service.
391+
s.pendingPayments = make(map[lntypes.Hash]*trackedPayment)
392+
393+
// Send an invalid payment over the payment chan
394+
// which should error and disable the service
395+
lnd.paymentChans[testHash] <- lndclient.PaymentStatus{
396+
State: lnrpc.Payment_SUCCEEDED,
397+
Fee: 234,
398+
Value: 1000,
399+
}
400+
401+
// Ensure that the service was eventually disabled.
402+
assertEventually(t, func() bool {
403+
isRunning := s.IsRunning()
404+
return isRunning == false
405+
})
406+
lnd.assertMainErrContains(
407+
t, "not mapped to any account",
408+
)
409+
410+
},
411+
}, {
412+
name: "err in payment update chan",
413+
setup: func(t *testing.T, lnd *mockLnd, s *InterceptorService) {
414+
acct := &OffChainBalanceAccount{
415+
ID: testID,
416+
Type: TypeInitialBalance,
417+
CurrentBalance: 1234,
418+
Payments: AccountPayments{
419+
testHash: {
420+
Status: lnrpc.Payment_IN_FLIGHT,
421+
FullAmount: 1234,
422+
},
423+
},
424+
}
425+
426+
err := s.store.UpdateAccount(acct)
427+
require.NoError(t, err)
428+
},
429+
validate: func(t *testing.T, lnd *mockLnd,
430+
s *InterceptorService) {
431+
// Ensure that the service was started successfully,
432+
// and lnd contains the payment request.
433+
require.True(t, s.IsRunning())
434+
lnd.assertPaymentRequests(t, map[lntypes.Hash]struct{}{
435+
testHash: {},
436+
})
437+
438+
// Now let's send an error over the payment error
439+
// channel. This should disable the service.
440+
lnd.paymentErrChan <- testErr
441+
442+
// Ensure that the service was eventually disabled.
443+
assertEventually(t, func() bool {
444+
isRunning := s.IsRunning()
445+
return isRunning == false
446+
})
447+
448+
lnd.assertMainErrContains(t, testErr.Error())
230449
},
231450
}, {
232451
name: "startup track in-flight payments",

0 commit comments

Comments
 (0)