lbcd/sqlite3/insertfail_test.go

140 lines
3.6 KiB
Go

// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package sqlite3_test
import (
"github.com/conformal/btcdb"
"github.com/conformal/btcdb/sqlite3"
"os"
"path/filepath"
"testing"
)
func TestFailOperational(t *testing.T) {
sqlite3.SetTestingT(t)
failtestOperationalMode(t, dbTmDefault)
failtestOperationalMode(t, dbTmNormal)
failtestOperationalMode(t, dbTmFast)
failtestOperationalMode(t, dbTmNoVerify)
}
func failtestOperationalMode(t *testing.T, mode int) {
// simplified basic operation is:
// 1) fetch block from remote server
// 2) look up all txin (except coinbase in db)
// 3) insert block
// Ignore db remove errors since it means we didn't have an old one.
dbname := "tstdbop1"
_ = os.Remove(dbname)
db, err := btcdb.CreateDB("sqlite", dbname)
if err != nil {
t.Errorf("Failed to open test database %v", err)
return
}
defer os.Remove(dbname)
defer db.Close()
switch mode {
case dbTmDefault: // default
// no setup
case dbTmNormal: // explicit normal
db.SetDBInsertMode(btcdb.InsertNormal)
case dbTmFast: // fast mode
db.SetDBInsertMode(btcdb.InsertFast)
if sqldb, ok := db.(*sqlite3.SqliteDb); ok {
sqldb.TempTblMax = 100
} else {
t.Errorf("not right type")
}
case dbTmNoVerify: // validated block
// no point in testing this
return
}
// Since we are dealing with small dataset, reduce cache size
sqlite3.SetBlockCacheSize(db, 2)
sqlite3.SetTxCacheSize(db, 3)
testdatafile := filepath.Join("testdata", "blocks1-256.bz2")
blocks, err := loadBlocks(t, testdatafile)
if err != nil {
t.Errorf("Unable to load blocks from test data for mode %v: %v",
mode, err)
return
}
err = nil
out:
for height := int64(0); height < int64(len(blocks)); height++ {
block := blocks[height]
mblock := block.MsgBlock()
blockname, _ := block.Sha()
if height == 248 {
// time to corrupt the datbase, to see if it leaves the block or tx in the db
if len(mblock.Transactions) != 2 {
t.Errorf("transaction #248 should have two transactions txid %v ?= 828ef3b079f9c23829c56fe86e85b4a69d9e06e5b54ea597eef5fb3ffef509fe", blockname)
return
}
tx := mblock.Transactions[1]
txin := tx.TxIn[0]
origintxsha := &txin.PreviousOutpoint.Hash
sqlite3.KillTx(db, origintxsha)
_, _, _, err = db.FetchTxBySha(origintxsha)
if err == nil {
t.Errorf("deleted tx found %v", origintxsha)
}
}
if height == 248 {
}
newheight, err := db.InsertBlock(block)
if err != nil {
if height != 248 {
t.Errorf("failed to insert block %v err %v", height, err)
break out
}
} else {
if height == 248 {
t.Errorf("block insert with missing input tx succeeded block %v err %v", height, err)
break out
}
}
if height == 248 {
for _, tx := range mblock.Transactions {
txsha, err := tx.TxSha()
_, _, _, err = db.FetchTxBySha(&txsha)
if err == nil {
t.Errorf("referenced tx found, should not have been %v, ", txsha)
}
}
}
if height == 248 {
exists := db.ExistsSha(blockname)
if exists == true {
t.Errorf("block still present after failed insert")
}
// if we got here with no error, testing was successful
break out
}
if newheight != height {
t.Errorf("height mismatch expect %v returned %v", height, newheight)
break out
}
}
switch mode {
case dbTmDefault: // default
// no cleanup
case dbTmNormal: // explicit normal
// no cleanup
case dbTmFast: // fast mode
db.SetDBInsertMode(btcdb.InsertNormal)
case dbTmNoVerify: // validated block
db.SetDBInsertMode(btcdb.InsertNormal)
}
}