345 lines
8.9 KiB
Go
345 lines
8.9 KiB
Go
package remap
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"regexp"
|
|
"testing"
|
|
)
|
|
|
|
type (
|
|
testMatcher struct {
|
|
Nm string
|
|
S string
|
|
M *ReMap
|
|
All bool
|
|
Expected map[string][][]byte
|
|
ExpectedStr map[string][]string
|
|
ParamInclNoMatch bool
|
|
ParamInclNoMatchStrict bool
|
|
ParamInclMustMatch bool
|
|
}
|
|
)
|
|
|
|
func TestRemap(t *testing.T) {
|
|
|
|
var matches map[string][][]byte
|
|
|
|
for midx, m := range []testMatcher{
|
|
// 1
|
|
testMatcher{
|
|
Nm: "No matches",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: nil,
|
|
},
|
|
// 2
|
|
testMatcher{
|
|
Nm: "Single mid match",
|
|
S: "This contains a single match in the middle of a string",
|
|
M: &ReMap{regexp.MustCompile(`\s+(?P<g1>match)\s+`)},
|
|
Expected: map[string][][]byte{
|
|
"g1": [][]byte{[]byte("match")},
|
|
},
|
|
},
|
|
// 3
|
|
testMatcher{
|
|
Nm: "multi mid match",
|
|
S: "This contains a single match and another match in the middle of a string",
|
|
M: &ReMap{regexp.MustCompile(`\s+(?P<g1>match) and another (?P<g1>match)\s+`)},
|
|
Expected: map[string][][]byte{
|
|
"g1": [][]byte{
|
|
[]byte("match"),
|
|
[]byte("match"),
|
|
},
|
|
},
|
|
},
|
|
// 4
|
|
testMatcher{
|
|
Nm: "line match",
|
|
S: "This\ncontains a\nsingle\nmatch\non a dedicated line",
|
|
M: &ReMap{regexp.MustCompile(`(?m)^(?P<g1>match)$`)},
|
|
Expected: map[string][][]byte{
|
|
"g1": [][]byte{
|
|
[]byte("match"),
|
|
},
|
|
},
|
|
},
|
|
// 5
|
|
testMatcher{
|
|
Nm: "multiline match",
|
|
S: "This\ncontains a\nsingle match and another\nmatch\nin the middle of a string",
|
|
M: &ReMap{regexp.MustCompile(`\s+(?P<g1>match) and another\s+(?P<g1>match)\s+`)},
|
|
All: true,
|
|
Expected: map[string][][]byte{
|
|
"g1": [][]byte{
|
|
[]byte("match"),
|
|
[]byte("match"),
|
|
},
|
|
},
|
|
},
|
|
// 6
|
|
// More closely mirrors something closer to real-life
|
|
testMatcher{
|
|
Nm: "mixed match",
|
|
S: " # No longer log hits/reqs/resps to file.\n" +
|
|
" #access_log /mnt/nginx_logs/vhost/tenant/site/access.log main;\n" +
|
|
" #error_log /mnt/nginx_logs/vhost/tenant/site/error.log;\n" +
|
|
" access_log off;\n" +
|
|
" error_log /dev/null;\n\n" +
|
|
" ssl_certificate /etc/nginx/tls/crt/tenant.pem;\n" +
|
|
" ssl_certificate_key /etc/nginx/tls/key/tenant.pem;\n\n",
|
|
M: &ReMap{regexp.MustCompile(`(?m)^\s*(?:error|access)_log\s+(?P<logpath>.+);\s*$`)},
|
|
All: true,
|
|
Expected: map[string][][]byte{
|
|
"logpath": [][]byte{
|
|
[]byte("off"),
|
|
[]byte("/dev/null"),
|
|
},
|
|
},
|
|
},
|
|
} {
|
|
if m.All {
|
|
matches = m.M.MapAll([]byte(m.S), false, false, false)
|
|
} else {
|
|
matches = m.M.Map([]byte(m.S), false, false, false)
|
|
}
|
|
t.Logf(
|
|
"#%d:\n\tsrc:\t'%s'\n\tptrn:\t'%s'\n\tmatch:\t%s\n",
|
|
midx+1,
|
|
m.S,
|
|
m.M.Regexp.String(),
|
|
testBmapToStrMap(matches),
|
|
)
|
|
if !reflect.DeepEqual(matches, m.Expected) {
|
|
t.Fatalf("Case #%d (\"%s\"): expected '%#v' != received '%#v'", midx+1, m.Nm, m.Expected, matches)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestRemapParams(t *testing.T) {
|
|
|
|
var matches map[string][][]byte
|
|
|
|
for midx, m := range []testMatcher{
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: nil,
|
|
ParamInclNoMatch: false,
|
|
ParamInclNoMatchStrict: false,
|
|
ParamInclMustMatch: false,
|
|
},
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: nil,
|
|
ParamInclNoMatch: false,
|
|
ParamInclNoMatchStrict: true,
|
|
ParamInclMustMatch: false,
|
|
},
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: nil,
|
|
ParamInclNoMatch: false,
|
|
ParamInclNoMatchStrict: true,
|
|
ParamInclMustMatch: true,
|
|
},
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: nil,
|
|
ParamInclNoMatch: false,
|
|
ParamInclNoMatchStrict: false,
|
|
ParamInclMustMatch: true,
|
|
},
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: make(map[string][][]byte),
|
|
ParamInclNoMatch: true,
|
|
ParamInclNoMatchStrict: false,
|
|
ParamInclMustMatch: false,
|
|
},
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: make(map[string][][]byte),
|
|
ParamInclNoMatch: true,
|
|
ParamInclNoMatchStrict: true,
|
|
ParamInclMustMatch: false,
|
|
},
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: make(map[string][][]byte),
|
|
ParamInclNoMatch: true,
|
|
ParamInclNoMatchStrict: true,
|
|
ParamInclMustMatch: true,
|
|
},
|
|
testMatcher{
|
|
Nm: "",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
Expected: make(map[string][][]byte),
|
|
ParamInclNoMatch: true,
|
|
ParamInclNoMatchStrict: false,
|
|
ParamInclMustMatch: true,
|
|
},
|
|
} {
|
|
if m.All {
|
|
matches = m.M.MapAll([]byte(m.S), m.ParamInclNoMatch, m.ParamInclNoMatchStrict, m.ParamInclMustMatch)
|
|
} else {
|
|
matches = m.M.Map([]byte(m.S), m.ParamInclNoMatch, m.ParamInclNoMatchStrict, m.ParamInclMustMatch)
|
|
}
|
|
t.Logf(
|
|
"%d: %v/%v/%v: %#v\n",
|
|
midx+1, m.ParamInclNoMatch, m.ParamInclNoMatchStrict, m.ParamInclMustMatch, matches,
|
|
)
|
|
if !reflect.DeepEqual(matches, m.Expected) {
|
|
t.Fatalf("Case #%d (\"%s\"): '%#v' != '%#v'", midx+1, m.Nm, m.ExpectedStr, matches)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestRemapString(t *testing.T) {
|
|
|
|
var matches map[string][]string
|
|
|
|
for midx, m := range []testMatcher{
|
|
// 1
|
|
testMatcher{
|
|
Nm: "No matches",
|
|
S: "this is a test",
|
|
M: &ReMap{regexp.MustCompile(``)},
|
|
ExpectedStr: nil,
|
|
},
|
|
// 2
|
|
testMatcher{
|
|
Nm: "Single mid match",
|
|
S: "This contains a single match in the middle of a string",
|
|
M: &ReMap{regexp.MustCompile(`\s+(?P<g1>match)\s+`)},
|
|
ExpectedStr: map[string][]string{
|
|
"g1": []string{"match"},
|
|
},
|
|
},
|
|
// 3
|
|
testMatcher{
|
|
Nm: "multi mid match",
|
|
S: "This contains a single match and another match in the middle of a string",
|
|
M: &ReMap{regexp.MustCompile(`\s+(?P<g1>match) and another (?P<g1>match)\s+`)},
|
|
ExpectedStr: map[string][]string{
|
|
"g1": []string{
|
|
"match",
|
|
"match",
|
|
},
|
|
},
|
|
},
|
|
// 4
|
|
testMatcher{
|
|
Nm: "line match",
|
|
S: "This\ncontains a\nsingle\nmatch\non a dedicated line",
|
|
M: &ReMap{regexp.MustCompile(`(?m)^(?P<g1>match)$`)},
|
|
ExpectedStr: map[string][]string{
|
|
"g1": []string{
|
|
"match",
|
|
},
|
|
},
|
|
},
|
|
// 5
|
|
testMatcher{
|
|
Nm: "multiline match",
|
|
S: "This\ncontains a\nsingle match and another\nmatch\nin the middle of a string",
|
|
M: &ReMap{regexp.MustCompile(`\s+(?P<g1>match) and another\s+(?P<g1>match)\s+`)},
|
|
All: true,
|
|
ExpectedStr: map[string][]string{
|
|
"g1": []string{
|
|
"match",
|
|
"match",
|
|
},
|
|
},
|
|
},
|
|
// 6
|
|
// More closely mirrors something closer to real-life
|
|
testMatcher{
|
|
Nm: "mixed match",
|
|
S: " # No longer log hits/reqs/resps to file.\n" +
|
|
" #access_log /mnt/nginx_logs/vhost/tenant/site/access.log main;\n" +
|
|
" #error_log /mnt/nginx_logs/vhost/tenant/site/error.log;\n" +
|
|
" access_log off;\n" +
|
|
" error_log /dev/null;\n\n" +
|
|
" ssl_certificate /etc/nginx/tls/crt/tenant.pem;\n" +
|
|
" ssl_certificate_key /etc/nginx/tls/key/tenant.pem;\n\n",
|
|
M: &ReMap{regexp.MustCompile(`(?m)^\s*(?:error|access)_log\s+(?P<logpath>.+);\s*$`)},
|
|
All: true,
|
|
ExpectedStr: map[string][]string{
|
|
"logpath": []string{
|
|
"off",
|
|
"/dev/null",
|
|
},
|
|
},
|
|
},
|
|
} {
|
|
if m.All {
|
|
matches = m.M.MapStringAll(m.S, false, false, false)
|
|
} else {
|
|
matches = m.M.MapString(m.S, false, false, false)
|
|
}
|
|
t.Logf(
|
|
"#%d:\n\tsrc:\t'%s'\n\tptrn:\t'%s'\n\tmatch:\t%s\n",
|
|
midx+1,
|
|
m.S,
|
|
m.M.Regexp.String(),
|
|
testSmapToStrMap(matches),
|
|
)
|
|
if !reflect.DeepEqual(matches, m.ExpectedStr) {
|
|
t.Fatalf("Case #%d (\"%s\"): '%#v' != '%#v'", midx+1, m.Nm, m.ExpectedStr, matches)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func testBmapToStrMap(bmap map[string][][]byte) (s string) {
|
|
|
|
if bmap == nil {
|
|
return
|
|
}
|
|
|
|
s = "\n"
|
|
for k, v := range bmap {
|
|
s += fmt.Sprintf("\t%s\n", k)
|
|
for _, i := range v {
|
|
s += fmt.Sprintf("\t\t%s\n", string(i))
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func testSmapToStrMap(smap map[string][]string) (s string) {
|
|
|
|
if smap == nil {
|
|
return
|
|
}
|
|
|
|
s = "\n"
|
|
for k, v := range smap {
|
|
s += fmt.Sprintf("\t%s\n", k)
|
|
for _, i := range v {
|
|
s += fmt.Sprintf("\t\t%s\n", i)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|