github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/time_test.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime_test 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "errors" 11 "internal/testenv" 12 "os/exec" 13 "reflect" 14 "runtime" 15 "testing" 16 "time" 17 ) 18 19 func TestFakeTime(t *testing.T) { 20 if runtime.GOOS == "windows" { 21 t.Skip("faketime not supported on windows") 22 } 23 24 // Faketime is advanced in checkdead. External linking brings in cgo, 25 // causing checkdead not working. 26 testenv.MustInternalLink(t, false) 27 28 t.Parallel() 29 30 exe, err := buildTestProg(t, "testfaketime", "-tags=faketime") 31 if err != nil { 32 t.Fatal(err) 33 } 34 35 var stdout, stderr bytes.Buffer 36 cmd := exec.Command(exe) 37 cmd.Stdout = &stdout 38 cmd.Stderr = &stderr 39 40 err = testenv.CleanCmdEnv(cmd).Run() 41 if err != nil { 42 t.Fatalf("exit status: %v\n%s", err, stderr.String()) 43 } 44 45 t.Logf("raw stdout: %q", stdout.String()) 46 t.Logf("raw stderr: %q", stderr.String()) 47 48 f1, err1 := parseFakeTime(stdout.Bytes()) 49 if err1 != nil { 50 t.Fatal(err1) 51 } 52 f2, err2 := parseFakeTime(stderr.Bytes()) 53 if err2 != nil { 54 t.Fatal(err2) 55 } 56 57 const time0 = 1257894000000000000 58 got := [][]fakeTimeFrame{f1, f2} 59 var want = [][]fakeTimeFrame{{ 60 {time0 + 1, "line 2\n"}, 61 {time0 + 1, "line 3\n"}, 62 {time0 + 1e9, "line 5\n"}, 63 {time0 + 1e9, "2009-11-10T23:00:01Z"}, 64 }, { 65 {time0, "line 1\n"}, 66 {time0 + 2, "line 4\n"}, 67 }} 68 if !reflect.DeepEqual(want, got) { 69 t.Fatalf("want %v, got %v", want, got) 70 } 71 } 72 73 type fakeTimeFrame struct { 74 time uint64 75 data string 76 } 77 78 func parseFakeTime(x []byte) ([]fakeTimeFrame, error) { 79 var frames []fakeTimeFrame 80 for len(x) != 0 { 81 if len(x) < 4+8+4 { 82 return nil, errors.New("truncated header") 83 } 84 const magic = "\x00\x00PB" 85 if string(x[:len(magic)]) != magic { 86 return nil, errors.New("bad magic") 87 } 88 x = x[len(magic):] 89 time := binary.BigEndian.Uint64(x) 90 x = x[8:] 91 dlen := binary.BigEndian.Uint32(x) 92 x = x[4:] 93 data := string(x[:dlen]) 94 x = x[dlen:] 95 frames = append(frames, fakeTimeFrame{time, data}) 96 } 97 return frames, nil 98 } 99 100 func TestTimeTimerType(t *testing.T) { 101 // runtime.timeTimer (exported for testing as TimeTimer) 102 // must have time.Timer and time.Ticker as a prefix 103 // (meaning those two must have the same layout). 104 runtimeTimeTimer := reflect.TypeOf(runtime.TimeTimer{}) 105 106 check := func(name string, typ reflect.Type) { 107 n1 := runtimeTimeTimer.NumField() 108 n2 := typ.NumField() 109 if n1 != n2+1 { 110 t.Errorf("runtime.TimeTimer has %d fields, want %d (%s has %d fields)", n1, n2+1, name, n2) 111 return 112 } 113 for i := 0; i < n2; i++ { 114 f1 := runtimeTimeTimer.Field(i) 115 f2 := typ.Field(i) 116 t1 := f1.Type 117 t2 := f2.Type 118 if t1 != t2 && !(t1.Kind() == reflect.UnsafePointer && t2.Kind() == reflect.Chan) { 119 t.Errorf("runtime.Timer field %s %v incompatible with %s field %s %v", f1.Name, t1, name, f2.Name, t2) 120 } 121 if f1.Offset != f2.Offset { 122 t.Errorf("runtime.Timer field %s offset %d incompatible with %s field %s offset %d", f1.Name, f1.Offset, name, f2.Name, f2.Offset) 123 } 124 } 125 } 126 127 check("time.Timer", reflect.TypeOf(time.Timer{})) 128 check("time.Ticker", reflect.TypeOf(time.Ticker{})) 129 }