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