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 `