github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/discv5/sim_run_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:43</date> 10 //</624342657300172800> 11 12 13 package discv5 14 15 import ( 16 "bufio" 17 "bytes" 18 "encoding/binary" 19 "errors" 20 "fmt" 21 "io" 22 "os" 23 "os/exec" 24 "runtime" 25 "strings" 26 "testing" 27 ) 28 29 func getnacl() (string, error) { 30 switch runtime.GOARCH { 31 case "amd64": 32 _, err := exec.LookPath("sel_ldr_x86_64") 33 return "amd64p32", err 34 case "i386": 35 _, err := exec.LookPath("sel_ldr_i386") 36 return "i386", err 37 default: 38 return "", errors.New("nacl is not supported on " + runtime.GOARCH) 39 } 40 } 41 42 //runwithplaygroundtime执行调用方 43 //在启用faketime的nacl沙盒中。 44 // 45 //必须从test*函数调用此函数 46 //当ishost为true时,调用方必须跳过实际测试。 47 func runWithPlaygroundTime(t *testing.T) (isHost bool) { 48 if runtime.GOOS == "nacl" { 49 return false 50 } 51 52 //打电话给对方。 53 callerPC, _, _, ok := runtime.Caller(1) 54 if !ok { 55 panic("can't get caller") 56 } 57 callerFunc := runtime.FuncForPC(callerPC) 58 if callerFunc == nil { 59 panic("can't get caller") 60 } 61 callerName := callerFunc.Name()[strings.LastIndexByte(callerFunc.Name(), '.')+1:] 62 if !strings.HasPrefix(callerName, "Test") { 63 panic("must be called from witin a Test* function") 64 } 65 testPattern := "^" + callerName + "$" 66 67 //不幸的是,runtime.faketime(操场时间模式)只在nacl上工作。氯化钠 68 //必须安装sdk并将其链接到路径才能使其工作。 69 arch, err := getnacl() 70 if err != nil { 71 t.Skip(err) 72 } 73 74 //使用nacl编译并运行调用测试。 75 //额外的标签确保使用了sim_main_test.go中的test main功能。 76 cmd := exec.Command("go", "test", "-v", "-tags", "faketime_simulation", "-timeout", "100h", "-run", testPattern, ".") 77 cmd.Env = append([]string{"GOOS=nacl", "GOARCH=" + arch}, os.Environ()...) 78 stdout, _ := cmd.StdoutPipe() 79 stderr, _ := cmd.StderrPipe() 80 go skipPlaygroundOutputHeaders(os.Stdout, stdout) 81 go skipPlaygroundOutputHeaders(os.Stderr, stderr) 82 if err := cmd.Run(); err != nil { 83 t.Error(err) 84 } 85 86 //确保测试功能不会在(非Nacl)主机进程中运行。 87 return true 88 } 89 90 func skipPlaygroundOutputHeaders(out io.Writer, in io.Reader) { 91 //附加输出可以不打印标题 92 //在Nacl二进制文件开始运行之前(例如编译器错误消息)。 93 bufin := bufio.NewReader(in) 94 output, err := bufin.ReadBytes(0) 95 output = bytes.TrimSuffix(output, []byte{0}) 96 if len(output) > 0 { 97 out.Write(output) 98 } 99 if err != nil { 100 return 101 } 102 bufin.UnreadByte() 103 104 //回放头:0 0 p b<8字节时间><4字节数据长度> 105 head := make([]byte, 4+8+4) 106 for { 107 if _, err := io.ReadFull(bufin, head); err != nil { 108 if err != io.EOF { 109 fmt.Fprintln(out, "read error:", err) 110 } 111 return 112 } 113 if !bytes.HasPrefix(head, []byte{0x00, 0x00, 'P', 'B'}) { 114 fmt.Fprintf(out, "expected playback header, got %q\n", head) 115 io.Copy(out, bufin) 116 return 117 } 118 //将数据复制到下一个标题。 119 size := binary.BigEndian.Uint32(head[12:]) 120 io.CopyN(out, bufin, int64(size)) 121 } 122 } 123