Tested and fixed multiplexer, add more helpers
This commit is contained in:
parent
74070f1cac
commit
21e2399fc4
9
TODO.md
9
TODO.md
@ -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)
|
||||
|
||||
@ -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
118
modules/base/helpers.go
Normal 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 }
|
||||
@ -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)
|
||||
|
||||
87
modules/base/multiplexer_test.go
Normal file
87
modules/base/multiplexer_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user