1
2
3
4
5 package trace
6
7 import (
8 "math"
9 "testing"
10 )
11
12 type sumTest struct {
13 value int64
14 sum int64
15 sumOfSquares float64
16 total int64
17 }
18
19 var sumTests = []sumTest{
20 {100, 100, 10000, 1},
21 {50, 150, 12500, 2},
22 {50, 200, 15000, 3},
23 {50, 250, 17500, 4},
24 }
25
26 type bucketingTest struct {
27 in int64
28 log int
29 bucket int
30 }
31
32 var bucketingTests = []bucketingTest{
33 {0, 0, 0},
34 {1, 1, 0},
35 {2, 2, 1},
36 {3, 2, 1},
37 {4, 3, 2},
38 {1000, 10, 9},
39 {1023, 10, 9},
40 {1024, 11, 10},
41 {1000000, 20, 19},
42 }
43
44 type multiplyTest struct {
45 in int64
46 ratio float64
47 expectedSum int64
48 expectedTotal int64
49 expectedSumOfSquares float64
50 }
51
52 var multiplyTests = []multiplyTest{
53 {15, 2.5, 37, 2, 562.5},
54 {128, 4.6, 758, 13, 77953.9},
55 }
56
57 type percentileTest struct {
58 fraction float64
59 expected int64
60 }
61
62 var percentileTests = []percentileTest{
63 {0.25, 48},
64 {0.5, 96},
65 {0.6, 109},
66 {0.75, 128},
67 {0.90, 205},
68 {0.95, 230},
69 {0.99, 256},
70 }
71
72 func TestSum(t *testing.T) {
73 var h histogram
74
75 for _, test := range sumTests {
76 h.addMeasurement(test.value)
77 sum := h.sum
78 if sum != test.sum {
79 t.Errorf("h.Sum = %v WANT: %v", sum, test.sum)
80 }
81
82 sumOfSquares := h.sumOfSquares
83 if sumOfSquares != test.sumOfSquares {
84 t.Errorf("h.SumOfSquares = %v WANT: %v", sumOfSquares, test.sumOfSquares)
85 }
86
87 total := h.total()
88 if total != test.total {
89 t.Errorf("h.Total = %v WANT: %v", total, test.total)
90 }
91 }
92 }
93
94 func TestMultiply(t *testing.T) {
95 var h histogram
96 for i, test := range multiplyTests {
97 h.addMeasurement(test.in)
98 h.Multiply(test.ratio)
99 if h.sum != test.expectedSum {
100 t.Errorf("#%v: h.sum = %v WANT: %v", i, h.sum, test.expectedSum)
101 }
102 if h.total() != test.expectedTotal {
103 t.Errorf("#%v: h.total = %v WANT: %v", i, h.total(), test.expectedTotal)
104 }
105 if h.sumOfSquares != test.expectedSumOfSquares {
106 t.Errorf("#%v: h.SumOfSquares = %v WANT: %v", i, test.expectedSumOfSquares, h.sumOfSquares)
107 }
108 }
109 }
110
111 func TestBucketingFunctions(t *testing.T) {
112 for _, test := range bucketingTests {
113 log := log2(test.in)
114 if log != test.log {
115 t.Errorf("log2 = %v WANT: %v", log, test.log)
116 }
117
118 bucket := getBucket(test.in)
119 if bucket != test.bucket {
120 t.Errorf("getBucket = %v WANT: %v", bucket, test.bucket)
121 }
122 }
123 }
124
125 func TestAverage(t *testing.T) {
126 a := new(histogram)
127 average := a.average()
128 if average != 0 {
129 t.Errorf("Average of empty histogram was %v WANT: 0", average)
130 }
131
132 a.addMeasurement(1)
133 a.addMeasurement(1)
134 a.addMeasurement(3)
135 const expected = float64(5) / float64(3)
136 average = a.average()
137
138 if !isApproximate(average, expected) {
139 t.Errorf("Average = %g WANT: %v", average, expected)
140 }
141 }
142
143 func TestStandardDeviation(t *testing.T) {
144 a := new(histogram)
145 add(a, 10, 1<<4)
146 add(a, 10, 1<<5)
147 add(a, 10, 1<<6)
148 stdDev := a.standardDeviation()
149 const expected = 19.95
150
151 if !isApproximate(stdDev, expected) {
152 t.Errorf("StandardDeviation = %v WANT: %v", stdDev, expected)
153 }
154
155
156 a = new(histogram)
157 stdDev = a.standardDeviation()
158
159 if !isApproximate(stdDev, 0) {
160 t.Errorf("StandardDeviation = %v WANT: 0", stdDev)
161 }
162
163 add(a, 1, 1<<4)
164 if !isApproximate(stdDev, 0) {
165 t.Errorf("StandardDeviation = %v WANT: 0", stdDev)
166 }
167
168 add(a, 10, 1<<4)
169 if !isApproximate(stdDev, 0) {
170 t.Errorf("StandardDeviation = %v WANT: 0", stdDev)
171 }
172 }
173
174 func TestPercentileBoundary(t *testing.T) {
175 a := new(histogram)
176 add(a, 5, 1<<4)
177 add(a, 10, 1<<6)
178 add(a, 5, 1<<7)
179
180 for _, test := range percentileTests {
181 percentile := a.percentileBoundary(test.fraction)
182 if percentile != test.expected {
183 t.Errorf("h.PercentileBoundary (fraction=%v) = %v WANT: %v", test.fraction, percentile, test.expected)
184 }
185 }
186 }
187
188 func TestCopyFrom(t *testing.T) {
189 a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
190 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
191 b := histogram{6, 36, []int64{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
192 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39}, 5, -1}
193
194 a.CopyFrom(&b)
195
196 if a.String() != b.String() {
197 t.Errorf("a.String = %s WANT: %s", a.String(), b.String())
198 }
199 }
200
201 func TestClear(t *testing.T) {
202 a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
203 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
204
205 a.Clear()
206
207 expected := "0, 0.000000, 0, 0, []"
208 if a.String() != expected {
209 t.Errorf("a.String = %s WANT %s", a.String(), expected)
210 }
211 }
212
213 func TestNew(t *testing.T) {
214 a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
215 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
216 b := a.New()
217
218 expected := "0, 0.000000, 0, 0, []"
219 if b.(*histogram).String() != expected {
220 t.Errorf("b.(*histogram).String = %s WANT: %s", b.(*histogram).String(), expected)
221 }
222 }
223
224 func TestAdd(t *testing.T) {
225
226
227 a := histogram{5, 25, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
228 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, 4, -1}
229 b := a.New()
230
231 expected := a.String()
232 a.Add(b)
233 if a.String() != expected {
234 t.Errorf("a.String = %s WANT: %s", a.String(), expected)
235 }
236
237
238 c := new(histogram)
239 d := new(histogram)
240 e := new(histogram)
241 c.addMeasurement(12)
242 d.addMeasurement(11)
243 e.addMeasurement(12)
244 e.addMeasurement(11)
245 c.Add(d)
246 if c.String() != e.String() {
247 t.Errorf("c.String = %s WANT: %s", c.String(), e.String())
248 }
249
250
251 f := new(histogram)
252 g := new(histogram)
253 h := new(histogram)
254 f.addMeasurement(4)
255 f.addMeasurement(12)
256 f.addMeasurement(100)
257 g.addMeasurement(18)
258 g.addMeasurement(36)
259 g.addMeasurement(255)
260 h.addMeasurement(4)
261 h.addMeasurement(12)
262 h.addMeasurement(100)
263 h.addMeasurement(18)
264 h.addMeasurement(36)
265 h.addMeasurement(255)
266 f.Add(g)
267 if f.String() != h.String() {
268 t.Errorf("f.String = %q WANT: %q", f.String(), h.String())
269 }
270
271
272 i := new(histogram)
273 j := new(histogram)
274 k := new(histogram)
275 j.addMeasurement(18)
276 j.addMeasurement(36)
277 j.addMeasurement(255)
278 k.addMeasurement(18)
279 k.addMeasurement(36)
280 k.addMeasurement(255)
281 i.Add(j)
282 if i.String() != k.String() {
283 t.Errorf("i.String = %q WANT: %q", i.String(), k.String())
284 }
285
286
287 l := new(histogram)
288 m := new(histogram)
289 n := new(histogram)
290 l.addMeasurement(0)
291 m.addMeasurement(18)
292 m.addMeasurement(36)
293 m.addMeasurement(255)
294 n.addMeasurement(0)
295 n.addMeasurement(18)
296 n.addMeasurement(36)
297 n.addMeasurement(255)
298 l.Add(m)
299 if l.String() != n.String() {
300 t.Errorf("l.String = %q WANT: %q", l.String(), n.String())
301 }
302
303
304 o := new(histogram)
305 p := new(histogram)
306 o.addMeasurement(0)
307 o.addMeasurement(2)
308 o.addMeasurement(0)
309 p.addMeasurement(0)
310 p.addMeasurement(0)
311 p.addMeasurement(2)
312 if o.String() != p.String() {
313 t.Errorf("o.String = %q WANT: %q", o.String(), p.String())
314 }
315 }
316
317 func add(h *histogram, times int, val int64) {
318 for i := 0; i < times; i++ {
319 h.addMeasurement(val)
320 }
321 }
322
323 func isApproximate(x, y float64) bool {
324 return math.Abs(x-y) < 1e-2
325 }
326
View as plain text