test(executor): add more executor unit test
This commit is contained in:
parent
ff7e0b0206
commit
bd0b04e63e
|
@ -120,16 +120,3 @@ func checkAssetExchangeInfo(aei *pb.AssetExchangeInfo) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkAssetExchangeInfoPair(aei0, aei1 *pb.AssetExchangeInfo) error {
|
|
||||||
if aei0.SenderOnSrc != aei1.ReceiverOnDst ||
|
|
||||||
aei0.ReceiverOnSrc != aei1.SenderOnDst ||
|
|
||||||
aei0.SenderOnDst != aei1.ReceiverOnSrc ||
|
|
||||||
aei0.ReceiverOnDst != aei1.SenderOnSrc ||
|
|
||||||
aei0.AssetOnSrc != aei1.AssetOnDst ||
|
|
||||||
aei0.AssetOnDst != aei1.AssetOnSrc {
|
|
||||||
return fmt.Errorf("unmatched exchange info pair")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,966 @@
|
||||||
|
package contracts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
appchainMgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
||||||
|
"github.com/meshplus/bitxhub-core/validator"
|
||||||
|
"github.com/meshplus/bitxhub-kit/types"
|
||||||
|
"github.com/meshplus/bitxhub-model/pb"
|
||||||
|
"github.com/meshplus/bitxhub/internal/constant"
|
||||||
|
"github.com/meshplus/bitxhub/pkg/vm/boltvm"
|
||||||
|
"github.com/meshplus/bitxhub/pkg/vm/boltvm/mock_stub"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAppchainManager_Appchain(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addr0 := types.Address{0}.String()
|
||||||
|
addr1 := types.Address{1}.String()
|
||||||
|
|
||||||
|
chain := &appchainMgr.Appchain{
|
||||||
|
ID: addr0,
|
||||||
|
Name: "appchain A",
|
||||||
|
Validators: "",
|
||||||
|
ConsensusType: 0,
|
||||||
|
ChainType: "fabric",
|
||||||
|
Desc: "",
|
||||||
|
Version: "",
|
||||||
|
PublicKey: "11111",
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(chain)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
o1 := mockStub.EXPECT().Caller().Return(addr0)
|
||||||
|
o2 := mockStub.EXPECT().Caller().Return(addr1)
|
||||||
|
gomock.InOrder(o1, o2)
|
||||||
|
mockStub.EXPECT().Get("appchain-"+addr0).Return(true, data)
|
||||||
|
mockStub.EXPECT().Get("appchain-"+addr1).Return(false, nil)
|
||||||
|
|
||||||
|
am := &AppchainManager{
|
||||||
|
Stub: mockStub,
|
||||||
|
}
|
||||||
|
|
||||||
|
res := am.Appchain()
|
||||||
|
assert.Equal(t, true, res.Ok)
|
||||||
|
assert.Equal(t, data, res.Result)
|
||||||
|
|
||||||
|
res = am.Appchain()
|
||||||
|
assert.Equal(t, false, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppchainManager_Appchains(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
var chains []*appchainMgr.Appchain
|
||||||
|
var chainsData [][]byte
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
addr := types.Address{byte(i)}.String()
|
||||||
|
|
||||||
|
chain := &appchainMgr.Appchain{
|
||||||
|
ID: addr,
|
||||||
|
Name: "appchain" + addr,
|
||||||
|
Validators: "",
|
||||||
|
ConsensusType: int32(i),
|
||||||
|
ChainType: "fabric",
|
||||||
|
Desc: "",
|
||||||
|
Version: "",
|
||||||
|
PublicKey: "pubkey" + addr,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(chain)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
chainsData = append(chainsData, data)
|
||||||
|
chains = append(chains, chain)
|
||||||
|
}
|
||||||
|
|
||||||
|
o1 := mockStub.EXPECT().Query(appchainMgr.PREFIX).Return(true, chainsData)
|
||||||
|
o2 := mockStub.EXPECT().Query(appchainMgr.PREFIX).Return(false, nil)
|
||||||
|
gomock.InOrder(o1, o2)
|
||||||
|
|
||||||
|
am := &AppchainManager{
|
||||||
|
Stub: mockStub,
|
||||||
|
}
|
||||||
|
|
||||||
|
res := am.Appchains()
|
||||||
|
assert.Equal(t, true, res.Ok)
|
||||||
|
|
||||||
|
var appchains []*appchainMgr.Appchain
|
||||||
|
err := json.Unmarshal(res.Result, &appchains)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 2, len(chains))
|
||||||
|
assert.Equal(t, chains[0], appchains[0])
|
||||||
|
assert.Equal(t, chains[1], appchains[1])
|
||||||
|
|
||||||
|
res = am.Appchains()
|
||||||
|
assert.Equal(t, true, res.Ok)
|
||||||
|
assert.Equal(t, []byte(nil), res.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterchainManager_Register(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addr := types.Address{}.String()
|
||||||
|
mockStub.EXPECT().Caller().Return(addr).AnyTimes()
|
||||||
|
mockStub.EXPECT().Set(gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
o1 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(false, nil)
|
||||||
|
|
||||||
|
interchain := pb.Interchain{
|
||||||
|
ID: addr,
|
||||||
|
InterchainCounter: make(map[string]uint64),
|
||||||
|
ReceiptCounter: make(map[string]uint64),
|
||||||
|
SourceReceiptCounter: make(map[string]uint64),
|
||||||
|
}
|
||||||
|
interchain.InterchainCounter[addr] = 1
|
||||||
|
interchain.ReceiptCounter[addr] = 1
|
||||||
|
interchain.SourceReceiptCounter[addr] = 1
|
||||||
|
data0, err := interchain.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
o2 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(true, data0)
|
||||||
|
|
||||||
|
interchain = pb.Interchain{
|
||||||
|
ID: addr,
|
||||||
|
InterchainCounter: make(map[string]uint64),
|
||||||
|
ReceiptCounter: make(map[string]uint64),
|
||||||
|
SourceReceiptCounter: make(map[string]uint64),
|
||||||
|
}
|
||||||
|
data1, err := interchain.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
o3 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(true, data1)
|
||||||
|
gomock.InOrder(o1, o2, o3)
|
||||||
|
|
||||||
|
im := &InterchainManager{mockStub}
|
||||||
|
|
||||||
|
res := im.Register()
|
||||||
|
assert.Equal(t, true, res.Ok)
|
||||||
|
|
||||||
|
ic := &pb.Interchain{}
|
||||||
|
err = ic.Unmarshal(res.Result)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, addr, ic.ID)
|
||||||
|
assert.Equal(t, 0, len(ic.InterchainCounter))
|
||||||
|
assert.Equal(t, 0, len(ic.ReceiptCounter))
|
||||||
|
assert.Equal(t, 0, len(ic.SourceReceiptCounter))
|
||||||
|
|
||||||
|
res = im.Register()
|
||||||
|
assert.Equal(t, true, res.Ok)
|
||||||
|
assert.Equal(t, data0, res.Result)
|
||||||
|
|
||||||
|
res = im.Register()
|
||||||
|
assert.Equal(t, true, res.Ok)
|
||||||
|
assert.Equal(t, data1, res.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterchainManager_Interchain(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addr := types.Address{}.String()
|
||||||
|
mockStub.EXPECT().Caller().Return(addr).AnyTimes()
|
||||||
|
mockStub.EXPECT().Set(gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
o1 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(false, nil)
|
||||||
|
|
||||||
|
interchain := pb.Interchain{
|
||||||
|
ID: addr,
|
||||||
|
InterchainCounter: make(map[string]uint64),
|
||||||
|
ReceiptCounter: make(map[string]uint64),
|
||||||
|
SourceReceiptCounter: make(map[string]uint64),
|
||||||
|
}
|
||||||
|
interchain.InterchainCounter[addr] = 1
|
||||||
|
interchain.ReceiptCounter[addr] = 1
|
||||||
|
interchain.SourceReceiptCounter[addr] = 1
|
||||||
|
data0, err := interchain.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
o2 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(true, data0)
|
||||||
|
gomock.InOrder(o1, o2)
|
||||||
|
|
||||||
|
im := &InterchainManager{mockStub}
|
||||||
|
|
||||||
|
res := im.Interchain()
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
|
||||||
|
res = im.Interchain()
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, data0, res.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterchainManager_GetInterchain(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addr := types.Address{}.String()
|
||||||
|
mockStub.EXPECT().Set(gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
o1 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(false, nil)
|
||||||
|
|
||||||
|
interchain := pb.Interchain{
|
||||||
|
ID: addr,
|
||||||
|
InterchainCounter: make(map[string]uint64),
|
||||||
|
ReceiptCounter: make(map[string]uint64),
|
||||||
|
SourceReceiptCounter: make(map[string]uint64),
|
||||||
|
}
|
||||||
|
interchain.InterchainCounter[addr] = 1
|
||||||
|
interchain.ReceiptCounter[addr] = 1
|
||||||
|
interchain.SourceReceiptCounter[addr] = 1
|
||||||
|
data0, err := interchain.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
o2 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(true, data0)
|
||||||
|
gomock.InOrder(o1, o2)
|
||||||
|
|
||||||
|
im := &InterchainManager{mockStub}
|
||||||
|
|
||||||
|
res := im.GetInterchain(addr)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
|
||||||
|
res = im.GetInterchain(addr)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, data0, res.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterchainManager_HandleIBTP(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
from := types.Address{0}.String()
|
||||||
|
to := types.Address{1}.String()
|
||||||
|
mockStub.EXPECT().Set(gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
f1 := mockStub.EXPECT().Get(appchainMgr.PREFIX+from).Return(false, nil)
|
||||||
|
|
||||||
|
interchain := pb.Interchain{
|
||||||
|
ID: from,
|
||||||
|
InterchainCounter: make(map[string]uint64),
|
||||||
|
ReceiptCounter: make(map[string]uint64),
|
||||||
|
SourceReceiptCounter: make(map[string]uint64),
|
||||||
|
}
|
||||||
|
interchain.InterchainCounter[to] = 1
|
||||||
|
interchain.ReceiptCounter[to] = 1
|
||||||
|
interchain.SourceReceiptCounter[to] = 1
|
||||||
|
data0, err := interchain.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
f2 := mockStub.EXPECT().Get(appchainMgr.PREFIX+from).Return(true, data0).AnyTimes()
|
||||||
|
mockStub.EXPECT().Get(appchainMgr.PREFIX+to).Return(true, data0).AnyTimes()
|
||||||
|
mockStub.EXPECT().CrossInvoke(gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Success(nil)).AnyTimes()
|
||||||
|
mockStub.EXPECT().AddObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
mockStub.EXPECT().GetTxIndex().Return(uint64(1)).AnyTimes()
|
||||||
|
mockStub.EXPECT().PostInterchainEvent(gomock.Any()).AnyTimes()
|
||||||
|
mockStub.EXPECT().GetTxHash().Return(types.Hash{}).AnyTimes()
|
||||||
|
gomock.InOrder(f1, f2)
|
||||||
|
|
||||||
|
im := &InterchainManager{mockStub}
|
||||||
|
|
||||||
|
fakeIBTP := []byte{1}
|
||||||
|
res := im.HandleIBTP(fakeIBTP)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
|
||||||
|
ibtp := &pb.IBTP{
|
||||||
|
From: from,
|
||||||
|
}
|
||||||
|
|
||||||
|
ibtpd, err := ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "this appchain does not exist", string(res.Result))
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "empty destination chain id", string(res.Result))
|
||||||
|
|
||||||
|
ibtp = &pb.IBTP{
|
||||||
|
From: from,
|
||||||
|
To: to,
|
||||||
|
Index: 0,
|
||||||
|
Type: pb.IBTP_INTERCHAIN,
|
||||||
|
Timestamp: 0,
|
||||||
|
Proof: nil,
|
||||||
|
Payload: nil,
|
||||||
|
Version: "",
|
||||||
|
Extra: nil,
|
||||||
|
}
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
mockStub.EXPECT().Caller().Return(ibtp.To)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "ibtp from != caller", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().Caller().Return(ibtp.From).MaxTimes(6)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "wrong index, required 2, but 0", string(res.Result))
|
||||||
|
|
||||||
|
ibtp.Index = 2
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
ibtp.Type = pb.IBTP_ASSET_EXCHANGE_INIT
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
ibtp.Type = pb.IBTP_ASSET_EXCHANGE_REFUND
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
ibtp.Type = pb.IBTP_ASSET_EXCHANGE_REDEEM
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
ibtp.Type = pb.IBTP_RECEIPT_SUCCESS
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "ibtp to != caller", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().Caller().Return(ibtp.To).AnyTimes()
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
ibtp.Type = pb.IBTP_RECEIPT_FAILURE
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
ibtp.Type = pb.IBTP_ASSET_EXCHANGE_RECEIPT
|
||||||
|
ibtpd, err = ibtp.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res = im.HandleIBTP(ibtpd)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInterchainManager_GetIBTPByID(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
from := types.Address{}.String()
|
||||||
|
to := types.Address{byte(1)}.String()
|
||||||
|
|
||||||
|
validID := fmt.Sprintf("%s-%s-1", from, to)
|
||||||
|
|
||||||
|
mockStub.EXPECT().Caller().Return(from).AnyTimes()
|
||||||
|
im := &InterchainManager{mockStub}
|
||||||
|
|
||||||
|
res := im.GetIBTPByID("a")
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "wrong ibtp id", string(res.Result))
|
||||||
|
|
||||||
|
res = im.GetIBTPByID("abc-def-10")
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "The caller does not have access to this ibtp", string(res.Result))
|
||||||
|
|
||||||
|
unexistId := fmt.Sprintf("%s-%s-10", from, to)
|
||||||
|
mockStub.EXPECT().GetObject(fmt.Sprintf("index-tx-%s", unexistId), gomock.Any()).Return(false)
|
||||||
|
|
||||||
|
res = im.GetIBTPByID(unexistId)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "this id is not existed", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(fmt.Sprintf("index-tx-%s", validID), gomock.Any()).Return(true)
|
||||||
|
res = im.GetIBTPByID(validID)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRole_GetRole(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addrs := []string{types.Address{0}.String(), types.Address{1}.String()}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, addrs).AnyTimes()
|
||||||
|
mockStub.EXPECT().Caller().Return(types.Address{0}.String())
|
||||||
|
|
||||||
|
im := &Role{mockStub}
|
||||||
|
|
||||||
|
res := im.GetRole()
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "admin", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().Caller().Return(types.Address{2}.String()).AnyTimes()
|
||||||
|
mockStub.EXPECT().CrossInvoke(gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Error(""))
|
||||||
|
|
||||||
|
res = im.GetRole()
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "none", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().CrossInvoke(gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Success(nil))
|
||||||
|
|
||||||
|
res = im.GetRole()
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "appchain_admin", string(res.Result))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRole_IsAdmin(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addrs := []string{types.Address{0}.String(), types.Address{1}.String()}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, addrs).AnyTimes()
|
||||||
|
|
||||||
|
im := &Role{mockStub}
|
||||||
|
|
||||||
|
res := im.IsAdmin(addrs[0])
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "true", string(res.Result))
|
||||||
|
|
||||||
|
res = im.IsAdmin(types.Address{2}.String())
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "false", string(res.Result))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRole_GetAdminRoles(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addrs := []string{types.Address{0}.String(), types.Address{1}.String()}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, addrs).AnyTimes()
|
||||||
|
|
||||||
|
im := &Role{mockStub}
|
||||||
|
|
||||||
|
res := im.GetAdminRoles()
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
var admins []string
|
||||||
|
err := json.Unmarshal(res.Result, &admins)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, len(addrs), len(admins))
|
||||||
|
for i, addr := range addrs {
|
||||||
|
assert.Equal(t, addr, admins[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRole_SetAdminRoles(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
addrs := []string{types.Address{0}.String(), types.Address{1}.String()}
|
||||||
|
mockStub.EXPECT().SetObject(adminRolesKey, addrs).AnyTimes()
|
||||||
|
|
||||||
|
im := &Role{mockStub}
|
||||||
|
|
||||||
|
data, err := json.Marshal(addrs)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
res := im.SetAdminRoles(string(data))
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuleManager_RegisterRule(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
id0 := types.Address{0}.String()
|
||||||
|
id1 := types.Address{1}.String()
|
||||||
|
|
||||||
|
mockStub.EXPECT().CrossInvoke(constant.AppchainMgrContractAddr.String(), "GetAppchain", pb.String(id0)).Return(boltvm.Success(nil))
|
||||||
|
mockStub.EXPECT().CrossInvoke(constant.AppchainMgrContractAddr.String(), "GetAppchain", pb.String(id1)).Return(boltvm.Error(""))
|
||||||
|
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
|
||||||
|
im := &RuleManager{mockStub}
|
||||||
|
|
||||||
|
addr := types.Address{2}.String()
|
||||||
|
res := im.RegisterRule(id0, addr)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
res = im.RegisterRule(id1, addr)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "this appchain does not exist", string(res.Result))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuleManager_GetRuleAddress(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
id0 := types.Address{0}.String()
|
||||||
|
id1 := types.Address{1}.String()
|
||||||
|
rule := Rule{
|
||||||
|
Address: "123",
|
||||||
|
Status: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(RuleKey(id0), gomock.Any()).SetArg(1, rule).Return(true)
|
||||||
|
mockStub.EXPECT().GetObject(RuleKey(id1), gomock.Any()).Return(false).MaxTimes(5)
|
||||||
|
|
||||||
|
im := &RuleManager{mockStub}
|
||||||
|
|
||||||
|
res := im.GetRuleAddress(id0, "")
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, rule.Address, string(res.Result))
|
||||||
|
|
||||||
|
res = im.GetRuleAddress(id1, "fabric")
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, validator.FabricRuleAddr, string(res.Result))
|
||||||
|
|
||||||
|
res = im.GetRuleAddress(id1, "hyperchain")
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "", string(res.Result))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuleManager_Audit(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
id0 := types.Address{0}.String()
|
||||||
|
id1 := types.Address{1}.String()
|
||||||
|
rule := Rule{
|
||||||
|
Address: "123",
|
||||||
|
Status: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(RuleKey(id0), gomock.Any()).SetArg(1, rule).Return(true)
|
||||||
|
mockStub.EXPECT().GetObject(RuleKey(id1), gomock.Any()).Return(false)
|
||||||
|
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||||
|
mockStub.EXPECT().GetObject("audit-record-"+id0, gomock.Any()).SetArg(1, []*ruleRecord{}).Return(true).AnyTimes()
|
||||||
|
|
||||||
|
im := &RuleManager{mockStub}
|
||||||
|
|
||||||
|
res := im.Audit(id1, 0, "")
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "this rule does not exist", string(res.Result))
|
||||||
|
|
||||||
|
res = im.Audit(id0, 1, "approve")
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStore_Get(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
key0 := "1"
|
||||||
|
val0 := "10"
|
||||||
|
key1 := "1"
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(key0, gomock.Any()).SetArg(1, val0).Return(true)
|
||||||
|
mockStub.EXPECT().GetObject(key1, gomock.Any()).Return(false)
|
||||||
|
|
||||||
|
im := &Store{mockStub}
|
||||||
|
|
||||||
|
res := im.Get(key0)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, val0, string(res.Result))
|
||||||
|
|
||||||
|
res = im.Get(key1)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "there is not exist key", string(res.Result))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStore_Set(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any())
|
||||||
|
|
||||||
|
im := &Store{mockStub}
|
||||||
|
|
||||||
|
res := im.Set("1", "2")
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransactionManager_Begin(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
id := types.Hash{}.String()
|
||||||
|
mockStub.EXPECT().AddObject(fmt.Sprintf("%s-%s", PREFIX, id), pb.TransactionStatus_BEGIN)
|
||||||
|
|
||||||
|
im := &TransactionManager{mockStub}
|
||||||
|
|
||||||
|
res := im.Begin(id)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransactionManager_Report(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
id0 := "id0"
|
||||||
|
id1 := "id1"
|
||||||
|
txInfoKey := fmt.Sprintf("%s-%s", PREFIX, id0)
|
||||||
|
|
||||||
|
im := &TransactionManager{mockStub}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(txInfoKey, gomock.Any()).SetArg(1, pb.TransactionStatus_SUCCESS).Return(true)
|
||||||
|
res := im.Report(id0, 0)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("transaction with Id %s is finished", id0), string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(txInfoKey, gomock.Any()).SetArg(1, pb.TransactionStatus_BEGIN).Return(true)
|
||||||
|
mockStub.EXPECT().SetObject(txInfoKey, pb.TransactionStatus_SUCCESS)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(txInfoKey, gomock.Any()).SetArg(1, pb.TransactionStatus_BEGIN).Return(true)
|
||||||
|
mockStub.EXPECT().SetObject(txInfoKey, pb.TransactionStatus_FAILURE)
|
||||||
|
res = im.Report(id0, 1)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(txInfoKey, gomock.Any()).Return(false).AnyTimes()
|
||||||
|
|
||||||
|
mockStub.EXPECT().Get(id0).Return(false, nil)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("cannot get global id of child tx id %s", id0), string(res.Result))
|
||||||
|
|
||||||
|
globalId := "globalId"
|
||||||
|
globalInfoKey := fmt.Sprintf("global-%s-%s", PREFIX, globalId)
|
||||||
|
mockStub.EXPECT().Get(id0).Return(true, []byte(globalId)).AnyTimes()
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).Return(false)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("transaction global id %s does not exist", globalId), string(res.Result))
|
||||||
|
|
||||||
|
txInfo := TransactionInfo{
|
||||||
|
GlobalState: pb.TransactionStatus_SUCCESS,
|
||||||
|
ChildTxInfo: make(map[string]pb.TransactionStatus),
|
||||||
|
}
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("transaction with global Id %s is finished", globalId), string(res.Result))
|
||||||
|
|
||||||
|
txInfo.GlobalState = pb.TransactionStatus_BEGIN
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("%s is not in transaction %s, %v", id0, globalId, txInfo), string(res.Result))
|
||||||
|
|
||||||
|
txInfo.ChildTxInfo[id0] = pb.TransactionStatus_SUCCESS
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true).MaxTimes(1)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("%s has already reported result", id0), string(res.Result))
|
||||||
|
|
||||||
|
txInfo.GlobalState = pb.TransactionStatus_BEGIN
|
||||||
|
txInfo.ChildTxInfo[id0] = pb.TransactionStatus_BEGIN
|
||||||
|
txInfo.ChildTxInfo[id1] = pb.TransactionStatus_BEGIN
|
||||||
|
expTxInfo := TransactionInfo{
|
||||||
|
GlobalState: pb.TransactionStatus_BEGIN,
|
||||||
|
ChildTxInfo: make(map[string]pb.TransactionStatus),
|
||||||
|
}
|
||||||
|
expTxInfo.ChildTxInfo[id0] = pb.TransactionStatus_SUCCESS
|
||||||
|
expTxInfo.ChildTxInfo[id1] = pb.TransactionStatus_BEGIN
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true).MaxTimes(1)
|
||||||
|
mockStub.EXPECT().SetObject(globalInfoKey, expTxInfo).MaxTimes(1)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
txInfo.GlobalState = pb.TransactionStatus_BEGIN
|
||||||
|
txInfo.ChildTxInfo[id0] = pb.TransactionStatus_BEGIN
|
||||||
|
txInfo.ChildTxInfo[id1] = pb.TransactionStatus_SUCCESS
|
||||||
|
expTxInfo.GlobalState = pb.TransactionStatus_SUCCESS
|
||||||
|
expTxInfo.ChildTxInfo[id0] = pb.TransactionStatus_SUCCESS
|
||||||
|
expTxInfo.ChildTxInfo[id1] = pb.TransactionStatus_SUCCESS
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true).MaxTimes(1)
|
||||||
|
mockStub.EXPECT().SetObject(globalInfoKey, expTxInfo).MaxTimes(1)
|
||||||
|
res = im.Report(id0, 0)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
|
||||||
|
txInfo.GlobalState = pb.TransactionStatus_BEGIN
|
||||||
|
txInfo.ChildTxInfo[id0] = pb.TransactionStatus_BEGIN
|
||||||
|
txInfo.ChildTxInfo[id1] = pb.TransactionStatus_SUCCESS
|
||||||
|
expTxInfo.GlobalState = pb.TransactionStatus_FAILURE
|
||||||
|
expTxInfo.ChildTxInfo[id0] = pb.TransactionStatus_FAILURE
|
||||||
|
expTxInfo.ChildTxInfo[id1] = pb.TransactionStatus_SUCCESS
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true).MaxTimes(1)
|
||||||
|
mockStub.EXPECT().SetObject(globalInfoKey, expTxInfo).MaxTimes(1)
|
||||||
|
res = im.Report(id0, 1)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransactionManager_GetStatus(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
id := "id"
|
||||||
|
txInfoKey := fmt.Sprintf("%s-%s", PREFIX, id)
|
||||||
|
globalInfoKey := fmt.Sprintf("global-%s-%s", PREFIX, id)
|
||||||
|
|
||||||
|
im := &TransactionManager{mockStub}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(txInfoKey, gomock.Any()).SetArg(1, pb.TransactionStatus_SUCCESS).Return(true).MaxTimes(1)
|
||||||
|
res := im.GetStatus(id)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "1", string(res.Result))
|
||||||
|
|
||||||
|
txInfo := TransactionInfo{
|
||||||
|
GlobalState: pb.TransactionStatus_BEGIN,
|
||||||
|
ChildTxInfo: make(map[string]pb.TransactionStatus),
|
||||||
|
}
|
||||||
|
mockStub.EXPECT().GetObject(txInfoKey, gomock.Any()).Return(false).AnyTimes()
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true).MaxTimes(1)
|
||||||
|
res = im.GetStatus(id)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "0", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(globalInfoKey, gomock.Any()).Return(false).AnyTimes()
|
||||||
|
mockStub.EXPECT().Get(id).Return(false, nil).MaxTimes(1)
|
||||||
|
res = im.GetStatus(id)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("cannot get global id of child tx id %s", id), string(res.Result))
|
||||||
|
|
||||||
|
globalId := "globalId"
|
||||||
|
globalIdInfoKey := fmt.Sprintf("global-%s-%s", PREFIX, globalId)
|
||||||
|
mockStub.EXPECT().Get(id).Return(true, []byte(globalId)).AnyTimes()
|
||||||
|
mockStub.EXPECT().GetObject(globalIdInfoKey, gomock.Any()).Return(false).MaxTimes(1)
|
||||||
|
res = im.GetStatus(id)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("transaction info for global id %s does not exist", globalId), string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(globalIdInfoKey, gomock.Any()).SetArg(1, txInfo).Return(true).MaxTimes(1)
|
||||||
|
res = im.GetStatus(id)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "0", string(res.Result))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransactionManager_BeginMultiTXs(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
id0 := "id0"
|
||||||
|
id1 := "id1"
|
||||||
|
globalId := "globalId"
|
||||||
|
txInfoKey := fmt.Sprintf("%s-%s", PREFIX, globalId)
|
||||||
|
globalInfoKey := fmt.Sprintf("global-%s-%s", PREFIX, globalId)
|
||||||
|
|
||||||
|
im := &TransactionManager{mockStub}
|
||||||
|
|
||||||
|
mockStub.EXPECT().Has(txInfoKey).Return(true).MaxTimes(1)
|
||||||
|
res := im.BeginMultiTXs(globalId, id0, id1)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "Transaction id already exists", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().Has(txInfoKey).Return(false).AnyTimes()
|
||||||
|
mockStub.EXPECT().Set(id0, []byte(globalId))
|
||||||
|
mockStub.EXPECT().Set(id1, []byte(globalId))
|
||||||
|
txInfo := TransactionInfo{
|
||||||
|
GlobalState: pb.TransactionStatus_BEGIN,
|
||||||
|
ChildTxInfo: make(map[string]pb.TransactionStatus),
|
||||||
|
}
|
||||||
|
txInfo.ChildTxInfo[id0] = pb.TransactionStatus_BEGIN
|
||||||
|
txInfo.ChildTxInfo[id1] = pb.TransactionStatus_BEGIN
|
||||||
|
mockStub.EXPECT().SetObject(globalInfoKey, txInfo)
|
||||||
|
res = im.BeginMultiTXs(globalId, id0, id1)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssetExchange_Init(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
from := types.Address{0}.String()
|
||||||
|
to := types.Address{1}.String()
|
||||||
|
|
||||||
|
ae := &AssetExchange{mockStub}
|
||||||
|
|
||||||
|
res := ae.Init(from, to, []byte{1})
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
|
||||||
|
aei := pb.AssetExchangeInfo{
|
||||||
|
Id: "123",
|
||||||
|
SenderOnSrc: "aliceSrc",
|
||||||
|
ReceiverOnSrc: "bobSrc",
|
||||||
|
AssetOnSrc: 10,
|
||||||
|
SenderOnDst: "bobDst",
|
||||||
|
ReceiverOnDst: "aliceDst",
|
||||||
|
AssetOnDst: 0,
|
||||||
|
}
|
||||||
|
info, err := aei.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
mockStub.EXPECT().Has(AssetExchangeKey(aei.Id)).Return(true).MaxTimes(1)
|
||||||
|
res = ae.Init(from, to, info)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "asset exhcange id already exists", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().Has(AssetExchangeKey(aei.Id)).Return(false).AnyTimes()
|
||||||
|
res = ae.Init(from, to, info)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "illegal asset exchange info", string(res.Result))
|
||||||
|
|
||||||
|
aei.AssetOnDst = 100
|
||||||
|
info, err = aei.Marshal()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
aer := AssetExchangeRecord{
|
||||||
|
Chain0: from,
|
||||||
|
Chain1: to,
|
||||||
|
Status: AssetExchangeInit,
|
||||||
|
Info: aei,
|
||||||
|
}
|
||||||
|
mockStub.EXPECT().SetObject(AssetExchangeKey(aei.Id), aer)
|
||||||
|
res = ae.Init(from, to, info)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssetExchange_Redeem(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
from := types.Address{0}.String()
|
||||||
|
to := types.Address{1}.String()
|
||||||
|
|
||||||
|
ae := &AssetExchange{mockStub}
|
||||||
|
|
||||||
|
aei := pb.AssetExchangeInfo{
|
||||||
|
Id: "123",
|
||||||
|
SenderOnSrc: "aliceSrc",
|
||||||
|
ReceiverOnSrc: "bobSrc",
|
||||||
|
AssetOnSrc: 10,
|
||||||
|
SenderOnDst: "bobDst",
|
||||||
|
ReceiverOnDst: "aliceDst",
|
||||||
|
AssetOnDst: 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
aer := AssetExchangeRecord{
|
||||||
|
Chain0: from,
|
||||||
|
Chain1: to,
|
||||||
|
Status: AssetExchangeRedeem,
|
||||||
|
Info: aei,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).Return(false).MaxTimes(1)
|
||||||
|
res := ae.Redeem(from, to, []byte(aei.Id))
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "asset exchange record does not exist", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).SetArg(1, aer).Return(true).MaxTimes(1)
|
||||||
|
res = ae.Redeem(from, to, []byte(aei.Id))
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "asset exchange status for this id is not 'Init'", string(res.Result))
|
||||||
|
|
||||||
|
aer.Status = AssetExchangeInit
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).SetArg(1, aer).Return(true).AnyTimes()
|
||||||
|
res = ae.Redeem(to, to, []byte(aei.Id))
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("invalid participator of asset exchange id %s", aei.Id), string(res.Result))
|
||||||
|
|
||||||
|
expAer := AssetExchangeRecord{
|
||||||
|
Chain0: from,
|
||||||
|
Chain1: to,
|
||||||
|
Status: AssetExchangeRedeem,
|
||||||
|
Info: aei,
|
||||||
|
}
|
||||||
|
mockStub.EXPECT().SetObject(AssetExchangeKey(aei.Id), expAer)
|
||||||
|
res = ae.Redeem(from, to, []byte(aei.Id))
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssetExchange_Refund(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
from := types.Address{0}.String()
|
||||||
|
to := types.Address{1}.String()
|
||||||
|
|
||||||
|
ae := &AssetExchange{mockStub}
|
||||||
|
|
||||||
|
aei := pb.AssetExchangeInfo{
|
||||||
|
Id: "123",
|
||||||
|
SenderOnSrc: "aliceSrc",
|
||||||
|
ReceiverOnSrc: "bobSrc",
|
||||||
|
AssetOnSrc: 10,
|
||||||
|
SenderOnDst: "bobDst",
|
||||||
|
ReceiverOnDst: "aliceDst",
|
||||||
|
AssetOnDst: 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
aer := AssetExchangeRecord{
|
||||||
|
Chain0: from,
|
||||||
|
Chain1: to,
|
||||||
|
Status: AssetExchangeRedeem,
|
||||||
|
Info: aei,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).Return(false).MaxTimes(1)
|
||||||
|
res := ae.Refund(from, to, []byte(aei.Id))
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "asset exchange record does not exist", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).SetArg(1, aer).Return(true).MaxTimes(1)
|
||||||
|
res = ae.Refund(from, to, []byte(aei.Id))
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "asset exchange status for this id is not 'Init'", string(res.Result))
|
||||||
|
|
||||||
|
aer.Status = AssetExchangeInit
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).SetArg(1, aer).Return(true).AnyTimes()
|
||||||
|
res = ae.Refund(to, to, []byte(aei.Id))
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, fmt.Sprintf("invalid participator of asset exchange id %s", aei.Id), string(res.Result))
|
||||||
|
|
||||||
|
expAer := AssetExchangeRecord{
|
||||||
|
Chain0: from,
|
||||||
|
Chain1: to,
|
||||||
|
Status: AssetExchangeRefund,
|
||||||
|
Info: aei,
|
||||||
|
}
|
||||||
|
mockStub.EXPECT().SetObject(AssetExchangeKey(aei.Id), expAer)
|
||||||
|
res = ae.Refund(from, to, []byte(aei.Id))
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssetExchange_GetStatus(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||||
|
|
||||||
|
aei := pb.AssetExchangeInfo{
|
||||||
|
Id: "123",
|
||||||
|
SenderOnSrc: "aliceSrc",
|
||||||
|
ReceiverOnSrc: "bobSrc",
|
||||||
|
AssetOnSrc: 10,
|
||||||
|
SenderOnDst: "bobDst",
|
||||||
|
ReceiverOnDst: "aliceDst",
|
||||||
|
AssetOnDst: 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
from := types.Address{0}.String()
|
||||||
|
to := types.Address{1}.String()
|
||||||
|
aer := AssetExchangeRecord{
|
||||||
|
Chain0: from,
|
||||||
|
Chain1: to,
|
||||||
|
Status: AssetExchangeRedeem,
|
||||||
|
Info: aei,
|
||||||
|
}
|
||||||
|
|
||||||
|
ae := &AssetExchange{mockStub}
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).Return(false).MaxTimes(1)
|
||||||
|
res := ae.GetStatus(aei.Id)
|
||||||
|
assert.False(t, res.Ok)
|
||||||
|
assert.Equal(t, "asset exchange record does not exist", string(res.Result))
|
||||||
|
|
||||||
|
mockStub.EXPECT().GetObject(AssetExchangeKey(aei.Id), gomock.Any()).SetArg(1, aer).Return(true).MaxTimes(1)
|
||||||
|
res = ae.GetStatus(aei.Id)
|
||||||
|
assert.True(t, res.Ok)
|
||||||
|
assert.Equal(t, "1", string(res.Result))
|
||||||
|
}
|
|
@ -105,10 +105,6 @@ func (exec *BlockExecutor) ExecuteBlock(block *pb.Block) {
|
||||||
exec.preBlockC <- block
|
exec.preBlockC <- block
|
||||||
}
|
}
|
||||||
|
|
||||||
func (exec *BlockExecutor) SyncExecuteBlock(block *pb.Block) {
|
|
||||||
exec.processExecuteEvent(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubscribeBlockEvent registers a subscription of NewBlockEvent.
|
// SubscribeBlockEvent registers a subscription of NewBlockEvent.
|
||||||
func (exec *BlockExecutor) SubscribeBlockEvent(ch chan<- events.NewBlockEvent) event.Subscription {
|
func (exec *BlockExecutor) SubscribeBlockEvent(ch chan<- events.NewBlockEvent) event.Subscription {
|
||||||
return exec.blockFeed.Subscribe(ch)
|
return exec.blockFeed.Subscribe(ch)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package executor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -16,6 +17,7 @@ import (
|
||||||
"github.com/meshplus/bitxhub-kit/log"
|
"github.com/meshplus/bitxhub-kit/log"
|
||||||
"github.com/meshplus/bitxhub-kit/types"
|
"github.com/meshplus/bitxhub-kit/types"
|
||||||
"github.com/meshplus/bitxhub-model/pb"
|
"github.com/meshplus/bitxhub-model/pb"
|
||||||
|
"github.com/meshplus/bitxhub/internal/constant"
|
||||||
"github.com/meshplus/bitxhub/internal/ledger"
|
"github.com/meshplus/bitxhub/internal/ledger"
|
||||||
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
|
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
|
||||||
"github.com/meshplus/bitxhub/internal/model/events"
|
"github.com/meshplus/bitxhub/internal/model/events"
|
||||||
|
@ -29,8 +31,42 @@ import (
|
||||||
const (
|
const (
|
||||||
keyPassword = "bitxhub"
|
keyPassword = "bitxhub"
|
||||||
from = "0x3f9d18f7c3a6e5e4c0b877fe3e688ab08840b997"
|
from = "0x3f9d18f7c3a6e5e4c0b877fe3e688ab08840b997"
|
||||||
|
to = "0x000018f7c3a6e5e4c0b877fe3e688ab08840b997"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
||||||
|
|
||||||
|
// mock data for ledger
|
||||||
|
chainMeta := &pb.ChainMeta{
|
||||||
|
Height: 1,
|
||||||
|
BlockHash: types.String2Hash(from),
|
||||||
|
}
|
||||||
|
mockLedger.EXPECT().GetChainMeta().Return(chainMeta).AnyTimes()
|
||||||
|
|
||||||
|
logger := log.NewWithModule("executor")
|
||||||
|
executor, err := New(mockLedger, logger)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, executor)
|
||||||
|
|
||||||
|
assert.Equal(t, mockLedger, executor.ledger)
|
||||||
|
assert.Equal(t, logger, executor.logger)
|
||||||
|
assert.NotNil(t, executor.interchainCounter)
|
||||||
|
assert.Equal(t, 0, len(executor.interchainCounter))
|
||||||
|
assert.NotNil(t, executor.preBlockC)
|
||||||
|
assert.NotNil(t, executor.blockC)
|
||||||
|
assert.NotNil(t, executor.persistC)
|
||||||
|
assert.NotNil(t, executor.ibtpVerify)
|
||||||
|
assert.NotNil(t, executor.validationEngine)
|
||||||
|
assert.Equal(t, 0, len(executor.normalTxs))
|
||||||
|
assert.Equal(t, 7, len(executor.boltContracts))
|
||||||
|
assert.Equal(t, chainMeta.BlockHash, executor.currentBlockHash)
|
||||||
|
assert.Equal(t, chainMeta.Height, executor.currentHeight)
|
||||||
|
assert.NotNil(t, executor.wasmInstances)
|
||||||
|
assert.Equal(t, 0, len(executor.wasmInstances))
|
||||||
|
}
|
||||||
|
|
||||||
func TestBlockExecutor_ExecuteBlock(t *testing.T) {
|
func TestBlockExecutor_ExecuteBlock(t *testing.T) {
|
||||||
mockCtl := gomock.NewController(t)
|
mockCtl := gomock.NewController(t)
|
||||||
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
||||||
|
@ -93,19 +129,22 @@ func TestBlockExecutor_ExecuteBlock(t *testing.T) {
|
||||||
NormalData := mockTxData(t, pb.TransactionData_NORMAL, pb.TransactionData_XVM, ibtp3)
|
NormalData := mockTxData(t, pb.TransactionData_NORMAL, pb.TransactionData_XVM, ibtp3)
|
||||||
NormalTx := mockTx(NormalData)
|
NormalTx := mockTx(NormalData)
|
||||||
txs = append(txs, NormalTx)
|
txs = append(txs, NormalTx)
|
||||||
|
// set tx with empty transaction data
|
||||||
|
emptyDataTx := mockTx(nil)
|
||||||
|
txs = append(txs, emptyDataTx)
|
||||||
|
|
||||||
// set signature for txs
|
// set signature for txs
|
||||||
for _, tx := range txs {
|
for _, tx := range txs {
|
||||||
|
tx.From, err = pubKey.Address()
|
||||||
|
assert.Nil(t, err)
|
||||||
sig, err := privKey.Sign(tx.SignHash().Bytes())
|
sig, err := privKey.Sign(tx.SignHash().Bytes())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
tx.Signature = sig
|
tx.Signature = sig
|
||||||
tx.From, err = pubKey.Address()
|
|
||||||
assert.Nil(t, err)
|
|
||||||
}
|
}
|
||||||
// set invalid signature tx
|
// set invalid signature tx
|
||||||
invalidTx := mockTx(nil)
|
invalidTx := mockTx(nil)
|
||||||
invalidTx.Signature = []byte("invalid")
|
|
||||||
invalidTx.From = types.String2Address(from)
|
invalidTx.From = types.String2Address(from)
|
||||||
|
invalidTx.Signature = []byte("invalid")
|
||||||
txs = append(txs, invalidTx)
|
txs = append(txs, invalidTx)
|
||||||
|
|
||||||
assert.Nil(t, exec.Start())
|
assert.Nil(t, exec.Start())
|
||||||
|
@ -117,24 +156,67 @@ func TestBlockExecutor_ExecuteBlock(t *testing.T) {
|
||||||
|
|
||||||
// count received block to end test
|
// count received block to end test
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(3)
|
wg.Add(2)
|
||||||
go listenBlock(&wg, done, ch)
|
go listenBlock(&wg, done, ch)
|
||||||
|
|
||||||
// send blocks to executor
|
// send blocks to executor
|
||||||
|
block1 := mockBlock(uint64(1), nil)
|
||||||
block2 := mockBlock(uint64(2), txs)
|
block2 := mockBlock(uint64(2), txs)
|
||||||
block4 := mockBlock(uint64(4), txs)
|
exec.ExecuteBlock(block1)
|
||||||
block3 := mockBlock(uint64(3), txs)
|
|
||||||
block6 := mockBlock(uint64(6), txs)
|
|
||||||
exec.ExecuteBlock(block2)
|
exec.ExecuteBlock(block2)
|
||||||
exec.ExecuteBlock(block4)
|
|
||||||
exec.ExecuteBlock(block6)
|
|
||||||
exec.ExecuteBlock(block3)
|
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
done <- true
|
done <- true
|
||||||
assert.Nil(t, exec.Stop())
|
assert.Nil(t, exec.Stop())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBlockExecutor_ApplyReadonlyTransactions(t *testing.T) {
|
||||||
|
mockCtl := gomock.NewController(t)
|
||||||
|
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
||||||
|
|
||||||
|
// mock data for ledger
|
||||||
|
chainMeta := &pb.ChainMeta{
|
||||||
|
Height: 1,
|
||||||
|
BlockHash: types.String2Hash(from),
|
||||||
|
}
|
||||||
|
|
||||||
|
privKey, err := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
addr, err := privKey.PublicKey().Address()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
id := fmt.Sprintf("%s-%s-%d", addr.String(), to, 1)
|
||||||
|
|
||||||
|
hash := types.Hash{1}
|
||||||
|
val, err := json.Marshal(hash)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
mockLedger.EXPECT().GetChainMeta().Return(chainMeta).AnyTimes()
|
||||||
|
mockLedger.EXPECT().Events(gomock.Any()).Return(nil).AnyTimes()
|
||||||
|
mockLedger.EXPECT().Commit(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||||
|
mockLedger.EXPECT().Clear().AnyTimes()
|
||||||
|
mockLedger.EXPECT().GetState(constant.InterchainContractAddr.Address(), []byte(fmt.Sprintf("index-tx-%s", id))).Return(true, val).AnyTimes()
|
||||||
|
mockLedger.EXPECT().PersistExecutionResult(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||||
|
mockLedger.EXPECT().FlushDirtyDataAndComputeJournal().Return(make(map[types.Address]*ledger.Account), &ledger.BlockJournal{}).AnyTimes()
|
||||||
|
mockLedger.EXPECT().PersistBlockData(gomock.Any()).AnyTimes()
|
||||||
|
logger := log.NewWithModule("executor")
|
||||||
|
|
||||||
|
exec, err := New(mockLedger, logger)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// mock data for block
|
||||||
|
var txs []*pb.Transaction
|
||||||
|
tx, err := genBVMContractTransaction(privKey, 1, constant.InterchainContractAddr.Address(), "GetIBTPByID", pb.String(id))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
txs = append(txs, tx)
|
||||||
|
receipts := exec.ApplyReadonlyTransactions(txs)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, len(receipts))
|
||||||
|
assert.Equal(t, hash.Bytes(), receipts[0].Ret)
|
||||||
|
assert.Equal(t, pb.Receipt_SUCCESS, receipts[0].Status)
|
||||||
|
}
|
||||||
|
|
||||||
func listenBlock(wg *sync.WaitGroup, done chan bool, blockCh chan events.NewBlockEvent) {
|
func listenBlock(wg *sync.WaitGroup, done chan bool, blockCh chan events.NewBlockEvent) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -263,6 +345,53 @@ func randAddress(t *testing.T) types.Address {
|
||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func genBVMContractTransaction(privateKey crypto.PrivateKey, nonce uint64, address types.Address, method string, args ...*pb.Arg) (*pb.Transaction, error) {
|
||||||
|
return genContractTransaction(pb.TransactionData_BVM, privateKey, nonce, address, method, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func genXVMContractTransaction(privateKey crypto.PrivateKey, nonce uint64, address types.Address, method string, args ...*pb.Arg) (*pb.Transaction, error) {
|
||||||
|
return genContractTransaction(pb.TransactionData_XVM, privateKey, nonce, address, method, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func genContractTransaction(vmType pb.TransactionData_VMType, privateKey crypto.PrivateKey, nonce uint64, address types.Address, method string, args ...*pb.Arg) (*pb.Transaction, error) {
|
||||||
|
from, err := privateKey.PublicKey().Address()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pl := &pb.InvokePayload{
|
||||||
|
Method: method,
|
||||||
|
Args: args[:],
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := pl.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
td := &pb.TransactionData{
|
||||||
|
Type: pb.TransactionData_INVOKE,
|
||||||
|
VmType: vmType,
|
||||||
|
Payload: data,
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := &pb.Transaction{
|
||||||
|
From: from,
|
||||||
|
To: address,
|
||||||
|
Data: td,
|
||||||
|
Timestamp: time.Now().UnixNano(),
|
||||||
|
Nonce: nonce,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Sign(privateKey); err != nil {
|
||||||
|
return nil, fmt.Errorf("tx sign: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.TransactionHash = tx.Hash()
|
||||||
|
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
func mockTxData(t *testing.T, dataType pb.TransactionData_Type, vmType pb.TransactionData_VMType, ibtp proto.Marshaler) *pb.TransactionData {
|
func mockTxData(t *testing.T, dataType pb.TransactionData_Type, vmType pb.TransactionData_VMType, ibtp proto.Marshaler) *pb.TransactionData {
|
||||||
ib, err := ibtp.Marshal()
|
ib, err := ibtp.Marshal()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
|
@ -115,7 +115,9 @@ func (pl *VerifyPool) verifyProof(ibtp *pb.IBTP, proof []byte) (bool, error) {
|
||||||
}
|
}
|
||||||
validateAddr = rl.Address
|
validateAddr = rl.Address
|
||||||
} else {
|
} else {
|
||||||
return false, fmt.Errorf("appchain didn't register rule")
|
if app.ChainType != "fabric" {
|
||||||
|
return false, fmt.Errorf("appchain didn't register rule")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, err = pl.ve.Validate(validateAddr, ibtp.From, proof, ibtp.Payload, app.Validators)
|
ok, err = pl.ve.Validate(validateAddr, ibtp.From, proof, ibtp.Payload, app.Validators)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
type Contract interface{}
|
type Contract interface{}
|
||||||
|
|
||||||
|
//go:generate mockgen -destination mock_stub/mock_stub.go -package mock_stub -source stub.go
|
||||||
type Stub interface {
|
type Stub interface {
|
||||||
// Caller
|
// Caller
|
||||||
Caller() string
|
Caller() string
|
||||||
|
|
Loading…
Reference in New Issue