210 lines
4.7 KiB
Go
210 lines
4.7 KiB
Go
package address
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/golang-lru/simplelru"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/cosmos/cosmos-sdk/internal/conv"
|
|
)
|
|
|
|
var (
|
|
lru, _ = simplelru.NewLRU(500, nil)
|
|
cacheOptions = CachedCodecOptions{
|
|
Mu: &sync.Mutex{},
|
|
Lru: lru,
|
|
}
|
|
)
|
|
|
|
func generateAddresses(totalAddresses int) ([][]byte, error) {
|
|
keys := make([][]byte, totalAddresses)
|
|
addr := make([]byte, 32)
|
|
for i := 0; i < totalAddresses; i++ {
|
|
_, err := rand.Read(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
keys[i] = addr
|
|
}
|
|
|
|
return keys, nil
|
|
}
|
|
|
|
func TestNewBech32Codec(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
mu *sync.Mutex
|
|
lru func(t *testing.T) *simplelru.LRU
|
|
error bool
|
|
}{
|
|
{
|
|
name: "lru and mutex provided",
|
|
mu: &sync.Mutex{},
|
|
lru: func(t *testing.T) *simplelru.LRU {
|
|
t.Helper()
|
|
newLru, err := simplelru.NewLRU(500, nil)
|
|
require.NoError(t, err)
|
|
return newLru
|
|
},
|
|
},
|
|
{
|
|
name: "both empty",
|
|
mu: nil,
|
|
lru: func(t *testing.T) *simplelru.LRU {
|
|
t.Helper()
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
name: "only lru provided",
|
|
mu: nil,
|
|
lru: func(t *testing.T) *simplelru.LRU {
|
|
t.Helper()
|
|
newLru, err := simplelru.NewLRU(500, nil)
|
|
require.NoError(t, err)
|
|
return newLru
|
|
},
|
|
error: true,
|
|
},
|
|
{
|
|
name: "only mutex provided",
|
|
mu: &sync.Mutex{},
|
|
lru: func(t *testing.T) *simplelru.LRU {
|
|
t.Helper()
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
newLru := tt.lru(t)
|
|
got, err := NewCachedBech32Codec("cosmos", CachedCodecOptions{
|
|
Mu: tt.mu,
|
|
Lru: newLru,
|
|
})
|
|
if tt.error {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
require.NotNil(t, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBech32Codec(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
prefix string
|
|
lru *simplelru.LRU
|
|
address string
|
|
}{
|
|
{
|
|
name: "create accounts cached bech32 codec",
|
|
prefix: "cosmos",
|
|
lru: lru,
|
|
address: "cosmos1p8s0p6gqc6c9gt77lgr2qqujz49huhu6a80smx",
|
|
},
|
|
{
|
|
name: "create validator cached bech32 codec",
|
|
prefix: "cosmosvaloper",
|
|
lru: lru,
|
|
address: "cosmosvaloper1sjllsnramtg3ewxqwwrwjxfgc4n4ef9u2lcnj0",
|
|
},
|
|
{
|
|
name: "create consensus cached bech32 codec",
|
|
prefix: "cosmosvalcons",
|
|
lru: lru,
|
|
address: "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ac, err := NewCachedBech32Codec(tt.prefix, cacheOptions)
|
|
require.NoError(t, err)
|
|
|
|
cached, ok := ac.(cachedBech32Codec)
|
|
require.True(t, ok)
|
|
require.Equal(t, cached.cache, tt.lru)
|
|
|
|
addr, err := ac.StringToBytes(tt.address)
|
|
require.NoError(t, err)
|
|
|
|
cachedAddr, ok := tt.lru.Get(tt.address)
|
|
require.True(t, ok)
|
|
require.Equal(t, addr, cachedAddr)
|
|
|
|
accAddr, err := ac.BytesToString(addr)
|
|
require.NoError(t, err)
|
|
|
|
cachedStrAddr, ok := tt.lru.Get(conv.UnsafeBytesToStr(addr))
|
|
require.True(t, ok)
|
|
cachedStrAddrMap, ok := cachedStrAddr.(map[string]string)
|
|
require.True(t, ok)
|
|
require.Equal(t, accAddr, cachedStrAddrMap[tt.prefix])
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMultipleBech32Codec(t *testing.T) {
|
|
cAc, err := NewCachedBech32Codec("cosmos", cacheOptions)
|
|
require.NoError(t, err)
|
|
cosmosAc, ok := cAc.(cachedBech32Codec)
|
|
require.True(t, ok)
|
|
sAc, err := NewCachedBech32Codec("stake", cacheOptions)
|
|
require.NoError(t, err)
|
|
stakeAc, ok := sAc.(cachedBech32Codec)
|
|
require.True(t, ok)
|
|
require.Equal(t, cosmosAc.cache, stakeAc.cache)
|
|
|
|
addr := make([]byte, 32)
|
|
_, err = rand.Read(addr)
|
|
require.NoError(t, err)
|
|
|
|
cosmosAddr, err := cosmosAc.BytesToString(addr)
|
|
require.NoError(t, err)
|
|
stakeAddr, err := stakeAc.BytesToString(addr)
|
|
require.NoError(t, err)
|
|
require.True(t, cosmosAddr != stakeAddr)
|
|
|
|
cachedCosmosAddr, err := cosmosAc.BytesToString(addr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, cosmosAddr, cachedCosmosAddr)
|
|
|
|
cachedStakeAddr, err := stakeAc.BytesToString(addr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, stakeAddr, cachedStakeAddr)
|
|
}
|
|
|
|
func TestBech32CodecRace(t *testing.T) {
|
|
ac, err := NewCachedBech32Codec("cosmos", cacheOptions)
|
|
require.NoError(t, err)
|
|
myAddrBz := []byte{0x1, 0x2, 0x3, 0x4, 0x5}
|
|
|
|
var (
|
|
wgStart, wgDone sync.WaitGroup
|
|
errCount atomic.Uint32
|
|
)
|
|
const n = 3
|
|
wgStart.Add(n)
|
|
wgDone.Add(n)
|
|
for i := 0; i < n; i++ {
|
|
go func() {
|
|
wgStart.Done()
|
|
wgStart.Wait() // wait for all routines started
|
|
|
|
got, err := ac.BytesToString(myAddrBz)
|
|
if err != nil || got != "cosmos1qypqxpq9dc9msf" {
|
|
errCount.Add(1)
|
|
}
|
|
wgDone.Done()
|
|
}()
|
|
}
|
|
wgDone.Wait() // wait for all routines completed
|
|
require.Equal(t, errCount.Load(), uint32(0))
|
|
}
|