nativetest: migrate Policy contract tests to neotest
This commit is contained in:
parent
48355ba9bf
commit
bbe92c21ea
5 changed files with 153 additions and 171 deletions
63
pkg/core/native/native_test/common_test.go
Normal file
63
pkg/core/native/native_test/common_test.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package native_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
func newNativeClient(t *testing.T, name string) *neotest.ContractInvoker {
|
||||
bc, acc := chain.NewSingle(t)
|
||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||
|
||||
return e.CommitteeInvoker(e.NativeHash(t, name))
|
||||
}
|
||||
|
||||
func testGetSet(t *testing.T, c *neotest.ContractInvoker, name string, defaultValue, minValue, maxValue int64) {
|
||||
getName := "get" + name
|
||||
setName := "set" + name
|
||||
|
||||
randomInvoker := c.WithSigners(c.NewAccount(t))
|
||||
committeeInvoker := c.WithSigners(c.Committee)
|
||||
|
||||
t.Run("set, not signed by committee", func(t *testing.T) {
|
||||
randomInvoker.InvokeFail(t, "invalid committee signature", setName, minValue+1)
|
||||
})
|
||||
t.Run("get, default value", func(t *testing.T) {
|
||||
randomInvoker.Invoke(t, defaultValue, getName)
|
||||
})
|
||||
t.Run("set, too small value", func(t *testing.T) {
|
||||
committeeInvoker.InvokeFail(t, "", setName, minValue-1)
|
||||
})
|
||||
|
||||
if maxValue != 0 {
|
||||
t.Run("set, too large value", func(t *testing.T) {
|
||||
// use big.Int because max can be `math.MaxInt64`
|
||||
max := big.NewInt(maxValue)
|
||||
max.Add(max, big.NewInt(1))
|
||||
committeeInvoker.InvokeFail(t, "", setName, max)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("set, success", func(t *testing.T) {
|
||||
// Set and get in the same block.
|
||||
txSet := committeeInvoker.PrepareInvoke(t, setName, defaultValue+1)
|
||||
txGet := randomInvoker.PrepareInvoke(t, getName)
|
||||
c.AddNewBlock(t, txSet, txGet)
|
||||
c.CheckHalt(t, txSet.Hash(), stackitem.Null{})
|
||||
|
||||
if name != "GasPerBlock" { // GasPerBlock is set on the next block
|
||||
c.CheckHalt(t, txGet.Hash(), stackitem.Make(defaultValue+1))
|
||||
} else {
|
||||
c.CheckHalt(t, txGet.Hash(), stackitem.Make(defaultValue))
|
||||
c.AddNewBlock(t)
|
||||
randomInvoker.Invoke(t, defaultValue+1, getName)
|
||||
}
|
||||
|
||||
// Get in the next block.
|
||||
randomInvoker.Invoke(t, defaultValue+1, getName)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package policyhelper
|
||||
|
||||
func Do() bool {
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
name: "Policy helper contract"
|
||||
sourceurl: https://github.com/nspcc-dev/neo-go
|
||||
supportedstandards: []
|
||||
safemethods: ["do"]
|
81
pkg/core/native/native_test/policy_test.go
Normal file
81
pkg/core/native/native_test/policy_test.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package native_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
func newPolicyClient(t *testing.T) *neotest.ContractInvoker {
|
||||
return newNativeClient(t, nativenames.Policy)
|
||||
}
|
||||
|
||||
func TestPolicy_FeePerByte(t *testing.T) {
|
||||
testGetSet(t, newPolicyClient(t), "FeePerByte", 1000, 0, 100_000_000)
|
||||
}
|
||||
|
||||
func TestPolicy_ExecFeeFactor(t *testing.T) {
|
||||
testGetSet(t, newPolicyClient(t), "ExecFeeFactor", interop.DefaultBaseExecFee, 1, 1000)
|
||||
}
|
||||
|
||||
func TestPolicy_StoragePrice(t *testing.T) {
|
||||
testGetSet(t, newPolicyClient(t), "StoragePrice", native.DefaultStoragePrice, 1, 10000000)
|
||||
}
|
||||
|
||||
func TestPolicy_BlockedAccounts(t *testing.T) {
|
||||
c := newPolicyClient(t)
|
||||
e := c.Executor
|
||||
randomInvoker := c.WithSigners(c.NewAccount(t))
|
||||
committeeInvoker := c.WithSigners(c.Committee)
|
||||
unlucky := util.Uint160{1, 2, 3}
|
||||
|
||||
t.Run("isBlocked", func(t *testing.T) {
|
||||
randomInvoker.Invoke(t, false, "isBlocked", unlucky)
|
||||
})
|
||||
|
||||
t.Run("block-unblock account", func(t *testing.T) {
|
||||
committeeInvoker.Invoke(t, true, "blockAccount", unlucky)
|
||||
randomInvoker.Invoke(t, true, "isBlocked", unlucky)
|
||||
committeeInvoker.Invoke(t, true, "unblockAccount", unlucky)
|
||||
randomInvoker.Invoke(t, false, "isBlocked", unlucky)
|
||||
})
|
||||
|
||||
t.Run("double-block", func(t *testing.T) {
|
||||
// block
|
||||
committeeInvoker.Invoke(t, true, "blockAccount", unlucky)
|
||||
|
||||
// double-block should fail
|
||||
committeeInvoker.Invoke(t, false, "blockAccount", unlucky)
|
||||
|
||||
// unblock
|
||||
committeeInvoker.Invoke(t, true, "unblockAccount", unlucky)
|
||||
|
||||
// unblock the same account should fail as we don't have it blocked
|
||||
committeeInvoker.Invoke(t, false, "unblockAccount", unlucky)
|
||||
})
|
||||
|
||||
t.Run("not signed by committee", func(t *testing.T) {
|
||||
randomInvoker.InvokeFail(t, "invalid committee signature", "blockAccount", unlucky)
|
||||
randomInvoker.InvokeFail(t, "invalid committee signature", "unblockAccount", unlucky)
|
||||
})
|
||||
|
||||
t.Run("block-unblock contract", func(t *testing.T) {
|
||||
committeeInvoker.InvokeFail(t, "cannot block native contract", "blockAccount", c.NativeHash(t, nativenames.Neo))
|
||||
|
||||
helper := neotest.CompileFile(t, c.CommitteeHash, "./helpers/policyhelper", "./helpers/policyhelper/policyhelper.yml")
|
||||
e.DeployContract(t, helper, nil)
|
||||
helperInvoker := e.CommitteeInvoker(helper.Hash)
|
||||
|
||||
helperInvoker.Invoke(t, true, "do")
|
||||
committeeInvoker.Invoke(t, true, "blockAccount", helper.Hash)
|
||||
helperInvoker.InvokeFail(t, fmt.Sprintf("contract %s is blocked", helper.Hash.StringLE()), "do")
|
||||
|
||||
committeeInvoker.Invoke(t, true, "unblockAccount", helper.Hash)
|
||||
helperInvoker.Invoke(t, true, "do")
|
||||
})
|
||||
}
|
|
@ -1,16 +1,12 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/internal/testchain"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -19,68 +15,6 @@ func transferFundsToCommittee(t *testing.T, chain *Blockchain) {
|
|||
chain.contracts.GAS.Hash, 1000_00000000)
|
||||
}
|
||||
|
||||
func testGetSet(t *testing.T, chain *Blockchain, hash util.Uint160, name string, defaultValue, minValue, maxValue int64) {
|
||||
getName := "get" + name
|
||||
setName := "set" + name
|
||||
|
||||
transferFundsToCommittee(t, chain)
|
||||
t.Run("set, not signed by committee", func(t *testing.T) {
|
||||
signer, err := wallet.NewAccount()
|
||||
require.NoError(t, err)
|
||||
invokeRes, err := invokeContractMethodBy(t, chain, signer, hash, setName, minValue+1)
|
||||
require.NoError(t, err)
|
||||
checkFAULTState(t, invokeRes)
|
||||
})
|
||||
|
||||
t.Run("get, defult value", func(t *testing.T) {
|
||||
res, err := invokeContractMethod(chain, 100000000, hash, getName)
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.Make(defaultValue))
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("set, too small value", func(t *testing.T) {
|
||||
res, err := invokeContractMethodGeneric(chain, 100000000, hash, setName, true, minValue-1)
|
||||
require.NoError(t, err)
|
||||
checkFAULTState(t, res)
|
||||
})
|
||||
|
||||
if maxValue != 0 {
|
||||
t.Run("set, too large value", func(t *testing.T) {
|
||||
// use big.Int because max can be `math.MaxInt64`
|
||||
max := big.NewInt(maxValue)
|
||||
max.Add(max, big.NewInt(1))
|
||||
res, err := invokeContractMethodGeneric(chain, 100000000, hash, setName, true, max)
|
||||
require.NoError(t, err)
|
||||
checkFAULTState(t, res)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("set, success", func(t *testing.T) {
|
||||
// Set and get in the same block.
|
||||
txSet, err := prepareContractMethodInvokeGeneric(chain, 100000000, hash, setName, true, defaultValue+1)
|
||||
require.NoError(t, err)
|
||||
txGet1, err := prepareContractMethodInvoke(chain, 100000000, hash, getName)
|
||||
require.NoError(t, err)
|
||||
aers, err := persistBlock(chain, txSet, txGet1)
|
||||
require.NoError(t, err)
|
||||
checkResult(t, aers[0], stackitem.Null{})
|
||||
if name != "GasPerBlock" { // GasPerBlock is set on the next block
|
||||
checkResult(t, aers[1], stackitem.Make(defaultValue+1))
|
||||
}
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get in the next block.
|
||||
res, err := invokeContractMethod(chain, 100000000, hash, getName)
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.Make(defaultValue+1))
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFeePerByte(t *testing.T) {
|
||||
chain := newTestChain(t)
|
||||
|
||||
|
@ -88,8 +22,6 @@ func TestFeePerByte(t *testing.T) {
|
|||
n := chain.contracts.Policy.GetFeePerByteInternal(chain.dao)
|
||||
require.Equal(t, 1000, int(n))
|
||||
})
|
||||
|
||||
testGetSet(t, chain, chain.contracts.Policy.Hash, "FeePerByte", 1000, 0, 100_000_000)
|
||||
}
|
||||
|
||||
func TestExecFeeFactor(t *testing.T) {
|
||||
|
@ -99,8 +31,6 @@ func TestExecFeeFactor(t *testing.T) {
|
|||
n := chain.contracts.Policy.GetExecFeeFactorInternal(chain.dao)
|
||||
require.EqualValues(t, interop.DefaultBaseExecFee, n)
|
||||
})
|
||||
|
||||
testGetSet(t, chain, chain.contracts.Policy.Hash, "ExecFeeFactor", interop.DefaultBaseExecFee, 1, 1000)
|
||||
}
|
||||
|
||||
func TestStoragePrice(t *testing.T) {
|
||||
|
@ -110,15 +40,10 @@ func TestStoragePrice(t *testing.T) {
|
|||
n := chain.contracts.Policy.GetStoragePriceInternal(chain.dao)
|
||||
require.Equal(t, int64(native.DefaultStoragePrice), n)
|
||||
})
|
||||
|
||||
testGetSet(t, chain, chain.contracts.Policy.Hash, "StoragePrice", native.DefaultStoragePrice, 1, 10000000)
|
||||
}
|
||||
|
||||
func TestBlockedAccounts(t *testing.T) {
|
||||
chain := newTestChain(t)
|
||||
account := util.Uint160{1, 2, 3}
|
||||
policyHash := chain.contracts.Policy.Metadata().Hash
|
||||
|
||||
transferTokenFromMultisigAccount(t, chain, testchain.CommitteeScriptHash(),
|
||||
chain.contracts.GAS.Hash, 100_00000000)
|
||||
|
||||
|
@ -126,100 +51,4 @@ func TestBlockedAccounts(t *testing.T) {
|
|||
isBlocked := chain.contracts.Policy.IsBlockedInternal(chain.dao, random.Uint160())
|
||||
require.Equal(t, false, isBlocked)
|
||||
})
|
||||
|
||||
t.Run("isBlocked, contract method", func(t *testing.T) {
|
||||
res, err := invokeContractMethod(chain, 100000000, policyHash, "isBlocked", random.Uint160())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(false))
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("block-unblock account", func(t *testing.T) {
|
||||
res, err := invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(true))
|
||||
|
||||
isBlocked := chain.contracts.Policy.IsBlockedInternal(chain.dao, account)
|
||||
require.Equal(t, isBlocked, true)
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "unblockAccount", true, account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(true))
|
||||
|
||||
isBlocked = chain.contracts.Policy.IsBlockedInternal(chain.dao, account)
|
||||
require.Equal(t, false, isBlocked)
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("double-block", func(t *testing.T) {
|
||||
// block
|
||||
res, err := invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(true))
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// double-block should fail
|
||||
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(false))
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// unblock
|
||||
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "unblockAccount", true, account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(true))
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
|
||||
// unblock the same account should fail as we don't have it blocked
|
||||
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "unblockAccount", true, account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(false))
|
||||
_, err = chain.persist(false)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("not signed by committee", func(t *testing.T) {
|
||||
signer, err := wallet.NewAccount()
|
||||
require.NoError(t, err)
|
||||
invokeRes, err := invokeContractMethodBy(t, chain, signer, policyHash, "blockAccount", account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkFAULTState(t, invokeRes)
|
||||
|
||||
invokeRes, err = invokeContractMethodBy(t, chain, signer, policyHash, "unblockAccount", account.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkFAULTState(t, invokeRes)
|
||||
})
|
||||
|
||||
t.Run("block-unblock contract", func(t *testing.T) {
|
||||
neoHash := chain.contracts.NEO.Metadata().Hash
|
||||
res, err := invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, neoHash.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkFAULTState(t, res)
|
||||
|
||||
cs, _ := getTestContractState(chain)
|
||||
require.NoError(t, chain.contracts.Management.PutContractState(chain.dao, cs))
|
||||
|
||||
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "blockAccount", true, cs.Hash.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(true))
|
||||
|
||||
res, err = invokeContractMethod(chain, 100000000, cs.Hash, "justReturn")
|
||||
require.NoError(t, err)
|
||||
checkFAULTState(t, res)
|
||||
|
||||
res, err = invokeContractMethodGeneric(chain, 100000000, policyHash, "unblockAccount", true, cs.Hash.BytesBE())
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.NewBool(true))
|
||||
|
||||
res, err = invokeContractMethod(chain, 100000000, cs.Hash, "justReturn")
|
||||
require.NoError(t, err)
|
||||
checkResult(t, res, stackitem.Null{})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue