github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/cli/smartcontract/smart_contract_test.go (about)

     1  package smartcontract
     2  
     3  import (
     4  	"flag"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/nspcc-dev/neo-go/internal/random"
     9  	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
    10  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
    11  	"github.com/stretchr/testify/require"
    12  	"github.com/urfave/cli"
    13  	"gopkg.in/yaml.v3"
    14  )
    15  
    16  func TestInitSmartContract(t *testing.T) {
    17  	d := t.TempDir()
    18  	testWD, err := os.Getwd()
    19  	require.NoError(t, err)
    20  	err = os.Chdir(d)
    21  	require.NoError(t, err)
    22  	t.Cleanup(func() { require.NoError(t, os.Chdir(testWD)) })
    23  	contractName := "testContract"
    24  
    25  	set := flag.NewFlagSet("flagSet", flag.ExitOnError)
    26  	set.String("name", contractName, "")
    27  	ctx := cli.NewContext(cli.NewApp(), set, nil)
    28  	require.NoError(t, initSmartContract(ctx))
    29  	dirInfo, err := os.Stat(contractName)
    30  	require.NoError(t, err)
    31  	require.True(t, dirInfo.IsDir())
    32  	files, err := os.ReadDir(contractName)
    33  	require.NoError(t, err)
    34  	require.Equal(t, 3, len(files))
    35  	require.Equal(t, "go.mod", files[0].Name())
    36  	require.Equal(t, "main.go", files[1].Name())
    37  	require.Equal(t, "neo-go.yml", files[2].Name())
    38  	main, err := os.ReadFile(contractName + "/" + files[1].Name())
    39  	require.NoError(t, err)
    40  	require.Equal(t,
    41  		`package `+contractName+`
    42  
    43  import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
    44  
    45  var notificationName string
    46  
    47  // init initializes notificationName before calling any other smart-contract method
    48  func init() {
    49  	notificationName = "Hello world!"
    50  }
    51  
    52  // RuntimeNotify sends runtime notification with "Hello world!" name
    53  func RuntimeNotify(args []any) {
    54      runtime.Notify(notificationName, args)
    55  }`, string(main))
    56  
    57  	manifest, err := os.ReadFile(contractName + "/" + files[2].Name())
    58  	require.NoError(t, err)
    59  	expected := `name: testContract
    60  sourceurl: http://example.com/
    61  safemethods: []
    62  supportedstandards: []
    63  events:
    64      - name: Hello world!
    65        parameters:
    66          - name: args
    67            type: Array
    68  permissions:
    69      - methods: '*'
    70  `
    71  	require.Equal(t, expected, string(manifest))
    72  }
    73  
    74  func testPermissionMarshal(t *testing.T, p *manifest.Permission, expected string) {
    75  	out, err := yaml.Marshal((*permission)(p))
    76  	require.NoError(t, err)
    77  	require.Equal(t, expected, string(out))
    78  
    79  	t.Run("Unmarshal", func(t *testing.T) {
    80  		actual := new(permission)
    81  		require.NoError(t, yaml.Unmarshal(out, actual))
    82  		require.Equal(t, p, (*manifest.Permission)(actual))
    83  	})
    84  }
    85  
    86  func TestPermissionMarshal(t *testing.T) {
    87  	t.Run("Wildcard", func(t *testing.T) {
    88  		p := manifest.NewPermission(manifest.PermissionWildcard)
    89  		testPermissionMarshal(t, p, "methods: '*'\n")
    90  	})
    91  	t.Run("no allowed methods", func(t *testing.T) {
    92  		p := manifest.NewPermission(manifest.PermissionWildcard)
    93  		p.Methods.Restrict()
    94  		testPermissionMarshal(t, p, "methods: []\n")
    95  	})
    96  	t.Run("hash", func(t *testing.T) {
    97  		h := random.Uint160()
    98  		p := manifest.NewPermission(manifest.PermissionHash, h)
    99  		testPermissionMarshal(t, p,
   100  			"hash: "+h.StringLE()+"\n"+
   101  				"methods: '*'\n")
   102  	})
   103  	t.Run("group with some methods", func(t *testing.T) {
   104  		priv, err := keys.NewPrivateKey()
   105  		require.NoError(t, err)
   106  
   107  		p := manifest.NewPermission(manifest.PermissionGroup, priv.PublicKey())
   108  		p.Methods.Add("abc")
   109  		p.Methods.Add("lamao")
   110  		testPermissionMarshal(t, p,
   111  			"group: "+priv.PublicKey().StringCompressed()+"\n"+
   112  				"methods:\n    - abc\n    - lamao\n")
   113  	})
   114  }
   115  
   116  func TestPermissionUnmarshalInvalid(t *testing.T) {
   117  	priv, err := keys.NewPrivateKey()
   118  	require.NoError(t, err)
   119  
   120  	pub := priv.PublicKey().StringCompressed()
   121  	u160 := random.Uint160().StringLE()
   122  	testCases := []string{
   123  		"hash: []\nmethods: '*'\n",                             // invalid hash type
   124  		"hash: notahex\nmethods: '*'\n",                        // invalid hash
   125  		"group: []\nmethods: '*'\n",                            // invalid group type
   126  		"group: notahex\nmethods: '*'\n",                       // invalid group
   127  		"hash: " + u160 + "\n",                                 // missing methods
   128  		"group: " + pub + "\nhash: " + u160 + "\nmethods: '*'", // hash/group conflict
   129  		"hash: " + u160 + "\nmethods:\n  a: b\n",               // invalid methods type
   130  		"hash: " + u160 + "\nmethods:\n- []\n",                 // methods array, invalid single
   131  	}
   132  
   133  	for _, tc := range testCases {
   134  		t.Run(tc, func(t *testing.T) {
   135  			require.Error(t, yaml.Unmarshal([]byte(tc), new(permission)))
   136  		})
   137  	}
   138  }