Skip to content

Commit

Permalink
Fix #16: StringSearchInterpolator does not cache answers.
Browse files Browse the repository at this point in the history
- Added tests exposing the issue.
- Fixed code.
- Added missing @OverRide annotations.
  • Loading branch information
belingueres authored and slachiewicz committed May 12, 2024
1 parent c74d84c commit d0a18bc
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept

recursionInterceptor.expressionResolutionStarted(realExpr);
try {
Object value = existingAnswers.get(realExpr);
Object value = getExistingAnswer(realExpr);
Object bestAnswer = null;

for (ValueSource valueSource : valueSources) {
Expand Down Expand Up @@ -197,6 +197,10 @@ private String interpolate(String input, RecursionInterceptor recursionIntercept
// behaviour
result.append(String.valueOf(value));
resolved = true;

if (cacheAnswers) {
existingAnswers.put(realExpr, value);
}
} else {
unresolvable.add(wholeExpr);
}
Expand Down Expand Up @@ -275,4 +279,13 @@ public String getEscapeString() {
public void setEscapeString(String escapeString) {
this.escapeString = escapeString;
}

/**
* For testing purposes only. Not part of the public API.
* @param key the key of a possible existing answer.
* @return the associated interpolated object, or null if there is none.
*/
protected Object getExistingAnswer(String key) {
return existingAnswers.get(key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,75 @@ public void clearFeedback() {}
"should not believe there is a cycle here");
}

public void testCacheAnswersTrue() throws InterpolationException {
Properties p = new Properties();
p.setProperty("key", "value");

class CountingStringSearchInterpolator extends StringSearchInterpolator {
private int existingCallCount;

@Override
protected Object getExistingAnswer(String key) {
Object value = super.getExistingAnswer(key);
if (value != null) {
++existingCallCount;
}
return value;
}

public int getExistingCallCount() {
return existingCallCount;
}
}

CountingStringSearchInterpolator interpolator = new CountingStringSearchInterpolator();
interpolator.setCacheAnswers(true);
interpolator.addValueSource(new PropertiesBasedValueSource(p));

String result = interpolator.interpolate("${key}-${key}-${key}-${key}");

assertEquals("value-value-value-value", result);
// first value is interpolated and saved, then the 3 next answers came from existing answer Map
assertEquals(3, interpolator.getExistingCallCount());

// answers are preserved between calls:
result = interpolator.interpolate("${key}-${key}-${key}-${key}");
assertEquals("value-value-value-value", result);
// 3 from the first call to interpolate(), plus 4 from second call
assertEquals(3 + 4, interpolator.getExistingCallCount());
}

public void testCacheAnswersFalse() throws InterpolationException {
Properties p = new Properties();
p.setProperty("key", "value");

class CountingStringSearchInterpolator extends StringSearchInterpolator {
private int existingCallCount;

@Override
protected Object getExistingAnswer(String key) {
Object value = super.getExistingAnswer(key);
if (value != null) {
++existingCallCount;
}
return value;
}

public int getExistingCallCount() {
return existingCallCount;
}
}

CountingStringSearchInterpolator interpolator = new CountingStringSearchInterpolator();
interpolator.addValueSource(new PropertiesBasedValueSource(p));

String result = interpolator.interpolate("${key}-${key}-${key}-${key}");

assertEquals("value-value-value-value", result);
// all values are interpolated each time
assertEquals(0, interpolator.getExistingCallCount());
}

public String getVar() {
return "testVar";
}
Expand Down

0 comments on commit d0a18bc

Please sign in to comment.