github.com/ethereum/go-ethereum@v1.16.1/accounts/abi/bind/v2/generate_test.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package bind_test
    18  
    19  import (
    20  	"encoding/json"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/ethereum/go-ethereum/accounts/abi/abigen"
    27  	"github.com/ethereum/go-ethereum/cmd/utils"
    28  	"github.com/ethereum/go-ethereum/common/compiler"
    29  	"github.com/ethereum/go-ethereum/crypto"
    30  )
    31  
    32  // Run go generate to recreate the test bindings.
    33  //
    34  //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/db/combined-abi.json -type DBStats -pkg db -out internal/contracts/db/bindings.go
    35  //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/events/combined-abi.json -type C -pkg events -out internal/contracts/events/bindings.go
    36  //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/nested_libraries/combined-abi.json -type C1 -pkg nested_libraries -out internal/contracts/nested_libraries/bindings.go
    37  //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/solc_errors/combined-abi.json -type C -pkg solc_errors -out internal/contracts/solc_errors/bindings.go
    38  //go:generate go run github.com/ethereum/go-ethereum/cmd/abigen -v2 -combined-json internal/contracts/uint256arrayreturn/combined-abi.json -type C -pkg uint256arrayreturn -out internal/contracts/uint256arrayreturn/bindings.go
    39  
    40  // TestBindingGeneration tests that re-running generation of bindings does not result in
    41  // mutations to the binding code.
    42  func TestBindingGeneration(t *testing.T) {
    43  	matches, _ := filepath.Glob("internal/contracts/*")
    44  	var dirs []string
    45  	for _, match := range matches {
    46  		f, _ := os.Stat(match)
    47  		if f.IsDir() {
    48  			dirs = append(dirs, f.Name())
    49  		}
    50  	}
    51  
    52  	for _, dir := range dirs {
    53  		var (
    54  			abis  []string
    55  			bins  []string
    56  			types []string
    57  			libs  = make(map[string]string)
    58  		)
    59  		basePath := filepath.Join("internal/contracts", dir)
    60  		combinedJsonPath := filepath.Join(basePath, "combined-abi.json")
    61  		abiBytes, err := os.ReadFile(combinedJsonPath)
    62  		if err != nil {
    63  			t.Fatalf("error trying to read file %s: %v", combinedJsonPath, err)
    64  		}
    65  		contracts, err := compiler.ParseCombinedJSON(abiBytes, "", "", "", "")
    66  		if err != nil {
    67  			t.Fatalf("Failed to read contract information from json output: %v", err)
    68  		}
    69  
    70  		for name, contract := range contracts {
    71  			// fully qualified name is of the form <solFilePath>:<type>
    72  			nameParts := strings.Split(name, ":")
    73  			typeName := nameParts[len(nameParts)-1]
    74  			abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse
    75  			if err != nil {
    76  				utils.Fatalf("Failed to parse ABIs from compiler output: %v", err)
    77  			}
    78  			abis = append(abis, string(abi))
    79  			bins = append(bins, contract.Code)
    80  			types = append(types, typeName)
    81  
    82  			// Derive the library placeholder which is a 34 character prefix of the
    83  			// hex encoding of the keccak256 hash of the fully qualified library name.
    84  			// Note that the fully qualified library name is the path of its source
    85  			// file and the library name separated by ":".
    86  			libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] // the first 2 chars are 0x
    87  			libs[libPattern] = typeName
    88  		}
    89  		code, err := abigen.BindV2(types, abis, bins, dir, libs, make(map[string]string))
    90  		if err != nil {
    91  			t.Fatalf("error creating bindings for package %s: %v", dir, err)
    92  		}
    93  
    94  		existingBindings, err := os.ReadFile(filepath.Join(basePath, "bindings.go"))
    95  		if err != nil {
    96  			t.Fatalf("ReadFile returned error: %v", err)
    97  		}
    98  		if code != string(existingBindings) {
    99  			t.Fatalf("code mismatch for %s", dir)
   100  		}
   101  	}
   102  }