github.com/ava-labs/subnet-evm@v0.6.4/accounts/abi/bind/precompilebind/precompile_contract_test_template.go (about)

     1  // (c) 2019-2022, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  package precompilebind
     4  
     5  // tmplSourcePrecompileConfigGo is the Go precompiled config source template.
     6  const tmplSourcePrecompileContractTestGo = `
     7  // Code generated
     8  // This file is a generated precompile contract test with the skeleton of test functions.
     9  // The file is generated by a template. Please inspect every code and comment in this file before use.
    10  
    11  package {{.Package}}
    12  
    13  import (
    14  	"testing"
    15  	"math/big"
    16  
    17  	"github.com/ava-labs/subnet-evm/core/state"
    18  	{{- if .Contract.AllowList}}
    19  	"github.com/ava-labs/subnet-evm/precompile/allowlist"
    20  	{{- end}}
    21  	"github.com/ava-labs/subnet-evm/precompile/testutils"
    22  	"github.com/ava-labs/subnet-evm/vmerrs"
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  var (
    28  	_ = vmerrs.ErrOutOfGas
    29  	_ = big.NewInt
    30  	_ = common.Big0
    31  	_ = require.New
    32  )
    33  
    34  // These tests are run against the precompile contract directly with
    35  // the given input and expected output. They're just a guide to
    36  // help you write your own tests. These tests are for general cases like
    37  // allowlist, readOnly behaviour, and gas cost. You should write your own
    38  // tests for specific cases.
    39  var(
    40  	tests = map[string]testutils.PrecompileTest{
    41  		{{- $contract := .Contract}}
    42  		{{- $structs := .Structs}}
    43  		{{- range .Contract.Funcs}}
    44  		{{- $func := .}}
    45  		{{- if $contract.AllowList}}
    46  		{{- $roles := mkList "NoRole" "Enabled" "Manager" "Admin"}}
    47  		{{- range $role := $roles}}
    48  		{{- $fail := and (not $func.Original.IsConstant) (eq $role "NoRole")}}
    49  		"calling {{decapitalise $func.Normalized.Name}} from {{$role}} should {{- if $fail}} fail {{- else}} succeed{{- end}}":  {
    50  			Caller:     allowlist.Test{{$role}}Addr,
    51  			BeforeHook: allowlist.SetDefaultRoles(Module.Address),
    52  			InputFn: func(t testing.TB) []byte {
    53  				{{- if len $func.Normalized.Inputs | lt 1}}
    54  				// CUSTOM CODE STARTS HERE
    55  				// populate test input here
    56  				testInput := {{capitalise $func.Normalized.Name}}Input{}
    57  				input, err := Pack{{$func.Normalized.Name}}(testInput)
    58  				{{- else if len $func.Normalized.Inputs | eq 1 }}
    59  				{{- $input := index $func.Normalized.Inputs 0}}
    60  				// CUSTOM CODE STARTS HERE
    61  				// set test input to a value here
    62  				var testInput {{bindtype $input.Type $structs}}
    63  				testInput = {{bindtypenew $input.Type $structs}}
    64  				input, err := Pack{{$func.Normalized.Name}}(testInput)
    65  				{{- else}}
    66  				input, err := Pack{{$func.Normalized.Name}}()
    67  				{{- end}}
    68  				require.NoError(t, err)
    69  				return input
    70  			},
    71  			{{- if not $fail}}
    72  			// This test is for a successful call. You can set the expected output here.
    73  			// CUSTOM CODE STARTS HERE
    74  			ExpectedRes: func() []byte{
    75  				{{- if len $func.Normalized.Outputs | eq 0}}
    76  				// this function does not return an output, leave this one as is
    77  				packedOutput := []byte{}
    78  				{{- else}}
    79  				{{- if len $func.Normalized.Outputs | lt 1}}
    80  				var output {{capitalise $func.Normalized.Name}}Output // CUSTOM CODE FOR AN OUTPUT
    81  				{{- else }}
    82  				{{$output := index $func.Normalized.Outputs 0}}
    83  				var output {{bindtype $output.Type $structs}} // CUSTOM CODE FOR AN OUTPUT
    84  				output = {{bindtypenew $output.Type $structs}} // CUSTOM CODE FOR AN OUTPUT
    85  				{{- end}}
    86  				packedOutput, err := Pack{{$func.Normalized.Name}}Output(output)
    87  				if err != nil {
    88  					panic(err)
    89  				}
    90  				{{- end}}
    91  				return packedOutput
    92  			}(),
    93  			{{- end}}
    94  			SuppliedGas: {{$func.Normalized.Name}}GasCost,
    95  			ReadOnly:    false,
    96  			ExpectedErr: {{if $fail}} ErrCannot{{$func.Normalized.Name}}.Error() {{- else}} "" {{- end}},
    97  		},
    98  		{{- end}}
    99  		{{- end}}
   100  		{{- if not $func.Original.IsConstant}}
   101  		"readOnly {{decapitalise $func.Normalized.Name}} should fail": {
   102  			Caller:	common.Address{1},
   103  			InputFn: func(t testing.TB) []byte {
   104  				{{- if len $func.Normalized.Inputs | lt 1}}
   105  				// CUSTOM CODE STARTS HERE
   106  				// populate test input here
   107  				testInput := {{capitalise $func.Normalized.Name}}Input{}
   108  				input, err := Pack{{$func.Normalized.Name}}(testInput)
   109  				{{- else if len $func.Normalized.Inputs | eq 1 }}
   110  				{{- $input := index $func.Normalized.Inputs 0}}
   111  				// CUSTOM CODE STARTS HERE
   112  				// set test input to a value here
   113  				var testInput {{bindtype $input.Type $structs}}
   114  				testInput = {{bindtypenew $input.Type $structs}}
   115  				input, err := Pack{{$func.Normalized.Name}}(testInput)
   116  				{{- else}}
   117  				input, err := Pack{{$func.Normalized.Name}}()
   118  				{{- end}}
   119  				require.NoError(t, err)
   120  				return input
   121  			},
   122  			SuppliedGas:  {{$func.Normalized.Name}}GasCost,
   123  			ReadOnly:    true,
   124  			ExpectedErr: vmerrs.ErrWriteProtection.Error(),
   125  		},
   126  		{{- end}}
   127  		"insufficient gas for {{decapitalise $func.Normalized.Name}} should fail": {
   128  			Caller:	common.Address{1},
   129  			InputFn: func(t testing.TB) []byte {
   130  				{{- if len $func.Normalized.Inputs | lt 1}}
   131  				// CUSTOM CODE STARTS HERE
   132  				// populate test input here
   133  				testInput := {{capitalise $func.Normalized.Name}}Input{}
   134  				input, err := Pack{{$func.Normalized.Name}}(testInput)
   135  				{{- else if len $func.Normalized.Inputs | eq 1 }}
   136  				{{- $input := index $func.Normalized.Inputs 0}}
   137  				// CUSTOM CODE STARTS HERE
   138  				// set test input to a value here
   139  				var testInput {{bindtype $input.Type $structs}}
   140  				testInput = {{bindtypenew $input.Type $structs}}
   141  				input, err := Pack{{$func.Normalized.Name}}(testInput)
   142  				{{- else}}
   143  				input, err := Pack{{$func.Normalized.Name}}()
   144  				{{- end}}
   145  				require.NoError(t, err)
   146  				return input
   147  			},
   148  			SuppliedGas: {{$func.Normalized.Name}}GasCost - 1,
   149  			ReadOnly:    false,
   150  			ExpectedErr: vmerrs.ErrOutOfGas.Error(),
   151  		},
   152  		{{- end}}
   153  		{{- if .Contract.Fallback}}
   154  		"insufficient gas for fallback should fail": {
   155  			Caller:	common.Address{1},
   156  			Input: []byte{},
   157  			SuppliedGas: {{.Contract.Type}}FallbackGasCost - 1,
   158  			ReadOnly:    false,
   159  			ExpectedErr: vmerrs.ErrOutOfGas.Error(),
   160  		},
   161  		"readOnly fallback should fail": {
   162  			Caller:	common.Address{1},
   163  			Input: []byte{},
   164  			SuppliedGas: {{.Contract.Type}}FallbackGasCost,
   165  			ReadOnly:    true,
   166  			ExpectedErr: vmerrs.ErrWriteProtection.Error(),
   167  		},
   168  		"fallback should succeed": {
   169  			Caller:	common.Address{1},
   170  			Input: []byte{},
   171  			SuppliedGas: {{.Contract.Type}}FallbackGasCost,
   172  			ReadOnly:    false,
   173  			ExpectedErr: "",
   174  			// CUSTOM CODE STARTS HERE
   175  			// set expected output here
   176  			ExpectedRes: []byte{},
   177  		},
   178  		{{- end}}
   179  	}
   180  )
   181  
   182  // Test{{.Contract.Type}}Run tests the Run function of the precompile contract.
   183  func Test{{.Contract.Type}}Run(t *testing.T) {
   184  	{{- if .Contract.AllowList}}
   185  	// Run tests with allowlist tests.
   186  	// This adds allowlist tests to your custom tests
   187  	// and runs them all together.
   188  	// Even if you don't add any custom tests, keep this. This will still
   189  	// run the default allowlist tests.
   190  	allowlist.RunPrecompileWithAllowListTests(t, Module, state.NewTestStateDB, tests)
   191  	{{- else}}
   192  	// Run tests.
   193  	for name, test := range tests {
   194  		t.Run(name, func(t *testing.T) {
   195  			test.Run(t, Module, state.NewTestStateDB(t))
   196  		})
   197  	}
   198  	{{- end}}
   199  }
   200  
   201  {{range .Contract.Events}}
   202  {{$hasData := false}}
   203  {{range .Normalized.Inputs}}
   204  {{ if not .Indexed}}
   205  {{ $hasData = true}}
   206  {{end}}
   207  {{end}}
   208  {{ if $hasData}}
   209  // TestPackUnpack{{.Normalized.Name}}EventData tests the Pack/Unpack{{.Normalized.Name}}EventData.
   210  func TestPackUnpack{{.Normalized.Name}}EventData(t *testing.T) {
   211  	// CUSTOM CODE STARTS HERE
   212  	// set test inputs with proper values here
   213  	{{- range .Normalized.Inputs}}
   214  		{{if .Indexed}}var {{decapitalise .Name}}Input {{bindtype .Type $structs}} = {{bindtypenew .Type $structs}}{{end}}
   215  	{{- end}}
   216  	{{if $hasData}} dataInput := {{.Normalized.Name}}EventData{{end}}{
   217  		{{- range .Normalized.Inputs}}
   218  			{{- if not .Indexed}}
   219  				{{capitalise .Name}}: {{bindtypenew .Type $structs}},
   220  			{{- end}}
   221  		{{- end}}
   222  	}
   223  
   224  	_, data, err := Pack{{.Normalized.Name}}Event(
   225  		{{- range .Normalized.Inputs}}
   226  			{{- if .Indexed}}
   227  				{{decapitalise .Name}}Input,
   228  			{{- end}}
   229  		{{- end}}
   230  		{{- if $hasData}}
   231  			dataInput,
   232  		{{- end}}
   233  	)
   234  	require.NoError(t, err)
   235  
   236  	unpacked, err := Unpack{{.Normalized.Name}}EventData(data)
   237  	require.NoError(t, err)
   238  	require.Equal(t, dataInput, unpacked)
   239  }
   240  {{end}}
   241  {{end}}
   242  
   243  func Benchmark{{.Contract.Type}}(b *testing.B) {
   244  	{{- if .Contract.AllowList}}
   245  	// Benchmark tests with allowlist tests.
   246  	// This adds allowlist tests to your custom tests
   247  	// and benchmarks them all together.
   248  	// Even if you don't add any custom tests, keep this. This will still
   249  	// run the default allowlist tests.
   250  	allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, tests)
   251  	{{- else}}
   252  	// Benchmark tests.
   253  	for name, test := range tests {
   254  		b.Run(name, func(b *testing.B) {
   255  			test.Bench(b, Module, state.NewTestStateDB(b))
   256  		})
   257  	}
   258  	{{- end}}
   259  }
   260  
   261  `