github.com/tri-stone/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 }