mirror of https://github.com/poanetwork/gecko.git
286 lines
7.2 KiB
Go
286 lines
7.2 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package avm
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/ava-labs/gecko/snow/choices"
|
|
|
|
"github.com/ava-labs/gecko/database/memdb"
|
|
"github.com/ava-labs/gecko/ids"
|
|
"github.com/ava-labs/gecko/snow/engine/common"
|
|
"github.com/ava-labs/gecko/utils/formatting"
|
|
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
|
)
|
|
|
|
func setup(t *testing.T) ([]byte, *VM, *Service) {
|
|
genesisBytes := BuildGenesisTest(t)
|
|
|
|
ctx.Lock.Lock()
|
|
|
|
// This VM initilialzation is very similar to that done by GenesisVM().
|
|
// However replacing the body of this function, with a call to GenesisVM
|
|
// causes a timeout while executing the test suite.
|
|
// https://github.com/ava-labs/gecko/pull/59#pullrequestreview-392478636
|
|
vm := &VM{}
|
|
err := vm.Initialize(
|
|
ctx,
|
|
memdb.New(),
|
|
genesisBytes,
|
|
make(chan common.Message, 1),
|
|
[]*common.Fx{&common.Fx{
|
|
ID: ids.Empty,
|
|
Fx: &secp256k1fx.Fx{},
|
|
}},
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
s := &Service{vm: vm}
|
|
return genesisBytes, vm, s
|
|
}
|
|
|
|
func TestServiceIssueTx(t *testing.T) {
|
|
genesisBytes, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
txArgs := &IssueTxArgs{}
|
|
txReply := &IssueTxReply{}
|
|
err := s.IssueTx(nil, txArgs, txReply)
|
|
if err == nil {
|
|
t.Fatal("Expected empty transaction to return an error")
|
|
}
|
|
|
|
tx := NewTx(t, genesisBytes, vm)
|
|
txArgs.Tx = formatting.CB58{Bytes: tx.Bytes()}
|
|
txReply = &IssueTxReply{}
|
|
if err := s.IssueTx(nil, txArgs, txReply); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !txReply.TxID.Equals(tx.ID()) {
|
|
t.Fatalf("Expected %q, got %q", txReply.TxID, tx.ID())
|
|
}
|
|
}
|
|
|
|
func TestServiceGetTxStatus(t *testing.T) {
|
|
genesisBytes, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
statusArgs := &GetTxStatusArgs{}
|
|
statusReply := &GetTxStatusReply{}
|
|
if err := s.GetTxStatus(nil, statusArgs, statusReply); err == nil {
|
|
t.Fatal("Expected empty transaction to return an error")
|
|
}
|
|
|
|
tx := NewTx(t, genesisBytes, vm)
|
|
statusArgs.TxID = tx.ID()
|
|
statusReply = &GetTxStatusReply{}
|
|
if err := s.GetTxStatus(nil, statusArgs, statusReply); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if expected := choices.Unknown; expected != statusReply.Status {
|
|
t.Fatalf(
|
|
"Expected an unsubmitted tx to have status %q, got %q",
|
|
expected.String(), statusReply.Status.String(),
|
|
)
|
|
}
|
|
|
|
txArgs := &IssueTxArgs{Tx: formatting.CB58{Bytes: tx.Bytes()}}
|
|
txReply := &IssueTxReply{}
|
|
if err := s.IssueTx(nil, txArgs, txReply); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
statusReply = &GetTxStatusReply{}
|
|
if err := s.GetTxStatus(nil, statusArgs, statusReply); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if expected := choices.Processing; expected != statusReply.Status {
|
|
t.Fatalf(
|
|
"Expected a submitted tx to have status %q, got %q",
|
|
expected.String(), statusReply.Status.String(),
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestServiceGetUTXOsInvalidAddress(t *testing.T) {
|
|
_, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
addr0 := keys[0].PublicKey().Address()
|
|
tests := []struct {
|
|
label string
|
|
args *GetUTXOsArgs
|
|
}{
|
|
{"[", &GetUTXOsArgs{[]string{""}}},
|
|
{"[-]", &GetUTXOsArgs{[]string{"-"}}},
|
|
{"[foo]", &GetUTXOsArgs{[]string{"foo"}}},
|
|
{"[foo-bar]", &GetUTXOsArgs{[]string{"foo-bar"}}},
|
|
{"[<ChainID>]", &GetUTXOsArgs{[]string{ctx.ChainID.String()}}},
|
|
{"[<ChainID>-]", &GetUTXOsArgs{[]string{fmt.Sprintf("%s-", ctx.ChainID.String())}}},
|
|
{"[<Unknown ID>-<addr0>]", &GetUTXOsArgs{[]string{fmt.Sprintf("%s-%s", ids.NewID([32]byte{42}).String(), addr0.String())}}},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.label, func(t *testing.T) {
|
|
utxosReply := &GetUTXOsReply{}
|
|
if err := s.GetUTXOs(nil, tt.args, utxosReply); err == nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestServiceGetUTXOs(t *testing.T) {
|
|
_, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
addr0 := keys[0].PublicKey().Address()
|
|
tests := []struct {
|
|
label string
|
|
args *GetUTXOsArgs
|
|
count int
|
|
}{
|
|
{
|
|
"Empty",
|
|
&GetUTXOsArgs{},
|
|
0,
|
|
}, {
|
|
"[<ChainID>-<unrelated address>]",
|
|
&GetUTXOsArgs{[]string{
|
|
// TODO: Should GetUTXOs() raise an error for this? The address portion is
|
|
// longer than addr0.String()
|
|
fmt.Sprintf("%s-%s", ctx.ChainID.String(), ids.NewID([32]byte{42}).String()),
|
|
}},
|
|
0,
|
|
}, {
|
|
"[<ChainID>-<addr0>]",
|
|
&GetUTXOsArgs{[]string{
|
|
fmt.Sprintf("%s-%s", ctx.ChainID.String(), addr0.String()),
|
|
}},
|
|
7,
|
|
}, {
|
|
"[<ChainID>-<addr0>,<ChainID>-<addr0>]",
|
|
&GetUTXOsArgs{[]string{
|
|
fmt.Sprintf("%s-%s", ctx.ChainID.String(), addr0.String()),
|
|
fmt.Sprintf("%s-%s", ctx.ChainID.String(), addr0.String()),
|
|
}},
|
|
7,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.label, func(t *testing.T) {
|
|
utxosReply := &GetUTXOsReply{}
|
|
if err := s.GetUTXOs(nil, tt.args, utxosReply); err != nil {
|
|
t.Error(err)
|
|
} else if tt.count != len(utxosReply.UTXOs) {
|
|
t.Errorf("Expected %d utxos, got %#v", tt.count, len(utxosReply.UTXOs))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetAssetDescription(t *testing.T) {
|
|
genesisBytes, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
genesisTx := GetFirstTxFromGenesisTest(genesisBytes, t)
|
|
|
|
avaAssetID := genesisTx.ID()
|
|
|
|
reply := GetAssetDescriptionReply{}
|
|
err := s.GetAssetDescription(nil, &GetAssetDescriptionArgs{
|
|
AssetID: avaAssetID.String(),
|
|
}, &reply)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if reply.Name != "myFixedCapAsset" {
|
|
t.Fatalf("Wrong name returned from GetAssetDescription %s", reply.Name)
|
|
}
|
|
if reply.Symbol != "MFCA" {
|
|
t.Fatalf("Wrong name returned from GetAssetDescription %s", reply.Symbol)
|
|
}
|
|
}
|
|
|
|
func TestGetBalance(t *testing.T) {
|
|
genesisBytes, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
genesisTx := GetFirstTxFromGenesisTest(genesisBytes, t)
|
|
|
|
avaAssetID := genesisTx.ID()
|
|
|
|
reply := GetBalanceReply{}
|
|
err := s.GetBalance(nil, &GetBalanceArgs{
|
|
Address: vm.Format(keys[0].PublicKey().Address().Bytes()),
|
|
AssetID: avaAssetID.String(),
|
|
}, &reply)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if reply.Balance != 300000 {
|
|
t.Fatalf("Wrong balance returned from GetBalance %d", reply.Balance)
|
|
}
|
|
}
|
|
|
|
func TestCreateFixedCapAsset(t *testing.T) {
|
|
_, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
reply := CreateFixedCapAssetReply{}
|
|
err := s.CreateFixedCapAsset(nil, &CreateFixedCapAssetArgs{
|
|
Name: "test asset",
|
|
Symbol: "test",
|
|
Denomination: 1,
|
|
InitialHolders: []*Holder{&Holder{
|
|
Amount: 123456789,
|
|
Address: vm.Format(keys[0].PublicKey().Address().Bytes()),
|
|
}},
|
|
}, &reply)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if reply.AssetID.String() != "wWBk78PGAU4VkXhESr3jiYyMCEzzPPcnVYeEnNr9g4JuvYs2x" {
|
|
t.Fatalf("Wrong assetID returned from CreateFixedCapAsset %s", reply.AssetID)
|
|
}
|
|
}
|
|
|
|
func TestCreateVariableCapAsset(t *testing.T) {
|
|
_, vm, s := setup(t)
|
|
defer ctx.Lock.Unlock()
|
|
defer vm.Shutdown()
|
|
|
|
reply := CreateVariableCapAssetReply{}
|
|
err := s.CreateVariableCapAsset(nil, &CreateVariableCapAssetArgs{
|
|
Name: "test asset",
|
|
Symbol: "test",
|
|
MinterSets: []Owners{
|
|
Owners{
|
|
Threshold: 1,
|
|
Minters: []string{
|
|
vm.Format(keys[0].PublicKey().Address().Bytes()),
|
|
},
|
|
},
|
|
},
|
|
}, &reply)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if reply.AssetID.String() != "SscTvpQFCZPNiRXyueDc7LdHT9EstHiva3AK6kuTgHTMd7DsU" {
|
|
t.Fatalf("Wrong assetID returned from CreateFixedCapAsset %s", reply.AssetID)
|
|
}
|
|
}
|