1// Copyright 2017 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 labels 15 16import ( 17 "encoding/json" 18 "testing" 19) 20 21func mustNewMatcher(t *testing.T, mType MatchType, value string) *Matcher { 22 m, err := NewMatcher(mType, "", value) 23 if err != nil { 24 t.Fatal(err) 25 } 26 return m 27} 28 29func TestMatcher(t *testing.T) { 30 tests := []struct { 31 matcher *Matcher 32 value string 33 match bool 34 }{ 35 { 36 matcher: mustNewMatcher(t, MatchEqual, "bar"), 37 value: "bar", 38 match: true, 39 }, 40 { 41 matcher: mustNewMatcher(t, MatchEqual, "bar"), 42 value: "foo-bar", 43 match: false, 44 }, 45 { 46 matcher: mustNewMatcher(t, MatchNotEqual, "bar"), 47 value: "bar", 48 match: false, 49 }, 50 { 51 matcher: mustNewMatcher(t, MatchNotEqual, "bar"), 52 value: "foo-bar", 53 match: true, 54 }, 55 { 56 matcher: mustNewMatcher(t, MatchRegexp, "bar"), 57 value: "bar", 58 match: true, 59 }, 60 { 61 matcher: mustNewMatcher(t, MatchRegexp, "bar"), 62 value: "foo-bar", 63 match: false, 64 }, 65 { 66 matcher: mustNewMatcher(t, MatchRegexp, ".*bar"), 67 value: "foo-bar", 68 match: true, 69 }, 70 { 71 matcher: mustNewMatcher(t, MatchNotRegexp, "bar"), 72 value: "bar", 73 match: false, 74 }, 75 { 76 matcher: mustNewMatcher(t, MatchNotRegexp, "bar"), 77 value: "foo-bar", 78 match: true, 79 }, 80 { 81 matcher: mustNewMatcher(t, MatchNotRegexp, ".*bar"), 82 value: "foo-bar", 83 match: false, 84 }, 85 { 86 matcher: mustNewMatcher(t, MatchRegexp, `foo.bar`), 87 value: "foo-bar", 88 match: true, 89 }, 90 { 91 matcher: mustNewMatcher(t, MatchRegexp, `foo\.bar`), 92 value: "foo-bar", 93 match: false, 94 }, 95 { 96 matcher: mustNewMatcher(t, MatchRegexp, `foo\.bar`), 97 value: "foo.bar", 98 match: true, 99 }, 100 { 101 matcher: mustNewMatcher(t, MatchEqual, "foo\nbar"), 102 value: "foo\nbar", 103 match: true, 104 }, 105 { 106 matcher: mustNewMatcher(t, MatchRegexp, "foo.bar"), 107 value: "foo\nbar", 108 match: false, 109 }, 110 { 111 matcher: mustNewMatcher(t, MatchRegexp, "(?s)foo.bar"), 112 value: "foo\nbar", 113 match: true, 114 }, 115 { 116 matcher: mustNewMatcher(t, MatchEqual, "~!=\""), 117 value: "~!=\"", 118 match: true, 119 }, 120 } 121 122 for _, test := range tests { 123 if test.matcher.Matches(test.value) != test.match { 124 t.Fatalf("Unexpected match result for matcher %v and value %q; want %v, got %v", test.matcher, test.value, test.match, !test.match) 125 } 126 } 127} 128 129func TestMatcherString(t *testing.T) { 130 tests := []struct { 131 name string 132 op MatchType 133 value string 134 want string 135 }{ 136 { 137 name: `foo`, 138 op: MatchEqual, 139 value: `bar`, 140 want: `foo="bar"`, 141 }, 142 { 143 name: `foo`, 144 op: MatchNotEqual, 145 value: `bar`, 146 want: `foo!="bar"`, 147 }, 148 { 149 name: `foo`, 150 op: MatchRegexp, 151 value: `bar`, 152 want: `foo=~"bar"`, 153 }, 154 { 155 name: `foo`, 156 op: MatchNotRegexp, 157 value: `bar`, 158 want: `foo!~"bar"`, 159 }, 160 { 161 name: `foo`, 162 op: MatchEqual, 163 value: `back\slash`, 164 want: `foo="back\\slash"`, 165 }, 166 { 167 name: `foo`, 168 op: MatchEqual, 169 value: `double"quote`, 170 want: `foo="double\"quote"`, 171 }, 172 { 173 name: `foo`, 174 op: MatchEqual, 175 value: `new 176line`, 177 want: `foo="new\nline"`, 178 }, 179 { 180 name: `foo`, 181 op: MatchEqual, 182 value: `tab stop`, 183 want: `foo="tab stop"`, 184 }, 185 } 186 187 for _, test := range tests { 188 m, err := NewMatcher(test.op, test.name, test.value) 189 if err != nil { 190 t.Fatal(err) 191 } 192 if got := m.String(); got != test.want { 193 t.Errorf("Unexpected string representation of matcher; want %v, got %v", test.want, got) 194 } 195 } 196} 197 198func TestMatcherJSONMarshal(t *testing.T) { 199 tests := []struct { 200 name string 201 op MatchType 202 value string 203 want string 204 }{ 205 { 206 name: `foo`, 207 op: MatchEqual, 208 value: `bar`, 209 want: `{"name":"foo","value":"bar","isRegex":false,"isEqual":true}`, 210 }, 211 { 212 name: `foo`, 213 op: MatchNotEqual, 214 value: `bar`, 215 want: `{"name":"foo","value":"bar","isRegex":false,"isEqual":false}`, 216 }, 217 { 218 name: `foo`, 219 op: MatchRegexp, 220 value: `bar`, 221 want: `{"name":"foo","value":"bar","isRegex":true,"isEqual":true}`, 222 }, 223 { 224 name: `foo`, 225 op: MatchNotRegexp, 226 value: `bar`, 227 want: `{"name":"foo","value":"bar","isRegex":true,"isEqual":false}`, 228 }, 229 } 230 231 cmp := func(m1, m2 Matcher) bool { 232 return m1.Name == m2.Name && m1.Value == m2.Value && m1.Type == m2.Type 233 } 234 235 for _, test := range tests { 236 m, err := NewMatcher(test.op, test.name, test.value) 237 if err != nil { 238 t.Fatal(err) 239 } 240 241 b, err := json.Marshal(m) 242 if err != nil { 243 t.Fatal(err) 244 } 245 if got := string(b); got != test.want { 246 t.Errorf("Unexpected JSON representation of matcher:\nwant:\t%v\ngot:\t%v", test.want, got) 247 } 248 249 var m2 Matcher 250 if err := json.Unmarshal(b, &m2); err != nil { 251 t.Fatal(err) 252 } 253 if !cmp(*m, m2) { 254 t.Errorf("Doing Marshal and Unmarshal seems to be losing data; before %#v, after %#v", m, m2) 255 } 256 } 257} 258 259func TestMatcherJSONUnmarshal(t *testing.T) { 260 tests := []struct { 261 name string 262 op MatchType 263 value string 264 want string 265 }{ 266 { 267 name: "foo", 268 op: MatchEqual, 269 value: "bar", 270 want: `{"name":"foo","value":"bar","isRegex":false}`, 271 }, 272 { 273 name: `foo`, 274 op: MatchEqual, 275 value: `bar`, 276 want: `{"name":"foo","value":"bar","isRegex":false,"isEqual":true}`, 277 }, 278 { 279 name: `foo`, 280 op: MatchNotEqual, 281 value: `bar`, 282 want: `{"name":"foo","value":"bar","isRegex":false,"isEqual":false}`, 283 }, 284 { 285 name: `foo`, 286 op: MatchRegexp, 287 value: `bar`, 288 want: `{"name":"foo","value":"bar","isRegex":true,"isEqual":true}`, 289 }, 290 { 291 name: `foo`, 292 op: MatchNotRegexp, 293 value: `bar`, 294 want: `{"name":"foo","value":"bar","isRegex":true,"isEqual":false}`, 295 }, 296 } 297 298 cmp := func(m1, m2 Matcher) bool { 299 return m1.Name == m2.Name && m1.Value == m2.Value && m1.Type == m2.Type 300 } 301 302 for _, test := range tests { 303 var m Matcher 304 if err := json.Unmarshal([]byte(test.want), &m); err != nil { 305 t.Fatal(err) 306 } 307 308 m2, err := NewMatcher(test.op, test.name, test.value) 309 if err != nil { 310 t.Fatal(err) 311 } 312 313 if !cmp(m, *m2) { 314 t.Errorf("Unmarshaling seems to be producing unexpected matchers; got %#v, expected %#v", m, m2) 315 } 316 } 317} 318