neo-go/pkg/core/blockchain_test.go
2020-01-16 10:16:24 +03:00

202 lines
5.1 KiB
Go

package core
import (
"testing"
"github.com/CityOfZion/neo-go/pkg/core/block"
"github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAddHeaders(t *testing.T) {
bc := newTestChain(t)
h1 := newBlock(1).Header()
h2 := newBlock(2).Header()
h3 := newBlock(3).Header()
if err := bc.AddHeaders(h1, h2, h3); err != nil {
t.Fatal(err)
}
assert.Equal(t, h3.Index, bc.HeaderHeight())
assert.Equal(t, uint32(0), bc.BlockHeight())
assert.Equal(t, h3.Hash(), bc.CurrentHeaderHash())
// Add them again, they should not be added.
if err := bc.AddHeaders(h3, h2, h1); err != nil {
t.Fatal(err)
}
assert.Equal(t, h3.Index, bc.HeaderHeight())
assert.Equal(t, uint32(0), bc.BlockHeight())
assert.Equal(t, h3.Hash(), bc.CurrentHeaderHash())
}
func TestAddBlock(t *testing.T) {
bc := newTestChain(t)
blocks := []*block.Block{
newBlock(1, newMinerTX()),
newBlock(2, newMinerTX()),
newBlock(3, newMinerTX()),
}
for i := 0; i < len(blocks); i++ {
if err := bc.AddBlock(blocks[i]); err != nil {
t.Fatal(err)
}
}
lastBlock := blocks[len(blocks)-1]
assert.Equal(t, lastBlock.Index, bc.HeaderHeight())
assert.Equal(t, lastBlock.Hash(), bc.CurrentHeaderHash())
// This one tests persisting blocks, so it does need to persist()
require.NoError(t, bc.persist())
for _, block := range blocks {
key := storage.AppendPrefix(storage.DataBlock, block.Hash().BytesLE())
if _, err := bc.dao.store.Get(key); err != nil {
t.Fatalf("block %s not persisted", block.Hash())
}
}
assert.Equal(t, lastBlock.Index, bc.BlockHeight())
assert.Equal(t, lastBlock.Hash(), bc.CurrentHeaderHash())
}
func TestScriptFromWitness(t *testing.T) {
witness := &transaction.Witness{}
h := util.Uint160{1, 2, 3}
res, err := ScriptFromWitness(h, witness)
require.NoError(t, err)
require.NotNil(t, res)
witness.VerificationScript = []byte{4, 8, 15, 16, 23, 42}
h = hash.Hash160(witness.VerificationScript)
res, err = ScriptFromWitness(h, witness)
require.NoError(t, err)
require.NotNil(t, res)
h[0] = ^h[0]
res, err = ScriptFromWitness(h, witness)
require.Error(t, err)
require.Nil(t, res)
}
func TestGetHeader(t *testing.T) {
bc := newTestChain(t)
block := newBlock(1, newMinerTX())
err := bc.AddBlock(block)
assert.Nil(t, err)
// Test unpersisted and persisted access
for i := 0; i < 2; i++ {
hash := block.Hash()
header, err := bc.GetHeader(hash)
require.NoError(t, err)
assert.Equal(t, block.Header(), header)
b2 := newBlock(2)
_, err = bc.GetHeader(b2.Hash())
assert.Error(t, err)
assert.NoError(t, bc.persist())
}
}
func TestGetBlock(t *testing.T) {
bc := newTestChain(t)
blocks := makeBlocks(100)
for i := 0; i < len(blocks); i++ {
if err := bc.AddBlock(blocks[i]); err != nil {
t.Fatal(err)
}
}
// Test unpersisted and persisted access
for j := 0; j < 2; j++ {
for i := 0; i < len(blocks); i++ {
block, err := bc.GetBlock(blocks[i].Hash())
if err != nil {
t.Fatalf("can't get block %d: %s, attempt %d", i, err, j)
}
assert.Equal(t, blocks[i].Index, block.Index)
assert.Equal(t, blocks[i].Hash(), block.Hash())
}
assert.NoError(t, bc.persist())
}
}
func TestHasBlock(t *testing.T) {
bc := newTestChain(t)
blocks := makeBlocks(50)
for i := 0; i < len(blocks); i++ {
if err := bc.AddBlock(blocks[i]); err != nil {
t.Fatal(err)
}
}
// Test unpersisted and persisted access
for j := 0; j < 2; j++ {
for i := 0; i < len(blocks); i++ {
assert.True(t, bc.HasBlock(blocks[i].Hash()))
}
newBlock := newBlock(51)
assert.False(t, bc.HasBlock(newBlock.Hash()))
assert.NoError(t, bc.persist())
}
}
func TestGetTransaction(t *testing.T) {
b1 := getDecodedBlock(t, 1)
block := getDecodedBlock(t, 2)
bc := newTestChain(t)
// Turn verification off, because these blocks are really from some other chain
// and can't be verified, but we don't care about that in this test.
bc.config.VerifyBlocks = false
assert.Nil(t, bc.AddBlock(b1))
assert.Nil(t, bc.AddBlock(block))
// Test unpersisted and persisted access
for j := 0; j < 2; j++ {
tx, height, err := bc.GetTransaction(block.Transactions[0].Hash())
require.Nil(t, err)
assert.Equal(t, block.Index, height)
assert.Equal(t, block.Transactions[0], tx)
assert.Equal(t, 10, io.GetVarSize(tx))
assert.Equal(t, 1, io.GetVarSize(tx.Attributes))
assert.Equal(t, 1, io.GetVarSize(tx.Inputs))
assert.Equal(t, 1, io.GetVarSize(tx.Outputs))
assert.Equal(t, 1, io.GetVarSize(tx.Scripts))
assert.NoError(t, bc.persist())
}
}
func TestClose(t *testing.T) {
defer func() {
r := recover()
assert.NotNil(t, r)
}()
bc := newTestChain(t)
blocks := makeBlocks(10)
for i := 0; i < len(blocks); i++ {
require.NoError(t, bc.AddBlock(blocks[i]))
}
bc.Close()
// It's a hack, but we use internal knowledge of MemoryStore
// implementation which makes it completely unusable (up to panicing)
// after Close().
_ = bc.dao.store.Put([]byte{0}, []byte{1})
// This should never be executed.
assert.Nil(t, t)
}