github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/test/init_test.go (about)

     1  package test
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"reflect"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  var (
    16  	baseDir       = filepath.Join(".", "testdata")
    17  	walletTestDir = filepath.Join(baseDir, "wallet_tests")
    18  	chainTestDir  = filepath.Join(baseDir, "chain_tests")
    19  	txTestDir     = filepath.Join(baseDir, "tx_tests")
    20  )
    21  
    22  func readJSON(reader io.Reader, value interface{}) error {
    23  	data, err := ioutil.ReadAll(reader)
    24  	if err != nil {
    25  		return fmt.Errorf("error reading JSON file: %v", err)
    26  	}
    27  	if err = json.Unmarshal(data, &value); err != nil {
    28  		if syntaxerr, ok := err.(*json.SyntaxError); ok {
    29  			line := findLine(data, syntaxerr.Offset)
    30  			return fmt.Errorf("JSON syntax error at line %v: %v", line, err)
    31  		}
    32  		return err
    33  	}
    34  	return nil
    35  }
    36  
    37  func readJSONFile(fn string, value interface{}) error {
    38  	file, err := os.Open(fn)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	defer file.Close()
    43  
    44  	if err := readJSON(file, value); err != nil {
    45  		return fmt.Errorf("%s in file %s", err.Error(), fn)
    46  	}
    47  	return nil
    48  }
    49  
    50  // findLine returns the line number for the given offset into data.
    51  func findLine(data []byte, offset int64) (line int) {
    52  	line = 1
    53  	for i, r := range string(data) {
    54  		if int64(i) >= offset {
    55  			return
    56  		}
    57  		if r == '\n' {
    58  			line++
    59  		}
    60  	}
    61  	return
    62  }
    63  
    64  // walk invokes its runTest argument for all subtests in the given directory.
    65  //
    66  // runTest should be a function of type func(t *testing.T, name string, x <TestType>),
    67  // where TestType is the type of the test contained in test files.
    68  func walk(t *testing.T, dir string, runTest interface{}) {
    69  	// Walk the directory.
    70  	dirinfo, err := os.Stat(dir)
    71  	if os.IsNotExist(err) || !dirinfo.IsDir() {
    72  		fmt.Fprintf(os.Stderr, "can't find test files in %s\n", dir)
    73  		t.Skip("missing test files")
    74  	}
    75  	err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
    76  		name := filepath.ToSlash(strings.TrimPrefix(path, dir+string(filepath.Separator)))
    77  		if info.IsDir() {
    78  			return nil
    79  		}
    80  		if filepath.Ext(path) == ".json" {
    81  			t.Run(name, func(t *testing.T) { runTestFile(t, path, name, runTest) })
    82  		}
    83  		return nil
    84  	})
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  }
    89  
    90  func runTestFile(t *testing.T, path, name string, runTest interface{}) {
    91  	m := makeMapFromTestFunc(runTest)
    92  	if err := readJSONFile(path, m.Addr().Interface()); err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	runTestFunc(runTest, t, name, m)
    96  }
    97  
    98  func makeMapFromTestFunc(f interface{}) reflect.Value {
    99  	stringT := reflect.TypeOf("")
   100  	testingT := reflect.TypeOf((*testing.T)(nil))
   101  	ftyp := reflect.TypeOf(f)
   102  	if ftyp.Kind() != reflect.Func || ftyp.NumIn() != 3 || ftyp.NumOut() != 0 || ftyp.In(0) != testingT || ftyp.In(1) != stringT {
   103  		panic(fmt.Sprintf("bad test function type: want func(*testing.T, string, <TestType>), have %s", ftyp))
   104  	}
   105  	testType := ftyp.In(2)
   106  	mp := reflect.New(testType)
   107  	return mp.Elem()
   108  }
   109  
   110  func runTestFunc(runTest interface{}, t *testing.T, name string, m reflect.Value) {
   111  	reflect.ValueOf(runTest).Call([]reflect.Value{
   112  		reflect.ValueOf(t),
   113  		reflect.ValueOf(name),
   114  		m,
   115  	})
   116  }