257 lines
4.4 KiB
Go

package ratecounter
import (
"fmt"
"io/ioutil"
"testing"
"time"
)
func TestRateCounter(t *testing.T) {
interval := 500 * time.Millisecond
r := NewRateCounter(interval)
check := func(expected int64) {
val := r.Rate()
if val != expected {
t.Error("Expected ", val, " to equal ", expected)
}
}
check(0)
r.Incr(1)
check(1)
r.Incr(2)
check(3)
time.Sleep(2 * interval)
check(0)
}
func TestRateCounterResetAndRestart(t *testing.T) {
interval := 100 * time.Millisecond
r := NewRateCounter(interval)
check := func(expected int64) {
val := r.Rate()
if val != expected {
t.Error("Expected ", val, " to equal ", expected)
}
}
check(0)
r.Incr(1)
check(1)
time.Sleep(2 * interval)
check(0)
time.Sleep(2 * interval)
r.Incr(2)
check(2)
time.Sleep(2 * interval)
check(0)
r.Incr(2)
check(2)
}
func TestRateCounterPartial(t *testing.T) {
interval := 500 * time.Millisecond
almostinterval := 400 * time.Millisecond
r := NewRateCounter(interval)
check := func(expected int64) {
val := r.Rate()
if val != expected {
t.Error("Expected ", val, " to equal ", expected)
}
}
check(0)
r.Incr(1)
check(1)
time.Sleep(almostinterval)
r.Incr(2)
check(3)
time.Sleep(almostinterval)
check(2)
time.Sleep(2 * interval)
check(0)
}
func TestRateCounterHighResolution(t *testing.T) {
interval := 500 * time.Millisecond
tenth := 50 * time.Millisecond
r := NewRateCounter(interval).WithResolution(100)
check := func(expected int64) {
val := r.Rate()
if val != expected {
t.Error("Expected ", val, " to equal ", expected)
}
}
check(0)
r.Incr(1)
check(1)
time.Sleep(2 * tenth)
r.Incr(1)
check(2)
time.Sleep(2 * tenth)
r.Incr(1)
check(3)
time.Sleep(interval - 5*tenth)
check(3)
time.Sleep(2 * tenth)
check(2)
time.Sleep(2 * tenth)
check(1)
time.Sleep(2 * tenth)
check(0)
}
func TestRateCounterLowResolution(t *testing.T) {
interval := 500 * time.Millisecond
tenth := 50 * time.Millisecond
r := NewRateCounter(interval).WithResolution(4)
check := func(expected int64) {
val := r.Rate()
if val != expected {
t.Error("Expected ", val, " to equal ", expected)
}
}
check(0)
r.Incr(1)
check(1)
time.Sleep(2 * tenth)
r.Incr(1)
check(2)
time.Sleep(2 * tenth)
r.Incr(1)
check(3)
time.Sleep(interval - 5*tenth)
check(3)
time.Sleep(2 * tenth)
check(1)
time.Sleep(2 * tenth)
check(0)
time.Sleep(2 * tenth)
check(0)
}
func TestRateCounterMinResolution(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("Resolution < 1 did not panic")
}
}()
NewRateCounter(500 * time.Millisecond).WithResolution(0)
}
func TestRateCounterNoResolution(t *testing.T) {
interval := 500 * time.Millisecond
tenth := 50 * time.Millisecond
r := NewRateCounter(interval).WithResolution(1)
check := func(expected int64) {
val := r.Rate()
if val != expected {
t.Error("Expected ", val, " to equal ", expected)
}
}
check(0)
r.Incr(1)
check(1)
time.Sleep(2 * tenth)
r.Incr(1)
check(2)
time.Sleep(2 * tenth)
r.Incr(1)
check(3)
time.Sleep(interval - 5*tenth)
check(3)
time.Sleep(2 * tenth)
check(0)
time.Sleep(2 * tenth)
check(0)
time.Sleep(2 * tenth)
check(0)
}
func TestRateCounter_String(t *testing.T) {
r := NewRateCounter(1 * time.Second)
if r.String() != "0" {
t.Error("Expected ", r.String(), " to equal ", "0")
}
r.Incr(1)
if r.String() != "1" {
t.Error("Expected ", r.String(), " to equal ", "1")
}
}
func TestRateCounter_Incr_ReturnsImmediately(t *testing.T) {
interval := 1 * time.Second
r := NewRateCounter(interval)
start := time.Now()
r.Incr(-1)
duration := time.Since(start)
if duration >= 1*time.Second {
t.Error("incr took", duration, "to return")
}
}
func BenchmarkRateCounter(b *testing.B) {
interval := 0 * time.Millisecond
r := NewRateCounter(interval)
for i := 0; i < b.N; i++ {
r.Incr(1)
r.Rate()
}
}
func BenchmarkRateCounter_Parallel(b *testing.B) {
interval := 0 * time.Millisecond
r := NewRateCounter(interval)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
r.Incr(1)
r.Rate()
}
})
}
func BenchmarkRateCounter_With5MillionExisting(b *testing.B) {
interval := 1 * time.Hour
r := NewRateCounter(interval)
for i := 0; i < 5000000; i++ {
r.Incr(1)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.Incr(1)
r.Rate()
}
}
func Benchmark_TimeNowAndAdd(b *testing.B) {
var a time.Time
for i := 0; i < b.N; i++ {
a = time.Now().Add(1 * time.Second)
}
fmt.Fprintln(ioutil.Discard, a)
}