@@ -39,23 +39,31 @@ public final class CelRegexExtensionsTest {
3939 CelRuntimeFactory .standardCelRuntimeBuilder ().addLibraries (CelExtensions .regex ()).build ();
4040
4141 @ Test
42- @ TestParameters ("{target: 'foo bar', regex: '(fo)o (ba)r', replaceStr: '$2 $1', res: 'ba fo'}" )
42+ @ TestParameters ("{target: 'abc', regex: '^', replaceStr: 'start_', res: 'start_abc'}" )
43+ @ TestParameters ("{target: 'abc', regex: '$', replaceStr: '_end', res: 'abc_end'}" )
44+ @ TestParameters ("{target: 'a-b', regex: '\\ \\ b', replaceStr: '|', res: '|a|-|b|'}" )
45+ @ TestParameters (
46+ "{target: 'foo bar', regex: '(fo)o (ba)r', replaceStr: '\\ \\ 2 \\ \\ 1', res: 'ba fo'}" )
47+ @ TestParameters ("{target: 'foo bar', regex: 'foo', replaceStr: '\\ \\ \\ \\ ', res: '\\ bar'}" )
4348 @ TestParameters ("{target: 'banana', regex: 'ana', replaceStr: 'x', res: 'bxna'}" )
44- @ TestParameters ("{target: 'abc', regex: 'b(.)', replaceStr: 'x$ 1', res: 'axc'}" )
49+ @ TestParameters ("{target: 'abc', regex: 'b(.)', replaceStr: 'x\\ \\ 1', res: 'axc'}" )
4550 @ TestParameters (
4651 "{target: 'hello world hello', regex: 'hello', replaceStr: 'hi', res: 'hi world hi'}" )
52+ @ TestParameters ("{target: 'ac', regex: 'a(b)?c', replaceStr: '[\\ \\ 1]', res: '[]'}" )
4753 @ TestParameters ("{target: 'apple pie', regex: 'p', replaceStr: 'X', res: 'aXXle Xie'}" )
4854 @ TestParameters (
4955 "{target: 'remove all spaces', regex: '\\ \\ s', replaceStr: '', res: 'removeallspaces'}" )
5056 @ TestParameters ("{target: 'digit:99919291992', regex: '\\ \\ d+', replaceStr: '3', res: 'digit:3'}" )
5157 @ TestParameters (
52- "{target: 'foo bar baz', regex: '\\ \\ w+', replaceStr: '($ 0)', res: '(foo) (bar) (baz)'}" )
58+ "{target: 'foo bar baz', regex: '\\ \\ w+', replaceStr: '(\\ \\ 0)', res: '(foo) (bar) (baz)'}" )
5359 @ TestParameters ("{target: '', regex: 'a', replaceStr: 'b', res: ''}" )
5460 @ TestParameters (
5561 "{target: 'User: Alice, Age: 30', regex: 'User: (?P<name>\\ \\ w+), Age: (?P<age>\\ \\ d+)',"
56- + " replaceStr: '${name} is ${age} years old', res: 'Alice is 30 years old'}" )
62+ + " replaceStr: '${name} is ${age} years old', res: '${name} is ${age} years old'}" )
5763 @ TestParameters (
58- "{target: 'abc', regex: '(?P<letter>b)', replaceStr: '[${letter}]', res: 'a[b]c'}" )
64+ "{target: 'User: Alice, Age: 30', regex: 'User: (?P<name>\\ \\ w+), Age: (?P<age>\\ \\ d+)',"
65+ + " replaceStr: '\\ \\ 1 is \\ \\ 2 years old', res: 'Alice is 30 years old'}" )
66+ @ TestParameters ("{target: 'hello ☃', regex: '☃', replaceStr: '❄', res: 'hello ❄'}" )
5967 public void replaceAll_success (String target , String regex , String replaceStr , String res )
6068 throws Exception {
6169 String expr = String .format ("regex.replace('%s', '%s', '%s')" , target , regex , replaceStr );
@@ -70,8 +78,8 @@ public void replaceAll_success(String target, String regex, String replaceStr, S
7078 public void replace_nested_success () throws Exception {
7179 String expr =
7280 "regex.replace("
73- + " regex.replace('%(foo) %(bar) %2','%\\ \\ ((\\ \\ w+)\\ \\ )','\\ \\ ${$ 1}'),"
74- + " '%(\\ \\ d+)', '\\ \\ $$ 1')" ;
81+ + " regex.replace('%(foo) %(bar) %2','%\\ \\ ((\\ \\ w+)\\ \\ )','${ \\ \\ 1}'),"
82+ + " '%(\\ \\ d+)', '$ \\ \\ 1')" ;
7583 CelRuntime .Program program = RUNTIME .createProgram (COMPILER .compile (expr ).getAst ());
7684
7785 Object result = program .eval ();
@@ -85,19 +93,18 @@ public void replace_nested_success() throws Exception {
8593 @ TestParameters ("{t: 'banana', re: 'a', rep: 'x', i: 2, res: 'bxnxna'}" )
8694 @ TestParameters ("{t: 'banana', re: 'a', rep: 'x', i: 100, res: 'bxnxnx'}" )
8795 @ TestParameters ("{t: 'banana', re: 'a', rep: 'x', i: -1, res: 'bxnxnx'}" )
88- @ TestParameters ("{t: 'banana', re: 'a', rep: 'x', i: -100, res: 'banana '}" )
96+ @ TestParameters ("{t: 'banana', re: 'a', rep: 'x', i: -100, res: 'bxnxnx '}" )
8997 @ TestParameters (
90- "{t: 'cat-dog dog-cat cat-dog dog-cat', re: '(cat)-(dog)', rep: '$2-$ 1', i: 1,"
98+ "{t: 'cat-dog dog-cat cat-dog dog-cat', re: '(cat)-(dog)', rep: '\\ \\ 2- \\ \\ 1', i: 1,"
9199 + " res: 'dog-cat dog-cat cat-dog dog-cat'}" )
92100 @ TestParameters (
93- "{t: 'cat-dog dog-cat cat-dog dog-cat', re: '(cat)-(dog)', rep: '$2-$ 1', i: 2, res: 'dog-cat "
94- + " dog-cat dog-cat dog-cat'}" )
101+ "{t: 'cat-dog dog-cat cat-dog dog-cat', re: '(cat)-(dog)', rep: '\\ \\ 2- \\ \\ 1', i: 2, res:"
102+ + " 'dog-cat dog-cat dog-cat dog-cat'}" )
95103 @ TestParameters ("{t: 'a.b.c', re: '\\ \\ .', rep: '-', i: 1, res: 'a-b.c'}" )
96104 @ TestParameters ("{t: 'a.b.c', re: '\\ \\ .', rep: '-', i: -1, res: 'a-b-c'}" )
97105 public void replaceCount_success (String t , String re , String rep , long i , String res )
98106 throws Exception {
99107 String expr = String .format ("regex.replace('%s', '%s', '%s', %d)" , t , re , rep , i );
100- System .out .println ("expr: " + expr );
101108 CelRuntime .Program program = RUNTIME .createProgram (COMPILER .compile (expr ).getAst ());
102109
103110 Object result = program .eval ();
@@ -108,7 +115,7 @@ public void replaceCount_success(String t, String re, String rep, long i, String
108115 @ Test
109116 @ TestParameters ("{target: 'foo bar', regex: '(', replaceStr: '$2 $1'}" )
110117 @ TestParameters ("{target: 'foo bar', regex: '[a-z', replaceStr: '$2 $1'}" )
111- public void replace_invalid_regex (String target , String regex , String replaceStr )
118+ public void replace_invalidRegex_throwsException (String target , String regex , String replaceStr )
112119 throws Exception {
113120 String expr = String .format ("regex.replace('%s', '%s', '%s')" , target , regex , replaceStr );
114121 CelAbstractSyntaxTree ast = COMPILER .compile (expr ).getAst ();
@@ -121,32 +128,48 @@ public void replace_invalid_regex(String target, String regex, String replaceStr
121128 }
122129
123130 @ Test
124- @ TestParameters ("{target: 'test', regex: '(.)', replaceStr: '$2'}" )
125- public void replace_invalid_captureGroup (String target , String regex , String replaceStr )
126- throws Exception {
127- String expr = String .format ("regex.replace('%s', '%s', '%s')" , target , regex , replaceStr );
131+ public void replace_invalidCaptureGroupReplaceStr_throwsException () throws Exception {
132+ String expr = "regex.replace('test', '(.)', '\\ \\ 2')" ;
128133 CelAbstractSyntaxTree ast = COMPILER .compile (expr ).getAst ();
129134
130135 CelEvaluationException e =
131136 assertThrows (CelEvaluationException .class , () -> RUNTIME .createProgram (ast ).eval ());
132137
133- assertThat (e ).hasCauseThat ().isInstanceOf (IndexOutOfBoundsException .class );
134- assertThat (e ).hasCauseThat ().hasMessageThat ().contains ("n > number of groups" );
138+ assertThat (e ).hasCauseThat ().isInstanceOf (IllegalArgumentException .class );
139+ assertThat (e )
140+ .hasCauseThat ()
141+ .hasMessageThat ()
142+ .contains ("Replacement string references group 2 but regex has only 1 group(s)" );
135143 }
136144
137145 @ Test
138- @ TestParameters (
139- "{target: 'id=123', regex: 'id=(?P<value>\\ \\ d+)', replaceStr: 'value: ${values}'}" )
140- public void replace_invalid_replaceStr (String target , String regex , String replaceStr )
141- throws Exception {
142- String expr = String .format ("regex.replace('%s', '%s', '%s')" , target , regex , replaceStr );
146+ public void replace_trailingBackslashReplaceStr_throwsException () throws Exception {
147+ String expr = "regex.replace('id=123', 'id=(?P<value>\\ \\ d+)', '\\ \\ ')" ;
148+ CelAbstractSyntaxTree ast = COMPILER .compile (expr ).getAst ();
149+
150+ CelEvaluationException e =
151+ assertThrows (CelEvaluationException .class , () -> RUNTIME .createProgram (ast ).eval ());
152+
153+ assertThat (e ).hasCauseThat ().isInstanceOf (IllegalArgumentException .class );
154+ assertThat (e )
155+ .hasCauseThat ()
156+ .hasMessageThat ()
157+ .contains ("Invalid replacement string: \\ not allowed at end" );
158+ }
159+
160+ @ Test
161+ public void replace_invalidGroupReferenceReplaceStr_throwsException () throws Exception {
162+ String expr = "regex.replace('id=123', 'id=(?P<value>\\ \\ d+)', '\\ \\ a')" ;
143163 CelAbstractSyntaxTree ast = COMPILER .compile (expr ).getAst ();
144164
145165 CelEvaluationException e =
146166 assertThrows (CelEvaluationException .class , () -> RUNTIME .createProgram (ast ).eval ());
147167
148168 assertThat (e ).hasCauseThat ().isInstanceOf (IllegalArgumentException .class );
149- assertThat (e ).hasCauseThat ().hasMessageThat ().contains ("group 'values' not found" );
169+ assertThat (e )
170+ .hasCauseThat ()
171+ .hasMessageThat ()
172+ .contains ("Invalid replacement string: \\ must be followed by a digit" );
150173 }
151174
152175 @ Test
@@ -208,6 +231,9 @@ private enum ExtractAllTestCase {
208231 NO_MATCH ("regex.extractAll('id:123, id:456', 'assa')" , ImmutableList .of ()),
209232 NO_CAPTURE_GROUP (
210233 "regex.extractAll('id:123, id:456', 'id:\\ \\ d+')" , ImmutableList .of ("id:123" , "id:456" )),
234+ CAPTURE_GROUP (
235+ "regex.extractAll('key=\" \" , key=\" val\" ', 'key=\" ([^\" ]*)\" ')" ,
236+ ImmutableList .of ("" , "val" )),
211237 SINGLE_NAMED_GROUP (
212238 "regex.extractAll('testuser@testdomain', '(?P<username>.*)@')" ,
213239 ImmutableList .of ("testuser" )),
0 commit comments