1 // Copyright 2017 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.
15 func TestProfBuf(t
*testing
.T
) {
18 write
:= func(t
*testing
.T
, b
*ProfBuf
, tag unsafe
.Pointer
, now
int64, hdr
[]uint64, stk
[]uintptr) {
19 b
.Write(&tag
, now
, hdr
, stk
)
21 read
:= func(t
*testing
.T
, b
*ProfBuf
, data
[]uint64, tags
[]unsafe
.Pointer
) {
22 rdata
, rtags
, eof
:= b
.Read(ProfBufNonBlocking
)
23 if !reflect
.DeepEqual(rdata
, data
) ||
!reflect
.DeepEqual(rtags
, tags
) {
24 t
.Fatalf("unexpected profile read:\nhave data %#x\nwant data %#x\nhave tags %#x\nwant tags %#x", rdata
, data
, rtags
, tags
)
27 t
.Fatalf("unexpected eof")
30 readBlock
:= func(t
*testing
.T
, b
*ProfBuf
, data
[]uint64, tags
[]unsafe
.Pointer
) func() {
34 rdata
, rtags
, reof
:= b
.Read(ProfBufBlocking
)
35 if !reflect
.DeepEqual(rdata
, data
) ||
!reflect
.DeepEqual(rtags
, tags
) || reof
!= eof
{
36 // Errorf, not Fatalf, because called in goroutine.
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
)
41 time
.Sleep(10 * time
.Millisecond
) // let goroutine run and block
45 case <-time
.After(1 * time
.Second
):
46 t
.Fatalf("timeout waiting for blocked read")
50 readEOF
:= func(t
*testing
.T
, b
*ProfBuf
) {
51 rdata
, rtags
, eof
:= b
.Read(ProfBufBlocking
)
52 if rdata
!= nil || rtags
!= nil ||
!eof
{
53 t
.Errorf("unexpected profile read: %#x, %#x, eof=%v; want nil, nil, eof=true", rdata
, rtags
, eof
)
55 rdata
, rtags
, eof
= b
.Read(ProfBufNonBlocking
)
56 if rdata
!= nil || rtags
!= nil ||
!eof
{
57 t
.Errorf("unexpected profile read (non-blocking): %#x, %#x, eof=%v; want nil, nil, eof=true", rdata
, rtags
, eof
)
61 myTags
:= make([]byte, 100)
62 t
.Logf("myTags is %p", &myTags
[0])
64 t
.Run("BasicWriteRead", func(t
*testing
.T
) {
65 b
:= NewProfBuf(2, 11, 1)
66 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
67 read(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])})
68 read(t
, b
, nil, nil) // release data returned by previous read
69 write(t
, b
, unsafe
.Pointer(&myTags
[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
70 read(t
, b
, []uint64{8, 99, 101, 102, 201, 202, 203, 204}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[2])})
73 t
.Run("ReadMany", func(t
*testing
.T
) {
74 b
:= NewProfBuf(2, 50, 50)
75 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
76 write(t
, b
, unsafe
.Pointer(&myTags
[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
77 write(t
, b
, unsafe
.Pointer(&myTags
[1]), 500, []uint64{502, 504}, []uintptr{506})
78 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])})
81 t
.Run("ReadManyShortData", func(t
*testing
.T
) {
82 b
:= NewProfBuf(2, 50, 50)
83 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
84 write(t
, b
, unsafe
.Pointer(&myTags
[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
85 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])})
88 t
.Run("ReadManyShortTags", func(t
*testing
.T
) {
89 b
:= NewProfBuf(2, 50, 50)
90 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
91 write(t
, b
, unsafe
.Pointer(&myTags
[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
92 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])})
95 t
.Run("ReadAfterOverflow1", func(t
*testing
.T
) {
96 // overflow record synthesized by write
97 b
:= NewProfBuf(2, 16, 5)
98 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9}) // uses 10
99 read(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])}) // reads 10 but still in use until next read
100 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5}) // uses 6
101 read(t
, b
, []uint64{6, 1, 2, 3, 4, 5}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])}) // reads 6 but still in use until next read
103 write(t
, b
, unsafe
.Pointer(&myTags
[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204, 205, 206, 207, 208, 209}) // no room
104 for i
:= 0; i
< 299; i
++ {
105 write(t
, b
, unsafe
.Pointer(&myTags
[3]), int64(100+i
), []uint64{101, 102}, []uintptr{201, 202, 203, 204}) // no room for overflow+this record
107 write(t
, b
, unsafe
.Pointer(&myTags
[1]), 500, []uint64{502, 504}, []uintptr{506}) // room for overflow+this record
108 read(t
, b
, []uint64{5, 99, 0, 0, 300, 5, 500, 502, 504, 506}, []unsafe
.Pointer
{nil, unsafe
.Pointer(&myTags
[1])})
111 t
.Run("ReadAfterOverflow2", func(t
*testing
.T
) {
112 // overflow record synthesized by read
113 b
:= NewProfBuf(2, 16, 5)
114 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
115 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})
116 for i
:= 0; i
< 299; i
++ {
117 write(t
, b
, unsafe
.Pointer(&myTags
[3]), 100, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
119 read(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])}) // reads 10 but still in use until next read
120 write(t
, b
, unsafe
.Pointer(&myTags
[1]), 500, []uint64{502, 504}, []uintptr{}) // still overflow
121 read(t
, b
, []uint64{5, 99, 0, 0, 301}, []unsafe
.Pointer
{nil}) // overflow synthesized by read
122 write(t
, b
, unsafe
.Pointer(&myTags
[1]), 500, []uint64{502, 505}, []uintptr{506}) // written
123 read(t
, b
, []uint64{5, 500, 502, 505, 506}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[1])})
126 t
.Run("ReadAtEndAfterOverflow", func(t
*testing
.T
) {
127 b
:= NewProfBuf(2, 12, 5)
128 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
129 write(t
, b
, unsafe
.Pointer(&myTags
[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
130 for i
:= 0; i
< 299; i
++ {
131 write(t
, b
, unsafe
.Pointer(&myTags
[3]), 100, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
133 read(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])})
134 read(t
, b
, []uint64{5, 99, 0, 0, 300}, []unsafe
.Pointer
{nil})
135 write(t
, b
, unsafe
.Pointer(&myTags
[1]), 500, []uint64{502, 504}, []uintptr{506})
136 read(t
, b
, []uint64{5, 500, 502, 504, 506}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[1])})
139 t
.Run("BlockingWriteRead", func(t
*testing
.T
) {
140 b
:= NewProfBuf(2, 11, 1)
141 wait
:= readBlock(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])})
142 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
144 wait
= readBlock(t
, b
, []uint64{8, 99, 101, 102, 201, 202, 203, 204}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[2])})
145 time
.Sleep(10 * time
.Millisecond
)
146 write(t
, b
, unsafe
.Pointer(&myTags
[2]), 99, []uint64{101, 102}, []uintptr{201, 202, 203, 204})
148 wait
= readBlock(t
, b
, nil, nil)
151 wait
= readBlock(t
, b
, nil, nil)
156 t
.Run("DataWraparound", func(t
*testing
.T
) {
157 b
:= NewProfBuf(2, 16, 1024)
158 for i
:= 0; i
< 10; i
++ {
159 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
160 read(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])})
161 read(t
, b
, nil, nil) // release data returned by previous read
165 t
.Run("TagWraparound", func(t
*testing
.T
) {
166 b
:= NewProfBuf(2, 1024, 2)
167 for i
:= 0; i
< 10; i
++ {
168 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
169 read(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])})
170 read(t
, b
, nil, nil) // release data returned by previous read
174 t
.Run("BothWraparound", func(t
*testing
.T
) {
175 b
:= NewProfBuf(2, 16, 2)
176 for i
:= 0; i
< 10; i
++ {
177 write(t
, b
, unsafe
.Pointer(&myTags
[0]), 1, []uint64{2, 3}, []uintptr{4, 5, 6, 7, 8, 9})
178 read(t
, b
, []uint64{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []unsafe
.Pointer
{unsafe
.Pointer(&myTags
[0])})
179 read(t
, b
, nil, nil) // release data returned by previous read