vitess-gh/go/stats/rates_test.go

143 строки
3.6 KiB
Go

/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package stats
import (
"expvar"
"testing"
"time"
)
// For tests, we want to control exactly the time used by Rates.
// The way Rates works is:
// - at creation, do a snapshot.
// - every interval, do a snapshot.
// So in these tests, we make sure to always call snapshot() every interval.
// We do other actions after epsilon, but then wait for intervalMinusEpsilon
// and call snapshot().
const (
interval = 1 * time.Second
epsilon = 50 * time.Millisecond
intervalMinusEpsilon = interval - epsilon
)
func TestRates(t *testing.T) {
now := time.Now()
timeNow = func() time.Time {
return now
}
clear()
c := NewCountersWithSingleLabel("rcounter1", "rcounter help", "label")
r := NewRates("rates1", c, 3, -1*time.Second)
r.snapshot()
now = now.Add(epsilon)
c.Add("tag1", 0)
c.Add("tag2", 0)
now = now.Add(intervalMinusEpsilon)
r.snapshot()
now = now.Add(epsilon)
checkRates(t, r, "after 1s", 0.0, `{"tag1":[0],"tag2":[0]}`)
c.Add("tag1", 10)
c.Add("tag2", 20)
now = now.Add(intervalMinusEpsilon)
r.snapshot()
now = now.Add(epsilon)
checkRates(t, r, "after 2s", 30.0, `{"tag1":[0,10],"tag2":[0,20]}`)
now = now.Add(intervalMinusEpsilon)
r.snapshot()
now = now.Add(epsilon)
checkRates(t, r, "after 3s", 0.0, `{"tag1":[0,10,0],"tag2":[0,20,0]}`)
now = now.Add(intervalMinusEpsilon)
r.snapshot()
now = now.Add(epsilon)
checkRates(t, r, "after 4s", 0.0, `{"tag1":[10,0,0],"tag2":[20,0,0]}`)
}
func checkRates(t *testing.T, r *Rates, desc string, wantRate float64, wantRateMap string) {
if got := r.String(); got != wantRateMap {
t.Errorf("%v: want %s, got %s", desc, wantRateMap, got)
}
if got := r.TotalRate(); got != wantRate {
t.Errorf("%v: want rate %v, got rate %v", desc, wantRate, got)
}
}
func TestRatesConsistency(t *testing.T) {
now := time.Now()
timeNow = func() time.Time {
return now
}
// This tests the following invariant: in the time window
// covered by rates, the sum of the rates reported must be
// equal to the count reported by the counter.
clear()
c := NewCountersWithSingleLabel("rcounter4", "rcounter4 help", "label")
r := NewRates("rates4", c, 100, -1*time.Second)
r.snapshot()
now = now.Add(epsilon)
c.Add("a", 1000)
now = now.Add(intervalMinusEpsilon)
r.snapshot()
now = now.Add(epsilon)
c.Add("a", 1)
now = now.Add(intervalMinusEpsilon)
r.snapshot()
now = now.Add(epsilon)
result := r.Get()
counts := c.Counts()
t.Logf("r.Get(): %v", result)
t.Logf("c.Counts(): %v", counts)
rate, count := result["a"], counts["a"]
var sum float64
for _, v := range rate {
sum += v
}
if sum != float64(counts["a"]) {
t.Errorf("rate inconsistent with count: sum of %v != %v", rate, count)
}
}
func TestRatesHook(t *testing.T) {
clear()
c := NewCountersWithSingleLabel("rcounter2", "rcounter2 help", "label")
var gotname string
var gotv *Rates
clear()
Register(func(name string, v expvar.Var) {
gotname = name
gotv = v.(*Rates)
})
v := NewRates("rates2", c, 2, 10*time.Second)
if gotname != "rates2" {
t.Errorf("want rates2, got %s", gotname)
}
if gotv != v {
t.Errorf("want %#v, got %#v", v, gotv)
}
}