2018-08-21 12:51:16 +00:00
|
|
|
package compiler_test
|
|
|
|
|
|
|
|
import (
|
2021-06-04 08:47:52 +00:00
|
|
|
"fmt"
|
2018-08-21 12:51:16 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
2021-02-19 10:48:45 +00:00
|
|
|
"strings"
|
2018-08-21 12:51:16 +00:00
|
|
|
"testing"
|
|
|
|
|
2020-03-03 14:21:42 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/compiler"
|
2020-06-25 16:21:49 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
2021-06-02 08:46:08 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
2020-01-14 14:33:04 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-08-21 12:51:16 +00:00
|
|
|
)
|
|
|
|
|
2019-12-03 15:18:14 +00:00
|
|
|
const examplePath = "../../examples"
|
2020-01-14 14:33:04 +00:00
|
|
|
const exampleCompilePath = "testdata/compile"
|
|
|
|
const exampleSavePath = exampleCompilePath + "/save"
|
2018-08-21 12:51:16 +00:00
|
|
|
|
2020-01-14 14:33:04 +00:00
|
|
|
type compilerTestCase struct {
|
|
|
|
name string
|
2020-02-29 15:55:16 +00:00
|
|
|
function func(*testing.T)
|
2020-01-14 14:33:04 +00:00
|
|
|
}
|
2018-08-21 12:51:16 +00:00
|
|
|
|
2020-01-14 14:33:04 +00:00
|
|
|
func TestCompiler(t *testing.T) {
|
2020-06-25 16:21:49 +00:00
|
|
|
// CompileAndSave use config.Version for proper .nef generation.
|
|
|
|
config.Version = "0.90.0-test"
|
2020-01-14 14:33:04 +00:00
|
|
|
testCases := []compilerTestCase{
|
2020-08-10 15:23:45 +00:00
|
|
|
{
|
|
|
|
name: "TestCompileDirectory",
|
|
|
|
function: func(t *testing.T) {
|
|
|
|
const multiMainDir = "testdata/multi"
|
|
|
|
_, di, err := compiler.CompileWithDebugInfo(multiMainDir, nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
m := map[string]bool{}
|
|
|
|
for i := range di.Methods {
|
2020-08-13 07:29:08 +00:00
|
|
|
m[di.Methods[i].ID] = true
|
2020-08-10 15:23:45 +00:00
|
|
|
}
|
|
|
|
require.Contains(t, m, "Func1")
|
|
|
|
require.Contains(t, m, "Func2")
|
|
|
|
},
|
|
|
|
},
|
2020-01-14 14:33:04 +00:00
|
|
|
{
|
|
|
|
name: "TestCompile",
|
2020-02-29 15:55:16 +00:00
|
|
|
function: func(t *testing.T) {
|
2020-01-14 14:33:04 +00:00
|
|
|
infos, err := ioutil.ReadDir(examplePath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
for _, info := range infos {
|
2021-03-22 18:13:29 +00:00
|
|
|
if !info.IsDir() {
|
|
|
|
// example smart contracts are located in the `examplePath` subdirectories, but
|
|
|
|
// there are also a couple of files inside the `examplePath` which doesn't need to be compiled
|
|
|
|
continue
|
|
|
|
}
|
2020-01-14 14:33:04 +00:00
|
|
|
infos, err := ioutil.ReadDir(path.Join(examplePath, info.Name()))
|
|
|
|
require.NoError(t, err)
|
2020-02-29 15:55:16 +00:00
|
|
|
require.False(t, len(infos) == 0, "detected smart contract folder with no contract in it")
|
2018-08-22 17:07:36 +00:00
|
|
|
|
2020-01-14 14:33:04 +00:00
|
|
|
filename := filterFilename(infos)
|
|
|
|
targetPath := path.Join(examplePath, info.Name(), filename)
|
2020-02-29 15:55:16 +00:00
|
|
|
require.NoError(t, compileFile(targetPath))
|
2020-01-14 14:33:04 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "TestCompileAndSave",
|
2020-02-29 15:55:16 +00:00
|
|
|
function: func(t *testing.T) {
|
2020-01-14 14:33:04 +00:00
|
|
|
infos, err := ioutil.ReadDir(exampleCompilePath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = os.MkdirAll(exampleSavePath, os.ModePerm)
|
|
|
|
require.NoError(t, err)
|
2021-03-01 11:14:15 +00:00
|
|
|
t.Cleanup(func() {
|
2020-01-14 14:33:04 +00:00
|
|
|
err := os.RemoveAll(exampleSavePath)
|
|
|
|
require.NoError(t, err)
|
2021-03-01 11:14:15 +00:00
|
|
|
})
|
2020-12-10 10:40:27 +00:00
|
|
|
outfile := exampleSavePath + "/test.nef"
|
|
|
|
_, err = compiler.CompileAndSave(exampleCompilePath+"/"+infos[0].Name(), &compiler.Options{Outfile: outfile})
|
|
|
|
require.NoError(t, err)
|
2020-01-14 14:33:04 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tcase := range testCases {
|
2020-02-29 15:55:16 +00:00
|
|
|
t.Run(tcase.name, tcase.function)
|
2018-08-21 12:51:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-22 17:07:36 +00:00
|
|
|
func filterFilename(infos []os.FileInfo) string {
|
|
|
|
for _, info := range infos {
|
|
|
|
if !info.IsDir() {
|
|
|
|
return info.Name()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2018-08-21 12:51:16 +00:00
|
|
|
func compileFile(src string) error {
|
2020-08-10 15:23:45 +00:00
|
|
|
_, err := compiler.Compile(src, nil)
|
2018-08-21 12:51:16 +00:00
|
|
|
return err
|
|
|
|
}
|
2021-02-19 10:48:45 +00:00
|
|
|
|
|
|
|
func TestOnPayableChecks(t *testing.T) {
|
|
|
|
compileAndCheck := func(t *testing.T, src string) error {
|
|
|
|
_, di, err := compiler.CompileWithDebugInfo("payable", strings.NewReader(src))
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = compiler.CreateManifest(di, &compiler.Options{})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("NEP-11, good", func(t *testing.T) {
|
|
|
|
src := `package payable
|
|
|
|
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
2021-05-05 10:22:26 +00:00
|
|
|
func OnNEP11Payment(from interop.Hash160, amount int, tokenID []byte, data interface{}) {}`
|
2021-02-19 10:48:45 +00:00
|
|
|
require.NoError(t, compileAndCheck(t, src))
|
|
|
|
})
|
|
|
|
t.Run("NEP-11, bad", func(t *testing.T) {
|
|
|
|
src := `package payable
|
|
|
|
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
2021-05-05 10:22:26 +00:00
|
|
|
func OnNEP11Payment(from interop.Hash160, amount int, oldParam string, tokenID []byte, data interface{}) {}`
|
2021-02-19 10:48:45 +00:00
|
|
|
require.Error(t, compileAndCheck(t, src))
|
|
|
|
})
|
|
|
|
t.Run("NEP-17, good", func(t *testing.T) {
|
|
|
|
src := `package payable
|
|
|
|
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
|
|
|
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {}`
|
|
|
|
require.NoError(t, compileAndCheck(t, src))
|
|
|
|
})
|
|
|
|
t.Run("NEP-17, bad", func(t *testing.T) {
|
|
|
|
src := `package payable
|
|
|
|
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
|
|
|
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}, extra int) {}`
|
|
|
|
require.Error(t, compileAndCheck(t, src))
|
|
|
|
})
|
|
|
|
}
|
2021-06-02 08:46:08 +00:00
|
|
|
|
|
|
|
func TestEventWarnings(t *testing.T) {
|
|
|
|
src := `package payable
|
|
|
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
|
|
|
func Main() { runtime.Notify("Event", 1) }`
|
|
|
|
|
|
|
|
_, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
t.Run("event it missing from config", func(t *testing.T) {
|
|
|
|
_, err = compiler.CreateManifest(di, &compiler.Options{})
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
t.Run("suppress", func(t *testing.T) {
|
|
|
|
_, err = compiler.CreateManifest(di, &compiler.Options{NoEventsCheck: true})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
t.Run("wrong parameter number", func(t *testing.T) {
|
|
|
|
_, err = compiler.CreateManifest(di, &compiler.Options{
|
|
|
|
ContractEvents: []manifest.Event{{Name: "Event"}},
|
|
|
|
})
|
|
|
|
require.Error(t, err)
|
|
|
|
})
|
|
|
|
t.Run("wrong parameter type", func(t *testing.T) {
|
|
|
|
_, err = compiler.CreateManifest(di, &compiler.Options{
|
|
|
|
ContractEvents: []manifest.Event{{
|
|
|
|
Name: "Event",
|
|
|
|
Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.StringType)},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.Error(t, err)
|
|
|
|
})
|
|
|
|
t.Run("good", func(t *testing.T) {
|
|
|
|
_, err = compiler.CreateManifest(di, &compiler.Options{
|
|
|
|
ContractEvents: []manifest.Event{{
|
|
|
|
Name: "Event",
|
|
|
|
Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.IntegerType)},
|
|
|
|
}},
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
}
|
2021-06-04 08:47:52 +00:00
|
|
|
|
|
|
|
func TestNotifyInVerify(t *testing.T) {
|
|
|
|
srcTmpl := `package payable
|
|
|
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
|
|
|
func Verify() bool { runtime.%s("Event"); return true }`
|
|
|
|
|
|
|
|
for _, name := range []string{"Notify", "Log"} {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
src := fmt.Sprintf(srcTmpl, name)
|
|
|
|
_, _, err := compiler.CompileWithOptions("eventTest", strings.NewReader(src),
|
|
|
|
&compiler.Options{ContractEvents: []manifest.Event{{Name: "Event"}}})
|
|
|
|
require.Error(t, err)
|
|
|
|
|
|
|
|
t.Run("suppress", func(t *testing.T) {
|
|
|
|
_, _, err := compiler.CompileWithOptions("eventTest", strings.NewReader(src),
|
|
|
|
&compiler.Options{NoEventsCheck: true})
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|