forked from TrueCloudLab/frostfs-contract
Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
700d091061 |
11 changed files with 451 additions and 69 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@ config.json
|
|||
/vendor/
|
||||
.idea
|
||||
/bin/
|
||||
*.out
|
||||
|
||||
# debhelpers
|
||||
**/.debhelper
|
||||
|
|
133
covertest/client.go
Normal file
133
covertest/client.go
Normal file
|
@ -0,0 +1,133 @@
|
|||
package covertest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"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/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// ContractInvoker is a client for a specific contract.
|
||||
type ContractInvoker struct {
|
||||
*neotest.ContractInvoker
|
||||
Methods []Method
|
||||
}
|
||||
|
||||
type Method struct {
|
||||
Name string
|
||||
Instructions []InstrHash
|
||||
}
|
||||
|
||||
// CommitteeInvoker creates a new ContractInvoker for the contract with hash h and a committee multisignature signer.
|
||||
func CommitteeInvoker(e *neotest.Executor, h util.Uint160) *ContractInvoker {
|
||||
return &ContractInvoker{
|
||||
ContractInvoker: &neotest.ContractInvoker{
|
||||
Executor: e,
|
||||
Hash: h,
|
||||
Signers: []neotest.Signer{e.Committee},
|
||||
},
|
||||
Methods: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke invokes the method with the args, persists the transaction and checks the result.
|
||||
// Returns transaction hash.
|
||||
func (c *ContractInvoker) Invoke(t testing.TB, result interface{}, method string, args ...interface{}) util.Uint256 {
|
||||
c.Methods = append(c.Methods, Method{
|
||||
Name: method,
|
||||
Instructions: nil,
|
||||
})
|
||||
tx := c.PrepareInvoke(t, method, args...)
|
||||
c.AddNewBlock(t, tx)
|
||||
c.CheckHalt(t, tx.Hash(), stackitem.Make(result))
|
||||
return tx.Hash()
|
||||
}
|
||||
|
||||
// InvokeFail invokes the method with the args, persists the transaction and checks the error message.
|
||||
// It returns the transaction hash.
|
||||
func (c *ContractInvoker) InvokeFail(t testing.TB, message string, method string, args ...interface{}) util.Uint256 {
|
||||
c.Methods = append(c.Methods, Method{
|
||||
Name: method,
|
||||
Instructions: nil,
|
||||
})
|
||||
tx := c.PrepareInvoke(t, method, args...)
|
||||
c.AddNewBlock(t, tx)
|
||||
c.CheckFault(t, tx.Hash(), message)
|
||||
return tx.Hash()
|
||||
}
|
||||
|
||||
// PrepareInvoke creates a new invocation transaction.
|
||||
func (c *ContractInvoker) PrepareInvoke(t testing.TB, method string, args ...interface{}) *transaction.Transaction {
|
||||
return c.NewTx(t, c.Signers, c.Hash, method, args...)
|
||||
}
|
||||
|
||||
// NewTx creates a new transaction which invokes the contract method.
|
||||
// The transaction is signed by the signers.
|
||||
func (c *ContractInvoker) NewTx(t testing.TB, signers []neotest.Signer,
|
||||
hash util.Uint160, method string, args ...interface{}) *transaction.Transaction {
|
||||
tx := c.NewUnsignedTx(t, hash, method, args...)
|
||||
return c.SignTx(t, tx, -1, signers...)
|
||||
}
|
||||
|
||||
// SignTx signs a transaction using the provided signers.
|
||||
func (c *ContractInvoker) SignTx(t testing.TB, tx *transaction.Transaction, sysFee int64, signers ...neotest.Signer) *transaction.Transaction {
|
||||
for _, acc := range signers {
|
||||
tx.Signers = append(tx.Signers, transaction.Signer{
|
||||
Account: acc.ScriptHash(),
|
||||
Scopes: transaction.Global,
|
||||
})
|
||||
}
|
||||
neotest.AddNetworkFee(c.Chain, tx, signers...)
|
||||
c.AddSystemFee(c.Chain, tx, sysFee)
|
||||
|
||||
for _, acc := range signers {
|
||||
require.NoError(t, acc.SignTx(c.Chain.GetConfig().Magic, tx))
|
||||
}
|
||||
return tx
|
||||
}
|
||||
|
||||
// AddSystemFee adds system fee to the transaction. If negative value specified,
|
||||
// then system fee is defined by test invocation.
|
||||
func (c *ContractInvoker) AddSystemFee(bc *core.Blockchain, tx *transaction.Transaction, sysFee int64) {
|
||||
if sysFee >= 0 {
|
||||
tx.SystemFee = sysFee
|
||||
return
|
||||
}
|
||||
ops, v, _ := TestInvoke(bc, tx) // ignore error to support failing transactions
|
||||
tx.SystemFee = v.GasConsumed()
|
||||
c.Methods[len(c.Methods)-1].Instructions = make([]InstrHash, len(ops))
|
||||
copy(c.Methods[len(c.Methods)-1].Instructions, ops)
|
||||
}
|
||||
|
||||
// TestInvoke creates a test VM with a dummy block and executes a transaction in it.
|
||||
func TestInvoke(bc *core.Blockchain, tx *transaction.Transaction) ([]InstrHash, *vm.VM, error) {
|
||||
lastBlock, err := bc.GetBlock(bc.GetHeaderHash(bc.BlockHeight()))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
b := &block.Block{
|
||||
Header: block.Header{
|
||||
Index: bc.BlockHeight() + 1,
|
||||
Timestamp: lastBlock.Timestamp + 1,
|
||||
},
|
||||
}
|
||||
|
||||
// `GetTestVM` as well as `Run` can use a transaction hash which will set a cached value.
|
||||
// This is unwanted behavior, so we explicitly copy the transaction to perform execution.
|
||||
ttx := *tx
|
||||
ic, _ := bc.GetTestVM(trigger.Application, &ttx, b)
|
||||
|
||||
defer ic.Finalize()
|
||||
|
||||
ic.VM.LoadWithFlags(tx.Script, callflag.All)
|
||||
ops, err := Run(ic.VM)
|
||||
return ops, ic.VM, err
|
||||
}
|
56
covertest/compile.go
Normal file
56
covertest/compile.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package covertest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/cli/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// ContractWithDebugInfo contains contract info for deployment and debug information for coverage.
|
||||
type ContractWithDebugInfo struct {
|
||||
Contract *neotest.Contract
|
||||
DebugInfo *compiler.DebugInfo
|
||||
}
|
||||
|
||||
// CompileFile compiles a contract from the file and returns its NEF, manifest, hash and debug information.
|
||||
func CompileFile(t testing.TB, sender util.Uint160, srcPath string, configPath string) *ContractWithDebugInfo {
|
||||
// nef.NewFile() cares about version a lot.
|
||||
config.Version = "neotest"
|
||||
|
||||
ne, di, err := compiler.CompileWithOptions(srcPath, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
conf, err := smartcontract.ParseContractConfig(configPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
o := &compiler.Options{}
|
||||
o.Name = conf.Name
|
||||
o.ContractEvents = conf.Events
|
||||
o.ContractSupportedStandards = conf.SupportedStandards
|
||||
o.Permissions = make([]manifest.Permission, len(conf.Permissions))
|
||||
for i := range conf.Permissions {
|
||||
o.Permissions[i] = manifest.Permission(conf.Permissions[i])
|
||||
}
|
||||
o.SafeMethods = conf.SafeMethods
|
||||
o.Overloads = conf.Overloads
|
||||
o.SourceURL = conf.SourceURL
|
||||
m, err := compiler.CreateManifest(di, o)
|
||||
require.NoError(t, err)
|
||||
|
||||
c := &neotest.Contract{
|
||||
Hash: state.CreateContractHash(sender, ne.Checksum, m.Name),
|
||||
NEF: ne,
|
||||
Manifest: m,
|
||||
}
|
||||
return &ContractWithDebugInfo{
|
||||
Contract: c,
|
||||
DebugInfo: di,
|
||||
}
|
||||
}
|
124
covertest/cover.go
Normal file
124
covertest/cover.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
package covertest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var mu sync.Mutex
|
||||
|
||||
type coverline struct {
|
||||
Doc string
|
||||
Opcode int
|
||||
StartLine int
|
||||
StartCol int
|
||||
EndLine int
|
||||
EndCol int
|
||||
WTFnumber int
|
||||
IsCovered bool
|
||||
}
|
||||
|
||||
// MakeCoverage generates an output file with coverage info in correct format
|
||||
func (c *ContractInvoker) MakeCoverage(t testing.TB, ctrdi *ContractWithDebugInfo, ctrPath string, fileName string) {
|
||||
docs := getDocuments(t, ctrdi.DebugInfo.Documents, ctrPath)
|
||||
cov := getSeqPoints(t, ctrdi.DebugInfo, docs)
|
||||
for _, iMethod := range c.Methods {
|
||||
countInstructions(cov, iMethod.Instructions)
|
||||
}
|
||||
printToFile(t, cov, fileName)
|
||||
}
|
||||
|
||||
func getDocuments(t testing.TB, docs []string, substr string) []int {
|
||||
res := make([]int, 0, len(docs))
|
||||
|
||||
for i, cDoc := range docs {
|
||||
if strings.Contains(cDoc, substr) {
|
||||
res = append(res, i)
|
||||
}
|
||||
}
|
||||
if len(res) == 0 {
|
||||
t.Log("Cannot get document\n")
|
||||
t.FailNow()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func getSeqPoints(t testing.TB, di *compiler.DebugInfo, docs []int) []coverline {
|
||||
res := make([]coverline, 0, 10)
|
||||
|
||||
for _, method := range di.Methods {
|
||||
maxLine := method.Range.End
|
||||
for _, seqPoint := range method.SeqPoints {
|
||||
if isValidDocument(seqPoint.Document, docs) && seqPoint.Opcode < int(maxLine) {
|
||||
res = append(res, coverline{
|
||||
Doc: di.Documents[seqPoint.Document],
|
||||
Opcode: seqPoint.Opcode,
|
||||
StartLine: seqPoint.StartLine,
|
||||
StartCol: seqPoint.StartCol,
|
||||
EndLine: seqPoint.EndLine,
|
||||
EndCol: seqPoint.EndCol,
|
||||
WTFnumber: 1,
|
||||
IsCovered: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func isValidDocument(iDocToCheck int, docs []int) bool {
|
||||
for _, iDoc := range docs {
|
||||
if iDoc == iDocToCheck {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func countInstructions(cov []coverline, codes []InstrHash) {
|
||||
for i := 0; i < len(cov); i++ {
|
||||
for _, code := range codes {
|
||||
if code.Offset == cov[i].Opcode {
|
||||
cov[i].IsCovered = true
|
||||
//cov[i].WTFnumber++
|
||||
//break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printToFile(t testing.TB, cov []coverline, name string) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
f, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer f.Close()
|
||||
|
||||
fi, err := os.Stat(name)
|
||||
require.NoError(t, err)
|
||||
firstToWrite := ""
|
||||
if fi.Size() == 0 {
|
||||
firstToWrite = "mode: set\n"
|
||||
}
|
||||
|
||||
_, err = f.WriteString(firstToWrite)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, info := range cov {
|
||||
covered := 0
|
||||
if info.IsCovered {
|
||||
covered++
|
||||
}
|
||||
line := fmt.Sprintf("%s:%d.%d,%d.%d %d %d\n", info.Doc, info.StartLine, info.StartCol, info.EndLine, info.EndCol, info.WTFnumber, covered)
|
||||
_, err = f.WriteString(line)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
58
covertest/run.go
Normal file
58
covertest/run.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
package covertest
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||
)
|
||||
|
||||
// InstrHash maps instruction with scripthash of a contract it belongs to.
|
||||
type InstrHash struct {
|
||||
Offset int
|
||||
Instruction opcode.Opcode
|
||||
ScriptHash util.Uint160
|
||||
}
|
||||
|
||||
// Run starts execution of the loaded program and accumulates all seen opcodes
|
||||
// together with the scripthash of a contract they belong to.
|
||||
// Original vm.Run(): https://github.com/nspcc-dev/neo-go/blob/v0.101.3/pkg/vm/vm.go#L418
|
||||
func Run(v *vm.VM) ([]InstrHash, error) {
|
||||
if !v.Ready() {
|
||||
return nil, errors.New("no program loaded")
|
||||
}
|
||||
|
||||
if v.HasFailed() {
|
||||
// VM already ran something and failed, in general its state is
|
||||
// undefined in this case so we can't run anything.
|
||||
return nil, errors.New("VM has failed")
|
||||
}
|
||||
|
||||
// vmstate.Halt (the default) or vmstate.Break are safe to continue.
|
||||
var ops []InstrHash
|
||||
for {
|
||||
switch {
|
||||
case v.HasFailed():
|
||||
// Should be caught and reported already by the v.Step(),
|
||||
// but we're checking here anyway just in case.
|
||||
return ops, errors.New("VM has failed")
|
||||
case v.HasHalted(), v.AtBreakpoint():
|
||||
// Normal exit from this loop.
|
||||
return ops, nil
|
||||
case v.State() == vmstate.None:
|
||||
nStr, curInstr := v.Context().NextInstr()
|
||||
ops = append(ops, InstrHash{
|
||||
Offset: nStr,
|
||||
Instruction: curInstr,
|
||||
ScriptHash: v.Context().ScriptHash(),
|
||||
})
|
||||
if err := v.Step(); err != nil {
|
||||
return ops, err
|
||||
}
|
||||
default:
|
||||
return ops, errors.New("unknown state")
|
||||
}
|
||||
}
|
||||
}
|
4
go.mod
4
go.mod
|
@ -4,7 +4,7 @@ go 1.14
|
|||
|
||||
require (
|
||||
github.com/mr-tron/base58 v1.2.0
|
||||
github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5
|
||||
github.com/nspcc-dev/neo-go v0.101.5-0.20230811211719-9fb154a376fc
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230810094130-11bb733f1a2c
|
||||
github.com/stretchr/testify v1.8.1
|
||||
)
|
||||
|
|
10
go.sum
10
go.sum
|
@ -698,14 +698,12 @@ github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:
|
|||
github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM=
|
||||
github.com/nspcc-dev/neo-go v0.99.2/go.mod h1:9P0yWqhZX7i/ChJ+zjtiStO1uPTolPFUM+L5oNznU8E=
|
||||
github.com/nspcc-dev/neo-go v0.100.1/go.mod h1:Nnp7F4e9IBccsgtCeLtUWV+0T6gk1PtP5HRtA13hUfc=
|
||||
github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5 h1:AXI2upTPeTqX+n4xrBEzPATgEviOM/Prg6UQ6KDm+DU=
|
||||
github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5/go.mod h1:Z0kpjwnTJj/ik/X6z18xjCL0X2+RNbqlnhKrl+MYgP8=
|
||||
github.com/nspcc-dev/neo-go v0.101.5-0.20230811211719-9fb154a376fc h1:U4x1uOG3JXy9TWgcH2B/ZOWfxZmerkymkZibBrxSA1Q=
|
||||
github.com/nspcc-dev/neo-go v0.101.5-0.20230811211719-9fb154a376fc/go.mod h1:QXxpZxJT2KedwM0Nlj8UO0/fZN2WIe4h/i03uBHKbnc=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220809123759-3094d3e0c14b/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a h1:63sh46kfKF/g2IE1z/EV8CBEKCVmGJXSSH0ZHqTDGCY=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5 h1:/d7mY5hYlNhmEXexKcyqSR0b1Hdl5hf/c5o8Vi/1vt4=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230810094130-11bb733f1a2c h1:upj+XyoI0dS7CYnZOTAeyuznhvDIJurQXL4FvHNKyl4=
|
||||
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230810094130-11bb733f1a2c/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg=
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs=
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs=
|
||||
github.com/nspcc-dev/neofs-api-go/v2 v2.14.0 h1:jhuN8Ldqz7WApvUJRFY0bjRXE1R3iCkboMX5QVZhHVk=
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"path"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/covertest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
|
@ -12,17 +13,17 @@ import (
|
|||
const balancePath = "../balance"
|
||||
|
||||
func deployBalanceContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
|
||||
c := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
c := covertest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
|
||||
args := make([]interface{}, 3)
|
||||
args[0] = false
|
||||
args[1] = addrNetmap
|
||||
args[2] = addrContainer
|
||||
|
||||
e.DeployContract(t, c, args)
|
||||
return c.Hash
|
||||
e.DeployContract(t, c.Contract, args)
|
||||
return c.Contract.Hash
|
||||
}
|
||||
|
||||
func balanceMint(t *testing.T, c *neotest.ContractInvoker, acc neotest.Signer, amount int64, details []byte) {
|
||||
func balanceMint(t *testing.T, c *covertest.ContractInvoker, acc neotest.Signer, amount int64, details []byte) {
|
||||
c.Invoke(t, stackitem.Null{}, "mint", acc.ScriptHash(), amount, details)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/covertest"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
||||
"github.com/mr-tron/base58"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
|
||||
|
@ -35,26 +36,26 @@ func deployContainerContract(t *testing.T, e *neotest.Executor, addrNetmap, addr
|
|||
args[4] = addrNNS
|
||||
args[5] = "frostfs"
|
||||
|
||||
c := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
e.DeployContract(t, c, args)
|
||||
return c.Hash
|
||||
c := covertest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
e.DeployContract(t, c.Contract, args)
|
||||
return c.Contract.Hash
|
||||
}
|
||||
|
||||
func newContainerInvoker(t *testing.T) (*neotest.ContractInvoker, *neotest.ContractInvoker, *neotest.ContractInvoker) {
|
||||
func newContainerInvoker(t *testing.T) (*covertest.ContractWithDebugInfo, *covertest.ContractInvoker, *covertest.ContractInvoker, *covertest.ContractInvoker) {
|
||||
e := newExecutor(t)
|
||||
|
||||
ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
ctrNetmap := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
||||
ctrBalance := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
ctrContainer := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
ctrNNS := covertest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
ctrNetmap := covertest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
||||
ctrBalance := covertest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
ctrContainer := covertest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
|
||||
e.DeployContract(t, ctrNNS, nil)
|
||||
deployNetmapContract(t, e, ctrBalance.Hash, ctrContainer.Hash,
|
||||
e.DeployContract(t, ctrNNS.Contract, nil)
|
||||
deployNetmapContract(t, e, ctrBalance.Contract.Hash, ctrContainer.Contract.Hash,
|
||||
container.RegistrationFeeKey, int64(containerFee),
|
||||
container.AliasFeeKey, int64(containerAliasFee))
|
||||
deployBalanceContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
|
||||
deployContainerContract(t, e, ctrNetmap.Hash, ctrBalance.Hash, ctrNNS.Hash)
|
||||
return e.CommitteeInvoker(ctrContainer.Hash), e.CommitteeInvoker(ctrBalance.Hash), e.CommitteeInvoker(ctrNetmap.Hash)
|
||||
deployBalanceContract(t, e, ctrNetmap.Contract.Hash, ctrContainer.Contract.Hash)
|
||||
deployContainerContract(t, e, ctrNetmap.Contract.Hash, ctrBalance.Contract.Hash, ctrNNS.Contract.Hash)
|
||||
return ctrContainer, covertest.CommitteeInvoker(e, ctrContainer.Contract.Hash), covertest.CommitteeInvoker(e, ctrBalance.Contract.Hash), covertest.CommitteeInvoker(e, ctrNetmap.Contract.Hash)
|
||||
}
|
||||
|
||||
func setContainerOwner(c []byte, acc neotest.Signer) {
|
||||
|
@ -86,7 +87,7 @@ func dummyContainer(owner neotest.Signer) testContainer {
|
|||
}
|
||||
|
||||
func TestContainerCount(t *testing.T) {
|
||||
c, cBal, _ := newContainerInvoker(t)
|
||||
ctrdi, c, cBal, _ := newContainerInvoker(t)
|
||||
|
||||
checkCount := func(t *testing.T, expected int64) {
|
||||
s, err := c.TestInvoke(t, "count")
|
||||
|
@ -120,9 +121,10 @@ func TestContainerCount(t *testing.T) {
|
|||
c.Invoke(t, stackitem.Null{}, "delete", cnt3.id[:], cnt3.sig, cnt3.pub, cnt3.token)
|
||||
checkCount(t, 0)
|
||||
checkContainerList(t, c, [][]byte{})
|
||||
c.MakeCoverage(t, ctrdi, "container", "c.out")
|
||||
}
|
||||
|
||||
func checkContainerList(t *testing.T, c *neotest.ContractInvoker, expected [][]byte) {
|
||||
func checkContainerList(t *testing.T, c *covertest.ContractInvoker, expected [][]byte) {
|
||||
t.Run("check with `list`", func(t *testing.T) {
|
||||
s, err := c.TestInvoke(t, "list", nil)
|
||||
require.NoError(t, err)
|
||||
|
@ -166,7 +168,7 @@ func checkContainerList(t *testing.T, c *neotest.ContractInvoker, expected [][]b
|
|||
}
|
||||
|
||||
func TestContainerPut(t *testing.T) {
|
||||
c, cBal, _ := newContainerInvoker(t)
|
||||
ctrdi, c, cBal, _ := newContainerInvoker(t)
|
||||
|
||||
acc := c.NewAccount(t)
|
||||
cnt := dummyContainer(acc)
|
||||
|
@ -182,8 +184,8 @@ func TestContainerPut(t *testing.T) {
|
|||
c.Invoke(t, stackitem.Null{}, "put", putArgs...)
|
||||
|
||||
t.Run("with nice names", func(t *testing.T) {
|
||||
ctrNNS := neotest.CompileFile(t, c.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
nnsHash := ctrNNS.Hash
|
||||
ctrNNS := covertest.CompileFile(t, c.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
nnsHash := ctrNNS.Contract.Hash
|
||||
|
||||
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
||||
|
||||
|
@ -231,9 +233,10 @@ func TestContainerPut(t *testing.T) {
|
|||
cNNS.Invoke(t, expected, "resolve", "domain.cdn", int64(nns.TXT))
|
||||
})
|
||||
})
|
||||
c.MakeCoverage(t, ctrdi, "container", "c.out")
|
||||
}
|
||||
|
||||
func addContainer(t *testing.T, c, cBal *neotest.ContractInvoker) (neotest.Signer, testContainer) {
|
||||
func addContainer(t *testing.T, c, cBal *covertest.ContractInvoker) (neotest.Signer, testContainer) {
|
||||
acc := c.NewAccount(t)
|
||||
cnt := dummyContainer(acc)
|
||||
|
||||
|
@ -243,7 +246,7 @@ func addContainer(t *testing.T, c, cBal *neotest.ContractInvoker) (neotest.Signe
|
|||
}
|
||||
|
||||
func TestContainerDelete(t *testing.T) {
|
||||
c, cBal, cNm := newContainerInvoker(t)
|
||||
ctrdi, c, cBal, cNm := newContainerInvoker(t)
|
||||
|
||||
acc, cnt := addContainer(t, c, cBal)
|
||||
cAcc := c.WithSigners(acc)
|
||||
|
@ -283,10 +286,11 @@ func TestContainerDelete(t *testing.T) {
|
|||
})
|
||||
|
||||
c.InvokeFail(t, container.NotFoundError, "get", cnt.id[:])
|
||||
c.MakeCoverage(t, ctrdi, "container", "c.out")
|
||||
}
|
||||
|
||||
func TestContainerOwner(t *testing.T) {
|
||||
c, cBal, _ := newContainerInvoker(t)
|
||||
ctrdi, c, cBal, _ := newContainerInvoker(t)
|
||||
|
||||
acc, cnt := addContainer(t, c, cBal)
|
||||
|
||||
|
@ -298,10 +302,11 @@ func TestContainerOwner(t *testing.T) {
|
|||
|
||||
owner := signerToOwner(acc)
|
||||
c.Invoke(t, stackitem.NewBuffer(owner), "owner", cnt.id[:])
|
||||
c.MakeCoverage(t, ctrdi, "container", "c.out")
|
||||
}
|
||||
|
||||
func TestContainerGet(t *testing.T) {
|
||||
c, cBal, _ := newContainerInvoker(t)
|
||||
ctrdi, c, cBal, _ := newContainerInvoker(t)
|
||||
|
||||
_, cnt := addContainer(t, c, cBal)
|
||||
|
||||
|
@ -318,6 +323,7 @@ func TestContainerGet(t *testing.T) {
|
|||
stackitem.NewByteArray(cnt.token),
|
||||
})
|
||||
c.Invoke(t, expected, "get", cnt.id[:])
|
||||
c.MakeCoverage(t, ctrdi, "container", "c.out")
|
||||
}
|
||||
|
||||
type eacl struct {
|
||||
|
@ -339,7 +345,7 @@ func dummyEACL(containerID [32]byte) eacl {
|
|||
}
|
||||
|
||||
func TestContainerSetEACL(t *testing.T) {
|
||||
c, cBal, _ := newContainerInvoker(t)
|
||||
ctrdi, c, cBal, _ := newContainerInvoker(t)
|
||||
|
||||
acc, cnt := addContainer(t, c, cBal)
|
||||
|
||||
|
@ -364,10 +370,11 @@ func TestContainerSetEACL(t *testing.T) {
|
|||
stackitem.NewByteArray(e.token),
|
||||
})
|
||||
c.Invoke(t, expected, "eACL", cnt.id[:])
|
||||
c.MakeCoverage(t, ctrdi, "container", "c.out")
|
||||
}
|
||||
|
||||
func TestContainerSizeEstimation(t *testing.T) {
|
||||
c, cBal, cNm := newContainerInvoker(t)
|
||||
ctrdi, c, cBal, cNm := newContainerInvoker(t)
|
||||
|
||||
_, cnt := addContainer(t, c, cBal)
|
||||
nodes := []testNodeInfo{
|
||||
|
@ -435,6 +442,7 @@ func TestContainerSizeEstimation(t *testing.T) {
|
|||
}
|
||||
checkEstimations(t, c, 2, cnt)
|
||||
checkEstimations(t, c, epoch, cnt, estimation{nodes[1].pub, int64(999)})
|
||||
c.MakeCoverage(t, ctrdi, "container", "c.out")
|
||||
}
|
||||
|
||||
type estimation struct {
|
||||
|
@ -442,7 +450,7 @@ type estimation struct {
|
|||
size int64
|
||||
}
|
||||
|
||||
func checkEstimations(t *testing.T, c *neotest.ContractInvoker, epoch int64, cnt testContainer, estimations ...estimation) {
|
||||
func checkEstimations(t *testing.T, c *covertest.ContractInvoker, epoch int64, cnt testContainer, estimations ...estimation) {
|
||||
// Check that listed estimations match expected
|
||||
listEstimations := getListEstimations(t, c, epoch, cnt)
|
||||
requireEstimationsMatch(t, estimations, listEstimations)
|
||||
|
@ -452,7 +460,7 @@ func checkEstimations(t *testing.T, c *neotest.ContractInvoker, epoch int64, cnt
|
|||
requireEstimationsMatch(t, estimations, iterEstimations)
|
||||
}
|
||||
|
||||
func getListEstimations(t *testing.T, c *neotest.ContractInvoker, epoch int64, cnt testContainer) []estimation {
|
||||
func getListEstimations(t *testing.T, c *covertest.ContractInvoker, epoch int64, cnt testContainer) []estimation {
|
||||
s, err := c.TestInvoke(t, "listContainerSizes", epoch)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -481,7 +489,7 @@ func getListEstimations(t *testing.T, c *neotest.ContractInvoker, epoch int64, c
|
|||
return convertStackToEstimations(sizes[1].Value().([]stackitem.Item))
|
||||
}
|
||||
|
||||
func getIterEstimations(t *testing.T, c *neotest.ContractInvoker, epoch int64) []estimation {
|
||||
func getIterEstimations(t *testing.T, c *covertest.ContractInvoker, epoch int64) []estimation {
|
||||
iterStack, err := c.TestInvoke(t, "iterateContainerSizes", epoch)
|
||||
require.NoError(t, err)
|
||||
iter := iterStack.Pop().Value().(*storage.Iterator)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/covertest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -16,37 +17,37 @@ import (
|
|||
|
||||
const frostfsidPath = "../frostfsid"
|
||||
|
||||
func deployFrostFSIDContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
|
||||
func deployFrostFSIDContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) (util.Uint160, *covertest.ContractWithDebugInfo) {
|
||||
args := make([]interface{}, 5)
|
||||
args[0] = false
|
||||
args[1] = addrNetmap
|
||||
args[2] = addrContainer
|
||||
|
||||
c := neotest.CompileFile(t, e.CommitteeHash, frostfsidPath, path.Join(frostfsidPath, "config.yml"))
|
||||
e.DeployContract(t, c, args)
|
||||
return c.Hash
|
||||
c := covertest.CompileFile(t, e.CommitteeHash, frostfsidPath, path.Join(frostfsidPath, "config.yml"))
|
||||
e.DeployContract(t, c.Contract, args)
|
||||
return c.Contract.Hash, c
|
||||
}
|
||||
|
||||
func newFrostFSIDInvoker(t *testing.T) *neotest.ContractInvoker {
|
||||
func newFrostFSIDInvoker(t *testing.T) (*covertest.ContractInvoker, *covertest.ContractWithDebugInfo) {
|
||||
e := newExecutor(t)
|
||||
|
||||
ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
ctrNetmap := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
||||
ctrBalance := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
ctrContainer := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
ctrNNS := covertest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
ctrNetmap := covertest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
||||
ctrBalance := covertest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
ctrContainer := covertest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
|
||||
e.DeployContract(t, ctrNNS, nil)
|
||||
deployNetmapContract(t, e, ctrBalance.Hash, ctrContainer.Hash,
|
||||
e.DeployContract(t, ctrNNS.Contract, nil)
|
||||
deployNetmapContract(t, e, ctrBalance.Contract.Hash, ctrContainer.Contract.Hash,
|
||||
container.RegistrationFeeKey, int64(containerFee),
|
||||
container.AliasFeeKey, int64(containerAliasFee))
|
||||
deployBalanceContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
|
||||
deployContainerContract(t, e, ctrNetmap.Hash, ctrBalance.Hash, ctrNNS.Hash)
|
||||
h := deployFrostFSIDContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
|
||||
return e.CommitteeInvoker(h)
|
||||
deployBalanceContract(t, e, ctrNetmap.Contract.Hash, ctrContainer.Contract.Hash)
|
||||
deployContainerContract(t, e, ctrNetmap.Contract.Hash, ctrBalance.Contract.Hash, ctrNNS.Contract.Hash)
|
||||
h, c := deployFrostFSIDContract(t, e, ctrNetmap.Contract.Hash, ctrContainer.Contract.Hash)
|
||||
return covertest.CommitteeInvoker(e, h), c
|
||||
}
|
||||
|
||||
func TestFrostFSID_AddKey(t *testing.T) {
|
||||
e := newFrostFSIDInvoker(t)
|
||||
e, c := newFrostFSIDInvoker(t)
|
||||
|
||||
pubs := make([][]byte, 6)
|
||||
for i := range pubs {
|
||||
|
@ -108,4 +109,5 @@ func TestFrostFSID_AddKey(t *testing.T) {
|
|||
arr = []stackitem.Item{stackitem.NewBuffer(pubs[3])}
|
||||
e.Invoke(t, stackitem.NewArray(arr), "key", owner)
|
||||
})
|
||||
e.MakeCoverage(t, c, "frostfsid", "c.out")
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/covertest"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/netmap"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
|
@ -36,19 +37,19 @@ func deployNetmapContract(t *testing.T, e *neotest.Executor, addrBalance, addrCo
|
|||
return c.Hash
|
||||
}
|
||||
|
||||
func newNetmapInvoker(t *testing.T, config ...interface{}) *neotest.ContractInvoker {
|
||||
func newNetmapInvoker(t *testing.T, config ...interface{}) *covertest.ContractInvoker {
|
||||
e := newExecutor(t)
|
||||
|
||||
ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
ctrNetmap := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
||||
ctrBalance := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
ctrContainer := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
ctrNNS := covertest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||
ctrNetmap := covertest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
||||
ctrBalance := covertest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||
ctrContainer := covertest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||
|
||||
e.DeployContract(t, ctrNNS, nil)
|
||||
deployContainerContract(t, e, ctrNetmap.Hash, ctrBalance.Hash, ctrNNS.Hash)
|
||||
deployBalanceContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
|
||||
deployNetmapContract(t, e, ctrBalance.Hash, ctrContainer.Hash, config...)
|
||||
return e.CommitteeInvoker(ctrNetmap.Hash)
|
||||
e.DeployContract(t, ctrNNS.Contract, nil)
|
||||
deployContainerContract(t, e, ctrNetmap.Contract.Hash, ctrBalance.Contract.Hash, ctrNNS.Contract.Hash)
|
||||
deployBalanceContract(t, e, ctrNetmap.Contract.Hash, ctrContainer.Contract.Hash)
|
||||
deployNetmapContract(t, e, ctrBalance.Contract.Hash, ctrContainer.Contract.Hash, config...)
|
||||
return covertest.CommitteeInvoker(e, ctrNetmap.Contract.Hash)
|
||||
}
|
||||
|
||||
func TestDeploySetConfig(t *testing.T) {
|
||||
|
@ -80,7 +81,7 @@ func dummyNodeInfo(acc neotest.Signer) testNodeInfo {
|
|||
}
|
||||
}
|
||||
|
||||
func newStorageNode(t *testing.T, c *neotest.ContractInvoker) testNodeInfo {
|
||||
func newStorageNode(t *testing.T, c *covertest.ContractInvoker) testNodeInfo {
|
||||
return dummyNodeInfo(c.NewAccount(t))
|
||||
}
|
||||
|
||||
|
@ -173,7 +174,7 @@ func TestUpdateSnapshotCount(t *testing.T) {
|
|||
|
||||
require.True(t, netmap.DefaultSnapshotCount > 5) // sanity check, adjust tests if false.
|
||||
|
||||
prepare := func(t *testing.T, cNm *neotest.ContractInvoker, epochCount int) [][]testNodeInfo {
|
||||
prepare := func(t *testing.T, cNm *covertest.ContractInvoker, epochCount int) [][]testNodeInfo {
|
||||
nodes := make([][]testNodeInfo, epochCount)
|
||||
nodes[0] = []testNodeInfo{newStorageNode(t, cNm)}
|
||||
cNm.Invoke(t, stackitem.Null{}, "addPeerIR", nodes[0][0].raw)
|
||||
|
@ -279,7 +280,7 @@ func TestUpdateSnapshotCount(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func checkSnapshotAt(t *testing.T, epoch int, cNm *neotest.ContractInvoker, nodes []testNodeInfo) {
|
||||
func checkSnapshotAt(t *testing.T, epoch int, cNm *covertest.ContractInvoker, nodes []testNodeInfo) {
|
||||
s, err := cNm.TestInvoke(t, "snapshot", int64(epoch))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, s.Len())
|
||||
|
@ -402,7 +403,7 @@ func TestUpdateState(t *testing.T) {
|
|||
checkNetmapCandidates(t, cNm, 0)
|
||||
}
|
||||
|
||||
func checkNetmapCandidates(t *testing.T, c *neotest.ContractInvoker, size int) []stackitem.Item {
|
||||
func checkNetmapCandidates(t *testing.T, c *covertest.ContractInvoker, size int) []stackitem.Item {
|
||||
s, err := c.TestInvoke(t, "netmapCandidates")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, s.Len())
|
||||
|
|
Loading…
Add table
Reference in a new issue