[#161] tests: reuse neo-go testing framework

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2021-10-26 14:28:14 +03:00 committed by Alex Vanin
parent 63673a5e54
commit 8553320e1c
10 changed files with 324 additions and 779 deletions

3
go.mod
View file

@ -4,7 +4,6 @@ go 1.14
require (
github.com/mr-tron/base58 v1.2.0
github.com/nspcc-dev/neo-go v0.97.2
github.com/nspcc-dev/neo-go v0.97.4-pre.0.20211115125313-0e1fe2f58b1a
github.com/stretchr/testify v1.7.0
go.uber.org/zap v1.18.1
)

31
go.sum
View file

@ -5,13 +5,9 @@ github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1
github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig=
github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I=
github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA=
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA=
github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig=
github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A=
github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs=
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530=
@ -22,12 +18,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI=
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
github.com/alicebob/miniredis/v2 v2.15.1 h1:Fw+ixAJPmKhCLBqDwHlTDqxUxp0xjEwXczEpt1B6r7k=
github.com/alicebob/miniredis/v2 v2.15.1/go.mod h1:gquAfGbzn92jvtrSC69+6zZnwSODVXVpYDRaGhWaL6I=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@ -71,13 +62,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/dgraph-io/badger/v2 v2.0.3 h1:inzdf6VF/NZ+tJ8RwwYMjJMvsOALTHYdozn0qSl6XJI=
github.com/dgraph-io/badger/v2 v2.0.3/go.mod h1:3KY8+bsP8wI0OEnQJAKpd4wIJW/Mm32yw2j/9FUVnIM=
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3 h1:MQLRM35Pp0yAyBYksjbj1nZI/w6eyRY/mWoM1sFf4kU=
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@ -97,8 +84,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -185,13 +170,17 @@ github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62pr
github.com/nspcc-dev/dbft v0.0.0-20200711144034-c526ccc6f570/go.mod h1:1FYQXSbb6/9HQIkoF8XO7W/S8N7AZRkBsgwbcXRvk0E=
github.com/nspcc-dev/dbft v0.0.0-20210302103605-cc75991b7cfb/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y=
github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y=
github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02 h1:JgRx27vfGw5WV5QbaNDy0iy2WD1XJO964wwAapaYKLg=
github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U=
github.com/nspcc-dev/hrw v1.0.9 h1:17VcAuTtrstmFppBjfRiia4K2wA/ukXZhLFS8Y8rz5Y=
github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU=
github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg=
github.com/nspcc-dev/neo-go v0.91.0/go.mod h1:G6HdOWvzQ6tlvFdvFSN/PgCzLPN/X/X4d5hTjFRUDcc=
github.com/nspcc-dev/neo-go v0.95.1/go.mod h1:bW07ge1WFXsBgqrcPpLUr6OcyQxHqM26MZNesWMdH0c=
github.com/nspcc-dev/neo-go v0.97.2 h1:oENXAc0ORjfYfFVyHy6aMyMLTosZsmSGeKgOvYGN3Eg=
github.com/nspcc-dev/neo-go v0.97.2/go.mod h1:yguwQBpWMTHx07INKoElJT8Gga1LUdTSi0gT75ywJ68=
github.com/nspcc-dev/neo-go v0.97.4-pre.0.20211111084655-0a7f8afcea5d h1:h3duQCMpHn0Vq1qeKYVdK5RQyNPu8JfpUrC9S9EsLZU=
github.com/nspcc-dev/neo-go v0.97.4-pre.0.20211111084655-0a7f8afcea5d/go.mod h1:i6TJVL2vwddNlP1CftD0b8qZ2mcTi9DzYxOlxkXxgg0=
github.com/nspcc-dev/neo-go v0.97.4-pre.0.20211115125313-0e1fe2f58b1a h1:H8BHO5syx7qT6LrRwLPbWunQCeaaveAnjunBiK1XGzg=
github.com/nspcc-dev/neo-go v0.97.4-pre.0.20211115125313-0e1fe2f58b1a/go.mod h1:i6TJVL2vwddNlP1CftD0b8qZ2mcTi9DzYxOlxkXxgg0=
github.com/nspcc-dev/neofs-api-go v1.24.0/go.mod h1:G7dqincfdjBrAbL5nxVp82emF05fSVEqe59ICsoRDI8=
github.com/nspcc-dev/neofs-api-go v1.27.1 h1:ONdKOnm0/hK6m38VTUliCHY6RTxg+IpAzY4G+BeOZG4=
github.com/nspcc-dev/neofs-api-go v1.27.1/go.mod h1:i0Cwgvcu9A4M4e58pydbXFisUhSxpfljmuWFPIp2btE=
@ -217,7 +206,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -277,8 +265,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs=
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
github.com/twmb/murmur3 v1.1.5 h1:i9OLS9fkuLzBXjt6dptlAEyk58fJsSTXbRg3SgVyqgk=
github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@ -291,8 +277,6 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da h1:NimzV1aGyq29m5ukMK0AMWEhFaL/lrEOaephfuoiARg=
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
@ -353,8 +337,9 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View file

@ -1,24 +1,28 @@
package tests
import (
"path"
"testing"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
const balancePath = "../balance"
func deployBalanceContract(t *testing.T, bc *core.Blockchain, addrNetmap, addrContainer util.Uint160) util.Uint160 {
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"))
args := make([]interface{}, 3)
args[0] = false
args[1] = addrNetmap
args[2] = addrContainer
return DeployContract(t, bc, balancePath, args)
e.DeployContract(t, c, args)
return c.Hash
}
func balanceMint(t *testing.T, bc *core.Blockchain, acc *wallet.Account, h util.Uint160, amount int64, details []byte) {
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "mint", acc.Contract.ScriptHash(), amount, details)
AddBlockCheckHalt(t, bc, tx)
func balanceMint(t *testing.T, c *neotest.ContractInvoker, acc neotest.Signer, amount int64, details []byte) {
c.Invoke(t, stackitem.Null{}, "mint", acc.ScriptHash(), amount, details)
}

View file

@ -1,282 +0,0 @@
package tests
import (
"encoding/hex"
"encoding/json"
"math/rand"
"strings"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"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/fee"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"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/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)
const validatorWIF = "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY"
// CommitteeAcc is an account used to sign tx as a committee.
var CommitteeAcc *wallet.Account
func init() {
CommitteeAcc, _ = wallet.NewAccountFromWIF(validatorWIF)
pubs := keys.PublicKeys{CommitteeAcc.PrivateKey().PublicKey()}
err := CommitteeAcc.ConvertMultisig(1, pubs)
if err != nil {
panic(err)
}
}
var _nonce uint32
func nonce() uint32 {
_nonce++
return _nonce
}
// NewChain creates new blockchain instance with a single validator and
// setups cleanup functions.
func NewChain(t *testing.T) *core.Blockchain {
protoCfg := config.ProtocolConfiguration{
Magic: netmode.UnitTestNet,
P2PSigExtensions: true,
SecondsPerBlock: 1,
StandbyCommittee: []string{hex.EncodeToString(CommitteeAcc.PrivateKey().PublicKey().Bytes())},
ValidatorsCount: 1,
VerifyBlocks: true,
VerifyTransactions: true,
}
st := storage.NewMemoryStore()
log := zaptest.NewLogger(t)
bc, err := core.NewBlockchain(st, protoCfg, log)
require.NoError(t, err)
go bc.Run()
t.Cleanup(bc.Close)
return bc
}
// PrepareInvoke creates new invocation transaction.
// Signer can be either bool or *wallet.Account.
// In the first case `true` means sign by committee, `false` means sign by validators.
func PrepareInvoke(t *testing.T, bc *core.Blockchain, signer interface{},
hash util.Uint160, method string, args ...interface{}) *transaction.Transaction {
w := io.NewBufBinWriter()
emit.AppCall(w.BinWriter, hash, method, callflag.All, args...)
require.NoError(t, w.Err)
script := w.Bytes()
tx := transaction.New(script, 0)
tx.Nonce = nonce()
tx.ValidUntilBlock = bc.BlockHeight() + 1
switch s := signer.(type) {
case *wallet.Account:
tx.Signers = append(tx.Signers, transaction.Signer{
Account: s.Contract.ScriptHash(),
Scopes: transaction.Global,
})
require.NoError(t, addNetworkFee(bc, tx, s))
require.NoError(t, addSystemFee(bc, tx))
require.NoError(t, s.SignTx(netmode.UnitTestNet, tx))
case []*wallet.Account:
for _, acc := range s {
tx.Signers = append(tx.Signers, transaction.Signer{
Account: acc.Contract.ScriptHash(),
Scopes: transaction.Global,
})
require.NoError(t, addNetworkFee(bc, tx, acc))
}
require.NoError(t, addSystemFee(bc, tx))
for _, acc := range s {
require.NoError(t, acc.SignTx(netmode.UnitTestNet, tx))
}
default:
panic("invalid signer")
}
return tx
}
// NewAccount creates new account and transfers 100.0 GAS to it.
func NewAccount(t *testing.T, bc *core.Blockchain) *wallet.Account {
acc, err := wallet.NewAccount()
require.NoError(t, err)
tx := PrepareInvoke(t, bc, CommitteeAcc,
bc.UtilityTokenHash(), "transfer",
CommitteeAcc.Contract.ScriptHash(), acc.Contract.ScriptHash(), int64(100_0000_0000), nil)
AddBlock(t, bc, tx)
CheckHalt(t, bc, tx.Hash())
return acc
}
// DeployContract compiles and deploys contract to bc.
// path should contain Go source files.
// data is an optional argument to `_deploy`.
func DeployContract(t *testing.T, bc *core.Blockchain, path string, data interface{}) util.Uint160 {
tx, h := newDeployTx(t, bc, path, data)
AddBlock(t, bc, tx)
CheckHalt(t, bc, tx.Hash())
return h
}
// CheckHalt checks that transaction persisted with HALT state.
func CheckHalt(t *testing.T, bc *core.Blockchain, h util.Uint256, stack ...stackitem.Item) *state.AppExecResult {
aer, err := bc.GetAppExecResults(h, trigger.Application)
require.NoError(t, err)
require.Equal(t, vm.HaltState, aer[0].VMState, aer[0].FaultException)
if len(stack) != 0 {
require.Equal(t, stack, aer[0].Stack)
}
return &aer[0]
}
// CheckFault checks that transaction persisted with FAULT state.
// Raised exception is also checked to contain s as a substring.
func CheckFault(t *testing.T, bc *core.Blockchain, h util.Uint256, s string) {
aer, err := bc.GetAppExecResults(h, trigger.Application)
require.NoError(t, err)
require.Equal(t, vm.FaultState, aer[0].VMState)
require.True(t, strings.Contains(aer[0].FaultException, s),
"expected: %s, got: %s", s, aer[0].FaultException)
}
// newDeployTx returns new deployment tx for contract.
func newDeployTx(t *testing.T, bc *core.Blockchain, ctrPath string, data interface{}) (*transaction.Transaction, util.Uint160) {
c, err := ContractInfo(CommitteeAcc.Contract.ScriptHash(), ctrPath)
require.NoError(t, err)
rawManifest, err := json.Marshal(c.Manifest)
require.NoError(t, err)
neb, err := c.NEF.Bytes()
require.NoError(t, err)
buf := io.NewBufBinWriter()
emit.AppCall(buf.BinWriter, bc.ManagementContractHash(), "deploy", callflag.All, neb, rawManifest, data)
require.NoError(t, buf.Err)
tx := transaction.New(buf.Bytes(), 100*native.GASFactor)
tx.Nonce = nonce()
tx.ValidUntilBlock = bc.BlockHeight() + 1
tx.Signers = []transaction.Signer{{
Account: CommitteeAcc.Contract.ScriptHash(),
Scopes: transaction.Global,
}}
require.NoError(t, addNetworkFee(bc, tx, CommitteeAcc))
require.NoError(t, CommitteeAcc.SignTx(netmode.UnitTestNet, tx))
return tx, c.Hash
}
func addSystemFee(bc *core.Blockchain, tx *transaction.Transaction) error {
v, _ := TestInvoke(bc, tx) // ignore error to support failing transactions
tx.SystemFee = v.GasConsumed()
return nil
}
func addNetworkFee(bc *core.Blockchain, tx *transaction.Transaction, sender *wallet.Account) error {
size := io.GetVarSize(tx)
netFee, sizeDelta := fee.Calculate(bc.GetBaseExecFee(), sender.Contract.Script)
tx.NetworkFee += netFee
size += sizeDelta
for _, cosigner := range tx.Signers {
contract := bc.GetContractState(cosigner.Account)
if contract != nil {
netFee, sizeDelta = fee.Calculate(bc.GetBaseExecFee(), contract.NEF.Script)
tx.NetworkFee += netFee
size += sizeDelta
}
}
tx.NetworkFee += int64(size) * bc.FeePerByte()
return nil
}
// AddBlock creates a new block from provided transactions and adds it on bc.
func AddBlock(t *testing.T, bc *core.Blockchain, txs ...*transaction.Transaction) *block.Block {
return addCustomBlock(t, bc, nil, txs...)
}
func addCustomBlock(t *testing.T, bc *core.Blockchain, blockFunc func(*block.Block), txs ...*transaction.Transaction) *block.Block {
lastBlock, err := bc.GetBlock(bc.GetHeaderHash(int(bc.BlockHeight())))
require.NoError(t, err)
b := &block.Block{
Header: block.Header{
NextConsensus: CommitteeAcc.Contract.ScriptHash(),
Script: transaction.Witness{
VerificationScript: CommitteeAcc.Contract.Script,
},
Timestamp: lastBlock.Timestamp + 1,
},
Transactions: txs,
}
b.PrevHash = lastBlock.Hash()
b.Index = bc.BlockHeight() + 1
b.RebuildMerkleRoot()
if blockFunc != nil {
blockFunc(b)
}
sign := CommitteeAcc.PrivateKey().SignHashable(uint32(netmode.UnitTestNet), b)
b.Script.InvocationScript = append([]byte{byte(opcode.PUSHDATA1), 64}, sign...)
require.NoError(t, bc.AddBlock(b))
return b
}
// AddBlockCheckHalt is a convenient wrapper over AddBlock and CheckHalt.
func AddBlockCheckHalt(t *testing.T, bc *core.Blockchain, txs ...*transaction.Transaction) *block.Block {
b := AddBlock(t, bc, txs...)
for _, tx := range txs {
CheckHalt(t, bc, tx.Hash())
}
return b
}
// CheckTestInvoke executes transaction without persisting it's state and
// compares the result with the expected.
func CheckTestInvoke(t *testing.T, bc *core.Blockchain, tx *transaction.Transaction, expected interface{}) {
v, err := TestInvoke(bc, tx)
require.NoError(t, err)
require.Equal(t, 1, v.Estack().Len())
require.Equal(t, stackitem.Make(expected), v.Estack().Pop().Item())
}
// TestInvoke creates a test VM with dummy block and executes transaction in it.
func TestInvoke(bc *core.Blockchain, tx *transaction.Transaction) (*vm.VM, error) {
lastBlock, err := bc.GetBlock(bc.GetHeaderHash(int(bc.BlockHeight())))
if err != nil {
return nil, err
}
b := &block.Block{Header: block.Header{
Index: bc.BlockHeight() + 1,
Timestamp: lastBlock.Timestamp + 1,
}}
v := bc.GetTestVM(trigger.Application, tx, b)
v.LoadWithFlags(tx.Script, callflag.All)
err = v.Run()
return v, err
}
func randomBytes(n int) []byte {
a := make([]byte, n)
rand.Read(a)
return a
}

View file

@ -1,69 +0,0 @@
package tests
import (
"path"
"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/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// Contract contains contract info for deployment.
type Contract struct {
Hash util.Uint160
NEF *nef.File
Manifest *manifest.Manifest
}
var contracts = map[string]*Contract{}
// ContractInfo compiles contract and returns it's NEF, manifest and hash.
func ContractInfo(sender util.Uint160, ctrPath string) (*Contract, error) {
if c, ok := contracts[ctrPath]; ok {
return c, nil
}
// nef.NewFile() cares about version a lot.
config.Version = "0.90.0-test"
avm, di, err := compiler.CompileWithDebugInfo(ctrPath, nil)
if err != nil {
return nil, err
}
ne, err := nef.NewFile(avm)
if err != nil {
return nil, err
}
conf, err := smartcontract.ParseContractConfig(path.Join(ctrPath, "config.yml"))
if err != nil {
return nil, 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
m, err := compiler.CreateManifest(di, o)
if err != nil {
return nil, err
}
c := &Contract{
Hash: state.CreateContractHash(sender, ne.Checksum, m.Name),
NEF: ne,
Manifest: m,
}
contracts[ctrPath] = c
return c, nil
}

View file

@ -2,17 +2,16 @@ package tests
import (
"crypto/sha256"
"strings"
"path"
"testing"
"github.com/mr-tron/base58"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"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"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neofs-contract/container"
"github.com/nspcc-dev/neofs-contract/nns"
"github.com/stretchr/testify/require"
)
const containerPath = "../container"
@ -22,7 +21,7 @@ const (
containerAliasFee = 0_0050_0000
)
func deployContainerContract(t *testing.T, bc *core.Blockchain, addrNetmap, addrBalance, addrNNS util.Uint160) util.Uint160 {
func deployContainerContract(t *testing.T, e *neotest.Executor, addrNetmap, addrBalance, addrNNS util.Uint160) util.Uint160 {
args := make([]interface{}, 6)
args[0] = int64(0)
args[1] = addrNetmap
@ -30,30 +29,31 @@ func deployContainerContract(t *testing.T, bc *core.Blockchain, addrNetmap, addr
args[3] = util.Uint160{} // not needed for now
args[4] = addrNNS
args[5] = "neofs"
return DeployContract(t, bc, containerPath, args)
c := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
e.DeployContract(t, c, args)
return c.Hash
}
func prepareContainerContract(t *testing.T, bc *core.Blockchain) (util.Uint160, util.Uint160) {
addrNNS := DeployContract(t, bc, nnsPath, nil)
func newContainerInvoker(t *testing.T) (*neotest.ContractInvoker, *neotest.ContractInvoker) {
e := newExecutor(t)
ctrNetmap, err := ContractInfo(CommitteeAcc.Contract.ScriptHash(), netmapPath)
require.NoError(t, err)
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"))
ctrBalance, err := ContractInfo(CommitteeAcc.Contract.ScriptHash(), balancePath)
require.NoError(t, err)
ctrContainer, err := ContractInfo(CommitteeAcc.Contract.ScriptHash(), containerPath)
require.NoError(t, err)
deployNetmapContract(t, bc, ctrBalance.Hash, ctrContainer.Hash,
e.DeployContract(t, ctrNNS, nil)
deployNetmapContract(t, e, ctrBalance.Hash, ctrContainer.Hash,
container.RegistrationFeeKey, int64(containerFee),
container.AliasFeeKey, int64(containerAliasFee))
balHash := deployBalanceContract(t, bc, ctrNetmap.Hash, ctrContainer.Hash)
return deployContainerContract(t, bc, ctrNetmap.Hash, ctrBalance.Hash, addrNNS), balHash
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)
}
func setContainerOwner(c []byte, acc *wallet.Account) {
owner, _ := base58.Decode(acc.Address)
func setContainerOwner(c []byte, acc neotest.Signer) {
owner, _ := base58.Decode(address.Uint160ToString(acc.ScriptHash()))
copy(c[6:], owner)
}
@ -62,7 +62,7 @@ type testContainer struct {
value, sig, pub, token []byte
}
func dummyContainer(owner *wallet.Account) testContainer {
func dummyContainer(owner neotest.Signer) testContainer {
value := randomBytes(100)
value[1] = 0 // zero offset
setContainerOwner(value, owner)
@ -77,179 +77,146 @@ func dummyContainer(owner *wallet.Account) testContainer {
}
func TestContainerPut(t *testing.T) {
bc := NewChain(t)
h, balanceHash := prepareContainerContract(t, bc)
c, cBal := newContainerInvoker(t)
acc := NewAccount(t, bc)
c := dummyContainer(acc)
acc := c.NewAccount(t)
cnt := dummyContainer(acc)
putArgs := []interface{}{c.value, c.sig, c.pub, c.token}
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "put", putArgs...)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "insufficient balance to create container")
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token}
c.InvokeFail(t, "insufficient balance to create container", "put", putArgs...)
balanceMint(t, bc, acc, balanceHash, containerFee*1, []byte{})
balanceMint(t, cBal, acc, containerFee*1, []byte{})
tx = PrepareInvoke(t, bc, acc, h, "put", putArgs...)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "alphabet witness check failed")
cAcc := c.WithSigners(acc)
cAcc.InvokeFail(t, "alphabet witness check failed", "put", putArgs...)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "put", putArgs...)
AddBlockCheckHalt(t, bc, tx)
c.Invoke(t, stackitem.Null{}, "put", putArgs...)
t.Run("with nice names", func(t *testing.T) {
nnsHash := contracts[nnsPath].Hash
ctrNNS := neotest.CompileFile(t, c.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
nnsHash := ctrNNS.Hash
balanceMint(t, bc, acc, balanceHash, containerFee*1, []byte{})
balanceMint(t, cBal, acc, containerFee*1, []byte{})
putArgs := []interface{}{c.value, c.sig, c.pub, c.token, "mycnt", ""}
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token, "mycnt", ""}
t.Run("no fee for alias", func(t *testing.T) {
tx = PrepareInvoke(t, bc, acc, h, "putNamed", putArgs...)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "insufficient balance to create container")
c.InvokeFail(t, "insufficient balance to create container", "putNamed", putArgs...)
})
balanceMint(t, bc, acc, balanceHash, containerAliasFee*1, []byte{})
balanceMint(t, cBal, acc, containerAliasFee*1, []byte{})
c.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "putNamed", putArgs...)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, nnsHash, "resolve", "mycnt.neofs", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte(base58.Encode(c.id[:]))),
}))
expected := stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte(base58.Encode(cnt.id[:]))),
})
cNNS := c.CommitteeInvoker(nnsHash)
cNNS.Invoke(t, expected, "resolve", "mycnt.neofs", int64(nns.TXT))
t.Run("name is already taken", func(t *testing.T) {
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "putNamed", putArgs...)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "name is already taken")
c.InvokeFail(t, "name is already taken", "putNamed", putArgs...)
})
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "delete", c.id[:], c.sig, c.token)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, nnsHash, "resolve", "mycnt.neofs", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, stackitem.Null{})
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.token)
cNNS.Invoke(t, stackitem.Null{}, "resolve", "mycnt.neofs", int64(nns.TXT))
t.Run("register in advance", func(t *testing.T) {
c.value[len(c.value)-1] = 10
c.id = sha256.Sum256(c.value)
cnt.value[len(cnt.value)-1] = 10
cnt.id = sha256.Sum256(cnt.value)
t.Run("bad domain owner", func(t *testing.T) {
tx = PrepareInvoke(t, bc, []*wallet.Account{acc, CommitteeAcc}, nnsHash, "register",
"baddomain.neofs", acc.Contract.ScriptHash(),
c1 := cNNS.WithSigners(acc, c.Committee)
c1.Invoke(t, true, "register",
"baddomain.neofs", acc.ScriptHash(),
"whateveriwant@world.com", int64(0), int64(0), int64(0), int64(0))
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "putNamed",
c.value, c.sig, c.pub, c.token, "baddomain", "neofs")
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "committee or container contract must own registered domain")
cAcc.InvokeFail(t, "committee or container contract must own registered domain",
"putNamed",
cnt.value, cnt.sig, cnt.pub, cnt.token, "baddomain", "neofs")
})
tx = PrepareInvoke(t, bc, CommitteeAcc, nnsHash, "register",
"second.neofs", CommitteeAcc.Contract.ScriptHash(),
cNNS.Invoke(t, true, "register",
"second.neofs", c.CommitteeHash,
"whateveriwant@world.com", int64(0), int64(0), int64(0), int64(0))
AddBlockCheckHalt(t, bc, tx)
balanceMint(t, bc, acc, balanceHash, (containerFee+containerAliasFee)*1, []byte{})
balanceMint(t, cBal, acc, (containerFee+containerAliasFee)*1, []byte{})
putArgs := []interface{}{c.value, c.sig, c.pub, c.token, "second", "neofs"}
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "putNamed", putArgs...)
AddBlockCheckHalt(t, bc, tx)
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token, "second", "neofs"}
c2 := c.WithSigners(c.Committee, acc)
c2.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
tx = PrepareInvoke(t, bc, CommitteeAcc, nnsHash, "resolve", "second.neofs", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte(base58.Encode(c.id[:]))),
}))
expected = stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte(base58.Encode(cnt.id[:])))})
cNNS.Invoke(t, expected, "resolve", "second.neofs", int64(nns.TXT))
})
})
}
func TestContainerDelete(t *testing.T) {
bc := NewChain(t)
h, balanceHash := prepareContainerContract(t, bc)
c, cBal := newContainerInvoker(t)
acc := NewAccount(t, bc)
c := dummyContainer(acc)
acc := c.NewAccount(t)
cnt := dummyContainer(acc)
balanceMint(t, bc, acc, balanceHash, containerFee*1, []byte{})
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "put",
c.value, c.sig, c.pub, c.token)
AddBlockCheckHalt(t, bc, tx)
balanceMint(t, cBal, acc, containerFee*1, []byte{})
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
tx = PrepareInvoke(t, bc, acc, h, "delete", c.id[:], c.sig, c.token)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "delete: alphabet witness check failed")
cAcc := c.WithSigners(acc)
cAcc.InvokeFail(t, "delete: alphabet witness check failed", "delete",
cnt.id[:], cnt.sig, cnt.token)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "delete", c.id[:], c.sig, c.token)
AddBlockCheckHalt(t, bc, tx)
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.token)
t.Run("missing container", func(t *testing.T) {
id := c.id
id := cnt.id
id[0] ^= 0xFF
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "delete", id[:], c.sig, c.token)
AddBlockCheckHalt(t, bc, tx)
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.token)
})
tx = PrepareInvoke(t, bc, acc, h, "get", c.id[:])
_, err := TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), container.NotFoundError))
c.InvokeFail(t, container.NotFoundError, "get", cnt.id[:])
}
func TestContainerOwner(t *testing.T) {
bc := NewChain(t)
h, balanceHash := prepareContainerContract(t, bc)
c, cBal := newContainerInvoker(t)
acc := NewAccount(t, bc)
balanceMint(t, bc, acc, balanceHash, containerFee*1, []byte{})
acc := c.NewAccount(t)
cnt := dummyContainer(acc)
c := dummyContainer(acc)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "put", c.value, c.sig, c.pub, c.token)
AddBlockCheckHalt(t, bc, tx)
balanceMint(t, cBal, acc, containerFee*1, []byte{})
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
t.Run("missing container", func(t *testing.T) {
id := c.id
id := cnt.id
id[0] ^= 0xFF
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "owner", id[:])
_, err := TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), container.NotFoundError))
c.InvokeFail(t, container.NotFoundError, "owner", id[:])
})
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "owner", c.id[:])
owner, _ := base58.Decode(acc.Address)
CheckTestInvoke(t, bc, tx, stackitem.NewBuffer(owner))
owner, _ := base58.Decode(address.Uint160ToString(acc.ScriptHash()))
c.Invoke(t, stackitem.NewBuffer(owner), "owner", cnt.id[:])
}
func TestContainerGet(t *testing.T) {
bc := NewChain(t)
h, balanceHash := prepareContainerContract(t, bc)
c, cBal := newContainerInvoker(t)
acc := NewAccount(t, bc)
balanceMint(t, bc, acc, balanceHash, containerFee*1, []byte{})
acc := c.NewAccount(t)
cnt := dummyContainer(acc)
c := dummyContainer(acc)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "put", c.value, c.sig, c.pub, c.token)
AddBlockCheckHalt(t, bc, tx)
balanceMint(t, cBal, acc, containerFee*1, []byte{})
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
t.Run("missing container", func(t *testing.T) {
id := c.id
id := cnt.id
id[0] ^= 0xFF
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "get", id[:])
_, err := TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), container.NotFoundError))
c.InvokeFail(t, container.NotFoundError, "get", id[:])
})
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "get", c.id[:])
CheckTestInvoke(t, bc, tx, stackitem.NewStruct([]stackitem.Item{
stackitem.NewByteArray(c.value),
stackitem.NewByteArray(c.sig),
stackitem.NewByteArray(c.pub),
stackitem.NewByteArray(c.token),
}))
expected := stackitem.NewStruct([]stackitem.Item{
stackitem.NewByteArray(cnt.value),
stackitem.NewByteArray(cnt.sig),
stackitem.NewByteArray(cnt.pub),
stackitem.NewByteArray(cnt.token),
})
c.Invoke(t, expected, "get", cnt.id[:])
}
type eacl struct {
@ -271,39 +238,33 @@ func dummyEACL(containerID [32]byte) eacl {
}
func TestContainerSetEACL(t *testing.T) {
bc := NewChain(t)
h, balanceHash := prepareContainerContract(t, bc)
c, cBal := newContainerInvoker(t)
acc := NewAccount(t, bc)
balanceMint(t, bc, acc, balanceHash, containerFee*1, []byte{})
acc := c.NewAccount(t)
cnt := dummyContainer(acc)
balanceMint(t, cBal, acc, containerFee*1, []byte{})
c := dummyContainer(acc)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "put", c.value, c.sig, c.pub, c.token)
AddBlockCheckHalt(t, bc, tx)
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
t.Run("missing container", func(t *testing.T) {
id := c.id
id := cnt.id
id[0] ^= 0xFF
e := dummyEACL(id)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "setEACL", e.value, e.sig, e.pub, e.token)
_, err := TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), container.NotFoundError))
c.InvokeFail(t, container.NotFoundError, "setEACL", e.value, e.sig, e.pub, e.token)
})
e := dummyEACL(c.id)
tx = PrepareInvoke(t, bc, acc, h, "setEACL", e.value, e.sig, e.pub, e.token)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "setEACL: alphabet witness check failed")
e := dummyEACL(cnt.id)
setArgs := []interface{}{e.value, e.sig, e.pub, e.token}
cAcc := c.WithSigners(acc)
cAcc.InvokeFail(t, "alphabet witness check failed", "setEACL", setArgs...)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "setEACL", e.value, e.sig, e.pub, e.token)
AddBlockCheckHalt(t, bc, tx)
c.Invoke(t, stackitem.Null{}, "setEACL", setArgs...)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "eACL", c.id[:])
CheckTestInvoke(t, bc, tx, stackitem.NewStruct([]stackitem.Item{
expected := stackitem.NewStruct([]stackitem.Item{
stackitem.NewByteArray(e.value),
stackitem.NewByteArray(e.sig),
stackitem.NewByteArray(e.pub),
stackitem.NewByteArray(e.token),
}))
})
c.Invoke(t, expected, "eACL", cnt.id[:])
}

11
tests/helpers.go Normal file
View file

@ -0,0 +1,11 @@
package tests
import (
"math/rand"
)
func randomBytes(n int) []byte {
a := make([]byte, n)
rand.Read(a)
return a
}

View file

@ -3,90 +3,88 @@ package tests
import (
"math/big"
"math/rand"
"path"
"testing"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"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/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neofs-contract/container"
"github.com/stretchr/testify/require"
)
const netmapPath = "../netmap"
func deployNetmapContract(t *testing.T, bc *core.Blockchain, addrBalance, addrContainer util.Uint160, config ...interface{}) util.Uint160 {
func deployNetmapContract(t *testing.T, e *neotest.Executor, addrBalance, addrContainer util.Uint160, config ...interface{}) util.Uint160 {
_, pubs, ok := vm.ParseMultiSigContract(e.Committee.Script())
require.True(t, ok)
args := make([]interface{}, 5)
args[0] = false
args[1] = addrBalance
args[2] = addrContainer
args[3] = []interface{}{CommitteeAcc.PrivateKey().PublicKey().Bytes()}
args[3] = []interface{}{pubs[0]}
args[4] = append([]interface{}{}, config...)
return DeployContract(t, bc, netmapPath, args)
c := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
e.DeployContract(t, c, args)
return c.Hash
}
func prepareNetmapContract(t *testing.T, bc *core.Blockchain, config ...interface{}) util.Uint160 {
addrNNS := DeployContract(t, bc, nnsPath, nil)
func newNetmapInvoker(t *testing.T, config ...interface{}) *neotest.ContractInvoker {
e := newExecutor(t)
ctrNetmap, err := ContractInfo(CommitteeAcc.Contract.ScriptHash(), netmapPath)
require.NoError(t, err)
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"))
ctrBalance, err := ContractInfo(CommitteeAcc.Contract.ScriptHash(), balancePath)
require.NoError(t, err)
ctrContainer, err := ContractInfo(CommitteeAcc.Contract.ScriptHash(), containerPath)
require.NoError(t, err)
deployContainerContract(t, bc, ctrNetmap.Hash, ctrBalance.Hash, addrNNS)
deployBalanceContract(t, bc, ctrNetmap.Hash, ctrContainer.Hash)
return deployNetmapContract(t, bc, ctrBalance.Hash, ctrContainer.Hash, config...)
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)
}
func TestDeploySetConfig(t *testing.T) {
bc := NewChain(t)
h := prepareNetmapContract(t, bc, "SomeKey", "TheValue", container.AliasFeeKey, int64(123))
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "config", "SomeKey")
CheckTestInvoke(t, bc, tx, "TheValue")
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "config", container.AliasFeeKey)
CheckTestInvoke(t, bc, tx, bigint.ToBytes(big.NewInt(123)))
c := newNetmapInvoker(t, "SomeKey", "TheValue", container.AliasFeeKey, int64(123))
c.Invoke(t, "TheValue", "config", "SomeKey")
c.Invoke(t, stackitem.NewByteArray(bigint.ToBytes(big.NewInt(123))),
"config", container.AliasFeeKey)
}
func dummyNodeInfo(acc *wallet.Account) []byte {
func dummyNodeInfo(acc neotest.Signer) []byte {
ni := make([]byte, 66)
rand.Read(ni)
copy(ni[2:], acc.PrivateKey().PublicKey().Bytes())
pub, _ := vm.ParseSignatureContract(acc.Script())
copy(ni[2:], pub)
return ni
}
func TestAddPeer(t *testing.T) {
bc := NewChain(t)
h := prepareNetmapContract(t, bc)
c := newNetmapInvoker(t)
acc := NewAccount(t, bc)
acc := c.NewAccount(t)
cAcc := c.WithSigners(acc)
dummyInfo := dummyNodeInfo(acc)
acc1 := NewAccount(t, bc)
tx := PrepareInvoke(t, bc, acc1, h, "addPeer", dummyInfo)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "witness check failed")
acc1 := c.NewAccount(t)
cAcc1 := c.WithSigners(acc1)
cAcc1.InvokeFail(t, "witness check failed", "addPeer", dummyInfo)
tx = PrepareInvoke(t, bc, acc, h, "addPeer", dummyInfo)
AddBlock(t, bc, tx)
aer := CheckHalt(t, bc, tx.Hash())
h := cAcc.Invoke(t, stackitem.Null{}, "addPeer", dummyInfo)
aer := cAcc.CheckHalt(t, h)
require.Equal(t, 1, len(aer.Events))
require.Equal(t, "AddPeer", aer.Events[0].Name)
require.Equal(t, stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(dummyInfo)}),
aer.Events[0].Item)
dummyInfo[0] ^= 0xFF
tx = PrepareInvoke(t, bc, acc, h, "addPeer", dummyInfo)
AddBlock(t, bc, tx)
aer = CheckHalt(t, bc, tx.Hash())
h = cAcc.Invoke(t, stackitem.Null{}, "addPeer", dummyInfo)
aer = cAcc.CheckHalt(t, h)
require.Equal(t, 1, len(aer.Events))
require.Equal(t, "AddPeer", aer.Events[0].Name)
require.Equal(t, stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray(dummyInfo)}),

