Added tests for single-thread connectBlocks

This commit is contained in:
Jakub Matys 2018-09-26 12:19:40 +02:00
parent db39b5ef51
commit 642310eb95
4 changed files with 453 additions and 392 deletions

11
db/test_helper.go Normal file
View File

@ -0,0 +1,11 @@
// +build integration
package db
func ConnectBlocks(w *SyncWorker, onNewBlock func(hash string), initialSync bool) error {
return w.connectBlocks(onNewBlock, initialSync)
}
func HandleFork(w *SyncWorker, localBestHeight uint32, localBestHash string, onNewBlock func(hash string), initialSync bool) error {
return w.handleFork(localBestHeight, localBestHash, onNewBlock, initialSync)
}

View File

@ -6,6 +6,7 @@ import (
"blockbook/db" "blockbook/db"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"io/ioutil" "io/ioutil"
"math/big" "math/big"
"os" "os"
@ -16,9 +17,9 @@ import (
) )
var testMap = map[string]func(t *testing.T, th *TestHandler){ var testMap = map[string]func(t *testing.T, th *TestHandler){
// "ConnectBlocks": nil, "ConnectBlocks": testConnectBlocks,
"ConnectBlocksParallel": testConnectBlocksParallel, "ConnectBlocksParallel": testConnectBlocksParallel,
// "DisconnectBlocks": nil, // "HandleFork": testHandleFork,
} }
type TestHandler struct { type TestHandler struct {
@ -33,13 +34,24 @@ type Range struct {
} }
type TestData struct { type TestData struct {
ConnectBlocks struct {
SyncRanges []Range `json:"syncRanges"` SyncRanges []Range `json:"syncRanges"`
Blocks map[uint32]BlockInfo `json:"blocks"` Blocks map[uint32]BlockInfo `json:"blocks"`
} `json:"connectBlocks"`
HandleFork struct {
SyncRanges []Range `json:"syncRanges"`
FakeBlocks map[uint32]BlockID `json:"fakeBlocks"`
RealBlocks map[uint32]BlockID `json:"realBlocks"`
} `json:"handleFork"`
}
type BlockID struct {
Height uint32 `json:"height"`
Hash string `json:"hash"`
} }
type BlockInfo struct { type BlockInfo struct {
Height uint32 `json:"height"` BlockID
Hash string `json:"hash"`
NoTxs uint32 `json:"noTxs"` NoTxs uint32 `json:"noTxs"`
TxDetails []*bchain.Tx `json:"txDetails"` TxDetails []*bchain.Tx `json:"txDetails"`
} }
@ -56,10 +68,9 @@ func IntegrationTest(t *testing.T, coin string, chain bchain.BlockChain, testCon
t.Fatalf("Failed loading of test data: %s", err) t.Fatalf("Failed loading of test data: %s", err)
} }
h := TestHandler{Coin: coin, Chain: chain, TestData: td}
for _, test := range tests { for _, test := range tests {
if f, found := testMap[test]; found { if f, found := testMap[test]; found {
h := TestHandler{Coin: coin, Chain: chain, TestData: td}
t.Run(test, func(t *testing.T) { f(t, &h) }) t.Run(test, func(t *testing.T) { f(t, &h) })
} else { } else {
t.Errorf("%s: test not found", test) t.Errorf("%s: test not found", test)
@ -92,7 +103,7 @@ func loadTestData(coin string, parser bchain.BlockChainParser) (*TestData, error
return nil, err return nil, err
} }
for _, b := range v.Blocks { for _, b := range v.ConnectBlocks.Blocks {
for _, tx := range b.TxDetails { for _, tx := range b.TxDetails {
// convert amounts in test json to bit.Int and clear the temporary JsonValue // convert amounts in test json to bit.Int and clear the temporary JsonValue
for i := range tx.Vout { for i := range tx.Vout {
@ -189,8 +200,45 @@ func withRocksDBAndSyncWorker(t *testing.T, h *TestHandler, startHeight uint32,
fn(d, sw, ch) fn(d, sw, ch)
} }
func testConnectBlocks(t *testing.T, h *TestHandler) {
for _, rng := range h.TestData.ConnectBlocks.SyncRanges {
withRocksDBAndSyncWorker(t, h, rng.Lower, func(d *db.RocksDB, sw *db.SyncWorker, ch chan os.Signal) {
upperHash, err := h.Chain.GetBlockHash(rng.Upper)
if err != nil {
t.Fatal(err)
}
err = db.ConnectBlocks(sw, func(hash string) {
if hash == upperHash {
close(ch)
}
}, true)
if err != nil {
if err.Error() != fmt.Sprintf("connectBlocks interrupted at height %d", rng.Upper) {
t.Fatal(err)
}
}
height, hash, err := d.GetBestBlock()
if err != nil {
t.Fatal(err)
}
if height != rng.Upper {
t.Fatalf("Upper block height mismatch: %d != %d", height, rng.Upper)
}
if hash != upperHash {
t.Fatalf("Upper block hash mismatch: %s != %s", hash, upperHash)
}
t.Run("verifyBlockInfo", func(t *testing.T) { verifyBlockInfo(t, d, h, rng) })
t.Run("verifyTransactions", func(t *testing.T) { verifyTransactions(t, d, h, rng) })
t.Run("verifyAddresses", func(t *testing.T) { verifyAddresses(t, d, h, rng) })
})
}
}
func testConnectBlocksParallel(t *testing.T, h *TestHandler) { func testConnectBlocksParallel(t *testing.T, h *TestHandler) {
for _, rng := range h.TestData.SyncRanges { for _, rng := range h.TestData.ConnectBlocks.SyncRanges {
withRocksDBAndSyncWorker(t, h, rng.Lower, func(d *db.RocksDB, sw *db.SyncWorker, ch chan os.Signal) { withRocksDBAndSyncWorker(t, h, rng.Lower, func(d *db.RocksDB, sw *db.SyncWorker, ch chan os.Signal) {
upperHash, err := h.Chain.GetBlockHash(rng.Upper) upperHash, err := h.Chain.GetBlockHash(rng.Upper)
if err != nil { if err != nil {
@ -222,7 +270,7 @@ func testConnectBlocksParallel(t *testing.T, h *TestHandler) {
func verifyBlockInfo(t *testing.T, d *db.RocksDB, h *TestHandler, rng Range) { func verifyBlockInfo(t *testing.T, d *db.RocksDB, h *TestHandler, rng Range) {
for height := rng.Lower; height <= rng.Upper; height++ { for height := rng.Lower; height <= rng.Upper; height++ {
block, found := h.TestData.Blocks[height] block, found := h.TestData.ConnectBlocks.Blocks[height]
if !found { if !found {
continue continue
} }
@ -257,7 +305,7 @@ func verifyTransactions(t *testing.T, d *db.RocksDB, h *TestHandler, rng Range)
checkMap := make(map[string][]bool) checkMap := make(map[string][]bool)
for height := rng.Lower; height <= rng.Upper; height++ { for height := rng.Lower; height <= rng.Upper; height++ {
block, found := h.TestData.Blocks[height] block, found := h.TestData.ConnectBlocks.Blocks[height]
if !found { if !found {
continue continue
} }
@ -305,7 +353,7 @@ func verifyAddresses(t *testing.T, d *db.RocksDB, h *TestHandler, rng Range) {
parser := h.Chain.GetChainParser() parser := h.Chain.GetChainParser()
for height := rng.Lower; height <= rng.Upper; height++ { for height := rng.Lower; height <= rng.Upper; height++ {
block, found := h.TestData.Blocks[height] block, found := h.TestData.ConnectBlocks.Blocks[height]
if !found { if !found {
continue continue
} }

View File

@ -1,4 +1,5 @@
{ {
"connectBlocks": {
"syncRanges": [ "syncRanges": [
{"lower": 541224, "upper": 541255}, {"lower": 541224, "upper": 541255},
{"lower": 542835, "upper": 542838} {"lower": 542835, "upper": 542838}
@ -396,4 +397,5 @@
] ]
} }
} }
}
} }

View File

@ -10,7 +10,7 @@
"bitcoin": { "bitcoin": {
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync",
"EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"], "EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"],
"sync": ["ConnectBlocksParallel"] "sync": ["ConnectBlocksParallel", "ConnectBlocks"]
}, },
"bitcoin_testnet": { "bitcoin_testnet": {
"rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync",