1 package org.codehaus.plexus.interpolation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Properties;
26
27 import org.codehaus.plexus.interpolation.os.OperatingSystemUtils;
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Test;
30
31 import static org.junit.jupiter.api.Assertions.assertEquals;
32 import static org.junit.jupiter.api.Assertions.fail;
33
34 public class StringSearchInterpolatorTest {
35
36 @BeforeEach
37 public void setUp() {
38 EnvarBasedValueSource.resetStatics();
39 }
40
41 @Test
42 public void testLongDelimitersInContext() throws InterpolationException {
43 String src = "This is a <expression>test.label</expression> for long delimiters in context.";
44 String result = "This is a test for long delimiters in context.";
45
46 Properties p = new Properties();
47 p.setProperty("test.label", "test");
48
49 StringSearchInterpolator interpolator = new StringSearchInterpolator("<expression>", "</expression>");
50 interpolator.addValueSource(new PropertiesBasedValueSource(p));
51
52 assertEquals(result, interpolator.interpolate(src));
53 }
54
55 @Test
56 public void testLongDelimitersWithNoStartContext() throws InterpolationException {
57 String src = "<expression>test.label</expression> for long delimiters in context.";
58 String result = "test for long delimiters in context.";
59
60 Properties p = new Properties();
61 p.setProperty("test.label", "test");
62
63 StringSearchInterpolator interpolator = new StringSearchInterpolator("<expression>", "</expression>");
64 interpolator.addValueSource(new PropertiesBasedValueSource(p));
65
66 assertEquals(result, interpolator.interpolate(src));
67 }
68
69 @Test
70 public void testLongDelimitersWithNoEndContext() throws InterpolationException {
71 String src = "This is a <expression>test.label</expression>";
72 String result = "This is a test";
73
74 Properties p = new Properties();
75 p.setProperty("test.label", "test");
76
77 StringSearchInterpolator interpolator = new StringSearchInterpolator("<expression>", "</expression>");
78 interpolator.addValueSource(new PropertiesBasedValueSource(p));
79
80 assertEquals(result, interpolator.interpolate(src));
81 }
82
83 @Test
84 public void testLongDelimitersWithNoContext() throws InterpolationException {
85 String src = "<expression>test.label</expression>";
86 String result = "test";
87
88 Properties p = new Properties();
89 p.setProperty("test.label", "test");
90
91 StringSearchInterpolator interpolator = new StringSearchInterpolator("<expression>", "</expression>");
92 interpolator.addValueSource(new PropertiesBasedValueSource(p));
93
94 assertEquals(result, interpolator.interpolate(src));
95 }
96
97 @Test
98 public void testLongDelimitersPassedToValueSource() throws InterpolationException {
99 String src = "<expression>test</expression>";
100
101 StringSearchInterpolator interpolator = new StringSearchInterpolator("<expression>", "</expression>");
102 interpolator.addValueSource(new AbstractValueSource(false) {
103
104 @Override
105 public Object getValue(String expression, String expressionStartDelimiter, String expressionEndDelimiter) {
106 assertEquals("<expression>", expressionStartDelimiter);
107 assertEquals("</expression>", expressionEndDelimiter);
108 return expression;
109 }
110
111 @Override
112 public Object getValue(String expression) {
113 fail("This method is not supposed to be called");
114 return null;
115 }
116 });
117
118 assertEquals("test", interpolator.interpolate(src));
119 }
120
121 @Test
122 public void testSimpleSubstitution() throws InterpolationException {
123 Properties p = new Properties();
124 p.setProperty("key", "value");
125
126 StringSearchInterpolator interpolator = new StringSearchInterpolator();
127 interpolator.addValueSource(new PropertiesBasedValueSource(p));
128
129 assertEquals("This is a test value.", interpolator.interpolate("This is a test ${key}."));
130 }
131
132 @Test
133 public void testSimpleSubstitution_TwoExpressions() throws InterpolationException {
134 Properties p = new Properties();
135 p.setProperty("key", "value");
136 p.setProperty("key2", "value2");
137
138 StringSearchInterpolator interpolator = new StringSearchInterpolator();
139 interpolator.addValueSource(new PropertiesBasedValueSource(p));
140
141 assertEquals("value-value2", interpolator.interpolate("${key}-${key2}"));
142 }
143
144 @Test
145 public void testBrokenExpression_LeaveItAlone() throws InterpolationException {
146 Properties p = new Properties();
147 p.setProperty("key", "value");
148
149 StringSearchInterpolator interpolator = new StringSearchInterpolator();
150 interpolator.addValueSource(new PropertiesBasedValueSource(p));
151
152 assertEquals("This is a test ${key.", interpolator.interpolate("This is a test ${key."));
153 }
154
155 @Test
156 public void testShouldFailOnExpressionCycle() {
157 Properties props = new Properties();
158 props.setProperty("key1", "${key2}");
159 props.setProperty("key2", "${key1}");
160
161 StringSearchInterpolator rbi = new StringSearchInterpolator();
162 rbi.addValueSource(new PropertiesBasedValueSource(props));
163
164 try {
165 rbi.interpolate("${key1}", new SimpleRecursionInterceptor());
166
167 fail("Should detect expression cycle and fail.");
168 } catch (InterpolationException e) {
169
170 }
171 }
172
173 @Test
174 public void testShouldResolveByUsingObject_List_Map() throws InterpolationException {
175 StringSearchInterpolator rbi = new StringSearchInterpolator();
176 rbi.addValueSource(new ObjectBasedValueSource(this));
177 String result =
178 rbi.interpolate("this is a ${var} ${list[1].name} ${anArray[2].name} ${map(Key with spaces).name}");
179
180 assertEquals("this is a testVar testIndexedWithList testIndexedWithArray testMap", result);
181 }
182
183 @Test
184 public void testShouldResolveByContextValue() throws InterpolationException {
185 StringSearchInterpolator rbi = new StringSearchInterpolator();
186
187 Map context = new HashMap();
188 context.put("var", "testVar");
189
190 rbi.addValueSource(new MapBasedValueSource(context));
191
192 String result = rbi.interpolate("this is a ${var}");
193
194 assertEquals("this is a testVar", result);
195 }
196
197 @Test
198 public void testShouldResolveByEnvar() throws IOException, InterpolationException {
199 OperatingSystemUtils.setEnvVarSource(new OperatingSystemUtils.EnvVarSource() {
200 public Map<String, String> getEnvMap() {
201 HashMap<String, String> map = new HashMap<String, String>();
202 map.put("SOME_ENV", "variable");
203 map.put("OTHER_ENV", "other variable");
204 return map;
205 }
206 });
207
208 StringSearchInterpolator rbi = new StringSearchInterpolator();
209
210 rbi.addValueSource(new EnvarBasedValueSource(false));
211
212 String result = rbi.interpolate("this is a ${env.SOME_ENV} ${env.OTHER_ENV}");
213
214 assertEquals("this is a variable other variable", result);
215 }
216
217 @Test
218 public void testUsePostProcessor_DoesNotChangeValue() throws InterpolationException {
219 StringSearchInterpolator rbi = new StringSearchInterpolator();
220
221 Map context = new HashMap();
222 context.put("test.var", "testVar");
223
224 rbi.addValueSource(new MapBasedValueSource(context));
225
226 rbi.addPostProcessor(new InterpolationPostProcessor() {
227 public Object execute(String expression, Object value) {
228 return null;
229 }
230 });
231
232 String result = rbi.interpolate("this is a ${test.var}");
233
234 assertEquals("this is a testVar", result);
235 }
236
237 @Test
238 public void testUsePostProcessor_ChangesValue() throws InterpolationException {
239
240 StringSearchInterpolator rbi = new StringSearchInterpolator();
241
242 Map context = new HashMap();
243 context.put("test.var", "testVar");
244
245 rbi.addValueSource(new MapBasedValueSource(context));
246
247 rbi.addPostProcessor(new InterpolationPostProcessor() {
248 public Object execute(String expression, Object value) {
249 return value + "2";
250 }
251 });
252
253 String result = rbi.interpolate("this is a ${test.var}");
254
255 assertEquals("this is a testVar2", result);
256 }
257
258 @Test
259 public void testSimpleSubstitutionWithDefinedExpr() throws InterpolationException {
260 Properties p = new Properties();
261 p.setProperty("key", "value");
262
263 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
264 interpolator.addValueSource(new PropertiesBasedValueSource(p));
265
266 assertEquals("This is a test value.", interpolator.interpolate("This is a test @{key}."));
267 }
268
269 @Test
270 public void testEscape() throws InterpolationException {
271 Properties p = new Properties();
272 p.setProperty("key", "value");
273
274 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
275 interpolator.setEscapeString("\\");
276 interpolator.addValueSource(new PropertiesBasedValueSource(p));
277
278 String result = interpolator.interpolate("This is a test \\@{key}.");
279
280 assertEquals("This is a test @{key}.", result);
281 }
282
283 @Test
284 public void testEscapeWithLongEscapeStr() throws InterpolationException {
285 Properties p = new Properties();
286 p.setProperty("key", "value");
287
288 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
289 interpolator.setEscapeString("$$");
290 interpolator.addValueSource(new PropertiesBasedValueSource(p));
291
292 String result = interpolator.interpolate("This is a test $$@{key}.");
293
294 assertEquals("This is a test @{key}.", result);
295 }
296
297 @Test
298 public void testEscapeWithLongEscapeStrAtStart() throws InterpolationException {
299 Properties p = new Properties();
300 p.setProperty("key", "value");
301
302 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
303 interpolator.setEscapeString("$$");
304 interpolator.addValueSource(new PropertiesBasedValueSource(p));
305
306 String result = interpolator.interpolate("$$@{key} This is a test.");
307
308 assertEquals("@{key} This is a test.", result);
309 }
310
311 @Test
312 public void testNotEscapeWithLongEscapeStrAtStart() throws InterpolationException {
313 Properties p = new Properties();
314 p.setProperty("key", "value");
315
316 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
317 interpolator.setEscapeString("$$");
318 interpolator.addValueSource(new PropertiesBasedValueSource(p));
319
320 String result = interpolator.interpolate("@{key} This is a test.");
321
322 assertEquals("value This is a test.", result);
323 }
324
325 @Test
326 public void testEscapeNotFailWithNullEscapeStr() throws InterpolationException {
327 Properties p = new Properties();
328 p.setProperty("key", "value");
329
330 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
331 interpolator.setEscapeString(null);
332 interpolator.addValueSource(new PropertiesBasedValueSource(p));
333
334 String result = interpolator.interpolate("This is a test @{key}.");
335
336 assertEquals("This is a test value.", result);
337 }
338
339 @Test
340 public void testOnlyEscapeExprAtStart() throws InterpolationException {
341 Properties p = new Properties();
342 p.setProperty("key", "value");
343
344 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
345 interpolator.setEscapeString("\\");
346 interpolator.addValueSource(new PropertiesBasedValueSource(p));
347
348 String result = interpolator.interpolate("\\@{key} This is a test.");
349
350 assertEquals("@{key} This is a test.", result);
351 }
352
353 @Test
354 public void testNotEscapeExprAtStart() throws InterpolationException {
355 Properties p = new Properties();
356 p.setProperty("key", "value");
357
358 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
359 interpolator.setEscapeString("\\");
360 interpolator.addValueSource(new PropertiesBasedValueSource(p));
361
362 String result = interpolator.interpolate("@{key} This is a test.");
363
364 assertEquals("value This is a test.", result);
365 }
366
367 @Test
368 public void testEscapeExprAtStart() throws InterpolationException {
369 Properties p = new Properties();
370 p.setProperty("key", "value");
371
372 StringSearchInterpolator interpolator = new StringSearchInterpolator("@", "@");
373 interpolator.setEscapeString("\\");
374 interpolator.addValueSource(new PropertiesBasedValueSource(p));
375
376 String result = interpolator.interpolate("\\@key@ This is a test @key@.");
377
378 assertEquals("@key@ This is a test value.", result);
379 }
380
381 @Test
382 public void testNPEFree() throws InterpolationException {
383 Properties p = new Properties();
384 p.setProperty("key", "value");
385
386 StringSearchInterpolator interpolator = new StringSearchInterpolator("@{", "}");
387 interpolator.setEscapeString("\\");
388 interpolator.addValueSource(new PropertiesBasedValueSource(p));
389
390 String result = interpolator.interpolate(null);
391
392 assertEquals("", result);
393 }
394
395 @Test
396 public void testInterruptedInterpolate() throws InterpolationException {
397 Interpolator interpolator = new StringSearchInterpolator();
398 RecursionInterceptor recursionInterceptor = new SimpleRecursionInterceptor();
399 final boolean[] error = new boolean[] {false};
400 interpolator.addValueSource(new ValueSource() {
401 public Object getValue(String expression) {
402 if (expression.equals("key")) {
403 if (error[0]) {
404 throw new IllegalStateException("broken");
405 }
406 return "val";
407 } else {
408 return null;
409 }
410 }
411
412 public List getFeedback() {
413 return Collections.EMPTY_LIST;
414 }
415
416 public void clearFeedback() {}
417 });
418 assertEquals("-val-", interpolator.interpolate("-${key}-", recursionInterceptor), "control case");
419 error[0] = true;
420 try {
421 interpolator.interpolate("-${key}-", recursionInterceptor);
422 fail("should have thrown exception");
423 } catch (IllegalStateException x) {
424
425 }
426 error[0] = false;
427 assertEquals(
428 "-val-",
429 interpolator.interpolate("-${key}-", recursionInterceptor),
430 "should not believe there is a cycle here");
431 }
432
433 @Test
434 public void testCacheAnswersTrue() throws InterpolationException {
435 Properties p = new Properties();
436 p.setProperty("key", "value");
437
438 class CountingStringSearchInterpolator extends StringSearchInterpolator {
439 private int existingCallCount;
440
441 @Override
442 protected Object getExistingAnswer(String key) {
443 Object value = super.getExistingAnswer(key);
444 if (value != null) {
445 ++existingCallCount;
446 }
447 return value;
448 }
449
450 public int getExistingCallCount() {
451 return existingCallCount;
452 }
453 }
454
455 CountingStringSearchInterpolator interpolator = new CountingStringSearchInterpolator();
456 interpolator.setCacheAnswers(true);
457 interpolator.addValueSource(new PropertiesBasedValueSource(p));
458
459 String result = interpolator.interpolate("${key}-${key}-${key}-${key}");
460
461 assertEquals("value-value-value-value", result);
462
463 assertEquals(3, interpolator.getExistingCallCount());
464
465
466 result = interpolator.interpolate("${key}-${key}-${key}-${key}");
467 assertEquals("value-value-value-value", result);
468
469 assertEquals(3 + 4, interpolator.getExistingCallCount());
470 }
471
472 @Test
473 public void testCacheAnswersFalse() throws InterpolationException {
474 Properties p = new Properties();
475 p.setProperty("key", "value");
476
477 class CountingStringSearchInterpolator extends StringSearchInterpolator {
478 private int existingCallCount;
479
480 @Override
481 protected Object getExistingAnswer(String key) {
482 Object value = super.getExistingAnswer(key);
483 if (value != null) {
484 ++existingCallCount;
485 }
486 return value;
487 }
488
489 public int getExistingCallCount() {
490 return existingCallCount;
491 }
492 }
493
494 CountingStringSearchInterpolator interpolator = new CountingStringSearchInterpolator();
495 interpolator.addValueSource(new PropertiesBasedValueSource(p));
496
497 String result = interpolator.interpolate("${key}-${key}-${key}-${key}");
498
499 assertEquals("value-value-value-value", result);
500
501 assertEquals(0, interpolator.getExistingCallCount());
502 }
503
504 public String getVar() {
505 return "testVar";
506 }
507
508 public Person[] getAnArray() {
509 Person[] array = new Person[3];
510 array[0] = new Person("Gabriel");
511 array[1] = new Person("Daniela");
512 array[2] = new Person("testIndexedWithArray");
513 return array;
514 }
515
516 public List<Person> getList() {
517 List<Person> list = new ArrayList<Person>();
518 list.add(new Person("Gabriel"));
519 list.add(new Person("testIndexedWithList"));
520 list.add(new Person("Daniela"));
521 return list;
522 }
523
524 public Map<String, Person> getMap() {
525 Map<String, Person> map = new HashMap<String, StringSearchInterpolatorTest.Person>();
526 map.put("Key with spaces", new Person("testMap"));
527 return map;
528 }
529
530 public static class Person {
531 private String name;
532
533 public Person(String name) {
534 this.name = name;
535 }
536
537 public String getName() {
538 return name;
539 }
540 }
541 }