Tested and fixed multiplexer, add more helpers

This commit is contained in:
Ethan Frey 2017-08-03 21:40:45 +02:00
parent 74070f1cac
commit 21e2399fc4
6 changed files with 213 additions and 63 deletions

View File

@ -1,9 +1,3 @@
# TODO for rewrite
* Add tests for new CheckTx
* Test Multiplexer
Alexis:
* merkle - proof (non-existence - maybe range)
@ -12,8 +6,7 @@ light-client proofs:
* make this sensible -> very tied to merkle proofs and API
* support new proof types
* abci add range suppprt
* expose more proof types in basecoin.Query
* merkle - api cleanup (also Bonsai)

View File

@ -6,60 +6,12 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin/modules/base"
wire "github.com/tendermint/go-wire"
cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/tmlibs/log"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/state"
)
//--------------------------------
// Setup tx and handler for validation test cases
const (
ValName = "val"
TypeValChange = ValName + "/change"
ByteValChange = 0xfe
)
func init() {
basecoin.TxMapper.RegisterImplementation(ValChangeTx{}, TypeValChange, ByteValChange)
}
type ValSetHandler struct {
basecoin.NopCheck
basecoin.NopInitState
basecoin.NopInitValidate
}
var _ basecoin.Handler = ValSetHandler{}
func (ValSetHandler) Name() string {
return ValName
}
func (ValSetHandler) DeliverTx(ctx basecoin.Context, store state.SimpleDB,
tx basecoin.Tx) (res basecoin.DeliverResult, err error) {
change, ok := tx.Unwrap().(ValChangeTx)
if !ok {
return res, errors.ErrUnknownTxType(tx)
}
res.Diff = change.Diff
return
}
type ValChangeTx struct {
Diff []*abci.Validator
}
func (v ValChangeTx) Wrap() basecoin.Tx {
return basecoin.Tx{v}
}
func (v ValChangeTx) ValidateBasic() error { return nil }
//-----------------------------------
// Test cases start here
@ -90,7 +42,7 @@ func TestEndBlock(t *testing.T) {
logger := log.NewNopLogger()
store := MockStore()
handler := ValSetHandler{}
handler := base.ValSetHandler{}
app := NewBasecoin(handler, store, logger)
val1 := makeVal()
@ -125,7 +77,7 @@ func TestEndBlock(t *testing.T) {
for i, tc := range cases {
app.BeginBlock(nil, nil)
for _, c := range tc.changes {
tx := ValChangeTx{c}.Wrap()
tx := base.ValChangeTx{c}.Wrap()
txBytes := wire.BinaryBytes(tx)
res := app.DeliverTx(txBytes)
require.True(res.IsOK(), "%#v", res)

118
modules/base/helpers.go Normal file
View File

@ -0,0 +1,118 @@
package base
import (
abci "github.com/tendermint/abci/types"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
"github.com/tendermint/basecoin/state"
)
//nolint
const (
NameVal = "val"
NamePrice = "price"
TypeValChange = NameVal + "/change"
ByteValChange = 0xfe
TypePriceShow = NamePrice + "/show"
BytePriceShow = 0xfd
)
func init() {
basecoin.TxMapper.
RegisterImplementation(ValChangeTx{}, TypeValChange, ByteValChange).
RegisterImplementation(PriceShowTx{}, TypePriceShow, BytePriceShow)
}
//--------------------------------
// Setup tx and handler for validation test cases
type ValSetHandler struct {
basecoin.NopCheck
basecoin.NopInitState
basecoin.NopInitValidate
}
var _ basecoin.Handler = ValSetHandler{}
func (ValSetHandler) Name() string {
return NameVal
}
func (ValSetHandler) DeliverTx(ctx basecoin.Context, store state.SimpleDB,
tx basecoin.Tx) (res basecoin.DeliverResult, err error) {
change, ok := tx.Unwrap().(ValChangeTx)
if !ok {
return res, errors.ErrUnknownTxType(tx)
}
res.Diff = change.Diff
return
}
type ValChangeTx struct {
Diff []*abci.Validator
}
func (v ValChangeTx) Wrap() basecoin.Tx {
return basecoin.Tx{v}
}
func (v ValChangeTx) ValidateBasic() error { return nil }
//--------------------------------
// Setup tx and handler for testing checktx fees/gas
// PriceData is the data we ping back
var PriceData = []byte{0xCA, 0xFE}
// PriceHandler returns checktx results based on the input
type PriceHandler struct {
basecoin.NopInitState
basecoin.NopInitValidate
}
var _ basecoin.Handler = PriceHandler{}
func (PriceHandler) Name() string {
return NamePrice
}
func (PriceHandler) CheckTx(ctx basecoin.Context, store state.SimpleDB,
tx basecoin.Tx) (res basecoin.CheckResult, err error) {
price, ok := tx.Unwrap().(PriceShowTx)
if !ok {
return res, errors.ErrUnknownTxType(tx)
}
res.GasAllocated = price.GasAllocated
res.GasPayment = price.GasPayment
res.Data = PriceData
return
}
func (PriceHandler) DeliverTx(ctx basecoin.Context, store state.SimpleDB,
tx basecoin.Tx) (res basecoin.DeliverResult, err error) {
_, ok := tx.Unwrap().(PriceShowTx)
if !ok {
return res, errors.ErrUnknownTxType(tx)
}
res.Data = PriceData
return
}
// PriceShowTx lets us bounce back a given fee/gas on CheckTx
type PriceShowTx struct {
GasAllocated uint
GasPayment uint
}
func NewPriceShowTx(gasAllocated, gasPayment uint) basecoin.Tx {
return PriceShowTx{GasAllocated: gasAllocated, GasPayment: gasPayment}.Wrap()
}
func (p PriceShowTx) Wrap() basecoin.Tx {
return basecoin.Tx{p}
}
func (v PriceShowTx) ValidateBasic() error { return nil }

View File

@ -32,7 +32,7 @@ var _ stack.Middleware = Multiplexer{}
// CheckTx splits the input tx and checks them all - fulfills Middlware interface
func (Multiplexer) CheckTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx, next basecoin.Checker) (res basecoin.CheckResult, err error) {
if mtx, ok := tx.Unwrap().(*MultiTx); ok {
if mtx, ok := tx.Unwrap().(MultiTx); ok {
return runAllChecks(ctx, store, mtx.Txs, next)
}
return next.CheckTx(ctx, store, tx)
@ -40,7 +40,7 @@ func (Multiplexer) CheckTx(ctx basecoin.Context, store state.SimpleDB, tx baseco
// DeliverTx splits the input tx and checks them all - fulfills Middlware interface
func (Multiplexer) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx, next basecoin.Deliver) (res basecoin.DeliverResult, err error) {
if mtx, ok := tx.Unwrap().(*MultiTx); ok {
if mtx, ok := tx.Unwrap().(MultiTx); ok {
return runAllDelivers(ctx, store, mtx.Txs, next)
}
return next.DeliverTx(ctx, store, tx)

View File

@ -0,0 +1,87 @@
package base
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/stack"
"github.com/tendermint/basecoin/state"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/go-wire/data"
"github.com/tendermint/tmlibs/log"
)
func TestMultiplexer(t *testing.T) {
assert := assert.New(t)
msg := "diddly"
chainID := "multi-verse"
height := uint64(100)
// Generic args here...
store := state.NewMemKVStore()
ctx := stack.NewContext(chainID, height, log.NewNopLogger())
// Build the stack
app := stack.
New(Multiplexer{}).
Dispatch(
stack.WrapHandler(stack.OKHandler{Log: msg}),
stack.WrapHandler(PriceHandler{}),
)
raw := stack.NewRawTx([]byte{1, 2, 3, 4})
fail := stack.NewFailTx()
price1 := NewPriceShowTx(123, 456)
price2 := NewPriceShowTx(1000, 2000)
price3 := NewPriceShowTx(11, 0)
join := func(data ...[]byte) []byte {
return wire.BinaryBytes(data)
}
cases := [...]struct {
tx basecoin.Tx
valid bool
gasAllocated uint
gasPayment uint
log string
data data.Bytes
}{
// test the components without multiplexer (no effect)
0: {raw, true, 0, 0, msg, nil},
1: {price1, true, 123, 456, "", PriceData},
2: {fail, false, 0, 0, "", nil},
// test multiplexer on error
3: {NewMultiTx(raw, fail, price1), false, 0, 0, "", nil},
// test combining info on multiplexer
4: {NewMultiTx(price1, raw), true, 123, 456, "\n" + msg, join(PriceData, nil)},
// add lots of prices
5: {NewMultiTx(price1, price2, price3), true, 1134, 2456, "\n\n", join(PriceData, PriceData, PriceData)},
// combine multiple logs
6: {NewMultiTx(raw, price3, raw), true, 11, 0, msg + "\n\n" + msg, join(nil, PriceData, nil)},
}
for i, tc := range cases {
cres, err := app.CheckTx(ctx, store, tc.tx)
if tc.valid {
assert.Nil(err, "%d: %+v", i, err)
assert.Equal(tc.log, cres.Log, "%d", i)
assert.Equal(tc.data, cres.Data, "%d", i)
assert.Equal(tc.gasAllocated, cres.GasAllocated, "%d", i)
assert.Equal(tc.gasPayment, cres.GasPayment, "%d", i)
} else {
assert.NotNil(err, "%d", i)
}
// make sure deliver returns error, not a panic crash
dres, err := app.DeliverTx(ctx, store, tc.tx)
if tc.valid {
assert.Nil(err, "%d: %+v", i, err)
assert.Equal(tc.log, dres.Log, "%d", i)
assert.Equal(tc.data, dres.Data, "%d", i)
} else {
assert.NotNil(err, "%d", i)
}
}
}

View File

@ -16,13 +16,13 @@ const (
//nolint
const (
// TypeMultiTx = NameMultiplexer + "/tx"
TypeMultiTx = NameMultiplexer + "/tx"
TypeChainTx = NameChain + "/tx"
)
func init() {
basecoin.TxMapper.
// RegisterImplementation(MultiTx{}, TypeMultiTx, ByteMultiTx).
RegisterImplementation(MultiTx{}, TypeMultiTx, ByteMultiTx).
RegisterImplementation(ChainTx{}, TypeChainTx, ByteChainTx)
}