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