Test validateBasic methods

This commit is contained in:
Alex Peters
2020-07-01 09:59:40 +02:00
parent f7b4acf47c
commit 44696c4a98
5 changed files with 336 additions and 110 deletions

View File

@@ -101,7 +101,7 @@ func TestFailFastImport(t *testing.T) {
}},
Contracts: nil,
}},
"happy path: code info and contract do match": {
"happy path: code id in info and contract do match": {
src: types.GenesisState{
Codes: []types.Code{{
CodeInfo: wasmTypes.CodeInfo{
@@ -112,13 +112,8 @@ func TestFailFastImport(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: addrFromUint64(1<<32 + 1),
ContractInfo: wasmTypes.ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &types.AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
},
ContractAddress: contractAddress(1, 1),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
},
},
},
@@ -135,21 +130,11 @@ func TestFailFastImport(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: addrFromUint64(1<<32 + 1),
ContractInfo: wasmTypes.ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &types.AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
},
ContractAddress: contractAddress(1, 1),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
}, {
ContractAddress: addrFromUint64(2<<32 + 1),
ContractInfo: wasmTypes.ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &types.AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
},
ContractAddress: contractAddress(2, 1),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
},
},
},
@@ -160,17 +145,12 @@ func TestFailFastImport(t *testing.T) {
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1),
ContractInfo: wasmTypes.ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &types.AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
},
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
},
},
},
},
"prevent duplicate contracts": {
"prevent duplicate contract address": {
src: types.GenesisState{
Codes: []types.Code{{
CodeInfo: wasmTypes.CodeInfo{
@@ -182,25 +162,15 @@ func TestFailFastImport(t *testing.T) {
Contracts: []types.Contract{
{
ContractAddress: contractAddress(1, 1),
ContractInfo: wasmTypes.ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &types.AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
},
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
}, {
ContractAddress: contractAddress(1, 1),
ContractInfo: wasmTypes.ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &types.AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
},
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
},
},
},
},
"prevent duplicate contract model": {
"prevent duplicate contract model keys": {
src: types.GenesisState{
Codes: []types.Code{{
CodeInfo: wasmTypes.CodeInfo{
@@ -211,13 +181,8 @@ func TestFailFastImport(t *testing.T) {
}},
Contracts: []types.Contract{
{
ContractAddress: addrFromUint64(1<<32 + 1),
ContractInfo: wasmTypes.ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &types.AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
},
ContractAddress: contractAddress(1, 1),
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
ContractState: []types.Model{
{
Key: []byte{0x1},

View File

@@ -1,35 +1,34 @@
package types
import (
"crypto/sha256"
"bytes"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/rand"
)
func TestValidateGenesisState(t *testing.T) {
specs := map[string]struct {
srcMutator func(state GenesisState)
srcMutator func(*GenesisState)
expError bool
}{
"all good": {
srcMutator: func(s GenesisState) {},
srcMutator: func(s *GenesisState) {},
},
"codeinfo invalid": {
srcMutator: func(s GenesisState) {
srcMutator: func(s *GenesisState) {
s.Codes[0].CodeInfo.CodeHash = nil
},
expError: true,
},
"contract invalid": {
srcMutator: func(s GenesisState) {
srcMutator: func(s *GenesisState) {
s.Contracts[0].ContractAddress = nil
},
expError: true,
},
"sequence invalid": {
srcMutator: func(s GenesisState) {
srcMutator: func(s *GenesisState) {
s.Sequences[0].IDKey = nil
},
expError: true,
@@ -37,7 +36,7 @@ func TestValidateGenesisState(t *testing.T) {
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
state := genesisFixture(spec.srcMutator)
state := GenesisFixture(spec.srcMutator)
got := state.ValidateBasic()
if spec.expError {
require.Error(t, got)
@@ -46,62 +45,86 @@ func TestValidateGenesisState(t *testing.T) {
require.NoError(t, got)
})
}
}
func genesisFixture(mutators ...func(state GenesisState)) GenesisState {
const (
numCodes = 2
numContracts = 2
numSequences = 2
)
fixture := GenesisState{
Codes: make([]Code, numCodes),
Contracts: make([]Contract, numContracts),
Sequences: make([]Sequence, numSequences),
}
for i := 0; i < numCodes; i++ {
fixture.Codes[i] = codeFixture()
}
for i := 0; i < numContracts; i++ {
fixture.Contracts[i] = contractFixture()
}
for i := 0; i < numSequences; i++ {
fixture.Sequences[i] = Sequence{
IDKey: rand.Bytes(5),
Value: uint64(i),
}
}
for _, m := range mutators {
m(fixture)
}
return fixture
}
func codeFixture() Code {
wasmCode := rand.Bytes(100)
codeHash := sha256.Sum256(wasmCode)
anyAddress := make([]byte, 20)
return Code{
CodeInfo: CodeInfo{
CodeHash: codeHash[:],
Creator: anyAddress,
func TestCodeValidateBasic(t *testing.T) {
specs := map[string]struct {
srcMutator func(*Code)
expError bool
}{
"all good": {srcMutator: func(_ *Code) {}},
"codeinfo invalid": {
srcMutator: func(c *Code) {
c.CodeInfo.CodeHash = nil
},
expError: true,
},
CodesBytes: wasmCode,
}
}
func contractFixture() Contract {
anyAddress := make([]byte, 20)
return Contract{
ContractAddress: anyAddress,
ContractInfo: ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
"codeBytes empty": {
srcMutator: func(c *Code) {
c.CodesBytes = []byte{}
},
expError: true,
},
"codeBytes nil": {
srcMutator: func(c *Code) {
c.CodesBytes = nil
},
expError: true,
},
"codeBytes greater limit": {
srcMutator: func(c *Code) {
c.CodesBytes = bytes.Repeat([]byte{0x1}, MaxWasmSize+1)
},
expError: true,
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
state := CodeFixture(spec.srcMutator)
got := state.ValidateBasic()
if spec.expError {
require.Error(t, got)
return
}
require.NoError(t, got)
})
}
}
func TestContractValidateBasic(t *testing.T) {
specs := map[string]struct {
srcMutator func(*Contract)
expError bool
}{
"all good": {srcMutator: func(_ *Contract) {}},
"contract address invalid": {
srcMutator: func(c *Contract) {
c.ContractAddress = nil
},
expError: true,
},
"contract info invalid": {
srcMutator: func(c *Contract) {
c.ContractInfo.Creator = nil
},
expError: true,
},
"contract state invalid": {
srcMutator: func(c *Contract) {
c.ContractState = append(c.ContractState, Model{})
},
expError: true,
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
state := ContractFixture(spec.srcMutator)
got := state.ValidateBasic()
if spec.expError {
require.Error(t, got)
return
}
require.NoError(t, got)
})
}
}

View File

@@ -0,0 +1,102 @@
package types
import (
"bytes"
"crypto/sha256"
"github.com/tendermint/tendermint/libs/rand"
)
func GenesisFixture(mutators ...func(*GenesisState)) GenesisState {
const (
numCodes = 2
numContracts = 2
numSequences = 2
)
fixture := GenesisState{
Codes: make([]Code, numCodes),
Contracts: make([]Contract, numContracts),
Sequences: make([]Sequence, numSequences),
}
for i := 0; i < numCodes; i++ {
fixture.Codes[i] = CodeFixture()
}
for i := 0; i < numContracts; i++ {
fixture.Contracts[i] = ContractFixture()
}
for i := 0; i < numSequences; i++ {
fixture.Sequences[i] = Sequence{
IDKey: rand.Bytes(5),
Value: uint64(i),
}
}
for _, m := range mutators {
m(&fixture)
}
return fixture
}
func CodeFixture(mutators ...func(*Code)) Code {
wasmCode := rand.Bytes(100)
codeHash := sha256.Sum256(wasmCode)
anyAddress := make([]byte, 20)
fixture := Code{
CodeInfo: CodeInfo{
CodeHash: codeHash[:],
Creator: anyAddress,
},
CodesBytes: wasmCode,
}
for _, m := range mutators {
m(&fixture)
}
return fixture
}
func CodeInfoFixture(mutators ...func(*CodeInfo)) CodeInfo {
wasmCode := bytes.Repeat([]byte{0x1}, 10)
codeHash := sha256.Sum256(wasmCode)
anyAddress := make([]byte, 20)
fixture := CodeInfo{
CodeHash: codeHash[:],
Creator: anyAddress,
Source: "https://example.com",
Builder: "my/builder:tag",
}
for _, m := range mutators {
m(&fixture)
}
return fixture
}
func ContractFixture(mutators ...func(*Contract)) Contract {
anyAddress := make([]byte, 20)
fixture := Contract{
ContractAddress: anyAddress,
ContractInfo: ContractInfoFixture(),
ContractState: []Model{{Key: []byte("anyKey"), Value: []byte("anyValue")}},
}
for _, m := range mutators {
m(&fixture)
}
return fixture
}
func ContractInfoFixture(mutators ...func(*ContractInfo)) ContractInfo {
anyAddress := make([]byte, 20)
fixture := ContractInfo{
CodeID: 1,
Creator: anyAddress,
Label: "any",
Created: &AbsoluteTxPosition{BlockHeight: 1, TxIndex: 1},
}
for _, m := range mutators {
m(&fixture)
}
return fixture
}

View File

@@ -97,6 +97,9 @@ func (c *ContractInfo) ValidateBasic() error {
if err := validateLabel(c.Label); err != nil {
return sdkerrors.Wrap(err, "label")
}
if c.Created == nil {
return sdkerrors.Wrap(ErrEmpty, "created")
}
if err := c.Created.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "created")
}

View File

@@ -0,0 +1,133 @@
package types
import (
"strings"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
)
func TestContractInfoValidateBasic(t *testing.T) {
specs := map[string]struct {
srcMutator func(*ContractInfo)
expError bool
}{
"all good": {srcMutator: func(_ *ContractInfo) {}},
"code id empty": {
srcMutator: func(c *ContractInfo) { c.CodeID = 0 },
expError: true,
},
"creator empty": {
srcMutator: func(c *ContractInfo) { c.Creator = nil },
expError: true,
},
"creator not an address": {
srcMutator: func(c *ContractInfo) { c.Creator = make([]byte, sdk.AddrLen-1) },
expError: true,
},
"admin empty": {
srcMutator: func(c *ContractInfo) { c.Admin = nil },
expError: false,
},
"admin not an address": {
srcMutator: func(c *ContractInfo) { c.Admin = make([]byte, sdk.AddrLen-1) },
expError: true,
},
"label empty": {
srcMutator: func(c *ContractInfo) { c.Label = "" },
expError: true,
},
"label exceeds limit": {
srcMutator: func(c *ContractInfo) { c.Label = strings.Repeat("a", MaxLabelSize+1) },
expError: true,
},
"init msg empty": {
srcMutator: func(c *ContractInfo) { c.InitMsg = nil },
},
"created nil": {
srcMutator: func(c *ContractInfo) { c.Created = nil },
expError: true,
},
"created invalid": {
srcMutator: func(c *ContractInfo) { c.Created = &AbsoluteTxPosition{BlockHeight: -1} },
expError: true,
},
"last updated nil": {
srcMutator: func(c *ContractInfo) { c.LastUpdated = nil },
},
"previous code id empty": {
srcMutator: func(c *ContractInfo) { c.PreviousCodeID = 0 },
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
state := ContractInfoFixture(spec.srcMutator)
got := state.ValidateBasic()
if spec.expError {
require.Error(t, got)
return
}
require.NoError(t, got)
})
}
}
func TestCodeInfoValidateBasic(t *testing.T) {
specs := map[string]struct {
srcMutator func(*CodeInfo)
expError bool
}{
"all good": {srcMutator: func(_ *CodeInfo) {}},
"code hash empty": {
srcMutator: func(c *CodeInfo) { c.CodeHash = []byte{} },
expError: true,
},
"code hash nil": {
srcMutator: func(c *CodeInfo) { c.CodeHash = nil },
expError: true,
},
"creator empty": {
srcMutator: func(c *CodeInfo) { c.Creator = nil },
expError: true,
},
"creator not an address": {
srcMutator: func(c *CodeInfo) { c.Creator = make([]byte, sdk.AddrLen-1) },
expError: true,
},
"source empty": {
srcMutator: func(c *CodeInfo) { c.Source = "" },
},
"source not an url": {
srcMutator: func(c *CodeInfo) { c.Source = "invalid" },
expError: true,
},
"source not an absolute url": {
srcMutator: func(c *CodeInfo) { c.Source = "../bar.txt" },
expError: true,
},
"source not https schema url": {
srcMutator: func(c *CodeInfo) { c.Source = "http://example.com" },
expError: true,
},
"builder tag exceeds limit": {
srcMutator: func(c *CodeInfo) { c.Builder = strings.Repeat("a", MaxBuildTagSize+1) },
expError: true,
},
"builder tag does not match pattern": {
srcMutator: func(c *CodeInfo) { c.Builder = "invalid" },
expError: true,
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
state := CodeInfoFixture(spec.srcMutator)
got := state.ValidateBasic()
if spec.expError {
require.Error(t, got)
return
}
require.NoError(t, got)
})
}
}