Skip to content

Commit 07ab96e

Browse files
committed
accounts/abi/abigen: add binding generation test that mirrors the --abi option (not providing the libraries or binaries as source of the binding, only the abi definition). Extract single converted v1 test into this new test case.
1 parent a4480b2 commit 07ab96e

File tree

2 files changed

+180
-5
lines changed

2 files changed

+180
-5
lines changed

accounts/abi/abigen/bindv2_test.go

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,31 @@ type bindV2Test struct {
3434
aliases map[string]string
3535
}
3636

37-
func bind(test *bindV2Test) (bound string, err error) {
37+
// bindABI returns bindings for a test case supplying only the ABI definition for bindings, and not the deployer
38+
// bytecode.
39+
func bindABI(test *bindV2Test) (bound string, err error) {
40+
var (
41+
abis []string
42+
bins []string
43+
types []string
44+
)
45+
libs := make(map[string]string)
46+
47+
for i := 0; i < len(test.types); i++ {
48+
abis = append(abis, test.abis[i])
49+
bins = append(bins, "")
50+
types = append(types, test.types[i])
51+
}
52+
53+
code, err := BindV2(types, abis, bins, "convertedv1bindtests", libs, test.aliases)
54+
if err != nil {
55+
return "", fmt.Errorf("error creating bindings: %v", err)
56+
}
57+
58+
return code, nil
59+
}
60+
61+
func bindCombinedJSON(test *bindV2Test) (bound string, err error) {
3862
var (
3963
abis []string
4064
bins []string
@@ -67,7 +91,7 @@ func bind(test *bindV2Test) (bound string, err error) {
6791
return code, nil
6892
}
6993

70-
var bindTests2 = []bindV2Test{
94+
var combinedJSONBindTestsV2 = []bindV2Test{
7195
{
7296
"Empty",
7397
[]string{`[]`},
@@ -260,18 +284,26 @@ var bindTests2 = []bindV2Test{
260284
},
261285
}
262286

287+
var abiBindTestCase = bindV2Test{
288+
"Structs",
289+
[]string{`[{"inputs":[],"name":"F","outputs":[{"components":[{"internalType":"bytes32","name":"B","type":"bytes32"}],"internalType":"structStructs.A[]","name":"a","type":"tuple[]"},{"internalType":"uint256[]","name":"c","type":"uint256[]"},{"internalType":"bool[]","name":"d","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"G","outputs":[{"components":[{"internalType":"bytes32","name":"B","type":"bytes32"}],"internalType":"structStructs.A[]","name":"a","type":"tuple[]"}],"stateMutability":"view","type":"function"}]`},
290+
[]string{`608060405234801561001057600080fd5b50610278806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806328811f591461003b5780636fecb6231461005b575b600080fd5b610043610070565b604051610052939291906101a0565b60405180910390f35b6100636100d6565b6040516100529190610186565b604080516002808252606082810190935282918291829190816020015b610095610131565b81526020019060019003908161008d575050805190915061026960611b9082906000906100be57fe5b60209081029190910101515293606093508392509050565b6040805160028082526060828101909352829190816020015b6100f7610131565b8152602001906001900390816100ef575050805190915061026960611b90829060009061012057fe5b602090810291909101015152905090565b60408051602081019091526000815290565b815260200190565b6000815180845260208085019450808401835b8381101561017b578151518752958201959082019060010161015e565b509495945050505050565b600060208252610199602083018461014b565b9392505050565b6000606082526101b3606083018661014b565b6020838203818501528186516101c98185610239565b91508288019350845b818110156101f3576101e5838651610143565b9484019492506001016101d2565b505084810360408601528551808252908201925081860190845b8181101561022b57825115158552938301939183019160010161020d565b509298975050505050505050565b9081526020019056fea2646970667358221220eb85327e285def14230424c52893aebecec1e387a50bb6b75fc4fdbed647f45f64736f6c63430006050033`},
291+
nil,
292+
nil,
293+
}
294+
263295
// TestBindingV2ConvertedV1Tests regenerates contracts from the v1 binding test cases (using v2 binding mode) and ensures
264296
// that no mutations occurred compared to the expected output included under internal/convertedv1bindtests.
265297
func TestBindingV2ConvertedV1Tests(t *testing.T) {
266-
for _, tc := range bindTests2 {
298+
for _, tc := range combinedJSONBindTestsV2 {
267299
fname := fmt.Sprintf("testdata/v2/%v.go.txt", strings.ToLower(tc.name))
268300
t.Run(tc.name, func(t *testing.T) {
269301
if tc.types == nil {
270302
tc.types = []string{tc.name}
271303
}
272-
have, err := bind(&tc)
304+
have, err := bindCombinedJSON(&tc)
273305
if err != nil {
274-
t.Fatalf("got error from bind: %v", err)
306+
t.Fatalf("got error from bindCombinedJSON: %v", err)
275307
}
276308
// Set this environment variable to regenerate the test outputs.
277309
if os.Getenv("WRITE_TEST_FILES") != "" {
@@ -291,6 +323,37 @@ func TestBindingV2ConvertedV1Tests(t *testing.T) {
291323
}
292324
}
293325

326+
// TestBindingV2ConvertedV1TestABI regenerates contracts from the v1 binding test cases (using v2 binding mode) and ensures
327+
// that no mutations occurred compared to the expected output included under internal/convertedv1bindtests. Binding generation
328+
// is performed sourcing only the ABI definition as input (this is what the --abi option of abigen does).
329+
func TestBindingV2ConvertedV1TestABI(t *testing.T) {
330+
tc := abiBindTestCase
331+
fname := fmt.Sprintf("testdata/v2/%v-abi.go.txt", strings.ToLower(tc.name))
332+
t.Run(tc.name, func(t *testing.T) {
333+
if tc.types == nil {
334+
tc.types = []string{tc.name}
335+
}
336+
have, err := bindABI(&tc)
337+
if err != nil {
338+
t.Fatalf("got error from bindCombinedJSON: %v", err)
339+
}
340+
// Set this environment variable to regenerate the test outputs.
341+
if os.Getenv("WRITE_TEST_FILES") != "" {
342+
if err := os.WriteFile((fname), []byte(have), 0666); err != nil {
343+
t.Fatalf("err writing expected output to file: %v\n", err)
344+
}
345+
}
346+
// Verify the generated code
347+
want, err := os.ReadFile(fname)
348+
if err != nil {
349+
t.Fatalf("failed to read file %v", fname)
350+
}
351+
if have != string(want) {
352+
t.Fatalf("wrong output: %v", prettyDiff(have, string(want)))
353+
}
354+
})
355+
}
356+
294357
func TestNormalizeArgs(t *testing.T) {
295358
type normalizeArgsTc struct {
296359
inp []string
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Code generated via abigen V2 - DO NOT EDIT.
2+
// This file is a generated binding and any manual changes will be lost.
3+
4+
package convertedv1bindtests
5+
6+
import (
7+
"errors"
8+
"math/big"
9+
10+
"github.com/ethereum/go-ethereum/accounts/abi"
11+
"github.com/ethereum/go-ethereum/accounts/abi/bind/v2"
12+
"github.com/ethereum/go-ethereum/common"
13+
"github.com/ethereum/go-ethereum/core/types"
14+
)
15+
16+
// Reference imports to suppress errors if they are not otherwise used.
17+
var (
18+
_ = errors.New
19+
_ = big.NewInt
20+
_ = common.Big1
21+
_ = types.BloomLookup
22+
_ = abi.ConvertType
23+
)
24+
25+
// Struct0 is an auto generated low-level Go binding around an user-defined struct.
26+
type Struct0 struct {
27+
B [32]byte
28+
}
29+
30+
// StructsMetaData contains all meta data concerning the Structs contract.
31+
var StructsMetaData = bind.MetaData{
32+
ABI: "[{\"inputs\":[],\"name\":\"F\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[]\",\"name\":\"c\",\"type\":\"uint256[]\"},{\"internalType\":\"bool[]\",\"name\":\"d\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"G\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"B\",\"type\":\"bytes32\"}],\"internalType\":\"structStructs.A[]\",\"name\":\"a\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
33+
}
34+
35+
// Structs is an auto generated Go binding around an Ethereum contract.
36+
type Structs struct {
37+
abi abi.ABI
38+
}
39+
40+
// NewStructs creates a new instance of Structs.
41+
func NewStructs() *Structs {
42+
parsed, err := StructsMetaData.ParseABI()
43+
if err != nil {
44+
panic(errors.New("invalid ABI: " + err.Error()))
45+
}
46+
return &Structs{abi: *parsed}
47+
}
48+
49+
// Instance creates a wrapper for a deployed contract instance at the given address.
50+
// Use this to create the instance object passed to abigen v2 library functions Call, Transact, etc.
51+
func (c *Structs) Instance(backend bind.ContractBackend, addr common.Address) *bind.BoundContract {
52+
return bind.NewContractInstance(backend, addr, c.abi)
53+
}
54+
55+
// F is a free data retrieval call binding the contract method 0x28811f59.
56+
//
57+
// Solidity: function F() view returns((bytes32)[] a, uint256[] c, bool[] d)
58+
func (structs *Structs) PackF() []byte {
59+
enc, err := structs.abi.Pack("F")
60+
if err != nil {
61+
panic(err)
62+
}
63+
return enc
64+
}
65+
66+
type FOutput struct {
67+
A []Struct0
68+
C []*big.Int
69+
D []bool
70+
}
71+
72+
func (structs *Structs) UnpackF(data []byte) (FOutput, error) {
73+
out, err := structs.abi.Unpack("F", data)
74+
75+
outstruct := new(FOutput)
76+
if err != nil {
77+
return *outstruct, err
78+
}
79+
80+
outstruct.A = *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
81+
82+
outstruct.C = *abi.ConvertType(out[1], new([]*big.Int)).(*[]*big.Int)
83+
84+
outstruct.D = *abi.ConvertType(out[2], new([]bool)).(*[]bool)
85+
86+
return *outstruct, err
87+
88+
}
89+
90+
// G is a free data retrieval call binding the contract method 0x6fecb623.
91+
//
92+
// Solidity: function G() view returns((bytes32)[] a)
93+
func (structs *Structs) PackG() []byte {
94+
enc, err := structs.abi.Pack("G")
95+
if err != nil {
96+
panic(err)
97+
}
98+
return enc
99+
}
100+
101+
func (structs *Structs) UnpackG(data []byte) ([]Struct0, error) {
102+
out, err := structs.abi.Unpack("G", data)
103+
104+
if err != nil {
105+
return *new([]Struct0), err
106+
}
107+
108+
out0 := *abi.ConvertType(out[0], new([]Struct0)).(*[]Struct0)
109+
110+
return out0, err
111+
112+
}

0 commit comments

Comments
 (0)