github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/smartcontract/nef/nef_test.go (about)

     1  package nef
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"strconv"
     7  	"testing"
     8  
     9  	"github.com/nspcc-dev/neo-go/internal/random"
    10  	"github.com/nspcc-dev/neo-go/internal/testserdes"
    11  	"github.com/nspcc-dev/neo-go/pkg/io"
    12  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
    13  	"github.com/nspcc-dev/neo-go/pkg/util"
    14  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestEncodeDecodeBinary(t *testing.T) {
    19  	script := []byte{12, 32, 84, 35, 14}
    20  	expected := &File{
    21  		Header: Header{
    22  			Magic:    Magic,
    23  			Compiler: "best compiler version 1",
    24  		},
    25  		Tokens: []MethodToken{{
    26  			Hash:       random.Uint160(),
    27  			Method:     "method",
    28  			ParamCount: 3,
    29  			HasReturn:  true,
    30  			CallFlag:   callflag.WriteStates,
    31  		}},
    32  		Script: script,
    33  	}
    34  
    35  	t.Run("invalid Magic", func(t *testing.T) {
    36  		expected.Header.Magic = 123
    37  		checkDecodeError(t, expected)
    38  	})
    39  
    40  	t.Run("invalid checksum", func(t *testing.T) {
    41  		expected.Header.Magic = Magic
    42  		expected.Checksum = 123
    43  		checkDecodeError(t, expected)
    44  	})
    45  
    46  	t.Run("zero-length script", func(t *testing.T) {
    47  		expected.Script = make([]byte, 0)
    48  		expected.Checksum = expected.CalculateChecksum()
    49  		checkDecodeError(t, expected)
    50  	})
    51  
    52  	t.Run("invalid script length", func(t *testing.T) {
    53  		newScript := make([]byte, stackitem.MaxSize+1)
    54  		expected.Script = newScript
    55  		expected.Checksum = expected.CalculateChecksum()
    56  		checkDecodeError(t, expected)
    57  	})
    58  	t.Run("invalid tokens list", func(t *testing.T) {
    59  		expected.Script = script
    60  		expected.Tokens[0].Method = "_reserved"
    61  		expected.Checksum = expected.CalculateChecksum()
    62  		checkDecodeError(t, expected)
    63  	})
    64  
    65  	t.Run("positive", func(t *testing.T) {
    66  		expected.Script = script
    67  		expected.Tokens[0].Method = "method"
    68  		expected.Checksum = expected.CalculateChecksum()
    69  		expected.Header.Magic = Magic
    70  		testserdes.EncodeDecodeBinary(t, expected, &File{})
    71  	})
    72  	t.Run("positive with empty tokens", func(t *testing.T) {
    73  		expected.Script = script
    74  		// Check `Tokens` won't be deserialized to `nil`. We expect them to be non-nil slice in the related code.
    75  		expected.Tokens = []MethodToken{}
    76  		expected.Checksum = expected.CalculateChecksum()
    77  		expected.Header.Magic = Magic
    78  		testserdes.EncodeDecodeBinary(t, expected, &File{})
    79  	})
    80  	t.Run("invalid reserved bytes", func(t *testing.T) {
    81  		expected.Script = script
    82  		expected.Tokens = expected.Tokens[:0]
    83  		expected.Checksum = expected.CalculateChecksum()
    84  		bytes, err := testserdes.EncodeBinary(expected)
    85  		require.NoError(t, err)
    86  
    87  		sz := io.GetVarSize(&expected.Header)
    88  		bytes[sz] = 1
    89  		err = testserdes.DecodeBinary(bytes, new(File))
    90  		require.ErrorIs(t, err, errInvalidReserved)
    91  
    92  		bytes[sz] = 0
    93  		bytes[sz+3] = 1
    94  		err = testserdes.DecodeBinary(bytes, new(File))
    95  		require.ErrorIs(t, err, errInvalidReserved)
    96  	})
    97  }
    98  
    99  func checkDecodeError(t *testing.T, expected *File) {
   100  	bytes, err := testserdes.EncodeBinary(expected)
   101  	require.NoError(t, err)
   102  	require.Error(t, testserdes.DecodeBinary(bytes, &File{}))
   103  }
   104  
   105  func TestBytesFromBytes(t *testing.T) {
   106  	script := []byte{12, 32, 84, 35, 14}
   107  	expected := File{
   108  		Header: Header{
   109  			Magic:    Magic,
   110  			Compiler: "best compiler version 1",
   111  		},
   112  		Tokens: []MethodToken{{
   113  			Hash:       random.Uint160(),
   114  			Method:     "someMethod",
   115  			ParamCount: 3,
   116  			HasReturn:  true,
   117  			CallFlag:   callflag.WriteStates,
   118  		}},
   119  		Script: script,
   120  	}
   121  	expected.Checksum = expected.CalculateChecksum()
   122  
   123  	bytes, err := expected.Bytes()
   124  	require.NoError(t, err)
   125  	actual, err := FileFromBytes(bytes)
   126  	require.NoError(t, err)
   127  	require.Equal(t, expected, actual)
   128  }
   129  
   130  func TestNewFileFromBytesLimits(t *testing.T) {
   131  	expected := File{
   132  		Header: Header{
   133  			Magic:    Magic,
   134  			Compiler: "best compiler version 1",
   135  		},
   136  		Tokens: []MethodToken{{
   137  			Hash:       random.Uint160(),
   138  			Method:     "someMethod",
   139  			ParamCount: 3,
   140  			HasReturn:  true,
   141  			CallFlag:   callflag.WriteStates,
   142  		}},
   143  		Script: make([]byte, stackitem.MaxSize-100),
   144  	}
   145  	expected.Checksum = expected.CalculateChecksum()
   146  
   147  	bytes, err := expected.BytesLong()
   148  	require.NoError(t, err)
   149  	_, err = FileFromBytes(bytes)
   150  	require.Error(t, err)
   151  	require.Contains(t, err.Error(), "invalid NEF file size")
   152  }
   153  
   154  func TestMarshalUnmarshalJSON(t *testing.T) {
   155  	expected := &File{
   156  		Header: Header{
   157  			Magic:    Magic,
   158  			Compiler: "test.compiler-test.ver",
   159  		},
   160  		Tokens: []MethodToken{{
   161  			Hash:       util.Uint160{0x12, 0x34, 0x56, 0x78, 0x91, 0x00},
   162  			Method:     "someMethod",
   163  			ParamCount: 3,
   164  			HasReturn:  true,
   165  			CallFlag:   callflag.WriteStates,
   166  		}},
   167  		Script: []byte{1, 2, 3, 4},
   168  	}
   169  	expected.Checksum = expected.CalculateChecksum()
   170  
   171  	data, err := json.Marshal(expected)
   172  	require.NoError(t, err)
   173  	require.JSONEq(t, `{
   174  		"magic":`+strconv.FormatUint(uint64(Magic), 10)+`,
   175  		"compiler": "test.compiler-test.ver",
   176  		"source": "",
   177  		"tokens": [
   178  			{
   179  	"hash": "0x`+expected.Tokens[0].Hash.StringLE()+`",
   180  	"method": "someMethod",
   181  	"paramcount": 3,
   182  	"hasreturnvalue": true,
   183  	"callflags": "`+expected.Tokens[0].CallFlag.String()+`"
   184  			}
   185  		],
   186  		"script": "`+base64.StdEncoding.EncodeToString(expected.Script)+`",
   187  		"checksum":`+strconv.FormatUint(uint64(expected.Checksum), 10)+`}`, string(data))
   188  
   189  	actual := new(File)
   190  	require.NoError(t, json.Unmarshal(data, actual))
   191  	require.Equal(t, expected, actual)
   192  }