Skip to content

Commit

Permalink
DARC smart contract unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Gilthoniel committed Apr 6, 2020
1 parent f4ecb70 commit 8703ddb
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 12 deletions.
16 changes: 11 additions & 5 deletions ledger/arc/darc/contract/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@ func (c Contract) Spawn(ctx sc.SpawnContext) (proto.Message, []byte, error) {
return nil, nil, xerrors.Errorf("couldn't decode argument: %v", err)
}

access, ok := gnrc.(darc.Access)
access, ok := gnrc.(darc.EvolvableAccessControl)
if !ok {
return nil, nil, xerrors.Errorf("invalid access type '%T'", gnrc)
return nil, nil,
xerrors.Errorf("'%T' does not implement 'darc.EvolvableAccessControl'", gnrc)
}

// Set a rule to allow the creator of the DARC to update it.
rule := arc.Compile(ContractName, "invoke")
access, err = access.Evolve(rule, ctx.GetTransaction().GetIdentity())
if err != nil {
return nil, nil, err
return nil, nil, xerrors.Errorf("couldn't evolve darc: %v", err)
}

darcpb, err := c.encoder.Pack(access)
Expand All @@ -54,14 +55,19 @@ func (c Contract) Invoke(ctx sc.InvokeContext) (proto.Message, error) {
return nil, xerrors.Errorf("couldn't read instance: %v", err)
}

access, err := c.factory.FromProto(instance.GetValue())
gnrc, err := c.factory.FromProto(instance.GetValue())
if err != nil {
return nil, xerrors.Errorf("couldn't decode darc: %v", err)
}

access, ok := gnrc.(darc.EvolvableAccessControl)
if !ok {
return nil, xerrors.Errorf("'%T' does not implement 'darc.EvolvableAccessControl'", gnrc)
}

// TODO: use argument to update the darc..

darcpb, err := c.encoder.Pack(access.(darc.Access))
darcpb, err := c.encoder.Pack(access)
if err != nil {
return nil, xerrors.Errorf("couldn't pack darc: %v", err)
}
Expand Down
75 changes: 72 additions & 3 deletions ledger/arc/darc/contract/mod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import (
"go.dedis.ch/fabric/ledger/arc/darc"
"go.dedis.ch/fabric/ledger/consumer"
"go.dedis.ch/fabric/ledger/consumer/smartcontract"
"golang.org/x/xerrors"
)

