Fix escaping for `Matcher.String()`
Now the string created will correctly parse back. Signed-off-by: beorn7 <beorn@grafana.com>
This commit is contained in:
parent
f7742393ae
commit
e1ab2477c0
|
@ -16,6 +16,7 @@ package labels
|
|||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MatchType is an enum for label matching types.
|
||||
|
@ -69,7 +70,7 @@ func NewMatcher(t MatchType, n, v string) (*Matcher, error) {
|
|||
}
|
||||
|
||||
func (m *Matcher) String() string {
|
||||
return fmt.Sprintf("%s%s%q", m.Name, m.Type, m.Value)
|
||||
return fmt.Sprintf(`%s%s"%s"`, m.Name, m.Type, openMetricsEscape(m.Value))
|
||||
}
|
||||
|
||||
// Matches returns whether the matcher matches the given string value.
|
||||
|
@ -86,3 +87,16 @@ func (m *Matcher) Matches(s string) bool {
|
|||
}
|
||||
panic("labels.Matcher.Matches: invalid match type")
|
||||
}
|
||||
|
||||
// openMetricsEscape is similar to the usual string escaping, but more
|
||||
// restricted. It merely replaces a new-line character with '\n', a double-quote
|
||||
// character with '\"', and a backslack with '\\', which is the escaping used by
|
||||
// OpenMetrics.
|
||||
func openMetricsEscape(s string) string {
|
||||
r := strings.NewReplacer(
|
||||
`\`, `\\`,
|
||||
"\n", `\n`,
|
||||
`"`, `\"`,
|
||||
)
|
||||
return r.Replace(s)
|
||||
}
|
||||
|
|
|
@ -122,3 +122,72 @@ func TestMatcher(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatcherString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
op MatchType
|
||||
value string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchEqual,
|
||||
value: `bar`,
|
||||
want: `foo="bar"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchNotEqual,
|
||||
value: `bar`,
|
||||
want: `foo!="bar"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchRegexp,
|
||||
value: `bar`,
|
||||
want: `foo=~"bar"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchNotRegexp,
|
||||
value: `bar`,
|
||||
want: `foo!~"bar"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchEqual,
|
||||
value: `back\slash`,
|
||||
want: `foo="back\\slash"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchEqual,
|
||||
value: `double"quote`,
|
||||
want: `foo="double\"quote"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchEqual,
|
||||
value: `new
|
||||
line`,
|
||||
want: `foo="new\nline"`,
|
||||
},
|
||||
{
|
||||
name: `foo`,
|
||||
op: MatchEqual,
|
||||
value: `tab stop`,
|
||||
want: `foo="tab stop"`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
m, err := NewMatcher(test.op, test.name, test.value)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := m.String(); got != test.want {
|
||||
t.Errorf("Unexpected string representation of matcher; want %v, got %v", test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue