1 // Copyright 2015 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 func isNear(x *Float, y float64, tolerance float64) bool {
14 return math.Abs(x.Value()-y) < tolerance
17 func isApproximate(x *Float, y float64) bool {
18 return isNear(x, y, 1e-2)
21 func checkApproximate(t *testing.T, o Observable, y float64) {
23 if !isApproximate(x, y) {
24 t.Errorf("Wanted %g, got %g", y, x.Value())
28 func checkNear(t *testing.T, o Observable, y, tolerance float64) {
30 if !isNear(x, y, tolerance) {
31 t.Errorf("Wanted %g +- %g, got %g", y, tolerance, x.Value())
35 var baseTime = time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)
37 func tu(s int64) time.Time {
38 return baseTime.Add(time.Duration(s) * time.Second)
41 func tu2(s int64, ns int64) time.Time {
42 return baseTime.Add(time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond)
45 func TestBasicTimeSeries(t *testing.T) {
46 ts := NewTimeSeries(NewFloat)
49 ts.AddWithTime(fo, tu(1))
50 ts.AddWithTime(fo, tu(1))
51 ts.AddWithTime(fo, tu(1))
52 ts.AddWithTime(fo, tu(1))
53 checkApproximate(t, ts.Range(tu(0), tu(1)), 40)
54 checkApproximate(t, ts.Total(), 40)
55 ts.AddWithTime(fo, tu(3))
56 ts.AddWithTime(fo, tu(3))
57 ts.AddWithTime(fo, tu(3))
58 checkApproximate(t, ts.Range(tu(0), tu(2)), 40)
59 checkApproximate(t, ts.Range(tu(2), tu(4)), 30)
60 checkApproximate(t, ts.Total(), 70)
61 ts.AddWithTime(fo, tu(1))
62 ts.AddWithTime(fo, tu(1))
63 checkApproximate(t, ts.Range(tu(0), tu(2)), 60)
64 checkApproximate(t, ts.Range(tu(2), tu(4)), 30)
65 checkApproximate(t, ts.Total(), 90)
67 ts.AddWithTime(fo, tu(100))
68 checkApproximate(t, ts.Range(tu(99), tu(100)), 100)
69 checkApproximate(t, ts.Range(tu(0), tu(4)), 36)
70 checkApproximate(t, ts.Total(), 190)
72 ts.AddWithTime(fo, tu(1))
73 ts.AddWithTime(fo, tu(1))
74 checkApproximate(t, ts.Range(tu(0), tu(4)), 44)
75 checkApproximate(t, ts.Range(tu(37), tu2(100, 100e6)), 100)
76 checkApproximate(t, ts.Range(tu(50), tu2(100, 100e6)), 100)
77 checkApproximate(t, ts.Range(tu(99), tu2(100, 100e6)), 100)
78 checkApproximate(t, ts.Total(), 210)
80 for i, l := range ts.ComputeRange(tu(36), tu(100), 64) {
82 checkApproximate(t, l, 100)
84 checkApproximate(t, l, 0)
88 checkApproximate(t, ts.Range(tu(0), tu(100)), 210)
89 checkApproximate(t, ts.Range(tu(10), tu(100)), 100)
91 for i, l := range ts.ComputeRange(tu(0), tu(100), 100) {
93 checkApproximate(t, l, 11)
95 checkApproximate(t, l, 10)
97 checkApproximate(t, l, 0)
102 func TestFloat(t *testing.T) {
104 if g, w := f.String(), "1"; g != w {
105 t.Errorf("Float(1).String = %q; want %q", g, w)
108 var o Observable = &f2
110 if g, w := f.Value(), 3.0; g != w {
111 t.Errorf("Float post-add = %v; want %v", g, w)
114 if g, w := f.Value(), 6.0; g != w {
115 t.Errorf("Float post-multiply = %v; want %v", g, w)
118 if g, w := f.Value(), 0.0; g != w {
119 t.Errorf("Float post-clear = %v; want %v", g, w)
122 if g, w := f.Value(), 2.0; g != w {
123 t.Errorf("Float post-CopyFrom = %v; want %v", g, w)
127 type mockClock struct {
131 func (m *mockClock) Time() time.Time { return m.time }
132 func (m *mockClock) Set(t time.Time) { m.time = t }
136 var testResolutions = []time.Duration{
137 10 * time.Second, // level holds one minute of observations
138 100 * time.Second, // level holds ten minutes of observations
139 10 * time.Minute, // level holds one hour of observations
142 // TestTimeSeries uses a small number of buckets to force a higher
143 // error rate on approximations from the timeseries.
144 type TestTimeSeries struct {
148 func TestExpectedErrorRate(t *testing.T) {
149 ts := new(TestTimeSeries)
150 fake := new(mockClock)
152 ts.timeSeries.init(testResolutions, NewFloat, buckets, fake)
153 for i := 1; i <= 61*61; i++ {
154 fake.Set(fake.Time().Add(1 * time.Second))
156 ts.AddWithTime(&ob, fake.Time())
158 // The results should be accurate within one missing bucket (1/6) of the observations recorded.
159 checkNear(t, ts.Latest(0, buckets), min(float64(i), 60), 10)
160 checkNear(t, ts.Latest(1, buckets), min(float64(i), 600), 100)
161 checkNear(t, ts.Latest(2, buckets), min(float64(i), 3600), 600)
165 func min(a, b float64) float64 {