package iavl import ( "fmt" "github.com/stretchr/testify/assert" "github.com/tendermint/tm-cmn/db" "math/big" "sync" "testing" ) func Int64ToBytes(i int64) []byte { v := big.NewInt(i) return v.Bytes() } func BytesToInt64(buf []byte) int64 { v:= big.NewInt(0) v.SetBytes(buf) return v.Int64() } //Self-increasing ID func GetNextId(tree *MutableTree, key []byte) int64 { _, bz := tree.Get(key) value := BytesToInt64(bz) tree.Set(key, Int64ToBytes(value+1)) return value } //MultAddress, race happens func TestIavlRaceMultAddr(t *testing.T) { db := db.NewMemDB() tree := NewMutableTree(db, 0) addrNum, iterNum := 5, 10 seenMap := make(map[string]string, addrNum*iterNum) var mtx sync.Mutex var wg sync.WaitGroup for addr := 0; addr <= addrNum; addr++ { wg.Add(1) key := []byte(fmt.Sprintf("address%v", addr)) tree.Set(key, Int64ToBytes(0)) go func(key []byte) { for iter := 0; iter < iterNum; iter++ { val := GetNextId(tree, key) mtx.Lock() _, seen := seenMap[fmt.Sprintf("%s-%d", string(key[:]), val)] assert.False(t, seen, "duplicate:%s-%d ", string(key[:]), val) seenMap[fmt.Sprintf("%s-%d", string(key[:]), val)] = "seen" mtx.Unlock() } defer wg.Done() }(key) } wg.Wait() } //SingleAddr, work as expected func TestIavlRaceSingleAddr(t *testing.T) { db := db.NewMemDB() tree := NewMutableTree(db, 100) iterNum := 100 seenMap := make(map[int]string, iterNum) var mtx sync.Mutex key := []byte("address") tree.Set(key, Int64ToBytes(0)) for iter := 0; iter < iterNum; iter++ { val := GetNextId(tree, key) mtx.Lock() _, seen := seenMap[int(val)] assert.False(t, seen, "duplicate:%d ", val) seenMap[int(val)] = "seen" mtx.Unlock() } } func TestInt2Byte(t *testing.T){ for i:=0; i<10000;i++{ v:= BytesToInt64(Int64ToBytes(int64(i))) assert.Equal(t, int64(i), v) } }