func TestContract_Spawn(t *testing.T) {
contract := Contract{
encoder: encoding.NewProtoEncoder(),
factory: darc.Factory{},
factory: darc.NewFactory(),
}

ctx := smartcontract.SpawnContext{
Expand All @@ -26,13 +27,31 @@ func TestContract_Spawn(t *testing.T) {
}

arg := &darc.AccessControlProto{Rules: map[string]*darc.Expression{
"darc:invoke": &darc.Expression{Matches: []string{"\252"}},
"darc:invoke": {Matches: []string{"\252"}},
}}

pb, arcid, err := contract.Spawn(ctx)
require.NoError(t, err)
require.Equal(t, []byte{0xff}, arcid)
require.True(t, proto.Equal(arg, pb), "%+v != %+v", pb, arg)

contract.factory = badArcFactory{err: xerrors.New("oops")}
_, _, err = contract.Spawn(ctx)
require.EqualError(t, err, "couldn't decode argument: oops")

contract.factory = badArcFactory{arc: fakeArc{}}
_, _, err = contract.Spawn(ctx)
require.EqualError(t, err,
"'contract.fakeArc' does not implement 'darc.EvolvableAccessControl'")

contract.factory = badArcFactory{arc: badArc{}}
_, _, err = contract.Spawn(ctx)
require.EqualError(t, err, "couldn't evolve darc: oops")

contract.factory = darc.NewFactory()
contract.encoder = badEncoder{}
_, _, err = contract.Spawn(ctx)
require.EqualError(t, err, "couldn't pack darc: oops")
}

func TestContract_Invoke(t *testing.T) {
Expand All @@ -49,6 +68,25 @@ func TestContract_Invoke(t *testing.T) {
pb, err := contract.Invoke(ctx)
require.NoError(t, err)
require.NotNil(t, pb)

ctx.Context = fakeContext{err: xerrors.New("oops")}
_, err = contract.Invoke(ctx)
require.EqualError(t, err, "couldn't read instance: oops")

ctx.Context = fakeContext{}
contract.factory = badArcFactory{err: xerrors.New("oops")}
_, err = contract.Invoke(ctx)
require.EqualError(t, err, "couldn't decode darc: oops")

contract.factory = badArcFactory{arc: fakeArc{}}
_, err = contract.Invoke(ctx)
require.EqualError(t, err,
"'contract.fakeArc' does not implement 'darc.EvolvableAccessControl'")

contract.factory = darc.NewFactory()
contract.encoder = badEncoder{}
_, err = contract.Invoke(ctx)
require.EqualError(t, err, "couldn't pack darc: oops")
}

func Test_NewGenesisTransaction(t *testing.T) {
Expand All @@ -68,6 +106,14 @@ func Test_RegisterContract(t *testing.T) {
// -----------------------------------------------------------------------------
// Utility functions

type badEncoder struct {
encoding.ProtoEncoder
}

func (e badEncoder) Pack(encoding.Packable) (proto.Message, error) {
return nil, xerrors.New("oops")
}

type fakeIdentity struct {
arc.Identity
}
Expand Down Expand Up @@ -98,12 +144,35 @@ func (i fakeInstance) GetValue() proto.Message {

type fakeContext struct {
consumer.Context
err error
}

func (ctx fakeContext) GetTransaction() consumer.Transaction {
return fakeTransaction{}
}

func (ctx fakeContext) Read([]byte) (consumer.Instance, error) {
return fakeInstance{}, nil
return fakeInstance{}, ctx.err
}

type fakeArc struct {
arc.AccessControl
}

type badArc struct {
arc.AccessControl
}

func (arc badArc) Evolve(string, ...arc.Identity) (darc.Access, error) {
return darc.Access{}, xerrors.New("oops")
}

type badArcFactory struct {
arc.AccessControlFactory
err error
arc arc.AccessControl
}

func (f badArcFactory) FromProto(proto.Message) (arc.AccessControl, error) {
return f.arc, f.err
}
14 changes: 13 additions & 1 deletion ledger/arc/darc/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,18 @@ import (

//go:generate protoc -I ./ --go_out=./ ./messages.proto

// EvolvableAccessControl is an extension of the arc.AccessControl interface to
// evolve the access control.
type EvolvableAccessControl interface {
arc.AccessControl

Evolve(rule string, targets ...arc.Identity) (Access, error)
}

// Access is the implementation for DARC of Access Control.
//
// - implements darc.EvolvableAccessControl
// - implements encoding.Packable
type Access struct {
rules map[string]expression
}
Expand All @@ -23,7 +34,8 @@ func newAccessControl() Access {
}
}

// Evolve updates the rule with the list of targets.
// Evolve implements darc.EvolvableAccessControl. It updates the rule with the
// list of targets.
func (ac Access) Evolve(rule string, targets ...arc.Identity) (Access, error) {
access := ac.Clone()

Expand Down
2 changes: 1 addition & 1 deletion ledger/arc/darc/mod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestFactory_FromProto(t *testing.T) {

pb := &AccessControlProto{
Rules: map[string]*Expression{
"fake": &Expression{
"fake": {
Matches: []string{"aa", "bb"},
},
},
Expand Down
2 changes: 2 additions & 0 deletions ledger/arc/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ type Identity interface {
// AccessControl is an abstraction to verify if an identity has access to a
// specific rule.
type AccessControl interface {
encoding.Packable

Match(rule string, idents ...Identity) error
}

Expand Down
4 changes: 2 additions & 2 deletions ledger/inventory/mem/mod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ func TestPage_GetFootprint(t *testing.T) {
func TestPage_Read(t *testing.T) {
page := inMemoryPage{
entries: map[Digest]inMemoryEntry{
Digest{1}: {value: &wrappers.StringValue{Value: "1"}},
Digest{2}: {value: &wrappers.StringValue{Value: "2"}},
{1}: {value: &wrappers.StringValue{Value: "1"}},
{2}: {value: &wrappers.StringValue{Value: "2"}},
},
}

Expand Down

0 comments on commit 8703ddb

Please sign in to comment.