Source file
src/runtime/time_test.go
1
2
3
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
25
26 testenv.MustInternalLink(t, deadlockBuildTypes)
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
102
103
104 runtimeTimeTimer := reflect.TypeOf(runtime.TimeTimer{})
105 runtimeTimeTimerPtr := reflect.PointerTo(runtimeTimeTimer)
106
107 check := func(name string, typ reflect.Type) {
108 typPtr := reflect.PointerTo(typ)
109 n1 := runtimeTimeTimer.NumField()
110 n2 := typ.NumField()
111 if n1 != n2+1 {
112 t.Errorf("runtime.TimeTimer has %d fields, want %d (%s has %d fields)", n1, n2+1, name, n2)
113 return
114 }
115 for i := 0; i < n2; i++ {
116 f1 := runtimeTimeTimer.Field(i)
117 f2 := typ.Field(i)
118 t1 := f1.Type
119 t2 := f2.Type
120
121 ok := t1 == t2
122 if !ok {
123
124
125
126 if t1.Kind() == reflect.UnsafePointer && t2.Kind() == reflect.Chan {
127 ok = true
128 }
129
130
131 if t1 == runtimeTimeTimerPtr && t2 == typPtr {
132 ok = true
133 }
134 }
135 if !ok {
136 t.Errorf("runtime.Timer field %s %v incompatible with %s field %s %v", f1.Name, t1, name, f2.Name, t2)
137 }
138
139 if f1.Offset != f2.Offset {
140 t.Errorf("runtime.Timer field %s offset %d incompatible with %s field %s offset %d", f1.Name, f1.Offset, name, f2.Name, f2.Offset)
141 }
142 }
143 }
144
145 check("time.Timer", reflect.TypeOf(time.Timer{}))
146 check("time.Ticker", reflect.TypeOf(time.Ticker{}))
147 }
148
View as plain text