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