| // Copyright 2013 The Prometheus Authors |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package model |
| |
| import ( |
| "fmt" |
| "sort" |
| "testing" |
| ) |
| |
| func testLabelNames(t testing.TB) { |
| scenarios := []struct { |
| in LabelNames |
| out LabelNames |
| }{ |
| { |
| in: LabelNames{"ZZZ", "zzz"}, |
| out: LabelNames{"ZZZ", "zzz"}, |
| }, |
| { |
| in: LabelNames{"aaa", "AAA"}, |
| out: LabelNames{"AAA", "aaa"}, |
| }, |
| } |
| |
| for i, scenario := range scenarios { |
| sort.Sort(scenario.in) |
| |
| for j, expected := range scenario.out { |
| if expected != scenario.in[j] { |
| t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j]) |
| } |
| } |
| } |
| } |
| |
| func TestLabelNames(t *testing.T) { |
| testLabelNames(t) |
| } |
| |
| func BenchmarkLabelNames(b *testing.B) { |
| for i := 0; i < b.N; i++ { |
| testLabelNames(b) |
| } |
| } |
| |
| func testLabelValues(t testing.TB) { |
| scenarios := []struct { |
| in LabelValues |
| out LabelValues |
| }{ |
| { |
| in: LabelValues{"ZZZ", "zzz"}, |
| out: LabelValues{"ZZZ", "zzz"}, |
| }, |
| { |
| in: LabelValues{"aaa", "AAA"}, |
| out: LabelValues{"AAA", "aaa"}, |
| }, |
| } |
| |
| for i, scenario := range scenarios { |
| sort.Sort(scenario.in) |
| |
| for j, expected := range scenario.out { |
| if expected != scenario.in[j] { |
| t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j]) |
| } |
| } |
| } |
| } |
| |
| func TestLabelValues(t *testing.T) { |
| testLabelValues(t) |
| } |
| |
| func BenchmarkLabelValues(b *testing.B) { |
| for i := 0; i < b.N; i++ { |
| testLabelValues(b) |
| } |
| } |
| |
| func TestValidationScheme_IsLabelNameValid(t *testing.T) { |
| scenarios := []struct { |
| ln string |
| legacyValid bool |
| utf8Valid bool |
| }{ |
| { |
| ln: "Avalid_23name", |
| legacyValid: true, |
| utf8Valid: true, |
| }, |
| { |
| ln: "_Avalid_23name", |
| legacyValid: true, |
| utf8Valid: true, |
| }, |
| { |
| ln: "1valid_23name", |
| legacyValid: false, |
| utf8Valid: true, |
| }, |
| { |
| ln: "avalid_23name", |
| legacyValid: true, |
| utf8Valid: true, |
| }, |
| { |
| ln: "Ava:lid_23name", |
| legacyValid: false, |
| utf8Valid: true, |
| }, |
| { |
| ln: "a lid_23name", |
| legacyValid: false, |
| utf8Valid: true, |
| }, |
| { |
| ln: ":leading_colon", |
| legacyValid: false, |
| utf8Valid: true, |
| }, |
| { |
| ln: "colon:in:the:middle", |
| legacyValid: false, |
| utf8Valid: true, |
| }, |
| { |
| ln: "a\xc5z", |
| legacyValid: false, |
| utf8Valid: false, |
| }, |
| { |
| ln: "dot.in.name", |
| legacyValid: false, |
| utf8Valid: true, |
| }, |
| { |
| ln: "", |
| legacyValid: false, |
| utf8Valid: false, |
| }, |
| } |
| for _, s := range scenarios { |
| t.Run(fmt.Sprintf("%s,%t,%t", s.ln, s.legacyValid, s.utf8Valid), func(t *testing.T) { |
| if LegacyValidation.IsValidLabelName(s.ln) != s.legacyValid { |
| t.Errorf("Expected %v for %q using LegacyValidation.IsValidLabelName", s.legacyValid, s.ln) |
| } |
| if LabelNameRE.MatchString(s.ln) != s.legacyValid { |
| t.Errorf("Expected %v for %q using legacy regexp match", s.legacyValid, s.ln) |
| } |
| if UTF8Validation.IsValidLabelName(s.ln) != s.utf8Valid { |
| t.Errorf("Expected %v for %q using UTF8Validation.IsValidLabelName", s.utf8Valid, s.ln) |
| } |
| |
| // Test deprecated functions. |
| origScheme := NameValidationScheme |
| t.Cleanup(func() { |
| NameValidationScheme = origScheme |
| }) |
| NameValidationScheme = LegacyValidation |
| labelName := LabelName(s.ln) |
| if labelName.IsValid() != s.legacyValid { |
| t.Errorf("Expected %v for %q using legacy IsValid method", s.legacyValid, s.ln) |
| } |
| NameValidationScheme = UTF8Validation |
| if labelName.IsValid() != s.utf8Valid { |
| t.Errorf("Expected %v for %q using UTF-8 IsValid method", s.utf8Valid, s.ln) |
| } |
| }) |
| } |
| } |
| |
| func TestSortLabelPairs(t *testing.T) { |
| labelPairs := LabelPairs{ |
| { |
| Name: "FooName", |
| Value: "FooValue", |
| }, |
| { |
| Name: "FooName", |
| Value: "BarValue", |
| }, |
| { |
| Name: "BarName", |
| Value: "FooValue", |
| }, |
| { |
| Name: "BazName", |
| Value: "BazValue", |
| }, |
| { |
| Name: "BarName", |
| Value: "FooValue", |
| }, |
| { |
| Name: "BazName", |
| Value: "FazValue", |
| }, |
| } |
| |
| sort.Sort(labelPairs) |
| |
| expectedLabelPairs := LabelPairs{ |
| { |
| Name: "BarName", |
| Value: "FooValue", |
| }, |
| { |
| Name: "BarName", |
| Value: "FooValue", |
| }, |
| { |
| Name: "BazName", |
| Value: "BazValue", |
| }, |
| { |
| Name: "BazName", |
| Value: "FazValue", |
| }, |
| { |
| Name: "FooName", |
| Value: "BarValue", |
| }, |
| } |
| |
| for i, expected := range expectedLabelPairs { |
| if expected.Name != labelPairs[i].Name || expected.Value != labelPairs[i].Value { |
| t.Errorf("%d expected %s, got %s", i, expected, labelPairs[i]) |
| } |
| } |
| } |