Rework Replacer loop to handle escaped braces (#3121)

Fixes #3116

* Rework Replacer loop to ignore escaped braces

* Add benchmark tests for replacer

* Optimise handling of escaped braces

* Handle escaped closing braces

* Remove additional check for closing brace

This commit removes the additional check for input in which the closing
brace appears before the opening brace. This check has been removed for
performance reasons as it is deemed an unlikely edge case.

* Check for escaped closing braces in placeholder name
This commit is contained in:
Bill Glover
2020-03-08 21:36:59 +00:00
committed by GitHub
parent ca6e54bbb8
commit 36a6c7daf0
2 changed files with 127 additions and 1 deletions

View File

@@ -35,30 +35,86 @@ func TestReplacer(t *testing.T) {
input: "{",
expect: "{",
},
{
input: `\{`,
expect: `{`,
},
{
input: "foo{",
expect: "foo{",
},
{
input: `foo\{`,
expect: `foo{`,
},
{
input: "foo{bar",
expect: "foo{bar",
},
{
input: `foo\{bar`,
expect: `foo{bar`,
},
{
input: "foo{bar}",
expect: "foo",
},
{
input: `foo\{bar\}`,
expect: `foo{bar}`,
},
{
input: "}",
expect: "}",
},
{
input: `\}`,
expect: `\}`,
},
{
input: "{}",
expect: "",
},
{
input: `\{\}`,
expect: `{}`,
},
{
input: `{"json": "object"}`,
expect: "",
},
{
input: `\{"json": "object"}`,
expect: `{"json": "object"}`,
},
{
input: `\{"json": "object"\}`,
expect: `{"json": "object"}`,
},
{
input: `\{"json": "object{bar}"\}`,
expect: `{"json": "object"}`,
},
{
input: `\{"json": \{"nested": "object"\}\}`,
expect: `{"json": {"nested": "object"}}`,
},
{
input: `\{"json": \{"nested": "{bar}"\}\}`,
expect: `{"json": {"nested": ""}}`,
},
{
input: `pre \{"json": \{"nested": "{bar}"\}\}`,
expect: `pre {"json": {"nested": ""}}`,
},
{
input: `\{"json": \{"nested": "{bar}"\}\} post`,
expect: `{"json": {"nested": ""}} post`,
},
{
input: `pre \{"json": \{"nested": "{bar}"\}\} post`,
expect: `pre {"json": {"nested": ""}} post`,
},
{
input: `{{`,
expect: "{{",
@@ -67,11 +123,39 @@ func TestReplacer(t *testing.T) {
input: `{{}`,
expect: "",
},
{
input: `{"json": "object"\}`,
expect: "",
},
{
input: `{unknown}`,
empty: "-",
expect: "-",
},
{
input: `back\slashes`,
expect: `back\slashes`,
},
{
input: `double back\\slashes`,
expect: `double back\\slashes`,
},
{
input: `placeholder {with \{ brace} in name`,
expect: `placeholder in name`,
},
{
input: `placeholder {with \} brace} in name`,
expect: `placeholder in name`,
},
{
input: `placeholder {with \} \} braces} in name`,
expect: `placeholder in name`,
},
{
input: `\{'group':'default','max_age':3600,'endpoints':[\{'url':'https://some.domain.local/a/d/g'\}],'include_subdomains':true\}`,
expect: `{'group':'default','max_age':3600,'endpoints':[{'url':'https://some.domain.local/a/d/g'}],'include_subdomains':true}`,
},
} {
actual := rep.ReplaceAll(tc.input, tc.empty)
if actual != tc.expect {
@@ -81,6 +165,35 @@ func TestReplacer(t *testing.T) {
}
}
func BenchmarkReplacer(b *testing.B) {
type testCase struct {
name, input, empty string
}
rep := testReplacer()
for _, bm := range []testCase{
{
name: "no placeholder",
input: `simple string`,
},
{
name: "placeholder",
input: `{"json": "object"}`,
},
{
name: "escaped placeholder",
input: `\{"json": \{"nested": "{bar}"\}\}`,
},
} {
b.Run(bm.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
rep.ReplaceAll(bm.input, bm.empty)
}
})
}
}
func TestReplacerSet(t *testing.T) {
rep := testReplacer()