Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
buck54321 committed Oct 26, 2021
1 parent 023a493 commit 629258c
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 9 deletions.
17 changes: 11 additions & 6 deletions client/asset/btc/btc.go
Expand Up @@ -768,7 +768,7 @@ func (btc *ExchangeWallet) Connect(ctx context.Context) (*sync.WaitGroup, error)
wg.Add(1)
go func() {
defer wg.Done()
btc.run(ctx)
btc.watchBlocks(ctx)
btc.shutdown()
}()
return &wg, nil
Expand Down Expand Up @@ -2384,9 +2384,9 @@ func (btc *ExchangeWallet) RegFeeConfirmations(_ context.Context, id dex.Bytes)
return uint32(tx.Confirmations), nil
}

// run pings for new blocks and runs the tipChange callback function when the
// block changes.
func (btc *ExchangeWallet) run(ctx context.Context) {
// watchBlocks pings for new blocks and runs the tipChange callback function
// when the block changes.
func (btc *ExchangeWallet) watchBlocks(ctx context.Context) {
ticker := time.NewTicker(blockTicker)
defer ticker.Stop()

Expand All @@ -2409,7 +2409,7 @@ func (btc *ExchangeWallet) run(ctx context.Context) {

// dequeuedBlock is where the queuedBlocks that time out will be sent for
// broadcast.
var dequeuedBlock chan *block
dequeuedBlock := make(chan *block, 1)

for {
select {
Expand All @@ -2423,6 +2423,10 @@ func (btc *ExchangeWallet) run(ctx context.Context) {
return
}

if queuedBlock != nil && *newTipHash == queuedBlock.block.hash {
continue
}

// This method is called frequently. Don't hold write lock
// unless tip has changed.
btc.tipMtx.RLock()
Expand Down Expand Up @@ -2468,7 +2472,8 @@ func (btc *ExchangeWallet) run(ctx context.Context) {

case dqBlock := <-dequeuedBlock:
btc.log.Warnf("Reporting a block found in polling that the wallet apparently "+
"never reported: %d %s. This may indicate a problem with the wallet.", dqBlock.height, dqBlock.hash)
"never reported: %d %s. If you see this message repeatedly, it may indicate "+
"an issue with the wallet.", dqBlock.height, dqBlock.hash)
btc.reportNewTip(ctx, dqBlock)

case <-ctx.Done():
Expand Down
13 changes: 10 additions & 3 deletions client/asset/btc/btc_test.go
Expand Up @@ -167,6 +167,7 @@ type testData struct {
signTxErr error
listUnspent []*ListUnspentResult
listUnspentErr error
tipChanged chan struct{}

// spv
fetchInputInfoTx *wire.MsgTx
Expand Down Expand Up @@ -195,6 +196,7 @@ func newTestData() *testData {
getCFilterScripts: make(map[chainhash.Hash][][]byte),
confsErr: WalletTransactionNotFound,
checkpoints: make(map[outPoint]*scanCheckpoint),
tipChanged: make(chan struct{}, 1),
}
}

Expand Down Expand Up @@ -567,7 +569,12 @@ func tNewWallet(segwit bool, walletType string) (*ExchangeWallet, *testData, fun

data := newTestData()
walletCfg := &asset.WalletConfig{
TipChange: func(error) {},
TipChange: func(error) {
select {
case data.tipChanged <- struct{}{}:
default:
}
},
}
walletCtx, shutdown := context.WithCancel(tCtx)
cfg := &BTCCloneCFG{
Expand Down Expand Up @@ -596,6 +603,7 @@ func tNewWallet(segwit bool, walletType string) (*ExchangeWallet, *testData, fun
chainParams: &chaincfg.MainNetParams,
wallet: &tBtcWallet{data},
cl: neutrinoClient,
tipChan: make(chan *block),
chainClient: nil,
acctNum: 0,
txBlocks: data.dbBlockForTx,
Expand All @@ -622,7 +630,7 @@ func tNewWallet(segwit bool, walletType string) (*ExchangeWallet, *testData, fun
hash: *bestHash,
}
wallet.tipMtx.Unlock()
go wallet.run(walletCtx)
go wallet.watchBlocks(walletCtx)

return wallet, data, shutdown, nil
}
Expand Down Expand Up @@ -2966,5 +2974,4 @@ func testTryRedemptionRequests(t *testing.T, segwit bool, walletType string) {
}
}
}

}
71 changes: 71 additions & 0 deletions client/asset/btc/spv_test.go
Expand Up @@ -699,3 +699,74 @@ func TestSendWithSubtract(t *testing.T) {
t.Fatalf("test passed with fees > available error")
}
}

func TestTryBlocksWithNotifier(t *testing.T) {
defaultWalletBlockAllowance := walletBlockAllowance
defaultBlockTicker := blockTicker

walletBlockAllowance = 30 * time.Millisecond
blockTicker = 5 * time.Millisecond

defer func() {
walletBlockAllowance = defaultWalletBlockAllowance
blockTicker = defaultBlockTicker
}()

wallet, node, shutdown, _ := tNewWallet(true, walletTypeSPV)
defer shutdown()

spv := wallet.node.(*spvWallet)

getNote := func(timeout time.Duration) bool {
select {
case <-node.tipChanged:
return true
case <-time.After(timeout):
return false
}
}

if getNote(walletBlockAllowance * 2) {
t.Fatalf("got a first block")
}

var tipHeight int64
addBlock := func() *block {
tipHeight++
h, _ := node.addRawTx(tipHeight, dummyTx())
return &block{tipHeight, *h}
}

addBlock()

// It should not come through on the block tick, since it will be cached.
if getNote(blockTicker * 2) {
t.Fatalf("got block that should've been cached")
}

// But it will come through after the blockAllowance, printing a warning.
if !getNote(walletBlockAllowance * 2) {
t.Fatal("block didn't time out")
}

// On the other hand, a wallet block should come through immediately. Not
// even waiting on the block tick.
spv.tipChan <- addBlock()
if !getNote(blockTicker / 2) {
t.Fatal("wallet block wasn't sent through")
}

// If we do the same thing but make sure that a polled block is queued
// first, we should still see the block right away, and the queued block
// should be canceled.
blk := addBlock()
time.Sleep(blockTicker * 2)
spv.tipChan <- blk
if !getNote(blockTicker / 2) {
t.Fatal("wallet block wasn't sent through with polled block queued")
}

if getNote(walletBlockAllowance * 2) {
t.Fatal("queued polled block that should have been canceled came through")
}
}

0 comments on commit 629258c

Please sign in to comment.