package db
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
dbm "github.com/tendermint/tm-db"
|
|
|
|
"github.com/tendermint/tendermint/crypto"
|
|
"github.com/tendermint/tendermint/crypto/tmhash"
|
|
"github.com/tendermint/tendermint/internal/test/factory"
|
|
tmrand "github.com/tendermint/tendermint/libs/rand"
|
|
"github.com/tendermint/tendermint/types"
|
|
"github.com/tendermint/tendermint/version"
|
|
)
|
|
|
|
func TestLast_FirstLightBlockHeight(t *testing.T) {
|
|
dbStore := New(dbm.NewMemDB())
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
// Empty store
|
|
height, err := dbStore.LastLightBlockHeight()
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, -1, height)
|
|
|
|
height, err = dbStore.FirstLightBlockHeight()
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, -1, height)
|
|
|
|
// 1 key
|
|
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, int64(1)))
|
|
require.NoError(t, err)
|
|
|
|
height, err = dbStore.LastLightBlockHeight()
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, 1, height)
|
|
|
|
height, err = dbStore.FirstLightBlockHeight()
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, 1, height)
|
|
}
|
|
|
|
func Test_SaveLightBlock(t *testing.T) {
|
|
dbStore := New(dbm.NewMemDB())
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
// Empty store
|
|
h, err := dbStore.LightBlock(1)
|
|
require.Error(t, err)
|
|
assert.Nil(t, h)
|
|
|
|
// 1 key
|
|
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, 1))
|
|
require.NoError(t, err)
|
|
|
|
size := dbStore.Size()
|
|
assert.Equal(t, uint16(1), size)
|
|
t.Log(size)
|
|
|
|
h, err = dbStore.LightBlock(1)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, h)
|
|
|
|
// Empty store
|
|
err = dbStore.DeleteLightBlock(1)
|
|
require.NoError(t, err)
|
|
|
|
h, err = dbStore.LightBlock(1)
|
|
require.Error(t, err)
|
|
assert.Nil(t, h)
|
|
|
|
}
|
|
|
|
func Test_LightBlockBefore(t *testing.T) {
|
|
dbStore := New(dbm.NewMemDB())
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
assert.Panics(t, func() {
|
|
_, _ = dbStore.LightBlockBefore(0)
|
|
_, _ = dbStore.LightBlockBefore(100)
|
|
})
|
|
|
|
err := dbStore.SaveLightBlock(randLightBlock(ctx, t, int64(2)))
|
|
require.NoError(t, err)
|
|
|
|
h, err := dbStore.LightBlockBefore(3)
|
|
require.NoError(t, err)
|
|
if assert.NotNil(t, h) {
|
|
assert.EqualValues(t, 2, h.Height)
|
|
}
|
|
|
|
_, err = dbStore.LightBlockBefore(2)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func Test_Prune(t *testing.T) {
|
|
dbStore := New(dbm.NewMemDB())
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
// Empty store
|
|
assert.EqualValues(t, 0, dbStore.Size())
|
|
err := dbStore.Prune(0)
|
|
require.NoError(t, err)
|
|
|
|
// One header
|
|
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, 2))
|
|
require.NoError(t, err)
|
|
|
|
assert.EqualValues(t, 1, dbStore.Size())
|
|
|
|
err = dbStore.Prune(1)
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, 1, dbStore.Size())
|
|
|
|
err = dbStore.Prune(0)
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, 0, dbStore.Size())
|
|
|
|
// Multiple headers
|
|
for i := 1; i <= 10; i++ {
|
|
err = dbStore.SaveLightBlock(randLightBlock(ctx, t, int64(i)))
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
err = dbStore.Prune(11)
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, 10, dbStore.Size())
|
|
|
|
err = dbStore.Prune(7)
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, 7, dbStore.Size())
|
|
}
|
|
|
|
func Test_Concurrency(t *testing.T) {
|
|
dbStore := New(dbm.NewMemDB())
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
var wg sync.WaitGroup
|
|
for i := 1; i <= 100; i++ {
|
|
wg.Add(1)
|
|
go func(i int64) {
|
|
defer wg.Done()
|
|
|
|
err := dbStore.SaveLightBlock(randLightBlock(ctx, t, i))
|
|
require.NoError(t, err)
|
|
|
|
_, err = dbStore.LightBlock(i)
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
|
|
if i > 2 {
|
|
_, err = dbStore.LightBlockBefore(i - 1)
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
}
|
|
|
|
_, err = dbStore.LastLightBlockHeight()
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
_, err = dbStore.FirstLightBlockHeight()
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
|
|
err = dbStore.Prune(3)
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
_ = dbStore.Size()
|
|
|
|
if i > 2 && i%2 == 0 {
|
|
err = dbStore.DeleteLightBlock(i - 1)
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
}
|
|
|
|
}(int64(i))
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func randLightBlock(ctx context.Context, t *testing.T, height int64) *types.LightBlock {
|
|
t.Helper()
|
|
vals, _ := factory.ValidatorSet(ctx, t, 2, 1)
|
|
return &types.LightBlock{
|
|
SignedHeader: &types.SignedHeader{
|
|
Header: &types.Header{
|
|
Version: version.Consensus{Block: version.BlockProtocol, App: 0},
|
|
ChainID: tmrand.Str(12),
|
|
Height: height,
|
|
Time: time.Now(),
|
|
LastBlockID: types.BlockID{},
|
|
LastCommitHash: crypto.CRandBytes(tmhash.Size),
|
|
DataHash: crypto.CRandBytes(tmhash.Size),
|
|
ValidatorsHash: crypto.CRandBytes(tmhash.Size),
|
|
NextValidatorsHash: crypto.CRandBytes(tmhash.Size),
|
|
ConsensusHash: crypto.CRandBytes(tmhash.Size),
|
|
AppHash: crypto.CRandBytes(tmhash.Size),
|
|
LastResultsHash: crypto.CRandBytes(tmhash.Size),
|
|
EvidenceHash: crypto.CRandBytes(tmhash.Size),
|
|
ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
|
|
},
|
|
Commit: &types.Commit{},
|
|
},
|
|
ValidatorSet: vals,
|
|
}
|
|
}
|