github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/cmd/ethtest/main.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // ethtest executes Ethereum JSON tests. 18 package main 19 20 import ( 21 "fmt" 22 "io" 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "strings" 27 28 "github.com/codegangsta/cli" 29 "github.com/ethereum/go-ethereum/core/vm" 30 "github.com/ethereum/go-ethereum/logger/glog" 31 "github.com/ethereum/go-ethereum/tests" 32 ) 33 34 var ( 35 continueOnError = false 36 testExtension = ".json" 37 defaultTest = "all" 38 defaultDir = "." 39 allTests = []string{"BlockTests", "StateTests", "TransactionTests", "VMTests", "RLPTests"} 40 testDirMapping = map[string]string{"BlockTests": "BlockchainTests"} 41 skipTests = []string{} 42 43 TestFlag = cli.StringFlag{ 44 Name: "test", 45 Usage: "Test type (string): VMTests, TransactionTests, StateTests, BlockTests", 46 Value: defaultTest, 47 } 48 FileFlag = cli.StringFlag{ 49 Name: "file", 50 Usage: "Test file or directory. Directories are searched for .json files 1 level deep", 51 Value: defaultDir, 52 EnvVar: "ETHEREUM_TEST_PATH", 53 } 54 ContinueOnErrorFlag = cli.BoolFlag{ 55 Name: "continue", 56 Usage: "Continue running tests on error (true) or [default] exit immediately (false)", 57 } 58 ReadStdInFlag = cli.BoolFlag{ 59 Name: "stdin", 60 Usage: "Accept input from stdin instead of reading from file", 61 } 62 SkipTestsFlag = cli.StringFlag{ 63 Name: "skip", 64 Usage: "Tests names to skip", 65 } 66 TraceFlag = cli.BoolFlag{ 67 Name: "trace", 68 Usage: "Enable VM tracing", 69 } 70 ) 71 72 func runTestWithReader(test string, r io.Reader) error { 73 glog.Infoln("runTest", test) 74 var err error 75 switch strings.ToLower(test) { 76 case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests": 77 err = tests.RunBlockTestWithReader(r, skipTests) 78 case "st", "state", "statetest", "statetests": 79 err = tests.RunStateTestWithReader(r, skipTests) 80 case "tx", "transactiontest", "transactiontests": 81 err = tests.RunTransactionTestsWithReader(r, skipTests) 82 case "vm", "vmtest", "vmtests": 83 err = tests.RunVmTestWithReader(r, skipTests) 84 case "rlp", "rlptest", "rlptests": 85 err = tests.RunRLPTestWithReader(r, skipTests) 86 default: 87 err = fmt.Errorf("Invalid test type specified: %v", test) 88 } 89 90 if err != nil { 91 return err 92 } 93 94 return nil 95 } 96 97 func getFiles(path string) ([]string, error) { 98 glog.Infoln("getFiles", path) 99 var files []string 100 f, err := os.Open(path) 101 if err != nil { 102 return nil, err 103 } 104 defer f.Close() 105 106 fi, err := f.Stat() 107 if err != nil { 108 return nil, err 109 } 110 111 switch mode := fi.Mode(); { 112 case mode.IsDir(): 113 fi, _ := ioutil.ReadDir(path) 114 files = make([]string, len(fi)) 115 for i, v := range fi { 116 // only go 1 depth and leave directory entires blank 117 if !v.IsDir() && v.Name()[len(v.Name())-len(testExtension):len(v.Name())] == testExtension { 118 files[i] = filepath.Join(path, v.Name()) 119 glog.Infoln("Found file", files[i]) 120 } 121 } 122 case mode.IsRegular(): 123 files = make([]string, 1) 124 files[0] = path 125 } 126 127 return files, nil 128 } 129 130 func runSuite(test, file string) { 131 var tests []string 132 133 if test == defaultTest { 134 tests = allTests 135 } else { 136 tests = []string{test} 137 } 138 139 for _, curTest := range tests { 140 glog.Infoln("runSuite", curTest, file) 141 var err error 142 var files []string 143 if test == defaultTest { 144 // check if we have an explicit directory mapping for the test 145 if _, ok := testDirMapping[curTest]; ok { 146 files, err = getFiles(filepath.Join(file, testDirMapping[curTest])) 147 } else { 148 // otherwise assume test name 149 files, err = getFiles(filepath.Join(file, curTest)) 150 } 151 } else { 152 files, err = getFiles(file) 153 } 154 if err != nil { 155 glog.Fatalln(err) 156 } 157 158 if len(files) == 0 { 159 glog.Warningln("No files matched path") 160 } 161 for _, curFile := range files { 162 // Skip blank entries 163 if len(curFile) == 0 { 164 continue 165 } 166 167 r, err := os.Open(curFile) 168 if err != nil { 169 glog.Fatalln(err) 170 } 171 defer r.Close() 172 173 err = runTestWithReader(curTest, r) 174 if err != nil { 175 if continueOnError { 176 glog.Errorln(err) 177 } else { 178 glog.Fatalln(err) 179 } 180 } 181 } 182 } 183 } 184 185 func setupApp(c *cli.Context) { 186 flagTest := c.GlobalString(TestFlag.Name) 187 flagFile := c.GlobalString(FileFlag.Name) 188 continueOnError = c.GlobalBool(ContinueOnErrorFlag.Name) 189 useStdIn := c.GlobalBool(ReadStdInFlag.Name) 190 skipTests = strings.Split(c.GlobalString(SkipTestsFlag.Name), " ") 191 vm.Debug = c.GlobalBool(TraceFlag.Name) 192 193 if !useStdIn { 194 runSuite(flagTest, flagFile) 195 } else { 196 if err := runTestWithReader(flagTest, os.Stdin); err != nil { 197 glog.Fatalln(err) 198 } 199 200 } 201 } 202 203 func main() { 204 glog.SetToStderr(true) 205 206 app := cli.NewApp() 207 app.Name = "ethtest" 208 app.Usage = "go-ethereum test interface" 209 app.Action = setupApp 210 app.Version = "0.2.0" 211 app.Author = "go-ethereum team" 212 213 app.Flags = []cli.Flag{ 214 TestFlag, 215 FileFlag, 216 ContinueOnErrorFlag, 217 ReadStdInFlag, 218 SkipTestsFlag, 219 TraceFlag, 220 } 221 222 if err := app.Run(os.Args); err != nil { 223 glog.Fatalln(err) 224 } 225 226 }