github.com/XiaoMi/Gaea@v1.2.5/stats/rates_test.go (about)

     1  /*
     2  Copyright 2017 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package stats
    18  
    19  import (
    20  	"expvar"
    21  	"testing"
    22  	"time"
    23  )
    24  
    25  // For tests, we want to control exactly the time used by Rates.
    26  // The way Rates works is:
    27  // - at creation, do a snapshot.
    28  // - every interval, do a snapshot.
    29  // So in these tests, we make sure to always call snapshot() every interval.
    30  // We do other actions after epsilon, but then wait for intervalMinusEpsilon
    31  // and call snapshot().
    32  const (
    33  	interval             = 1 * time.Second
    34  	epsilon              = 50 * time.Millisecond
    35  	intervalMinusEpsilon = interval - epsilon
    36  )
    37  
    38  func TestRates(t *testing.T) {
    39  	now := time.Now()
    40  	timeNow = func() time.Time {
    41  		return now
    42  	}
    43  
    44  	clear()
    45  	c := NewCountersWithSingleLabel("rcounter1", "rcounter help", "label")
    46  	r := NewRates("rates1", c, 3, -1*time.Second)
    47  	r.snapshot()
    48  	now = now.Add(epsilon)
    49  	c.Add("tag1", 0)
    50  	c.Add("tag2", 0)
    51  	now = now.Add(intervalMinusEpsilon)
    52  	r.snapshot()
    53  	now = now.Add(epsilon)
    54  	checkRates(t, r, "after 1s", 0.0, `{"tag1":[0],"tag2":[0]}`)
    55  
    56  	c.Add("tag1", 10)
    57  	c.Add("tag2", 20)
    58  	now = now.Add(intervalMinusEpsilon)
    59  	r.snapshot()
    60  	now = now.Add(epsilon)
    61  	checkRates(t, r, "after 2s", 30.0, `{"tag1":[0,10],"tag2":[0,20]}`)
    62  
    63  	now = now.Add(intervalMinusEpsilon)
    64  	r.snapshot()
    65  	now = now.Add(epsilon)
    66  	checkRates(t, r, "after 3s", 0.0, `{"tag1":[0,10,0],"tag2":[0,20,0]}`)
    67  
    68  	now = now.Add(intervalMinusEpsilon)
    69  	r.snapshot()
    70  	now = now.Add(epsilon)
    71  	checkRates(t, r, "after 4s", 0.0, `{"tag1":[10,0,0],"tag2":[20,0,0]}`)
    72  }
    73  
    74  func checkRates(t *testing.T, r *Rates, desc string, wantRate float64, wantRateMap string) {
    75  	if got := r.String(); got != wantRateMap {
    76  		t.Errorf("%v: want %s, got %s", desc, wantRateMap, got)
    77  	}
    78  	if got := r.TotalRate(); got != wantRate {
    79  		t.Errorf("%v: want rate %v, got rate %v", desc, wantRate, got)
    80  	}
    81  }
    82  
    83  func TestRatesConsistency(t *testing.T) {
    84  	now := time.Now()
    85  	timeNow = func() time.Time {
    86  		return now
    87  	}
    88  
    89  	// This tests the following invariant: in the time window
    90  	// covered by rates, the sum of the rates reported must be
    91  	// equal to the count reported by the counter.
    92  	clear()
    93  	c := NewCountersWithSingleLabel("rcounter4", "rcounter4 help", "label")
    94  	r := NewRates("rates4", c, 100, -1*time.Second)
    95  	r.snapshot()
    96  
    97  	now = now.Add(epsilon)
    98  	c.Add("a", 1000)
    99  	now = now.Add(intervalMinusEpsilon)
   100  	r.snapshot()
   101  	now = now.Add(epsilon)
   102  	c.Add("a", 1)
   103  	now = now.Add(intervalMinusEpsilon)
   104  	r.snapshot()
   105  	now = now.Add(epsilon)
   106  
   107  	result := r.Get()
   108  	counts := c.Counts()
   109  	t.Logf("r.Get(): %v", result)
   110  	t.Logf("c.Counts(): %v", counts)
   111  
   112  	rate, count := result["a"], counts["a"]
   113  
   114  	var sum float64
   115  	for _, v := range rate {
   116  		sum += v
   117  	}
   118  	if sum != float64(counts["a"]) {
   119  		t.Errorf("rate inconsistent with count: sum of %v != %v", rate, count)
   120  	}
   121  
   122  }
   123  
   124  func TestRatesHook(t *testing.T) {
   125  	clear()
   126  	c := NewCountersWithSingleLabel("rcounter2", "rcounter2 help", "label")
   127  	var gotname string
   128  	var gotv *Rates
   129  	clear()
   130  	Register(func(name string, v expvar.Var) {
   131  		gotname = name
   132  		gotv = v.(*Rates)
   133  	})
   134  
   135  	v := NewRates("rates2", c, 2, 10*time.Second)
   136  	if gotname != "rates2" {
   137  		t.Errorf("want rates2, got %s", gotname)
   138  	}
   139  	if gotv != v {
   140  		t.Errorf("want %#v, got %#v", v, gotv)
   141  	}
   142  }