accounts/abi/bind: make link test case failure output the index of the subtest that failed.

This commit is contained in:
Jared Wasinger 2024-12-19 17:00:13 +07:00 committed by Felix Lange
parent b4f1a3c009
commit 7f301229bf
2 changed files with 175 additions and 30 deletions

View file

@ -0,0 +1,124 @@
package bind
import (
"fmt"
"testing"
"github.com/ethereum/go-ethereum/crypto"
)
type bindV2Test struct {
name string
abis []string
bytecodes []string
types []string
expectedBindings string
}
func bind(test *bindV2Test) (bound string, err error) {
var (
abis []string
bins []string
types []string
)
libs := make(map[string]string)
for i := 0; i < len(test.types); i++ {
// fully qualified name is of the form <solFilePath>:<type>
typeName := test.types[i]
bin := test.bytecodes[i]
abis = append(abis, test.abis[i])
bins = append(bins, bin)
types = append(types, typeName)
// Derive the library placeholder which is a 34 character prefix of the
// hex encoding of the keccak256 hash of the fully qualified library name.
// Note that the fully qualified library name is the path of its source
// file and the library name separated by ":".
libPattern := crypto.Keccak256Hash([]byte(typeName)).String()[2:36] // the first 2 chars are 0x
libs[libPattern] = typeName
}
code, err := BindV2(types, abis, bins, "bindv2test", libs, make(map[string]string))
if err != nil {
return "", fmt.Errorf("error creating bindings: %v", err)
}
return code, nil
}
var bindTests2 = []bindV2Test{
{
"Empty",
[]string{`[]`},
[]string{`606060405260068060106000396000f3606060405200`},
nil,
`// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindv2test
import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
`,
},
{
"Token",
[]string{`[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"spentAllowance","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"inputs":[{"name":"initialSupply","type":"uint256"},{"name":"tokenName","type":"string"},{"name":"decimalUnits","type":"uint8"},{"name":"tokenSymbol","type":"string"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]`},
[]string{`60606040526040516107fd3803806107fd83398101604052805160805160a05160c051929391820192909101600160a060020a0333166000908152600360209081526040822086905581548551838052601f6002600019610100600186161502019093169290920482018390047f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56390810193919290918801908390106100e857805160ff19168380011785555b506101189291505b8082111561017157600081556001016100b4565b50506002805460ff19168317905550505050610658806101a56000396000f35b828001600101855582156100ac579182015b828111156100ac5782518260005055916020019190600101906100fa565b50508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017557805160ff19168380011785555b506100c89291506100b4565b5090565b82800160010185558215610165579182015b8281111561016557825182600050559160200191906001019061018756606060405236156100775760e060020a600035046306fdde03811461007f57806323b872dd146100dc578063313ce5671461010e57806370a082311461011a57806395d89b4114610132578063a9059cbb1461018e578063cae9ca51146101bd578063dc3080f21461031c578063dd62ed3e14610341575b610365610002565b61036760008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b6103d5600435602435604435600160a060020a038316600090815260036020526040812054829010156104f357610002565b6103e760025460ff1681565b6103d560043560036020526000908152604090205481565b610367600180546020600282841615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b610365600435602435600160a060020a033316600090815260036020526040902054819010156103f157610002565b60806020604435600481810135601f8101849004909302840160405260608381526103d5948235946024803595606494939101919081908382808284375094965050505050505060006000836004600050600033600160a060020a03168152602001908152602001600020600050600087600160a060020a031681526020019081526020016000206000508190555084905080600160a060020a0316638f4ffcb1338630876040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a03168152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156102f25780820380516001836020036101000a031916815260200191505b50955050505050506000604051808303816000876161da5a03f11561000257505050509392505050565b6005602090815260043560009081526040808220909252602435815220546103d59081565b60046020818152903560009081526040808220909252602435815220546103d59081565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103c75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a03821660009081526040902054808201101561041357610002565b806003600050600033600160a060020a03168152602001908152602001600020600082828250540392505081905550806003600050600084600160a060020a0316815260200190815260200160002060008282825054019250508190555081600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b820191906000526020600020905b8154815290600101906020018083116104ce57829003601f168201915b505050505081565b600160a060020a03831681526040812054808301101561051257610002565b600160a060020a0380851680835260046020908152604080852033949094168086529382528085205492855260058252808520938552929052908220548301111561055c57610002565b816003600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816003600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816005600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054019250508190555082600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3939250505056`},
nil,
`// Code generated via abigen V2 - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindv2test
import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = abi.ConvertType
)
`,
},
}
func TestBindingV2(t *testing.T) {
for _, tc := range bindTests2 {
code, err := bind(&tc)
if err != nil {
t.Fatalf("got error from bind: %v", err)
}
if code != tc.expectedBindings {
t.Fatalf("'%s'\n!=\n'%s'\n", code, tc.expectedBindings)
}
}
}

View file

