1// Copyright 2013 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package model 15 16import "testing" 17 18func testMetric(t testing.TB) { 19 var scenarios = []struct { 20 input LabelSet 21 fingerprint Fingerprint 22 fastFingerprint Fingerprint 23 }{ 24 { 25 input: LabelSet{}, 26 fingerprint: 14695981039346656037, 27 fastFingerprint: 14695981039346656037, 28 }, 29 { 30 input: LabelSet{ 31 "first_name": "electro", 32 "occupation": "robot", 33 "manufacturer": "westinghouse", 34 }, 35 fingerprint: 5911716720268894962, 36 fastFingerprint: 11310079640881077873, 37 }, 38 { 39 input: LabelSet{ 40 "x": "y", 41 }, 42 fingerprint: 8241431561484471700, 43 fastFingerprint: 13948396922932177635, 44 }, 45 { 46 input: LabelSet{ 47 "a": "bb", 48 "b": "c", 49 }, 50 fingerprint: 3016285359649981711, 51 fastFingerprint: 3198632812309449502, 52 }, 53 { 54 input: LabelSet{ 55 "a": "b", 56 "bb": "c", 57 }, 58 fingerprint: 7122421792099404749, 59 fastFingerprint: 5774953389407657638, 60 }, 61 } 62 63 for i, scenario := range scenarios { 64 input := Metric(scenario.input) 65 66 if scenario.fingerprint != input.Fingerprint() { 67 t.Errorf("%d. expected %d, got %d", i, scenario.fingerprint, input.Fingerprint()) 68 } 69 if scenario.fastFingerprint != input.FastFingerprint() { 70 t.Errorf("%d. expected %d, got %d", i, scenario.fastFingerprint, input.FastFingerprint()) 71 } 72 } 73} 74 75func TestMetric(t *testing.T) { 76 testMetric(t) 77} 78 79func BenchmarkMetric(b *testing.B) { 80 for i := 0; i < b.N; i++ { 81 testMetric(b) 82 } 83} 84 85func TestMetricNameIsValid(t *testing.T) { 86 var scenarios = []struct { 87 mn LabelValue 88 valid bool 89 }{ 90 { 91 mn: "Avalid_23name", 92 valid: true, 93 }, 94 { 95 mn: "_Avalid_23name", 96 valid: true, 97 }, 98 { 99 mn: "1valid_23name", 100 valid: false, 101 }, 102 { 103 mn: "avalid_23name", 104 valid: true, 105 }, 106 { 107 mn: "Ava:lid_23name", 108 valid: true, 109 }, 110 { 111 mn: "a lid_23name", 112 valid: false, 113 }, 114 { 115 mn: ":leading_colon", 116 valid: true, 117 }, 118 { 119 mn: "colon:in:the:middle", 120 valid: true, 121 }, 122 { 123 mn: "", 124 valid: false, 125 }, 126 } 127 128 for _, s := range scenarios { 129 if IsValidMetricName(s.mn) != s.valid { 130 t.Errorf("Expected %v for %q using IsValidMetricName function", s.valid, s.mn) 131 } 132 if MetricNameRE.MatchString(string(s.mn)) != s.valid { 133 t.Errorf("Expected %v for %q using regexp matching", s.valid, s.mn) 134 } 135 } 136} 137 138func TestMetricClone(t *testing.T) { 139 m := Metric{ 140 "first_name": "electro", 141 "occupation": "robot", 142 "manufacturer": "westinghouse", 143 } 144 145 m2 := m.Clone() 146 147 if len(m) != len(m2) { 148 t.Errorf("expected the length of the cloned metric to be equal to the input metric") 149 } 150 151 for ln, lv := range m2 { 152 expected := m[ln] 153 if expected != lv { 154 t.Errorf("expected label value %s but got %s for label name %s", expected, lv, ln) 155 } 156 } 157} 158 159func TestMetricToString(t *testing.T) { 160 scenarios := []struct { 161 name string 162 input Metric 163 expected string 164 }{ 165 { 166 name: "valid metric without __name__ label", 167 input: Metric{ 168 "first_name": "electro", 169 "occupation": "robot", 170 "manufacturer": "westinghouse", 171 }, 172 expected: `{first_name="electro", manufacturer="westinghouse", occupation="robot"}`, 173 }, 174 { 175 name: "valid metric with __name__ label", 176 input: Metric{ 177 "__name__": "electro", 178 "occupation": "robot", 179 "manufacturer": "westinghouse", 180 }, 181 expected: `electro{manufacturer="westinghouse", occupation="robot"}`, 182 }, 183 { 184 name: "empty metric with __name__ label", 185 input: Metric{ 186 "__name__": "fooname", 187 }, 188 expected: "fooname", 189 }, 190 { 191 name: "empty metric", 192 input: Metric{}, 193 expected: "{}", 194 }, 195 } 196 197 for _, scenario := range scenarios { 198 t.Run(scenario.name, func(t *testing.T) { 199 actual := scenario.input.String() 200 if actual != scenario.expected { 201 t.Errorf("expected string output %s but got %s", actual, scenario.expected) 202 } 203 }) 204 } 205} 206