github.com/google/cloudprober@v0.11.3/metrics/map_test.go (about)

     1  // Copyright 2017 The Cloudprober Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package metrics
    16  
    17  import (
    18  	"reflect"
    19  	"testing"
    20  )
    21  
    22  func verify(t *testing.T, m *Map, expectedKeys []string, expectedMap map[string]int64) {
    23  	t.Helper()
    24  
    25  	if !reflect.DeepEqual(m.Keys(), expectedKeys) {
    26  		t.Errorf("Map doesn't have expected keys. Got: %q, Expected: %q", m.Keys(), expectedKeys)
    27  	}
    28  	for k, v := range expectedMap {
    29  		if m.GetKey(k).Int64() != v {
    30  			t.Errorf("Key values not as expected. Key: %s, Got: %d, Expected: %d", k, m.GetKey(k).Int64(), v)
    31  		}
    32  	}
    33  }
    34  
    35  func TestMap(t *testing.T) {
    36  	m := NewMap("code", NewInt(0))
    37  	m.IncKeyBy("200", NewInt(4000))
    38  
    39  	verify(t, m, []string{"200"}, map[string]int64{"200": 4000})
    40  
    41  	m.IncKey("500")
    42  	verify(t, m, []string{"200", "500"}, map[string]int64{
    43  		"200": 4000,
    44  		"500": 1,
    45  	})
    46  
    47  	// Verify that keys are ordered
    48  	m.IncKey("404")
    49  	verify(t, m, []string{"200", "404", "500"}, map[string]int64{
    50  		"200": 4000,
    51  		"404": 1,
    52  		"500": 1,
    53  	})
    54  
    55  	// Clone m for verification later
    56  	m1 := m.Clone().(*Map)
    57  
    58  	// Verify add works as expected
    59  	m2 := NewMap("code", NewInt(0))
    60  	m2.IncKeyBy("403", NewInt(2))
    61  	err := m.Add(m2)
    62  	if err != nil {
    63  		t.Errorf("Add two maps produced error. Err: %v", err)
    64  	}
    65  	verify(t, m, []string{"200", "403", "404", "500"}, map[string]int64{
    66  		"200": 4000,
    67  		"403": 2,
    68  		"404": 1,
    69  		"500": 1,
    70  	})
    71  
    72  	// Verify that clones value has not changed
    73  	verify(t, m1, []string{"200", "404", "500"}, map[string]int64{
    74  		"200": 4000,
    75  		"404": 1,
    76  		"500": 1,
    77  	})
    78  }
    79  
    80  func TestMapSubtractCounter(t *testing.T) {
    81  	m1 := NewMap("code", NewInt(0))
    82  	m1.IncKeyBy("200", NewInt(4000))
    83  	m1.IncKeyBy("403", NewInt(2))
    84  
    85  	m2 := m1.Clone().(*Map)
    86  	m2.IncKeyBy("200", NewInt(400))
    87  	m2.IncKey("500")
    88  	m2Clone := m2.Clone() // We'll use this for reset testing below.
    89  
    90  	expectReset := false
    91  	wasReset, err := m2.SubtractCounter(m1)
    92  	if err != nil {
    93  		t.Errorf("Unexpected error: %v", err)
    94  	}
    95  	if wasReset != expectReset {
    96  		t.Errorf("wasReset=%v, expected=%v", wasReset, expectReset)
    97  	}
    98  	verify(t, m2, []string{"200", "403", "500"}, map[string]int64{
    99  		"200": 400,
   100  		"403": 0,
   101  		"500": 1,
   102  	})
   103  
   104  	// Expect a reset this time, as m3 (m) will be smaller than m2Clone.
   105  	m3 := m1.Clone()
   106  	expectReset = true
   107  	wasReset, err = m3.SubtractCounter(m2Clone)
   108  	if err != nil {
   109  		t.Errorf("Unexpected error: %v", err)
   110  	}
   111  	if wasReset != expectReset {
   112  		t.Errorf("wasReset=%v, expected=%v", wasReset, expectReset)
   113  	}
   114  	verify(t, m3.(*Map), []string{"200", "403"}, map[string]int64{
   115  		"200": 4000,
   116  		"403": 2,
   117  	})
   118  
   119  }
   120  
   121  func TestMapString(t *testing.T) {
   122  	m := NewMap("lat", NewFloat(0))
   123  	m.IncKeyBy("p99", NewFloat(4000))
   124  	m.IncKeyBy("p50", NewFloat(20))
   125  
   126  	s := m.String()
   127  	expectedString := "map:lat,p50:20.000,p99:4000.000"
   128  	if s != expectedString {
   129  		t.Errorf("m.String()=%s, expected=%s", s, expectedString)
   130  	}
   131  
   132  	m2, err := ParseMapFromString(s)
   133  	if err != nil {
   134  		t.Errorf("ParseMapFromString(%s) returned error: %v", s, err)
   135  	}
   136  
   137  	s1 := m2.String()
   138  	if s1 != s {
   139  		t.Errorf("ParseMapFromString(%s).String() = %s, expected = %s", s, s1, s)
   140  	}
   141  }
   142  
   143  func TestMapAllocsPerRun(t *testing.T) {
   144  	var v *Map
   145  	mapNewAvg := testing.AllocsPerRun(100, func() {
   146  		v = NewMap("code", NewInt(0))
   147  		v.IncKeyBy("200", NewInt(22))
   148  		v.IncKeyBy("404", NewInt(4500))
   149  		v.IncKeyBy("403", NewInt(4500))
   150  	})
   151  
   152  	mapStringAvg := testing.AllocsPerRun(100, func() {
   153  		_ = v.String()
   154  	})
   155  
   156  	t.Logf("Average allocations per run: ForMapNew=%v, ForMapString=%v", mapNewAvg, mapStringAvg)
   157  }