lib/storage: fix matching against tag filter with empty name

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/137
This commit is contained in:
Aliaksandr Valialkin 2019-07-30 15:14:09 +03:00
parent 5b8526e925
commit b7c4b0c6d2
3 changed files with 84 additions and 6 deletions

View file

@ -1430,7 +1430,7 @@ func matchTagFilters(mn *MetricName, tfs []*tagFilter, kb *bytesutil.ByteBuffer)
continue continue
} }
// Found the matching tag name. Match for the value. // Found the matching tag name. Match the value.
b := tag.Marshal(kb.B) b := tag.Marshal(kb.B)
kb.B = b[:len(kb.B)] kb.B = b[:len(kb.B)]
ok, err := matchTagFilter(b, tf) ok, err := matchTagFilter(b, tf)
@ -1443,7 +1443,7 @@ func matchTagFilters(mn *MetricName, tfs []*tagFilter, kb *bytesutil.ByteBuffer)
tagMatched = true tagMatched = true
break break
} }
if !tagMatched { if !tagMatched && !tf.isNegative {
// Matching tag name wasn't found. // Matching tag name wasn't found.
return false, nil return false, nil
} }

View file

@ -804,8 +804,8 @@ func TestMatchTagFilters(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
if ok { if !ok {
t.Fatalf("Shouldn't match") t.Fatalf("Should match")
} }
tfs.Reset(mn.AccountID, mn.ProjectID) tfs.Reset(mn.AccountID, mn.ProjectID)
if err := tfs.Add([]byte("non-existing-tag"), []byte("foob.+metric"), true, true); err != nil { if err := tfs.Add([]byte("non-existing-tag"), []byte("foob.+metric"), true, true); err != nil {
@ -815,8 +815,19 @@ func TestMatchTagFilters(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
if ok { if !ok {
t.Fatalf("Shouldn't match") t.Fatalf("Should match")
}
tfs.Reset(mn.AccountID, mn.ProjectID)
if err := tfs.Add([]byte("non-existing-tag"), []byte(".+"), true, true); err != nil {
t.Fatalf("cannot add regexp, negative filter: %s", err)
}
ok, err = matchTagFilters(&mn, toTFPointers(tfs.tfs), &bb)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !ok {
t.Fatalf("Should match")
} }
// Negative match by existing tag // Negative match by existing tag
@ -910,6 +921,17 @@ func TestMatchTagFilters(t *testing.T) {
if !ok { if !ok {
t.Fatalf("Should match") t.Fatalf("Should match")
} }
tfs.Reset(mn.AccountID, mn.ProjectID)
if err := tfs.Add([]byte("key 3"), []byte(""), true, false); err != nil {
t.Fatalf("cannot add regexp, negative filter: %s", err)
}
ok, err = matchTagFilters(&mn, toTFPointers(tfs.tfs), &bb)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !ok {
t.Fatalf("Should match")
}
// Positive match by multiple tags and MetricGroup // Positive match by multiple tags and MetricGroup
tfs.Reset(mn.AccountID, mn.ProjectID) tfs.Reset(mn.AccountID, mn.ProjectID)

View file

@ -308,6 +308,62 @@ func TestTagFilterMatchSuffix(t *testing.T) {
mismatch("bar") mismatch("bar")
match("xhttpbar") match("xhttpbar")
}) })
t.Run("non-empty-string-regexp-negative-match", func(t *testing.T) {
value := ".+"
isNegative := true
isRegexp := true
expectedPrefix := tvNoTrailingTagSeparator("")
init(value, isNegative, isRegexp, expectedPrefix)
if len(tf.orSuffixes) != 0 {
t.Fatalf("unexpected non-zero number of or suffixes: %d; %q", len(tf.orSuffixes), tf.orSuffixes)
}
match("")
mismatch("x")
mismatch("foo")
})
t.Run("non-empty-string-regexp-match", func(t *testing.T) {
value := ".+"
isNegative := false
isRegexp := true
expectedPrefix := tvNoTrailingTagSeparator("")
init(value, isNegative, isRegexp, expectedPrefix)
if len(tf.orSuffixes) != 0 {
t.Fatalf("unexpected non-zero number of or suffixes: %d; %q", len(tf.orSuffixes), tf.orSuffixes)
}
mismatch("")
match("x")
match("foo")
})
t.Run("match-all-regexp-negative-match", func(t *testing.T) {
value := ".*"
isNegative := true
isRegexp := true
expectedPrefix := tvNoTrailingTagSeparator("")
init(value, isNegative, isRegexp, expectedPrefix)
if len(tf.orSuffixes) != 0 {
t.Fatalf("unexpected non-zero number of or suffixes: %d; %q", len(tf.orSuffixes), tf.orSuffixes)
}
mismatch("")
mismatch("x")
mismatch("foo")
})
t.Run("match-all-regexp-match", func(t *testing.T) {
value := ".*"
isNegative := false
isRegexp := true
expectedPrefix := tvNoTrailingTagSeparator("")
init(value, isNegative, isRegexp, expectedPrefix)
if len(tf.orSuffixes) != 0 {
t.Fatalf("unexpected non-zero number of or suffixes: %d; %q", len(tf.orSuffixes), tf.orSuffixes)
}
match("")
match("x")
match("foo")
})
} }
func TestGetOrValues(t *testing.T) { func TestGetOrValues(t *testing.T) {