Source file
src/runtime/profbuf_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 . "runtime"
9 "slices"
10 "testing"
11 "time"
12 "unsafe"
13 )
14
15 func TestProfBuf(t *testing.T) {
16 const hdrSize = 2
17
18 write := func(t *testing.T, b *ProfBuf, tag unsafe.Pointer, now int64, hdr []uint64, stk []uintptr) {
19 b.Write(&tag, now, hdr, stk)
20 }
21 read := func(t *testing.T, b *ProfBuf, data []uint64, tags []unsafe.Pointer) {
22 rdata, rtags, eof := b.Read(ProfBufNonBlocking)
23 if !slices.Equal(rdata, data) || !slices.Equal(rtags, tags) {
24 t.Fatalf("unexpected profile read:\nhave data %#x\nwant data %#x\nhave tags %#x\nwant tags %#x", rdata, data, rtags, tags)
25 }
26 if eof {
27 t.Fatalf("unexpected eof")
28 }
29 }
30 readBlock := func(t *testing.T, b *ProfBuf, data []uint64, tags []unsafe.Pointer) func() {
31 c := make(chan int)
32 go func() {
33 eof := data == nil
34 rdata, rtags, reof := b.Read(ProfBufBlocking)
35 if !slices.Equal(rdata, data) || !slices.Equal(rtags, tags) || reof != eof {
36
37 t.Errorf("unexpected profile read:\nhave data %#x\nwant data %#x\nhave tags %#x\nwant tags %#x\nhave eof=%v, want %v", rdata, data, rtags, tags, reof, eof)
38 }
39 c <- 1
40 }()
41 time.Sleep(10 * time.Millisecond)
42 return func() { <-c }
43 }
44 readEOF := func(t *testing.T, b *ProfBuf) {
45 rdata, rtags, eof := b.Read(ProfBufBlocking)
46 if rdata != nil || rtags != nil || !eof {
47 t.Errorf("unexpected profile read: %#x, %#x, eof=%v; want nil, nil, eof=true", rdata, rtags, eof)
48 }
49 rdata, rtags, eof = b.Read(ProfBufNonBlocking)
50 if rdata != nil || rtags != nil || !eof {
51 t.Errorf("unexpected profile read (non-blocking): %#x, %#x, eof=%v; want nil, nil, eof=true", rdata, rtags, eof)
52 }
53 }
54
55 myTags := make([]byte, 100)
56 t.Logf("myTags is %p", &myTags[0])
57
58 t.Run("BasicWriteRead", func(t *testing.T) {
59 b := NewProfBuf(2, 11, 1)
60 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
61 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
62 read(t, b, nil, nil)
63 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
64 read(t, b, []uint64{8, 99, 101, 102, 201, 202, 203, 204}, []unsafe.Pointer{unsafe.Pointer(&myTags[2])})
65 })
66
67 t.Run("ReadMany", func(t *testing.T) {
68 b := NewProfBuf(2, 50, 50)
69 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
70 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
71 write(t, b, unsafe.Pointer(&myTags[1]), 500, []uint64{502, 504}, []uintptr{506})
72 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 99, 101, 102, 201, 202, 203, 204, 5, 500, 502, 504, 506}, []unsafe.Pointer{unsafe.Pointer(&myTags[0]), unsafe.Pointer(&myTags[2]), unsafe.Pointer(&myTags[1])})
73 })
74
75 t.Run("ReadManyShortData", func(t *testing.T) {
76 b := NewProfBuf(2, 50, 50)
77 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
78 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
79 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 99, 101, 102, 201, 202, 203, 204}, []unsafe.Pointer{unsafe.Pointer(&myTags[0]), unsafe.Pointer(&myTags[2])})
80 })
81
82 t.Run("ReadManyShortTags", func(t *testing.T) {
83 b := NewProfBuf(2, 50, 50)
84 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
85 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
86 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 99, 101, 102, 201, 202, 203, 204}, []unsafe.Pointer{unsafe.Pointer(&myTags[0]), unsafe.Pointer(&myTags[2])})
87 })
88
89 t.Run("ReadAfterOverflow1", func(t *testing.T) {
90
91 b := NewProfBuf(2, 16, 5)
92 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
93 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
94 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5})
95 read(t, b, []uint64{6, 1, 2, 3, 4, 5}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
96
97 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204, 205, 206, 207, 208, 209})
98 for i := 0; i < 299; i++ {
99 write(t, b, unsafe.Pointer(&myTags[3]), int64(100+i), []uint64{101, 102}, []uintptr{201, 202, 203, 204})
100 }
101 write(t, b, unsafe.Pointer(&myTags[1]), 500, []uint64{502, 504}, []uintptr{506})
102 read(t, b, []uint64{5, 99, 0, 0, 300, 5, 500, 502, 504, 506}, []unsafe.Pointer{nil, unsafe.Pointer(&myTags[1])})
103 })
104
105 t.Run("ReadAfterOverflow2", func(t *testing.T) {
106
107 b := NewProfBuf(2, 16, 5)
108 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
109 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213})
110 for i := 0; i < 299; i++ {
111 write(t, b, unsafe.Pointer(&myTags[3]), 100, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
112 }
113 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
114 write(t, b, unsafe.Pointer(&myTags[1]), 500, []uint64{502, 504}, []uintptr{})
115 read(t, b, []uint64{5, 99, 0, 0, 301}, []unsafe.Pointer{nil})
116 write(t, b, unsafe.Pointer(&myTags[1]), 500, []uint64{502, 505}, []uintptr{506})
117 read(t, b, []uint64{5, 500, 502, 505, 506}, []unsafe.Pointer{unsafe.Pointer(&myTags[1])})
118 })
119
120 t.Run("ReadAtEndAfterOverflow", func(t *testing.T) {
121 b := NewProfBuf(2, 12, 5)
122 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
123 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
124 for i := 0; i < 299; i++ {
125 write(t, b, unsafe.Pointer(&myTags[3]), 100, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
126 }
127 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
128 read(t, b, []uint64{5, 99, 0, 0, 300}, []unsafe.Pointer{nil})
129 write(t, b, unsafe.Pointer(&myTags[1]), 500, []uint64{502, 504}, []uintptr{506})
130 read(t, b, []uint64{5, 500, 502, 504, 506}, []unsafe.Pointer{unsafe.Pointer(&myTags[1])})
131 })
132
133 t.Run("BlockingWriteRead", func(t *testing.T) {
134 b := NewProfBuf(2, 11, 1)
135 wait := readBlock(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
136 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
137 wait()
138 wait = readBlock(t, b, []uint64{8, 99, 101, 102, 201, 202, 203, 204}, []unsafe.Pointer{unsafe.Pointer(&myTags[2])})
139 time.Sleep(10 * time.Millisecond)
140 write(t, b, unsafe.Pointer(&myTags[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
141 wait()
142 wait = readBlock(t, b, nil, nil)
143 b.Close()
144 wait()
145 wait = readBlock(t, b, nil, nil)
146 wait()
147 readEOF(t, b)
148 })
149
150 t.Run("DataWraparound", func(t *testing.T) {
151 b := NewProfBuf(2, 16, 1024)
152 for i := 0; i < 10; i++ {
153 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
154 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
155 read(t, b, nil, nil)
156 }
157 })
158
159 t.Run("TagWraparound", func(t *testing.T) {
160 b := NewProfBuf(2, 1024, 2)
161 for i := 0; i < 10; i++ {
162 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
163 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
164 read(t, b, nil, nil)
165 }
166 })
167
168 t.Run("BothWraparound", func(t *testing.T) {
169 b := NewProfBuf(2, 16, 2)
170 for i := 0; i < 10; i++ {
171 write(t, b, unsafe.Pointer(&myTags[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
172 read(t, b, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe.Pointer{unsafe.Pointer(&myTags[0])})
173 read(t, b, nil, nil)
174 }
175 })
176 }
177
View as plain text