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  }