func TestValUpdates(t *testing.T) {
	dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test")  
	if err != nil {
		t.Fatal(err)
	}
	kvstore := NewPersistentKVStoreApplication(dir)
	total := 10
	nInit := 5
	vals := RandVals(total)
	kvstore.InitChain(types.RequestInitChain{
		Validators: vals[:nInit],
	})
	vals1, vals2 := vals[:nInit], kvstore.Validators()
	valsEqual(t, vals1, vals2)
	var v1, v2, v3 types.ValidatorUpdate
	v1, v2 = vals[nInit], vals[nInit+1]
	diff := []types.ValidatorUpdate{v1, v2}
	tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power)
	tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power)
	makeApplyBlock(t, kvstore, 1, diff, tx1, tx2)
	vals1, vals2 = vals[:nInit+2], kvstore.Validators()
	valsEqual(t, vals1, vals2)
	v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit]
	v1.Power = 0
	v2.Power = 0
	v3.Power = 0
	diff = []types.ValidatorUpdate{v1, v2, v3}
	tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
	tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power)
	tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power)
	makeApplyBlock(t, kvstore, 2, diff, tx1, tx2, tx3)
	vals1 = append(vals[:nInit-2], vals[nInit+1])
	vals2 = kvstore.Validators()
	valsEqual(t, vals1, vals2)
	v1 = vals[0]
	if v1.Power == 5 {
		v1.Power = 6
	} else {
		v1.Power = 5
	}
	diff = []types.ValidatorUpdate{v1}
	tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
	makeApplyBlock(t, kvstore, 3, diff, tx1)
	vals1 = append([]types.ValidatorUpdate{v1}, vals1[1:]...)
	vals2 = kvstore.Validators()
	valsEqual(t, vals1, vals2)
}
add a validator, remove a validator, update a validator
package kvstore
import (
	"bytes"
	"fmt"
	"io/ioutil"
	"sort"
	"testing"
	"github.com/stretchr/testify/require"
	cmn "github.com/XuanMaoSecLab/DolphinChain/libs/common"
	"github.com/XuanMaoSecLab/DolphinChain/libs/log"
	abcicli "github.com/XuanMaoSecLab/DolphinChain/abci/client"
	"github.com/XuanMaoSecLab/DolphinChain/abci/example/code"
	abciserver "github.com/XuanMaoSecLab/DolphinChain/abci/server"
	"github.com/XuanMaoSecLab/DolphinChain/abci/types"
)
func testKVStore(t *testing.T, app types.Application, tx []byte, key, value string) {
	ar := app.DeliverTx(tx)
	require.False(t, ar.IsErr(), ar)
	ar = app.DeliverTx(tx)
	require.False(t, ar.IsErr(), ar)
	resQuery := app.Query(types.RequestQuery{
		Path: "/store",
		Data: []byte(key),
	})
	require.Equal(t, code.CodeTypeOK, resQuery.Code)
	require.Equal(t, value, string(resQuery.Value))
	resQuery = app.Query(types.RequestQuery{
		Path:  "/store",
		Data:  []byte(key),
		Prove: true,
	})
	require.EqualValues(t, code.CodeTypeOK, resQuery.Code)
	require.Equal(t, value, string(resQuery.Value))
}
func TestKVStoreKV(t *testing.T) {
	kvstore := NewKVStoreApplication()
	key := "abc"
	value := key
	tx := []byte(key)
	testKVStore(t, kvstore, tx, key, value)
	value = "def"
	tx = []byte(key + "=" + value)
	testKVStore(t, kvstore, tx, key, value)
}
func TestPersistentKVStoreKV(t *testing.T) {
	dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test")  
	if err != nil {
		t.Fatal(err)
	}
	kvstore := NewPersistentKVStoreApplication(dir)
	key := "abc"
	value := key
	tx := []byte(key)
	testKVStore(t, kvstore, tx, key, value)
	value = "def"
	tx = []byte(key + "=" + value)
	testKVStore(t, kvstore, tx, key, value)
}
func TestPersistentKVStoreInfo(t *testing.T) {
	dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test")  
	if err != nil {
		t.Fatal(err)
	}
	kvstore := NewPersistentKVStoreApplication(dir)
	InitKVStore(kvstore)
	height := int64(0)
	resInfo := kvstore.Info(types.RequestInfo{})
	if resInfo.LastBlockHeight != height {
		t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
	}
	height = int64(1)
	hash := []byte("foo")
	header := types.Header{
		Height: int64(height),
	}
	kvstore.BeginBlock(types.RequestBeginBlock{Hash: hash, Header: header})
	kvstore.EndBlock(types.RequestEndBlock{Height: header.Height})
	kvstore.Commit()
	resInfo = kvstore.Info(types.RequestInfo{})
	if resInfo.LastBlockHeight != height {
		t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
	}
}