1 // Copyright 2020 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.
13 var dummyTimeHistogram TimeHistogram
15 func TestTimeHistogram(t
*testing
.T
) {
16 // We need to use a global dummy because this
17 // could get stack-allocated with a non-8-byte alignment.
18 // The result of this bad alignment is a segfault on
19 // 32-bit platforms when calling Record.
20 h
:= &dummyTimeHistogram
22 // Record exactly one sample in each bucket.
23 for i
:= 0; i
< TimeHistNumSuperBuckets
; i
++ {
26 base
= int64(1) << (i
+ TimeHistSubBucketBits
- 1)
28 for j
:= 0; j
< TimeHistNumSubBuckets
; j
++ {
36 // Hit the underflow bucket.
39 // Check to make sure there's exactly one count in each
41 for i
:= uint(0); i
< TimeHistNumSuperBuckets
; i
++ {
42 for j
:= uint(0); j
< TimeHistNumSubBuckets
; j
++ {
43 c
, ok
:= h
.Count(i
, j
)
45 t
.Errorf("hit underflow bucket unexpectedly: (%d, %d)", i
, j
)
47 t
.Errorf("bucket (%d, %d) has count that is not 1: %d", i
, j
, c
)
51 c
, ok
:= h
.Count(TimeHistNumSuperBuckets
, 0)
53 t
.Errorf("expected to hit underflow bucket: (%d, %d)", TimeHistNumSuperBuckets
, 0)
56 t
.Errorf("underflow bucket has count that is not 1: %d", c
)
59 // Check overflow behavior.
60 // By hitting a high value, we should just be adding into the highest bucket.
61 h
.Record(math
.MaxInt64
)
62 c
, ok
= h
.Count(TimeHistNumSuperBuckets
-1, TimeHistNumSubBuckets
-1)
64 t
.Error("hit underflow bucket in highest bucket unexpectedly")
66 t
.Errorf("highest has count that is not 2: %d", c
)
69 dummyTimeHistogram
= TimeHistogram
{}
72 func TestTimeHistogramMetricsBuckets(t
*testing
.T
) {
73 buckets
:= TimeHistogramMetricsBuckets()
75 nonInfBucketsLen
:= TimeHistNumSubBuckets
* TimeHistNumSuperBuckets
76 expBucketsLen
:= nonInfBucketsLen
+ 2 // Count -Inf and +Inf.
77 if len(buckets
) != expBucketsLen
{
78 t
.Fatalf("unexpected length of buckets: got %d, want %d", len(buckets
), expBucketsLen
)
80 // Check the first non-Inf 2*TimeHistNumSubBuckets buckets in order, skipping the
81 // first bucket which should be -Inf (checked later).
83 // Because of the way this scheme works, the bottom TimeHistNumSubBuckets
84 // buckets are fully populated, and then the next TimeHistNumSubBuckets
85 // have the TimeHistSubBucketBits'th bit set, while the bottom are once
86 // again fully populated.
87 for i
:= 1; i
<= 2*TimeHistNumSubBuckets
+1; i
++ {
88 if got
, want
:= buckets
[i
], float64(i
-1)/1e9
; got
!= want
{
89 t
.Errorf("expected bucket %d to have value %e, got %e", i
, want
, got
)
93 idxToBucket
:= map[int]float64{
95 33: float64(0x10<<1) / 1e9
,
96 34: float64(0x11<<1) / 1e9
,
97 49: float64(0x10<<2) / 1e9
,
98 58: float64(0x19<<2) / 1e9
,
99 65: float64(0x10<<3) / 1e9
,
100 513: float64(0x10<<31) / 1e9
,
101 519: float64(0x16<<31) / 1e9
,
102 expBucketsLen
- 2: float64(0x1f<<43) / 1e9
,
103 expBucketsLen
- 1: math
.Inf(1),
105 for idx
, bucket
:= range idxToBucket
{
106 if got
, want
:= buckets
[idx
], bucket
; got
!= want
{
107 t
.Errorf("expected bucket %d to have value %e, got %e", idx
, want
, got
)