Ekaterina Lebedeva
9e3ac59aa8
Use `require` to check for errors and instead of just printing result to Stdout, t.Log to print errors. Added functions to calculate start offset, check if contract method has result and to get random int to put. Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
117 lines
3.5 KiB
Go
117 lines
3.5 KiB
Go
package contract
|
|
|
|
import (
|
|
"errors"
|
|
"math/rand"
|
|
"path"
|
|
"testing"
|
|
|
|
"git.frostfs.info/TrueCloudLab/contract-coverage-primer/covertest"
|
|
"github.com/davecgh/go-spew/spew"
|
|
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
|
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
|
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const ctrPath = "../impulse"
|
|
|
|
// Key for tests
|
|
var (
|
|
validKey = []byte{1, 2, 3, 4, 5}
|
|
invalidKey = []byte{1, 2, 3}
|
|
)
|
|
|
|
func newExecutor(t *testing.T) *neotest.Executor {
|
|
bc, acc := chain.NewSingle(t)
|
|
return neotest.NewExecutor(t, bc, acc, acc)
|
|
}
|
|
|
|
func TestContract(t *testing.T) {
|
|
e := newExecutor(t)
|
|
ctrDI := covertest.CompileFile(t, e.CommitteeHash, ctrPath, path.Join(ctrPath, "config.yml"))
|
|
ctr := ctrDI.Contract
|
|
e.DeployContract(t, ctr, nil)
|
|
inv := e.CommitteeInvoker(ctr.Hash)
|
|
|
|
// test get without put
|
|
inv.InvokeFail(t, "Cannot get number", "getNumber", validKey)
|
|
|
|
// test put-get with valid key
|
|
inv.Invoke(t, stackitem.Null{}, "putNumber", validKey, 42)
|
|
inv.Invoke(t, 42, "getNumber", validKey)
|
|
|
|
// test invalid key
|
|
inv.InvokeFail(t, "Invalid key size", "putNumber", invalidKey, 42)
|
|
inv.InvokeFail(t, "Invalid key size", "getNumber", invalidKey)
|
|
}
|
|
|
|
func TestRun(t *testing.T) {
|
|
e := newExecutor(t)
|
|
ctrDI := covertest.CompileFile(t, e.CommitteeHash, ctrPath, path.Join(ctrPath, "config.yml"))
|
|
e.DeployContract(t, ctrDI.Contract, nil)
|
|
|
|
startOffsetPutNumber, err := getStartOffset(ctrDI.DebugInfo, "PutNumber")
|
|
require.NoError(t, err)
|
|
|
|
hasResult, err := hasResult(ctrDI.DebugInfo, "PutNumber")
|
|
require.NoError(t, err)
|
|
|
|
someNum := getNumToPut()
|
|
|
|
// setting up a VM for covertest.Run()
|
|
covertestRunVM := setUpVMForPut(t, e, ctrDI.Contract, hasResult, startOffsetPutNumber, someNum, invalidKey)
|
|
res, covErr := covertest.Run(covertestRunVM)
|
|
t.Log("Printing collected instructions:")
|
|
spew.Dump(res)
|
|
t.Log("covertest.Run() returned an error: ", covErr)
|
|
|
|
// setting up a VM for vm.Run()
|
|
origRunVM := setUpVMForPut(t, e, ctrDI.Contract, hasResult, startOffsetPutNumber, someNum, invalidKey)
|
|
runerr := origRunVM.Run()
|
|
t.Log("vm.Run() returned an error: ", covErr)
|
|
|
|
//check if errors are the same
|
|
require.Equal(t, runerr.Error(), covErr.Error())
|
|
|
|
//check if the number of elements on the stack is the same
|
|
require.Equal(t, origRunVM.Estack().Len(), covertestRunVM.Estack().Len())
|
|
}
|
|
|
|
func setUpVMForPut(t *testing.T, e *neotest.Executor, contract *neotest.Contract, hasResult bool, methodOff int, num int, key []byte) (v *vm.VM) {
|
|
ic, err := e.Chain.GetTestVM(trigger.Application, nil, nil)
|
|
require.NoError(t, err)
|
|
ic.VM.LoadNEFMethod(contract.NEF, contract.Hash, contract.Hash, callflag.All, hasResult, methodOff, -1, nil)
|
|
ic.VM.Context().Estack().PushVal(num)
|
|
ic.VM.Context().Estack().PushVal(key)
|
|
return ic.VM
|
|
}
|
|
|
|
func getStartOffset(di *compiler.DebugInfo, methodID string) (int, error) {
|
|
for _, method := range di.Methods {
|
|
if method.ID == methodID {
|
|
return int(method.Range.Start), nil
|
|
}
|
|
}
|
|
return 0, errors.New("Method not found")
|
|
}
|
|
|
|
func hasResult(di *compiler.DebugInfo, methodID string) (bool, error) {
|
|
for _, method := range di.Methods {
|
|
if method.ID == methodID {
|
|
if method.ReturnType == "Void" {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, errors.New("Method not found")
|
|
}
|
|
|
|
func getNumToPut() int {
|
|
return rand.Intn(100)
|
|
}
|