@@ -351,77 +351,146 @@ func TestWalletOperationRunner_ReceiptLookupTimeoutDoesNotBlockRunner(t *testing
351351}
352352
353353func TestWalletOperationRunner_BroadcastTimeoutDoesNotFailOperation (t * testing.T ) {
354- db := testutil .NewTestDB (t )
355- repos := repository .NewRepositories (db )
356- ctx := context .Background ()
357- op , _ , err := repos .WalletOperations .CreateOrGet (ctx , repository.CreateWalletOperationInput {
358- Type : model .WalletOperationTypeFund ,
359- ClientRequestID : "fund-broadcast-timeout" ,
360- Amount : "100" ,
361- })
362- if err != nil {
363- t .Fatalf ("CreateOrGet: %v" , err )
364- }
354+ for _ , tc := range []struct {
355+ name string
356+ opType model.WalletOperationType
357+ amount string
358+ operator * fakeWalletOperator
359+ }{
360+ {name : "fund" , opType : model .WalletOperationTypeFund , amount : "100" , operator : & fakeWalletOperator {blockFund : true }},
361+ {name : "withdraw" , opType : model .WalletOperationTypeWithdraw , amount : "100" , operator : & fakeWalletOperator {blockWithdraw : true }},
362+ {name : "approve" , opType : model .WalletOperationTypeApprove , amount : "0" , operator : & fakeWalletOperator {blockApprove : true }},
363+ } {
364+ t .Run (tc .name , func (t * testing.T ) {
365+ db := testutil .NewTestDB (t )
366+ repos := repository .NewRepositories (db )
367+ ctx := context .Background ()
368+ op , _ , err := repos .WalletOperations .CreateOrGet (ctx , repository.CreateWalletOperationInput {
369+ Type : tc .opType ,
370+ ClientRequestID : string (tc .opType ) + "-broadcast-timeout" ,
371+ Amount : tc .amount ,
372+ })
373+ if err != nil {
374+ t .Fatalf ("CreateOrGet: %v" , err )
375+ }
365376
366- operator := & fakeWalletOperator {blockFund : true }
367- runner := NewWalletOperationRunner (repos , operator , nil , time .Millisecond , nil , WithWalletOperationTimeouts (time .Millisecond , 0 ))
377+ runner := NewWalletOperationRunner (repos , tc .operator , nil , time .Millisecond , nil , WithWalletOperationTimeouts (time .Millisecond , 0 ))
368378
369- started := time .Now ()
370- runner .runOnce (ctx )
371- if time .Since (started ) > time .Second {
372- t .Fatal ("runOnce did not return after broadcast timeout" )
373- }
379+ started := time .Now ()
380+ runner .runOnce (ctx )
381+ if time .Since (started ) > time .Second {
382+ t .Fatal ("runOnce did not return after broadcast timeout" )
383+ }
374384
375- got , err := repos .WalletOperations .GetByID (ctx , op .ID )
376- if err != nil {
377- t .Fatalf ("GetByID: %v" , err )
378- }
379- if got .Status != model .WalletOperationStatusRunning {
380- t .Fatalf ("status = %q, want running until lease expiry" , got .Status )
381- }
382- if got .TxHash != nil {
383- t .Fatalf ("tx_hash = %v, want nil" , got .TxHash )
385+ got , err := repos .WalletOperations .GetByID (ctx , op .ID )
386+ if err != nil {
387+ t .Fatalf ("GetByID: %v" , err )
388+ }
389+ if got .Status != model .WalletOperationStatusRunning {
390+ t .Fatalf ("status = %q, want running until lease expiry" , got .Status )
391+ }
392+ if got .TxHash != nil {
393+ t .Fatalf ("tx_hash = %v, want nil" , got .TxHash )
394+ }
395+ })
384396 }
385397}
386398
387399func TestWalletOperationRunner_RemainsHealthyWhileBroadcasting (t * testing.T ) {
388- db := testutil .NewTestDB (t )
389- repos := repository .NewRepositories (db )
390- ctx , cancel := context .WithCancel (context .Background ())
391- defer cancel ()
400+ for _ , tc := range []struct {
401+ name string
402+ opType model.WalletOperationType
403+ amount string
404+ operator func (started , release chan struct {}) * fakeWalletOperator
405+ }{
406+ {
407+ name : "fund" ,
408+ opType : model .WalletOperationTypeFund ,
409+ amount : "100" ,
410+ operator : func (started , release chan struct {}) * fakeWalletOperator {
411+ return & fakeWalletOperator {
412+ fundHash : common .HexToHash ("0x123" ).Hex (),
413+ onFund : func (context.Context ) {
414+ close (started )
415+ <- release
416+ },
417+ }
418+ },
419+ },
420+ {
421+ name : "withdraw" ,
422+ opType : model .WalletOperationTypeWithdraw ,
423+ amount : "100" ,
424+ operator : func (started , release chan struct {}) * fakeWalletOperator {
425+ return & fakeWalletOperator {
426+ withdrawHash : common .HexToHash ("0x123" ).Hex (),
427+ onWithdraw : func (context.Context ) {
428+ close (started )
429+ <- release
430+ },
431+ }
432+ },
433+ },
434+ {
435+ name : "approve" ,
436+ opType : model .WalletOperationTypeApprove ,
437+ amount : "0" ,
438+ operator : func (started , release chan struct {}) * fakeWalletOperator {
439+ return & fakeWalletOperator {
440+ approveHash : common .HexToHash ("0x123" ).Hex (),
441+ onApprove : func (context.Context ) {
442+ close (started )
443+ <- release
444+ },
445+ }
446+ },
447+ },
448+ } {
449+ t .Run (tc .name , func (t * testing.T ) {
450+ db := testutil .NewTestDB (t )
451+ repos := repository .NewRepositories (db )
452+ ctx , cancel := context .WithCancel (context .Background ())
453+ defer cancel ()
392454
393- if _ , _ , err := repos .WalletOperations .CreateOrGet (ctx , repository.CreateWalletOperationInput {
394- Type : model . WalletOperationTypeFund ,
395- ClientRequestID : "fund -slow-broadcast" ,
396- Amount : "100" ,
397- }); err != nil {
398- t .Fatalf ("CreateOrGet: %v" , err )
399- }
455+ if _ , _ , err := repos .WalletOperations .CreateOrGet (ctx , repository.CreateWalletOperationInput {
456+ Type : tc . opType ,
457+ ClientRequestID : string ( tc . opType ) + " -slow-broadcast" ,
458+ Amount : tc . amount ,
459+ }); err != nil {
460+ t .Fatalf ("CreateOrGet: %v" , err )
461+ }
400462
401- started := make (chan struct {})
402- release := make (chan struct {})
403- operator := & fakeWalletOperator {
404- fundHash : common .HexToHash ("0x123" ).Hex (),
405- onFund : func (context.Context ) {
406- close (started )
407- <- release
408- },
409- }
410- runner := NewWalletOperationRunner (repos , operator , nil , time .Nanosecond , nil )
463+ started := make (chan struct {})
464+ release := make (chan struct {})
465+ var releaseOnce sync.Once
466+ defer releaseOnce .Do (func () { close (release ) })
467+
468+ operator := tc .operator (started , release )
469+ runner := NewWalletOperationRunner (repos , operator , nil , time .Nanosecond , nil )
470+
471+ done := make (chan struct {})
472+ go func () {
473+ runner .runOnce (ctx )
474+ close (done )
475+ }()
476+ select {
477+ case <- started :
478+ case <- time .After (time .Second ):
479+ t .Fatal ("wallet broadcast did not start" )
480+ }
411481
412- done := make (chan struct {})
413- go func () {
414- runner .runOnce (ctx )
415- close (done )
416- }()
417- <- started
482+ if ! runner .Healthy () {
483+ t .Fatal ("runner is unhealthy during an active wallet broadcast" )
484+ }
418485
419- if ! runner .Healthy () {
420- t .Fatal ("runner is unhealthy during an active wallet broadcast" )
486+ releaseOnce .Do (func () { close (release ) })
487+ select {
488+ case <- done :
489+ case <- time .After (time .Second ):
490+ t .Fatal ("runOnce did not finish after releasing broadcast" )
491+ }
492+ })
421493 }
422-
423- close (release )
424- <- done
425494}
426495
427496func TestWalletOperationRunner_RecoversSubmittedAndMarksExpiredRunningUnknown (t * testing.T ) {
@@ -512,7 +581,11 @@ type fakeWalletOperator struct {
512581 withdrawAmount * big.Int
513582 approveCalled bool
514583 onFund func (context.Context )
584+ onWithdraw func (context.Context )
585+ onApprove func (context.Context )
515586 blockFund bool
587+ blockWithdraw bool
588+ blockApprove bool
516589 fundErr error
517590 withdrawErr error
518591 approveErr error
@@ -533,16 +606,30 @@ func (f *fakeWalletOperator) FundUSDFC(ctx context.Context, amount *big.Int) (st
533606 return f .fundHash , nil
534607}
535608
536- func (f * fakeWalletOperator ) WithdrawUSDFC (_ context.Context , amount * big.Int ) (string , error ) {
609+ func (f * fakeWalletOperator ) WithdrawUSDFC (ctx context.Context , amount * big.Int ) (string , error ) {
537610 f .withdrawAmount = new (big.Int ).Set (amount )
611+ if f .onWithdraw != nil {
612+ f .onWithdraw (ctx )
613+ }
614+ if f .blockWithdraw {
615+ <- ctx .Done ()
616+ return "" , ctx .Err ()
617+ }
538618 if f .withdrawErr != nil {
539619 return "" , f .withdrawErr
540620 }
541621 return f .withdrawHash , nil
542622}
543623
544- func (f * fakeWalletOperator ) ApproveFWSS (context.Context ) (string , error ) {
624+ func (f * fakeWalletOperator ) ApproveFWSS (ctx context.Context ) (string , error ) {
545625 f .approveCalled = true
626+ if f .onApprove != nil {
627+ f .onApprove (ctx )
628+ }
629+ if f .blockApprove {
630+ <- ctx .Done ()
631+ return "" , ctx .Err ()
632+ }
546633 if f .approveErr != nil {
547634 return "" , f .approveErr
548635 }
0 commit comments