@ -124,7 +124,7 @@ func __linkDeps(metadata MetaData, depMap map[string]*MetaData, roots *map[strin
return linked
}
func testLinkCase(t *testing.T, tcInput linkTestCaseInput) {
func testLinkCase(tcInput linkTestCaseInput) error {
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
var testAddrNonce uint64
overridesAddrs := make(map[common.Address]struct{})
@ -159,7 +159,7 @@ func testLinkCase(t *testing.T, tcInput linkTestCaseInput) {
var dep common.Address
dep.SetBytes(deployer[i : i+20])
if _, ok := overridesAddrs[dep]; !ok {
t.Fatalf("reference to dependent contract that has not yet been deployed: %x\n", dep)
return common.Address{}, nil, fmt.Errorf("reference to dependent contract that has not yet been deployed: %x\n", dep)
}
}
}
@ -190,55 +190,60 @@ func testLinkCase(t *testing.T, tcInput linkTestCaseInput) {
deployParams := NewDeploymentParams(contractsList, nil, overrides)
res, err := LinkAndDeploy(deployParams, mockDeploy)
if err != nil {
t.Fatalf("got error from LinkAndDeploy: %v\n", err)
return err
}
if len(res.Txs) != len(tcInput.expectDeployed) {
t.Fatalf("got %d deployed contracts. expected %d.\n", len(res.Addrs), len(tcInput.expectDeployed))
return fmt.Errorf("got %d deployed contracts. expected %d.\n", len(res.Addrs), len(tcInput.expectDeployed))
}
for contract, _ := range tcInput.expectDeployed {
pattern := crypto.Keccak256Hash([]byte(string(contract))).String()[2:36]
if _, ok := res.Addrs[pattern]; !ok {
t.Fatalf("expected contract %s was not deployed\n", string(contract))
return fmt.Errorf("expected contract %s was not deployed\n", string(contract))
}
}
return nil
}
func TestContractLinking(t *testing.T) {
var linkTestCases = []linkTestCaseInput{
// test simple contract without any dependencies or overrides
testLinkCase(t, linkTestCaseInput{
{
map[rune][]rune{
'a': {}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}}})
'a': {}},
},
// test deployment of a contract that depends on somes libraries.
testLinkCase(t, linkTestCaseInput{
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}}})
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}},
},
// test deployment of a contract that depends on some libraries,
// one of which has its own library dependencies.
testLinkCase(t, linkTestCaseInput{
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'e': {'f', 'g', 'h', 'i'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}}})
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}},
},
// test single contract only without deps
testLinkCase(t, linkTestCaseInput{
{
map[rune][]rune{
'a': {}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {},
}})
},
},
// test that libraries at different levels of the tree can share deps,
// and that these shared deps will only be deployed once.
testLinkCase(t, linkTestCaseInput{
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'e': {'f', 'g', 'h', 'i', 'm'},
@ -246,56 +251,63 @@ func TestContractLinking(t *testing.T) {
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}, 'j': {}, 'k': {}, 'l': {}, 'm': {},
}})
},
},
// test two contracts can be deployed which don't share deps
testLinkCase(t, linkTestCaseInput{
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'f': {'g', 'h', 'i', 'j'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'i': {}, 'j': {},
}})
},
},
// test two contracts can be deployed which share deps
testLinkCase(t, linkTestCaseInput{
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'f': {'g', 'c', 'd', 'h'}},
map[rune]struct{}{},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {},
}})
},
},
// test one contract with overrides for all lib deps
testLinkCase(t, linkTestCaseInput{
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'}},
map[rune]struct{}{'b': {}, 'c': {}, 'd': {}, 'e': {}},
map[rune]struct{}{
'a': {}}})
'a': {}},
},
// test one contract with overrides for some lib deps
testLinkCase(t, linkTestCaseInput{
linkTestCaseInput{
map[rune][]rune{
'a': {'b', 'c'}},
map[rune]struct{}{'b': {}, 'c': {}},
map[rune]struct{}{
'a': {}}})
'a': {}},
},
// test deployment of a contract with overrides
testLinkCase(t, linkTestCaseInput{
linkTestCaseInput{
map[rune][]rune{
'a': {}},
map[rune]struct{}{'a': {}},
map[rune]struct{}{}})
map[rune]struct{}{},
},
// two contracts ('a' and 'f') share some dependencies. contract 'a' is marked as an override. expect that any of
// its depdencies that aren't shared with 'f' are not deployed.
testLinkCase(t, linkTestCaseInput{map[rune][]rune{
linkTestCaseInput{map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'f': {'g', 'c', 'd', 'h'}},
map[rune]struct{}{'a': {}},
map[rune]struct{}{
'f': {}, 'g': {}, 'c': {}, 'd': {}, 'h': {}}})
'f': {}, 'g': {}, 'c': {}, 'd': {}, 'h': {}},
},
// test nested libraries that share deps at different levels of the tree... with override.
// same condition as above test: no sub-dependencies of
testLinkCase(t, linkTestCaseInput{
{
map[rune][]rune{
'a': {'b', 'c', 'd', 'e'},
'e': {'f', 'g', 'h', 'i', 'm'},
@ -305,5 +317,14 @@ func TestContractLinking(t *testing.T) {
'i': {},
},
map[rune]struct{}{
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'm': {}}})
'a': {}, 'b': {}, 'c': {}, 'd': {}, 'e': {}, 'f': {}, 'g': {}, 'h': {}, 'm': {}},
},
}
func TestContractLinking(t *testing.T) {
for i, tc := range linkTestCases {
if err := testLinkCase(tc); err != nil {
t.Fatalf("test case %d failed: %v", i, err)
}
}
}