@@ -32,10 +32,12 @@ type mockLnd struct {
32
32
invoiceReq chan lndclient.InvoiceSubscriptionRequest
33
33
paymentReq chan lntypes.Hash
34
34
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
39
41
}
40
42
41
43
func newMockLnd () * mockLnd {
@@ -44,9 +46,10 @@ func newMockLnd() *mockLnd {
44
46
invoiceReq : make (
45
47
chan lndclient.InvoiceSubscriptionRequest , 10 ,
46
48
),
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 ),
50
53
paymentChans : make (
51
54
map [lntypes.Hash ]chan lndclient.PaymentStatus ,
52
55
),
@@ -144,28 +147,28 @@ func (m *mockLnd) SubscribeInvoices(_ context.Context,
144
147
req lndclient.InvoiceSubscriptionRequest ) (<- chan * lndclient.Invoice ,
145
148
<- chan error , error ) {
146
149
147
- if m .callErr != nil {
148
- return nil , nil , m .callErr
150
+ if m .invoiceSubscriptionErr != nil {
151
+ return nil , nil , m .invoiceSubscriptionErr
149
152
}
150
153
151
154
m .invoiceReq <- req
152
155
153
- return m .invoiceChan , m .errChan , nil
156
+ return m .invoiceChan , m .invoiceErrChan , nil
154
157
}
155
158
156
159
// TrackPayment picks up a previously started payment and returns a payment
157
160
// update stream and an error stream.
158
161
func (m * mockLnd ) TrackPayment (_ context.Context ,
159
162
hash lntypes.Hash ) (chan lndclient.PaymentStatus , chan error , error ) {
160
163
161
- if m .callErr != nil {
162
- return nil , nil , m .callErr
164
+ if m .trackPaymentErr != nil {
165
+ return nil , nil , m .trackPaymentErr
163
166
}
164
167
165
168
m .paymentReq <- hash
166
169
m .paymentChans [hash ] = make (chan lndclient.PaymentStatus , 1 )
167
170
168
- return m .paymentChans [hash ], m .errChan , nil
171
+ return m .paymentChans [hash ], m .paymentErrChan , nil
169
172
}
170
173
171
174
// TestAccountService tests that the account service can track payments and
@@ -181,15 +184,92 @@ func TestAccountService(t *testing.T) {
181
184
validate func (t * testing.T , lnd * mockLnd ,
182
185
s * InterceptorService )
183
186
}{{
184
- name : "startup err on tracking payment " ,
187
+ name : "startup err on invoice subscription " ,
185
188
setup : func (t * testing.T , lnd * mockLnd , s * InterceptorService ) {
186
- lnd .callErr = testErr
189
+ lnd .invoiceSubscriptionErr = testErr
187
190
},
188
191
startupErr : testErr .Error (),
189
192
validate : func (t * testing.T , lnd * mockLnd ,
190
193
s * InterceptorService ) {
191
194
192
195
lnd .assertNoInvoiceRequest (t )
196
+ require .False (t , s .IsRunning ())
197
+ },
198
+ }, {
199
+ name : "err on invoice update" ,
200
+ setup : func (t * testing.T , lnd * mockLnd , s * InterceptorService ) {
201
+ acct := & OffChainBalanceAccount {
202
+ ID : testID ,
203
+ Type : TypeInitialBalance ,
204
+ CurrentBalance : 1234 ,
205
+ Invoices : AccountInvoices {
206
+ testHash : {},
207
+ },
208
+ }
209
+
210
+ err := s .store .UpdateAccount (acct )
211
+ require .NoError (t , err )
212
+ },
213
+ validate : func (t * testing.T , lnd * mockLnd ,
214
+ s * InterceptorService ) {
215
+
216
+ // Start by closing the store. This should cause an
217
+ // error once we make an invoice update, as the service
218
+ // will fail when persisting the invoice update.
219
+ s .store .Close ()
220
+
221
+ // Ensure that the service was started successfully and
222
+ // still running though, despite the closing of the
223
+ // db store.
224
+ require .True (t , s .IsRunning ())
225
+
226
+ // Now let's send the invoice update, which should fail.
227
+ lnd .invoiceChan <- & lndclient.Invoice {
228
+ AddIndex : 12 ,
229
+ SettleIndex : 12 ,
230
+ Hash : testHash ,
231
+ AmountPaid : 777 ,
232
+ State : invpkg .ContractSettled ,
233
+ }
234
+
235
+ // Ensure that the service was eventually disabled.
236
+ assertEventually (t , func () bool {
237
+ isRunning := s .IsRunning ()
238
+ return isRunning == false
239
+ })
240
+ lnd .assertMainErrContains (t , "database not open" )
241
+ },
242
+ }, {
243
+ name : "err in invoice err channel" ,
244
+ setup : func (t * testing.T , lnd * mockLnd , s * InterceptorService ) {
245
+ acct := & OffChainBalanceAccount {
246
+ ID : testID ,
247
+ Type : TypeInitialBalance ,
248
+ CurrentBalance : 1234 ,
249
+ Invoices : AccountInvoices {
250
+ testHash : {},
251
+ },
252
+ }
253
+
254
+ err := s .store .UpdateAccount (acct )
255
+ require .NoError (t , err )
256
+ },
257
+ validate : func (t * testing.T , lnd * mockLnd ,
258
+ s * InterceptorService ) {
259
+ // Ensure that the service was started successfully.
260
+ require .True (t , s .IsRunning ())
261
+
262
+ // Now let's send an error over the invoice error
263
+ // channel. This should disable the service.
264
+ lnd .invoiceErrChan <- testErr
265
+
266
+ // Ensure that the service was eventually disabled.
267
+ assertEventually (t , func () bool {
268
+ isRunning := s .IsRunning ()
269
+ return isRunning == false
270
+ })
271
+
272
+ lnd .assertMainErrContains (t , testErr .Error ())
193
273
},
194
274
}, {
195
275
name : "goroutine err sent on main err chan" ,
@@ -207,7 +287,7 @@ func TestAccountService(t *testing.T) {
207
287
err := s .store .UpdateAccount (acct )
208
288
require .NoError (t , err )
209
289
210
- lnd .errChan <- testErr
290
+ lnd .mainErrChan <- testErr
211
291
},
212
292
validate : func (t * testing.T , lnd * mockLnd ,
213
293
s * InterceptorService ) {
@@ -239,6 +319,135 @@ func TestAccountService(t *testing.T) {
239
319
lnd .assertNoPaymentRequest (t )
240
320
lnd .assertInvoiceRequest (t , 0 , 0 )
241
321
lnd .assertNoMainErr (t )
322
+ require .True (t , s .IsRunning ())
323
+ },
324
+ }, {
325
+ name : "startup err on payment tracking" ,
326
+ setup : func (t * testing.T , lnd * mockLnd , s * InterceptorService ) {
327
+ acct := & OffChainBalanceAccount {
328
+ ID : testID ,
329
+ Type : TypeInitialBalance ,
330
+ CurrentBalance : 1234 ,
331
+ Invoices : AccountInvoices {
332
+ testHash : {},
333
+ },
334
+ Payments : AccountPayments {
335
+ testHash : {
336
+ Status : lnrpc .Payment_IN_FLIGHT ,
337
+ FullAmount : 1234 ,
338
+ },
339
+ },
340
+ }
341
+
342
+ err := s .store .UpdateAccount (acct )
343
+ require .NoError (t , err )
344
+
345
+ lnd .trackPaymentErr = testErr
346
+ },
347
+ validate : func (t * testing.T , lnd * mockLnd ,
348
+ s * InterceptorService ) {
349
+
350
+ // Assert that the invoice subscription succeeded.
351
+ require .Contains (t , s .invoiceToAccount , testHash )
352
+
353
+ // But setting up the payment tracking should have failed.
354
+ require .False (t , s .IsRunning ())
355
+
356
+ // Finally let's assert that we didn't successfully add the
357
+ // payment to pending payment, and that lnd isn't awaiting
358
+ // the payment request.
359
+ require .NotContains (t , s .pendingPayments , testHash )
360
+ lnd .assertNoPaymentRequest (t )
361
+ },
362
+ }, {
363
+ name : "err on payment update" ,
364
+ setup : func (t * testing.T , lnd * mockLnd , s * InterceptorService ) {
365
+ acct := & OffChainBalanceAccount {
366
+ ID : testID ,
367
+ Type : TypeInitialBalance ,
368
+ CurrentBalance : 1234 ,
369
+ Payments : AccountPayments {
370
+ testHash : {
371
+ Status : lnrpc .Payment_IN_FLIGHT ,
372
+ FullAmount : 1234 ,
373
+ },
374
+ },
375
+ }
376
+
377
+ err := s .store .UpdateAccount (acct )
378
+ require .NoError (t , err )
379
+ },
380
+ validate : func (t * testing.T , lnd * mockLnd ,
381
+ s * InterceptorService ) {
382
+ // Ensure that the service was started successfully,
383
+ // and lnd contains the payment request.
384
+ require .True (t , s .IsRunning ())
385
+ lnd .assertPaymentRequests (t , map [lntypes.Hash ]struct {}{
386
+ testHash : {},
387
+ })
388
+
389
+ // Now let's wipe the service's pending payments.
390
+ // This will cause an error send an update over
391
+ // the payment channel, which should disable the
392
+ // service.
393
+ s .pendingPayments = make (map [lntypes.Hash ]* trackedPayment )
394
+
395
+ // Send an invalid payment over the payment chan
396
+ // which should error and disable the service
397
+ lnd .paymentChans [testHash ] <- lndclient.PaymentStatus {
398
+ State : lnrpc .Payment_SUCCEEDED ,
399
+ Fee : 234 ,
400
+ Value : 1000 ,
401
+ }
402
+
403
+ // Ensure that the service was eventually disabled.
404
+ assertEventually (t , func () bool {
405
+ isRunning := s .IsRunning ()
406
+ return isRunning == false
407
+ })
408
+ lnd .assertMainErrContains (
409
+ t , "not mapped to any account" ,
410
+ )
411
+
412
+ },
413
+ }, {
414
+ name : "err in payment update chan" ,
415
+ setup : func (t * testing.T , lnd * mockLnd , s * InterceptorService ) {
416
+ acct := & OffChainBalanceAccount {
417
+ ID : testID ,
418
+ Type : TypeInitialBalance ,
419
+ CurrentBalance : 1234 ,
420
+ Payments : AccountPayments {
421
+ testHash : {
422
+ Status : lnrpc .Payment_IN_FLIGHT ,
423
+ FullAmount : 1234 ,
424
+ },
425
+ },
426
+ }
427
+
428
+ err := s .store .UpdateAccount (acct )
429
+ require .NoError (t , err )
430
+ },
431
+ validate : func (t * testing.T , lnd * mockLnd ,
432
+ s * InterceptorService ) {
433
+ // Ensure that the service was started successfully,
434
+ // and lnd contains the payment request.
435
+ require .True (t , s .IsRunning ())
436
+ lnd .assertPaymentRequests (t , map [lntypes.Hash ]struct {}{
437
+ testHash : {},
438
+ })
439
+
440
+ // Now let's send an error over the payment error
441
+ // channel. This should disable the service.
442
+ lnd .paymentErrChan <- testErr
443
+
444
+ // Ensure that the service was eventually disabled.
445
+ assertEventually (t , func () bool {
446
+ isRunning := s .IsRunning ()
447
+ return isRunning == false
448
+ })
449
+
450
+ lnd .assertMainErrContains (t , testErr .Error ())
242
451
},
243
452
}, {
244
453
name : "startup track in-flight payments" ,
0 commit comments