First end-to-end role tests
This commit is contained in:
parent
9ea34e9c8f
commit
33c9aa96f3
|
@ -0,0 +1,95 @@
|
||||||
|
package roles_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/tendermint/go-wire/data"
|
||||||
|
|
||||||
|
"github.com/tendermint/basecoin"
|
||||||
|
"github.com/tendermint/basecoin/modules/roles"
|
||||||
|
"github.com/tendermint/basecoin/stack"
|
||||||
|
"github.com/tendermint/basecoin/state"
|
||||||
|
)
|
||||||
|
|
||||||
|
// shortcut for the lazy
|
||||||
|
type ba []basecoin.Actor
|
||||||
|
|
||||||
|
func createRole(app basecoin.Handler, store state.KVStore,
|
||||||
|
name []byte, min uint32, sigs ...basecoin.Actor) (basecoin.Actor, error) {
|
||||||
|
tx := roles.NewCreateRoleTx(name, min, sigs)
|
||||||
|
ctx := stack.MockContext("foo", 1)
|
||||||
|
_, err := app.DeliverTx(ctx, store, tx)
|
||||||
|
return roles.NewPerm(name), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssumeRole(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
// one handle to add a role, another to check permissions
|
||||||
|
disp := stack.NewDispatcher(
|
||||||
|
stack.WrapHandler(roles.NewHandler()),
|
||||||
|
stack.WrapHandler(stack.CheckHandler{}),
|
||||||
|
)
|
||||||
|
// and wrap with the roles middleware
|
||||||
|
app := stack.New(roles.NewMiddleware()).Use(disp)
|
||||||
|
|
||||||
|
// basic state for the app
|
||||||
|
ctx := stack.MockContext("role-chain", 123)
|
||||||
|
store := state.NewMemKVStore()
|
||||||
|
|
||||||
|
// potential actors
|
||||||
|
a := basecoin.Actor{App: "sig", Address: []byte("jae")}
|
||||||
|
b := basecoin.Actor{App: "sig", Address: []byte("bucky")}
|
||||||
|
c := basecoin.Actor{App: "sig", Address: []byte("ethan")}
|
||||||
|
d := basecoin.Actor{App: "tracko", Address: []byte("rigel")}
|
||||||
|
|
||||||
|
// devs is a 2-of-3 multisig
|
||||||
|
devs := data.Bytes{0, 1, 0, 1}
|
||||||
|
pdev, err := createRole(app, store, devs, 2, b, c, d)
|
||||||
|
require.Nil(err)
|
||||||
|
|
||||||
|
// deploy requires a dev role, or supreme authority
|
||||||
|
deploy := data.Bytes("deploy")
|
||||||
|
_, err = createRole(app, store, deploy, 1, a, pdev)
|
||||||
|
require.Nil(err)
|
||||||
|
|
||||||
|
// now, let's test the roles are set properly
|
||||||
|
cases := []struct {
|
||||||
|
valid bool
|
||||||
|
roles []data.Bytes // which roles we try to assume (can be multiple!)
|
||||||
|
signers []basecoin.Actor // which people sign the tx
|
||||||
|
required []basecoin.Actor // which permission we require to succeed
|
||||||
|
}{
|
||||||
|
// basic checks to see logic works
|
||||||
|
{true, nil, nil, nil},
|
||||||
|
{true, nil, ba{b, c}, ba{b}},
|
||||||
|
{false, nil, ba{b}, ba{b, c}},
|
||||||
|
|
||||||
|
// simple role check
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range cases {
|
||||||
|
// set the signers, the required check
|
||||||
|
myCtx := ctx.WithPermissions(tc.signers...)
|
||||||
|
tx := stack.NewCheckTx(tc.required)
|
||||||
|
// and the roles we attempt to assume
|
||||||
|
for _, r := range tc.roles {
|
||||||
|
tx = roles.NewAssumeRoleTx(r, tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// try CheckTx and DeliverTx and make sure they both assert permissions
|
||||||
|
_, err := app.CheckTx(myCtx, store, tx)
|
||||||
|
_, err2 := app.DeliverTx(myCtx, store, tx)
|
||||||
|
if tc.valid {
|
||||||
|
assert.Nil(err, "%d: %+v", i, err)
|
||||||
|
assert.Nil(err2, "%d: %+v", i, err2)
|
||||||
|
} else {
|
||||||
|
assert.NotNil(err, "%d", i)
|
||||||
|
assert.NotNil(err2, "%d", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,21 @@ var (
|
||||||
MaxMembers = 20
|
MaxMembers = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint
|
||||||
|
const (
|
||||||
|
ByteAssumeRoleTx = 0x23
|
||||||
|
ByteCreateRoleTx = 0x24
|
||||||
|
|
||||||
|
TypeAssumeRoleTx = NameRole + "/assume" // no prefix needed as it is middleware
|
||||||
|
TypeCreateRoleTx = NameRole + "/create" // prefix needed for dispatcher
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
basecoin.TxMapper.
|
||||||
|
RegisterImplementation(AssumeRoleTx{}, TypeAssumeRoleTx, ByteAssumeRoleTx).
|
||||||
|
RegisterImplementation(CreateRoleTx{}, TypeCreateRoleTx, ByteCreateRoleTx)
|
||||||
|
}
|
||||||
|
|
||||||
// AssumeRoleTx is a layered tx that can wrap your normal tx to give it
|
// AssumeRoleTx is a layered tx that can wrap your normal tx to give it
|
||||||
// the authority to use a given role.
|
// the authority to use a given role.
|
||||||
type AssumeRoleTx struct {
|
type AssumeRoleTx struct {
|
||||||
|
|
|
@ -174,9 +174,11 @@ func (p PanicHandler) DeliverTx(ctx basecoin.Context, store state.KVStore, tx ba
|
||||||
|
|
||||||
// CheckHandler accepts CheckTx and verifies the permissions
|
// CheckHandler accepts CheckTx and verifies the permissions
|
||||||
type CheckHandler struct {
|
type CheckHandler struct {
|
||||||
PassOption
|
basecoin.NopOption
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ basecoin.Handler = CheckHandler{}
|
||||||
|
|
||||||
// Name - return handler's name
|
// Name - return handler's name
|
||||||
func (CheckHandler) Name() string {
|
func (CheckHandler) Name() string {
|
||||||
return NameCheck
|
return NameCheck
|
||||||
|
|
|
@ -77,6 +77,7 @@ func TestCheck(t *testing.T) {
|
||||||
valid bool
|
valid bool
|
||||||
signers, required []basecoin.Actor
|
signers, required []basecoin.Actor
|
||||||
}{
|
}{
|
||||||
|
{true, nil, nil},
|
||||||
{true, []basecoin.Actor{a}, []basecoin.Actor{a}},
|
{true, []basecoin.Actor{a}, []basecoin.Actor{a}},
|
||||||
{true, []basecoin.Actor{a, b}, []basecoin.Actor{a}},
|
{true, []basecoin.Actor{a, b}, []basecoin.Actor{a}},
|
||||||
{false, []basecoin.Actor{a}, []basecoin.Actor{a, b}},
|
{false, []basecoin.Actor{a}, []basecoin.Actor{a, b}},
|
||||||
|
|
Loading…
Reference in New Issue