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