github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/tests/init_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:50</date> 10 //</624342685875965952> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package tests 29 30 import ( 31 "encoding/json" 32 "fmt" 33 "io" 34 "io/ioutil" 35 "os" 36 "path/filepath" 37 "reflect" 38 "regexp" 39 "sort" 40 "strings" 41 "testing" 42 43 "github.com/ethereum/go-ethereum/params" 44 ) 45 46 var ( 47 baseDir = filepath.Join(".", "testdata") 48 blockTestDir = filepath.Join(baseDir, "BlockchainTests") 49 stateTestDir = filepath.Join(baseDir, "GeneralStateTests") 50 transactionTestDir = filepath.Join(baseDir, "TransactionTests") 51 vmTestDir = filepath.Join(baseDir, "VMTests") 52 rlpTestDir = filepath.Join(baseDir, "RLPTests") 53 difficultyTestDir = filepath.Join(baseDir, "BasicTests") 54 ) 55 56 func readJSON(reader io.Reader, value interface{}) error { 57 data, err := ioutil.ReadAll(reader) 58 if err != nil { 59 return fmt.Errorf("error reading JSON file: %v", err) 60 } 61 if err = json.Unmarshal(data, &value); err != nil { 62 if syntaxerr, ok := err.(*json.SyntaxError); ok { 63 line := findLine(data, syntaxerr.Offset) 64 return fmt.Errorf("JSON syntax error at line %v: %v", line, err) 65 } 66 return err 67 } 68 return nil 69 } 70 71 func readJSONFile(fn string, value interface{}) error { 72 file, err := os.Open(fn) 73 if err != nil { 74 return err 75 } 76 defer file.Close() 77 78 err = readJSON(file, value) 79 if err != nil { 80 return fmt.Errorf("%s in file %s", err.Error(), fn) 81 } 82 return nil 83 } 84 85 // 86 func findLine(data []byte, offset int64) (line int) { 87 line = 1 88 for i, r := range string(data) { 89 if int64(i) >= offset { 90 return 91 } 92 if r == '\n' { 93 line++ 94 } 95 } 96 return 97 } 98 99 // 100 type testMatcher struct { 101 configpat []testConfig 102 failpat []testFailure 103 skiploadpat []*regexp.Regexp 104 skipshortpat []*regexp.Regexp 105 } 106 107 type testConfig struct { 108 p *regexp.Regexp 109 config params.ChainConfig 110 } 111 112 type testFailure struct { 113 p *regexp.Regexp 114 reason string 115 } 116 117 // 118 func (tm *testMatcher) skipShortMode(pattern string) { 119 tm.skipshortpat = append(tm.skipshortpat, regexp.MustCompile(pattern)) 120 } 121 122 // 123 func (tm *testMatcher) skipLoad(pattern string) { 124 tm.skiploadpat = append(tm.skiploadpat, regexp.MustCompile(pattern)) 125 } 126 127 // 128 func (tm *testMatcher) fails(pattern string, reason string) { 129 if reason == "" { 130 panic("empty fail reason") 131 } 132 tm.failpat = append(tm.failpat, testFailure{regexp.MustCompile(pattern), reason}) 133 } 134 135 // 136 func (tm *testMatcher) config(pattern string, cfg params.ChainConfig) { 137 tm.configpat = append(tm.configpat, testConfig{regexp.MustCompile(pattern), cfg}) 138 } 139 140 // 141 func (tm *testMatcher) findSkip(name string) (reason string, skipload bool) { 142 if testing.Short() { 143 for _, re := range tm.skipshortpat { 144 if re.MatchString(name) { 145 return "skipped in -short mode", false 146 } 147 } 148 } 149 for _, re := range tm.skiploadpat { 150 if re.MatchString(name) { 151 return "skipped by skipLoad", true 152 } 153 } 154 return "", false 155 } 156 157 // 158 func (tm *testMatcher) findConfig(name string) *params.ChainConfig { 159 // 160 for _, m := range tm.configpat { 161 if m.p.MatchString(name) { 162 return &m.config 163 } 164 } 165 return new(params.ChainConfig) 166 } 167 168 // 169 func (tm *testMatcher) checkFailure(t *testing.T, name string, err error) error { 170 // 171 failReason := "" 172 for _, m := range tm.failpat { 173 if m.p.MatchString(name) { 174 failReason = m.reason 175 break 176 } 177 } 178 if failReason != "" { 179 t.Logf("expected failure: %s", failReason) 180 if err != nil { 181 t.Logf("error: %v", err) 182 return nil 183 } 184 return fmt.Errorf("test succeeded unexpectedly") 185 } 186 return err 187 } 188 189 // 190 // 191 // 192 // 193 func (tm *testMatcher) walk(t *testing.T, dir string, runTest interface{}) { 194 // 195 dirinfo, err := os.Stat(dir) 196 if os.IsNotExist(err) || !dirinfo.IsDir() { 197 fmt.Fprintf(os.Stderr, "can't find test files in %s, did you clone the tests submodule?\n", dir) 198 t.Skip("missing test files") 199 } 200 err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 201 name := filepath.ToSlash(strings.TrimPrefix(path, dir+string(filepath.Separator))) 202 if info.IsDir() { 203 if _, skipload := tm.findSkip(name + "/"); skipload { 204 return filepath.SkipDir 205 } 206 return nil 207 } 208 if filepath.Ext(path) == ".json" { 209 t.Run(name, func(t *testing.T) { tm.runTestFile(t, path, name, runTest) }) 210 } 211 return nil 212 }) 213 if err != nil { 214 t.Fatal(err) 215 } 216 } 217 218 func (tm *testMatcher) runTestFile(t *testing.T, path, name string, runTest interface{}) { 219 if r, _ := tm.findSkip(name); r != "" { 220 t.Skip(r) 221 } 222 t.Parallel() 223 224 // 225 m := makeMapFromTestFunc(runTest) 226 if err := readJSONFile(path, m.Addr().Interface()); err != nil { 227 t.Fatal(err) 228 } 229 230 // 231 keys := sortedMapKeys(m) 232 if len(keys) == 1 { 233 runTestFunc(runTest, t, name, m, keys[0]) 234 } else { 235 for _, key := range keys { 236 name := name + "/" + key 237 t.Run(key, func(t *testing.T) { 238 if r, _ := tm.findSkip(name); r != "" { 239 t.Skip(r) 240 } 241 runTestFunc(runTest, t, name, m, key) 242 }) 243 } 244 } 245 } 246 247 func makeMapFromTestFunc(f interface{}) reflect.Value { 248 stringT := reflect.TypeOf("") 249 testingT := reflect.TypeOf((*testing.T)(nil)) 250 ftyp := reflect.TypeOf(f) 251 if ftyp.Kind() != reflect.Func || ftyp.NumIn() != 3 || ftyp.NumOut() != 0 || ftyp.In(0) != testingT || ftyp.In(1) != stringT { 252 panic(fmt.Sprintf("bad test function type: want func(*testing.T, string, <TestType>), have %s", ftyp)) 253 } 254 testType := ftyp.In(2) 255 mp := reflect.New(reflect.MapOf(stringT, testType)) 256 return mp.Elem() 257 } 258 259 func sortedMapKeys(m reflect.Value) []string { 260 keys := make([]string, m.Len()) 261 for i, k := range m.MapKeys() { 262 keys[i] = k.String() 263 } 264 sort.Strings(keys) 265 return keys 266 } 267 268 func runTestFunc(runTest interface{}, t *testing.T, name string, m reflect.Value, key string) { 269 reflect.ValueOf(runTest).Call([]reflect.Value{ 270 reflect.ValueOf(t), 271 reflect.ValueOf(name), 272 m.MapIndex(reflect.ValueOf(key)), 273 }) 274 } 275