More thorough tests on coin module

This commit is contained in:
Ethan Frey 2017-06-30 20:26:17 +02:00
parent 27a31953f9
commit 673b51f3b0
5 changed files with 174 additions and 6 deletions

View File

@ -43,21 +43,21 @@ func (h Handler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoi
return basecoin.Result{}, nil
}
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (*SendTx, error) {
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (send SendTx, err error) {
// check if the tx is proper type and valid
send, ok := tx.Unwrap().(*SendTx)
send, ok := tx.Unwrap().(SendTx)
if !ok {
return nil, errors.UnknownTxType(tx)
return send, errors.UnknownTxType(tx)
}
err := send.ValidateBasic()
err = send.ValidateBasic()
if err != nil {
return nil, err
return send, err
}
// check if all inputs have permission
for _, in := range send.Inputs {
if !ctx.HasPermission(in.Address) {
return nil, errors.Unauthorized()
return send, errors.Unauthorized()
}
}
return send, nil

View File

@ -0,0 +1,75 @@
package coin
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/types"
)
func TestHandlerPermissions(t *testing.T) {
assert := assert.New(t)
// TODO: need to update this when we actually have token store
h := Handler{}
// these are all valid, except for minusCoins
addr1 := basecoin.Actor{App: "coin", Address: []byte{1, 2}}
addr2 := basecoin.Actor{App: "role", Address: []byte{7, 8}}
someCoins := types.Coins{{"atom", 123}}
minusCoins := types.Coins{{"eth", -34}}
cases := []struct {
valid bool
tx SendTx
perms []basecoin.Actor
}{
// auth works with different apps
{true,
SendTx{
Inputs: []TxInput{NewTxInput(addr1, someCoins, 2)},
Outputs: []TxOutput{NewTxOutput(addr2, someCoins)}},
[]basecoin.Actor{addr1}},
{true,
SendTx{
Inputs: []TxInput{NewTxInput(addr2, someCoins, 2)},
Outputs: []TxOutput{NewTxOutput(addr1, someCoins)}},
[]basecoin.Actor{addr1, addr2}},
// wrong permissions fail
{false,
SendTx{
Inputs: []TxInput{NewTxInput(addr1, someCoins, 2)},
Outputs: []TxOutput{NewTxOutput(addr2, someCoins)}},
[]basecoin.Actor{}},
{false,
SendTx{
Inputs: []TxInput{NewTxInput(addr1, someCoins, 2)},
Outputs: []TxOutput{NewTxOutput(addr2, someCoins)}},
[]basecoin.Actor{addr2}},
// invalid input fails
{false,
SendTx{
Inputs: []TxInput{NewTxInput(addr1, minusCoins, 2)},
Outputs: []TxOutput{NewTxOutput(addr2, minusCoins)}},
[]basecoin.Actor{addr2}},
}
for i, tc := range cases {
ctx := stack.MockContext().WithPermissions(tc.perms...)
_, err := h.CheckTx(ctx, nil, tc.tx.Wrap())
if tc.valid {
assert.Nil(err, "%d: %+v", i, err)
} else {
assert.NotNil(err, "%d", i)
}
_, err = h.DeliverTx(ctx, nil, tc.tx.Wrap())
if tc.valid {
assert.Nil(err, "%d: %+v", i, err)
} else {
assert.NotNil(err, "%d", i)
}
}
}

View File

@ -9,6 +9,16 @@ import (
"github.com/tendermint/basecoin/types"
)
func init() {
basecoin.TxMapper.RegisterImplementation(SendTx{}, TypeSend, ByteSend)
}
// we reserve the 0x20-0x3f range for standard modules
const (
ByteSend = 0x20
TypeSend = "send"
)
//-----------------------------------------------------------------------------
type TxInput struct {

View File

@ -4,8 +4,10 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/types"
"github.com/tendermint/go-wire/data"
)
// these are some constructs for the test cases
@ -169,5 +171,33 @@ func TestTxValidateTx(t *testing.T) {
assert.NotNil(err, "%d", i)
}
}
}
func TestTxSerializeTx(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
addr1 := basecoin.Actor{App: "coin", Address: []byte{1, 2}}
addr2 := basecoin.Actor{App: "coin", Address: []byte{3, 4}}
someCoins := types.Coins{{"atom", 123}}
send := SendTx{
Inputs: []TxInput{NewTxInput(addr1, someCoins, 2)},
Outputs: []TxOutput{NewTxOutput(addr2, someCoins)},
}.Wrap()
js, err := data.ToJSON(send)
require.Nil(err)
var tx basecoin.Tx
err = data.FromJSON(js, &tx)
require.Nil(err)
assert.Equal(send, tx)
bin, err := data.ToWire(send)
require.Nil(err)
var tx2 basecoin.Tx
err = data.FromWire(bin, &tx2)
require.Nil(err)
assert.Equal(send, tx2)
}

53
stack/mock.go Normal file
View File

@ -0,0 +1,53 @@
package stack
import (
"bytes"
"github.com/tendermint/tmlibs/log"
"github.com/tendermint/basecoin"
)
type mockContext struct {
perms []basecoin.Actor
log.Logger
}
func MockContext() basecoin.Context {
return mockContext{
Logger: log.NewNopLogger(),
}
}
var _ basecoin.Context = mockContext{}
// WithPermissions will panic if they try to set permission without the proper app
func (c mockContext) WithPermissions(perms ...basecoin.Actor) basecoin.Context {
return mockContext{
perms: append(c.perms, perms...),
Logger: c.Logger,
}
}
func (c mockContext) HasPermission(perm basecoin.Actor) bool {
for _, p := range c.perms {
if perm.App == p.App && bytes.Equal(perm.Address, p.Address) {
return true
}
}
return false
}
// IsParent ensures that this is derived from the given secureClient
func (c mockContext) IsParent(other basecoin.Context) bool {
_, ok := other.(mockContext)
return ok
}
// Reset should clear out all permissions,
// but carry on knowledge that this is a child
func (c mockContext) Reset() basecoin.Context {
return mockContext{
Logger: c.Logger,
}
}