github.com/datachainlab/burrow@v0.25.0/deploy/compile/compilers_test.go (about)

     1  package compile
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/hyperledger/burrow/logging"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  // full solc response object
    16  // individual contract items
    17  type SolcItem struct {
    18  	Bin string `json:"bin"`
    19  	Abi string `json:"abi"`
    20  }
    21  
    22  type SolcResponse struct {
    23  	Contracts map[string]*SolcItem `mapstructure:"contracts" json:"contracts"`
    24  	Version   string               `mapstructure:"version" json:"version"` // json encoded
    25  }
    26  
    27  func BlankSolcItem() *SolcItem {
    28  	return &SolcItem{}
    29  }
    30  
    31  func BlankSolcResponse() *SolcResponse {
    32  	return &SolcResponse{
    33  		Version:   "",
    34  		Contracts: make(map[string]*SolcItem),
    35  	}
    36  }
    37  
    38  func TestLocalMulti(t *testing.T) {
    39  	os.Chdir(testContractPath()) // important to maintain relative paths
    40  
    41  	expectedSolcResponse := BlankSolcResponse()
    42  	actualOutput, err := exec.Command("solc", "--combined-json", "bin,abi", "contractImport1.sol").CombinedOutput()
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  
    47  	warning, responseJSON := extractWarningJSON(strings.TrimSpace(string(actualOutput)))
    48  	err = json.Unmarshal([]byte(responseJSON), expectedSolcResponse)
    49  
    50  	respItemArray := make([]ResponseItem, 0)
    51  
    52  	for contract, item := range expectedSolcResponse.Contracts {
    53  		respItem := ResponseItem{
    54  			Objectname: objectName(strings.TrimSpace(contract)),
    55  		}
    56  		respItem.Contract.Evm.Bytecode.Object = item.Bin
    57  		respItemArray = append(respItemArray, respItem)
    58  	}
    59  	expectedResponse := &Response{
    60  		Objects: respItemArray,
    61  		Warning: warning,
    62  		Version: "",
    63  		Error:   "",
    64  	}
    65  	resp, err := Compile("contractImport1.sol", false, "", make(map[string]string), logging.NewNoopLogger())
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	allClear := true
    70  	for _, object := range expectedResponse.Objects {
    71  		if !contains(resp.Objects, object) {
    72  			allClear = false
    73  		}
    74  	}
    75  	if !allClear {
    76  		t.Errorf("Got incorrect response, expected %v, \n\n got %v", expectedResponse, resp)
    77  	}
    78  }
    79  
    80  func TestLocalSingle(t *testing.T) {
    81  	os.Chdir(testContractPath()) // important to maintain relative paths
    82  
    83  	expectedSolcResponse := BlankSolcResponse()
    84  
    85  	shellCmd := exec.Command("solc", "--combined-json", "bin,abi", "simpleContract.sol")
    86  	actualOutput, err := shellCmd.CombinedOutput()
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  
    91  	warning, responseJSON := extractWarningJSON(strings.TrimSpace(string(actualOutput)))
    92  	err = json.Unmarshal([]byte(responseJSON), expectedSolcResponse)
    93  
    94  	respItemArray := make([]ResponseItem, 0)
    95  
    96  	for contract, item := range expectedSolcResponse.Contracts {
    97  		respItem := ResponseItem{
    98  			Objectname: objectName(strings.TrimSpace(contract)),
    99  			Filename:   "simpleContract.sol",
   100  		}
   101  		respItem.Contract.Abi = json.RawMessage(item.Abi)
   102  		respItem.Contract.Evm.Bytecode.Object = item.Bin
   103  		respItem.Contract.Evm.Bytecode.LinkReferences = []byte("{}")
   104  		respItemArray = append(respItemArray, respItem)
   105  	}
   106  	expectedResponse := &Response{
   107  		Objects: respItemArray,
   108  		Warning: warning,
   109  		Version: "",
   110  		Error:   "",
   111  	}
   112  	resp, err := Compile("simpleContract.sol", false, "", make(map[string]string), logging.NewNoopLogger())
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	for i := range resp.Objects {
   117  		resp.Objects[i].Contract.Metadata = ""
   118  		resp.Objects[i].Contract.Devdoc = nil
   119  		resp.Objects[i].Contract.Evm.Bytecode.Opcodes = ""
   120  	}
   121  	assert.Equal(t, expectedResponse, resp)
   122  }
   123  
   124  func TestFaultyContract(t *testing.T) {
   125  	var expectedSolcResponse Response
   126  
   127  	actualOutput, err := exec.Command("solc", "--combined-json", "bin,abi", "faultyContract.sol").CombinedOutput()
   128  	err = json.Unmarshal(actualOutput, expectedSolcResponse)
   129  	t.Log(expectedSolcResponse.Error)
   130  	resp, err := Compile("faultyContract.sol", false, "", make(map[string]string), logging.NewNoopLogger())
   131  	t.Log(resp.Error)
   132  	if err != nil {
   133  		if expectedSolcResponse.Error != resp.Error {
   134  			t.Errorf("Expected %v got %v", expectedSolcResponse.Error, resp.Error)
   135  		}
   136  	}
   137  	output := strings.TrimSpace(string(actualOutput))
   138  	err = json.Unmarshal([]byte(output), expectedSolcResponse)
   139  }
   140  
   141  func testContractPath() string {
   142  	baseDir, _ := os.Getwd()
   143  	return filepath.Join(baseDir, "..", "..", "tests", "compilers_fixtures")
   144  }
   145  
   146  // The solidity 0.4.21 compiler appends something called auxdata to the end of the bin file (this is visible with
   147  // solc --asm). This is a swarm hash of the metadata, and it's always at the end. This includes the path of the
   148  // solidity source file, so it will differ.
   149  func trimAuxdata(bin string) string {
   150  	return bin[:len(bin)-86]
   151  }
   152  
   153  func extractWarningJSON(output string) (warning string, json string) {
   154  	jsonBeginsCertainly := strings.Index(output, `{"contracts":`)
   155  
   156  	if jsonBeginsCertainly > 0 {
   157  		warning = output[:jsonBeginsCertainly]
   158  		json = output[jsonBeginsCertainly:]
   159  	} else {
   160  		json = output
   161  	}
   162  	return
   163  }
   164  
   165  func contains(s []ResponseItem, e ResponseItem) bool {
   166  	for _, a := range s {
   167  		if a.Contract.Evm.Bytecode.Object == e.Contract.Evm.Bytecode.Object {
   168  			return true
   169  		}
   170  	}
   171  	return false
   172  }