View file

@ -3,14 +3,13 @@ package tests
import (
"fmt"
"math/big"
"strings"
"path"
"testing"
"time"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neofs-contract/nns"
"github.com/stretchr/testify/require"
)
@ -19,161 +18,141 @@ const nnsPath = "../nns"
const msPerYear = 365 * 24 * time.Hour / time.Millisecond
func newNNSInvoker(t *testing.T, addRoot bool) *neotest.ContractInvoker {
e := newExecutor(t)
ctr := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
e.DeployContract(t, ctr, nil)
c := e.CommitteeInvoker(ctr.Hash)
if addRoot {
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
c.Invoke(t, true, "register",
"com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
}
return c
}
func TestNNSGeneric(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, false)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "symbol")
CheckTestInvoke(t, bc, tx, "NNS")
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "decimals")
CheckTestInvoke(t, bc, tx, 0)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "totalSupply")
CheckTestInvoke(t, bc, tx, 0)
c.Invoke(t, "NNS", "symbol")
c.Invoke(t, 0, "decimals")
c.Invoke(t, 0, "totalSupply")
}
func TestNNSRegisterTLD(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, false)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"0com", CommitteeAcc.Contract.ScriptHash(),
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "invalid domain name format")
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, acc, h, "register",
"com", acc.Contract.ScriptHash(),
c.InvokeFail(t, "invalid domain name format", "register",
"0com", c.CommitteeHash,
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "not witnessed by committee")
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
acc := c.NewAccount(t)
cAcc := c.WithSigners(acc)
cAcc.InvokeFail(t, "not witnessed by committee", "register",
"com", acc.ScriptHash(),
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckHalt(t, bc, tx.Hash())
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c.Invoke(t, true, "register",
"com", c.CommitteeHash,
"email@nspcc.ru", refresh, retry, expire, ttl)
c.InvokeFail(t, "TLD already exists", "register",
"com", c.CommitteeHash,
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "TLD already exists")
}
func TestNNSRegister(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, false)
accTop := NewAccount(t, bc)
accTop := c.NewAccount(t)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, accTop}, h, "register",
"com", accTop.Contract.ScriptHash(),
c1 := c.WithSigners(c.Committee, accTop)
c1.Invoke(t, true, "register",
"com", accTop.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "register",
"testdomain.com", acc.Contract.ScriptHash(),
acc := c.NewAccount(t)
c2 := c.WithSigners(c.Committee, acc)
c2.InvokeFail(t, "not witnessed by admin", "register",
"testdomain.com", acc.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "not witnessed by admin")
tx = PrepareInvoke(t, bc, []*wallet.Account{accTop, acc}, h, "register",
"testdomain.com", acc.Contract.ScriptHash(),
c3 := c.WithSigners(accTop, acc)
c3.Invoke(t, true, "register",
"testdomain.com", acc.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
b := AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "getRecords", "testdomain.com", int64(nns.SOA))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
b := c.TopBlock(t)
expected := stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
[]byte(fmt.Sprintf("testdomain.com myemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)))}))
b.Timestamp, refresh, retry, expire, ttl)))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.SOA))
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
cAcc := c.WithSigners(acc)
cAcc.Invoke(t, stackitem.Null{}, "addRecord",
"testdomain.com", int64(nns.TXT), "first TXT record")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
cAcc.Invoke(t, stackitem.Null{}, "addRecord",
"testdomain.com", int64(nns.TXT), "second TXT record")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "getRecords", "testdomain.com", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{
expected = stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte("first TXT record")),
stackitem.NewByteArray([]byte("second TXT record"))}))
stackitem.NewByteArray([]byte("second TXT record"))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
tx = PrepareInvoke(t, bc, acc, h, "setRecord",
cAcc.Invoke(t, stackitem.Null{}, "setRecord",
"testdomain.com", int64(nns.TXT), int64(0), "replaced first")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "getRecords", "testdomain.com", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{
expected = stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte("replaced first")),
stackitem.NewByteArray([]byte("second TXT record"))}))
stackitem.NewByteArray([]byte("second TXT record"))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
}
func TestNNSUpdateSOA(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, true)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"testdomain.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
refresh *= 2
retry *= 2
expire *= 2
ttl *= 2
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "updateSOA",
c.Invoke(t, stackitem.Null{}, "updateSOA",
"testdomain.com", "newemail@nspcc.ru", refresh, retry, expire, ttl)
b := AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "getRecords", "testdomain.com", int64(nns.SOA))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
b := c.TopBlock(t)
expected := stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
[]byte(fmt.Sprintf("testdomain.com newemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)))}))
b.Timestamp, refresh, retry, expire, ttl)))})
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.SOA))
}
func TestNNSGetAllRecords(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, true)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"testdomain.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
c.Invoke(t, stackitem.Null{}, "addRecord", "testdomain.com", int64(nns.TXT), "first TXT record")
c.Invoke(t, stackitem.Null{}, "addRecord", "testdomain.com", int64(nns.A), "1.2.3.4")
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "addRecord",
"testdomain.com", int64(nns.TXT), "first TXT record")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "addRecord",
"testdomain.com", int64(nns.A), "1.2.3.4")
b := AddBlockCheckHalt(t, bc, tx)
b := c.TopBlock(t)
expSOA := fmt.Sprintf("testdomain.com myemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "getAllRecords", "testdomain.com")
v, err := TestInvoke(bc, tx)
s, err := c.TestInvoke(t, "getAllRecords", "testdomain.com")
require.NoError(t, err)
iter := v.Estack().Pop().Value().(*storage.Iterator)
iter := s.Pop().Value().(*storage.Iterator)
require.True(t, iter.Next())
require.Equal(t, stackitem.NewStruct([]stackitem.Item{
stackitem.Make("testdomain.com"), stackitem.Make(int64(nns.A)),
@ -196,153 +175,99 @@ func TestNNSGetAllRecords(t *testing.T) {
}
func TestExpiration(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, true)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
b := AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"testdomain.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
b := c.NewUnsignedBlock(t)
b.Timestamp = c.TopBlock(t).Timestamp + uint64(msPerYear) - 1
require.NoError(t, c.Chain.AddBlock(c.SignBlock(b)))
addCustomBlock(t, bc, func(curr *block.Block) {
curr.Timestamp = b.Timestamp + uint64(msPerYear) - 1
})
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "getAllRecords", "testdomain.com")
_, err := TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), "parent domain has expired"))
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "ownerOf", "testdomain.com")
_, err = TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), "parent domain has expired"), err.Error())
c.InvokeFail(t, "name has expired", "getAllRecords", "testdomain.com")
c.InvokeFail(t, "name has expired", "ownerOf", "testdomain.com")
}
func TestNNSSetAdmin(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, true)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"testdomain.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
acc := c.NewAccount(t)
cAcc := c.WithSigners(acc)
cAcc.InvokeFail(t, "not witnessed by admin", "addRecord",
"testdomain.com", int64(nns.TXT), "won't be added")
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "not witnessed by admin")
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "setAdmin",
"testdomain.com", acc.Contract.ScriptHash())
AddBlockCheckHalt(t, bc, tx)
c1 := c.WithSigners(c.Committee, acc)
c1.Invoke(t, stackitem.Null{}, "setAdmin", "testdomain.com", acc.ScriptHash())
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
cAcc.Invoke(t, stackitem.Null{}, "addRecord",
"testdomain.com", int64(nns.TXT), "will be added")
AddBlockCheckHalt(t, bc, tx)
}
func TestNNSIsAvailable(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, false)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "com")
CheckTestInvoke(t, bc, tx, true)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "domain.com")
_, err := TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), "TLD not found"))
c.Invoke(t, true, "isAvailable", "com")
c.InvokeFail(t, "TLD not found", "isAvailable", "domain.com")
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c.Invoke(t, true, "register",
"com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "com")
CheckTestInvoke(t, bc, tx, false)
c.Invoke(t, false, "isAvailable", "com")
c.Invoke(t, true, "isAvailable", "domain.com")
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "domain.com")
CheckTestInvoke(t, bc, tx, true)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "register",
"domain.com", acc.Contract.ScriptHash(),
acc := c.NewAccount(t)
c1 := c.WithSigners(c.Committee, acc)
c1.Invoke(t, true, "register",
"domain.com", acc.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "domain.com")
CheckTestInvoke(t, bc, tx, false)
c.Invoke(t, false, "isAvailable", "domain.com")
}
func TestNNSRenew(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, true)
acc := c.NewAccount(t)
c1 := c.WithSigners(c.Committee, acc)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c1.Invoke(t, true, "register",
"testdomain.com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "register",
"testdomain.com", acc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
b := AddBlockCheckHalt(t, bc, tx)
const msPerYear = 365 * 24 * time.Hour / time.Millisecond
b := c.TopBlock(t)
ts := b.Timestamp + 2*uint64(msPerYear)
tx = PrepareInvoke(t, bc, acc, h, "renew", "testdomain.com")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "properties", "testdomain.com")
CheckTestInvoke(t, bc, tx, stackitem.NewMapWithValue([]stackitem.MapElement{
cAcc := c.WithSigners(acc)
cAcc.Invoke(t, ts, "renew", "testdomain.com")
expected := stackitem.NewMapWithValue([]stackitem.MapElement{
{stackitem.Make("name"), stackitem.Make("testdomain.com")},
{stackitem.Make("expiration"), stackitem.Make(b.Timestamp + 2*uint64(msPerYear))},
}))
{stackitem.Make("expiration"), stackitem.Make(ts)}})
cAcc.Invoke(t, expected, "properties", "testdomain.com")
}
func TestNNSResolve(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
c := newNNSInvoker(t, true)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
c.Invoke(t, true, "register",
"test.com", c.CommitteeHash,
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"test.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "addRecord",
c.Invoke(t, stackitem.Null{}, "addRecord",
"test.com", int64(nns.TXT), "expected result")
AddBlockCheckHalt(t, bc, tx)
records := stackitem.NewArray([]stackitem.Item{stackitem.Make("expected result")})
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "resolve", "test.com", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, records)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "resolve", "test.com.", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, records)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "resolve", "test.com..", int64(nns.TXT))
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "invalid domain name format")
c.Invoke(t, records, "resolve", "test.com", int64(nns.TXT))
c.Invoke(t, records, "resolve", "test.com.", int64(nns.TXT))
c.InvokeFail(t, "invalid domain name format", "resolve", "test.com..", int64(nns.TXT))
}

13
tests/util.go Normal file
View file

@ -0,0 +1,13 @@
package tests
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/neotest"
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
)
func newExecutor(t *testing.T) *neotest.Executor {
bc, acc := chain.NewSingle(t)
return neotest.NewExecutor(t, bc, acc, acc)
}