http://git-wip-us.apache.org/repos/asf/commons-text/blob/4b67dd51/src/test/java/org/apache/commons/text/StrSubstitutorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/text/StrSubstitutorTest.java b/src/test/java/org/apache/commons/text/StrSubstitutorTest.java index 4ab52ed..cbd95c3 100644 --- a/src/test/java/org/apache/commons/text/StrSubstitutorTest.java +++ b/src/test/java/org/apache/commons/text/StrSubstitutorTest.java @@ -1,876 +1,832 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.text; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import org.apache.commons.lang3.mutable.MutableObject; -import org.apache.commons.text.lookup.StringLookup; -import org.apache.commons.text.lookup.StringLookupFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Test class for {@link StrSubstitutor}. - */ -public class StrSubstitutorTest { - - private Map<String, String> values; - - @Before - public void setUp() throws Exception { - values = new HashMap<>(); - values.put("animal", "quick brown fox"); - values.put("target", "lazy dog"); - } - - @After - public void tearDown() throws Exception { - values = null; - } - - //----------------------------------------------------------------------- - /** - * Tests simple key replace. - */ - @Test - public void testReplaceSimple() { - doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true); - } - - /** - * Tests simple key replace. - */ - @Test - public void testReplaceSolo() { - doTestReplace("quick brown fox", "${animal}", false); - } - - /** - * Tests replace with no variables. - */ - @Test - public void testReplaceNoVariables() { - doTestNoReplace("The balloon arrived."); - } - - /** - * Tests replace with null. - */ - @Test - public void testReplaceNull() { - doTestNoReplace(null); - } - - /** - * Tests replace with null. - */ - @Test - public void testReplaceEmpty() { - doTestNoReplace(""); - } - - /** - * Tests key replace changing map after initialization (not recommended). - */ - @Test - public void testReplaceChangedMap() { - final StrSubstitutor sub = new StrSubstitutor(values); - values.put("target", "moon"); - assertEquals("The quick brown fox jumps over the moon.", - sub.replace("The ${animal} jumps over the ${target}.")); - } - - /** - * Tests unknown key replace. - */ - @Test - public void testReplaceUnknownKey() { - doTestReplace("The ${person} jumps over the lazy dog.", "The ${person} jumps over the ${target}.", true); - doTestReplace("The ${person} jumps over the lazy dog. 1234567890.", - "The ${person} jumps over the ${target}. ${undefined.number:-1234567890}.", true); - } - - /** - * Tests adjacent keys. - */ - @Test - public void testReplaceAdjacentAtStart() { - values.put("code", "GBP"); - values.put("amount", "12.50"); - final StrSubstitutor sub = new StrSubstitutor(values); - assertEquals("GBP12.50 charged", sub.replace("${code}${amount} charged")); - } - - /** - * Tests adjacent keys. - */ - @Test - public void testReplaceAdjacentAtEnd() { - values.put("code", "GBP"); - values.put("amount", "12.50"); - final StrSubstitutor sub = new StrSubstitutor(values); - assertEquals("Amount is GBP12.50", sub.replace("Amount is ${code}${amount}")); - } - - /** - * Tests simple recursive replace. - */ - @Test - public void testReplaceRecursive() { - values.put("animal", "${critter}"); - values.put("target", "${pet}"); - values.put("pet", "${petCharacteristic} dog"); - values.put("petCharacteristic", "lazy"); - values.put("critter", "${critterSpeed} ${critterColor} ${critterType}"); - values.put("critterSpeed", "quick"); - values.put("critterColor", "brown"); - values.put("critterType", "fox"); - doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true); - - values.put("pet", "${petCharacteristicUnknown:-lazy} dog"); - doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true); - } - - @Test - public void testDisableSubstitutionInValues() { - final StrSubstitutor sub = new StrSubstitutor(values); - sub.setDisableSubstitutionInValues(true); - values.put("animal", "${critter}"); - values.put("target", "${pet}"); - values.put("pet", "${petCharacteristic} dog"); - values.put("petCharacteristic", "lazy"); - values.put("critter", "${critterSpeed} ${critterColor} ${critterType}"); - values.put("critterSpeed", "quick"); - values.put("critterColor", "brown"); - values.put("critterType", "fox"); - doTestReplace(sub, "The ${critter} jumps over the ${pet}.", "The ${animal} jumps over the ${target}.", true); - } - - /** - * Tests escaping. - */ - @Test - public void testReplaceEscaping() { - doTestReplace("The ${animal} jumps over the lazy dog.", "The $${animal} jumps over the ${target}.", true); - } - - /** - * Tests escaping. - */ - @Test - public void testReplaceSoloEscaping() { - doTestReplace("${animal}", "$${animal}", false); - } - - /** - * Tests complex escaping. - */ - @Test - public void testReplaceComplexEscaping() { - doTestReplace("The ${quick brown fox} jumps over the lazy dog.", - "The $${${animal}} jumps over the ${target}.", true); - doTestReplace("The ${quick brown fox} jumps over the lazy dog. ${1234567890}.", - "The $${${animal}} jumps over the ${target}. $${${undefined.number:-1234567890}}.", true); - } - - /** - * Tests when no prefix or suffix. - */ - @Test - public void testReplaceNoPrefixNoSuffix() { - doTestReplace("The animal jumps over the lazy dog.", "The animal jumps over the ${target}.", true); - } - - /** - * Tests when no incomplete prefix. - */ - @Test - public void testReplaceIncompletePrefix() { - doTestReplace("The {animal} jumps over the lazy dog.", "The {animal} jumps over the ${target}.", true); - } - - /** - * Tests when prefix but no suffix. - */ - @Test - public void testReplacePrefixNoSuffix() { - doTestReplace("The ${animal jumps over the ${target} lazy dog.", - "The ${animal jumps over the ${target} ${target}.", true); - } - - /** - * Tests when suffix but no prefix. - */ - @Test - public void testReplaceNoPrefixSuffix() { - doTestReplace("The animal} jumps over the lazy dog.", "The animal} jumps over the ${target}.", true); - } - - /** - * Tests when no variable name. - */ - @Test - public void testReplaceEmptyKeys() { - doTestReplace("The ${} jumps over the lazy dog.", "The ${} jumps over the ${target}.", true); - doTestReplace("The animal jumps over the lazy dog.", "The ${:-animal} jumps over the ${target}.", true); - } - - /** - * Tests replace creates output same as input. - */ - @Test - public void testReplaceToIdentical() { - values.put("animal", "$${${thing}}"); - values.put("thing", "animal"); - doTestReplace("The ${animal} jumps.", "The ${animal} jumps.", true); - } - - /** - * Tests a cyclic replace operation. - * The cycle should be detected and cause an exception to be thrown. - */ - @Test - public void testCyclicReplacement() { - final Map<String, String> map = new HashMap<>(); - map.put("animal", "${critter}"); - map.put("target", "${pet}"); - map.put("pet", "${petCharacteristic} dog"); - map.put("petCharacteristic", "lazy"); - map.put("critter", "${critterSpeed} ${critterColor} ${critterType}"); - map.put("critterSpeed", "quick"); - map.put("critterColor", "brown"); - map.put("critterType", "${animal}"); - StrSubstitutor sub = new StrSubstitutor(map); - try { - sub.replace("The ${animal} jumps over the ${target}."); - fail("Cyclic replacement was not detected!"); - } catch (final IllegalStateException ex) { - // expected - } - - // also check even when default value is set. - map.put("critterType", "${animal:-fox}"); - sub = new StrSubstitutor(map); - try { - sub.replace("The ${animal} jumps over the ${target}."); - fail("Cyclic replacement was not detected!"); - } catch (final IllegalStateException ex) { - // expected - } - } - - /** - * Tests interpolation with weird boundary patterns. - */ - @Test - public void testReplaceWeirdPattens() { - doTestNoReplace(""); - doTestNoReplace("${}"); - doTestNoReplace("${ }"); - doTestNoReplace("${\t}"); - doTestNoReplace("${\n}"); - doTestNoReplace("${\b}"); - doTestNoReplace("${"); - doTestNoReplace("$}"); - doTestNoReplace("}"); - doTestNoReplace("${}$"); - doTestNoReplace("${${"); - doTestNoReplace("${${}}"); - doTestNoReplace("${$${}}"); - doTestNoReplace("${$$${}}"); - doTestNoReplace("${$$${$}}"); - doTestNoReplace("${${}}"); - doTestNoReplace("${${ }}"); - } - - /** - * Tests simple key replace. - */ - @Test - public void testReplacePartialString_noReplace() { - final StrSubstitutor sub = new StrSubstitutor(); - assertEquals("${animal} jumps", sub.replace("The ${animal} jumps over the ${target}.", 4, 15)); - } - - /** - * Tests whether a variable can be replaced in a variable name. - */ - @Test - public void testReplaceInVariable() { - values.put("animal.1", "fox"); - values.put("animal.2", "mouse"); - values.put("species", "2"); - final StrSubstitutor sub = new StrSubstitutor(values); - sub.setEnableSubstitutionInVariables(true); - assertEquals( - "Wrong result (1)", - "The mouse jumps over the lazy dog.", - sub.replace("The ${animal.${species}} jumps over the ${target}.")); - values.put("species", "1"); - assertEquals( - "Wrong result (2)", - "The fox jumps over the lazy dog.", - sub.replace("The ${animal.${species}} jumps over the ${target}.")); - assertEquals( - "Wrong result (3)", - "The fox jumps over the lazy dog.", - sub.replace("The ${unknown.animal.${unknown.species:-1}:-fox} " - + "jumps over the ${unknow.target:-lazy dog}.")); - } - - /** - * Tests whether substitution in variable names is disabled per default. - */ - @Test - public void testReplaceInVariableDisabled() { - values.put("animal.1", "fox"); - values.put("animal.2", "mouse"); - values.put("species", "2"); - final StrSubstitutor sub = new StrSubstitutor(values); - assertEquals( - "Wrong result (1)", - "The ${animal.${species}} jumps over the lazy dog.", - sub.replace("The ${animal.${species}} jumps over the ${target}.")); - assertEquals( - "Wrong result (2)", - "The ${animal.${species:-1}} jumps over the lazy dog.", - sub.replace("The ${animal.${species:-1}} jumps over the ${target}.")); - } - - /** - * Tests complex and recursive substitution in variable names. - */ - @Test - public void testReplaceInVariableRecursive() { - values.put("animal.2", "brown fox"); - values.put("animal.1", "white mouse"); - values.put("color", "white"); - values.put("species.white", "1"); - values.put("species.brown", "2"); - final StrSubstitutor sub = new StrSubstitutor(values); - sub.setEnableSubstitutionInVariables(true); - assertEquals( - "Wrong result (1)", - "The white mouse jumps over the lazy dog.", - sub.replace("The ${animal.${species.${color}}} jumps over the ${target}.")); - assertEquals( - "Wrong result (2)", - "The brown fox jumps over the lazy dog.", - sub.replace("The ${animal.${species.${unknownColor:-brown}}} jumps over the ${target}.")); - } - - @Test - public void testDefaultValueDelimiters() { - final Map<String, String> map = new HashMap<>(); - map.put("animal", "fox"); - map.put("target", "dog"); - - StrSubstitutor sub = new StrSubstitutor(map, "${", "}", '$'); - assertEquals("The fox jumps over the lazy dog. 1234567890.", - sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number:-1234567890}.")); - - sub = new StrSubstitutor(map, "${", "}", '$', "?:"); - assertEquals("The fox jumps over the lazy dog. 1234567890.", - sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number?:1234567890}.")); - - sub = new StrSubstitutor(map, "${", "}", '$', "||"); - assertEquals("The fox jumps over the lazy dog. 1234567890.", - sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number||1234567890}.")); - - sub = new StrSubstitutor(map, "${", "}", '$', "!"); - assertEquals("The fox jumps over the lazy dog. 1234567890.", - sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}.")); - - sub = new StrSubstitutor(map, "${", "}", '$', ""); - sub.setValueDelimiterMatcher(null); - assertEquals("The fox jumps over the lazy dog. ${undefined.number!1234567890}.", - sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}.")); - - sub = new StrSubstitutor(map, "${", "}", '$'); - sub.setValueDelimiterMatcher(null); - assertEquals("The fox jumps over the lazy dog. ${undefined.number!1234567890}.", - sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}.")); - } - - //----------------------------------------------------------------------- - /** - * Tests protected. - */ - @Test - public void testResolveVariable() { - final StrBuilder builder = new StrBuilder("Hi ${name}!"); - final Map<String, String> map = new HashMap<>(); - map.put("name", "commons"); - final StrSubstitutor sub = new StrSubstitutor(map) { - @Override - protected String resolveVariable(final String variableName, final StrBuilder buf, final int startPos, - final int endPos) { - assertEquals("name", variableName); - assertSame(builder, buf); - assertEquals(3, startPos); - assertEquals(10, endPos); - return "jakarta"; - } - }; - sub.replaceIn(builder); - assertEquals("Hi jakarta!", builder.toString()); - } - - //----------------------------------------------------------------------- - /** - * Tests constructor. - */ - @Test - public void testConstructorNoArgs() { - final StrSubstitutor sub = new StrSubstitutor(); - assertEquals("Hi ${name}", sub.replace("Hi ${name}")); - } - - /** - * Tests constructor. - */ - @Test - public void testConstructorMapPrefixSuffix() { - final Map<String, String> map = new HashMap<>(); - map.put("name", "commons"); - final StrSubstitutor sub = new StrSubstitutor(map, "<", ">"); - assertEquals("Hi < commons", sub.replace("Hi $< <name>")); - } - - /** - * Tests constructor. - */ - @Test - public void testConstructorMapFull() { - final Map<String, String> map = new HashMap<>(); - map.put("name", "commons"); - StrSubstitutor sub = new StrSubstitutor(map, "<", ">", '!'); - assertEquals("Hi < commons", sub.replace("Hi !< <name>")); - sub = new StrSubstitutor(map, "<", ">", '!', "||"); - assertEquals("Hi < commons", sub.replace("Hi !< <name2||commons>")); - } - - //----------------------------------------------------------------------- - /** - * Tests get set. - */ - @Test - public void testGetSetEscape() { - final StrSubstitutor sub = new StrSubstitutor(); - assertEquals('$', sub.getEscapeChar()); - sub.setEscapeChar('<'); - assertEquals('<', sub.getEscapeChar()); - } - - /** - * Tests get set. - */ - @Test - public void testGetSetPrefix() { - final StrSubstitutor sub = new StrSubstitutor(); - assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher); - sub.setVariablePrefix('<'); - assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.CharMatcher); - - sub.setVariablePrefix("<<"); - assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher); - try { - sub.setVariablePrefix((String) null); - fail(); - } catch (final IllegalArgumentException ex) { - // expected - } - assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher); - - final StrMatcher matcher = StrMatcher.commaMatcher(); - sub.setVariablePrefixMatcher(matcher); - assertSame(matcher, sub.getVariablePrefixMatcher()); - try { - sub.setVariablePrefixMatcher((StrMatcher) null); - fail(); - } catch (final IllegalArgumentException ex) { - // expected - } - assertSame(matcher, sub.getVariablePrefixMatcher()); - } - - /** - * Tests get set. - */ - @Test - public void testGetSetSuffix() { - final StrSubstitutor sub = new StrSubstitutor(); - assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher); - sub.setVariableSuffix('<'); - assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.CharMatcher); - - sub.setVariableSuffix("<<"); - assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher); - try { - sub.setVariableSuffix((String) null); - fail(); - } catch (final IllegalArgumentException ex) { - // expected - } - assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher); - - final StrMatcher matcher = StrMatcher.commaMatcher(); - sub.setVariableSuffixMatcher(matcher); - assertSame(matcher, sub.getVariableSuffixMatcher()); - try { - sub.setVariableSuffixMatcher((StrMatcher) null); - fail(); - } catch (final IllegalArgumentException ex) { - // expected - } - assertSame(matcher, sub.getVariableSuffixMatcher()); - } - - /** - * Tests get set. - */ - @Test - public void testGetSetValueDelimiter() { - final StrSubstitutor sub = new StrSubstitutor(); - assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.StringMatcher); - sub.setValueDelimiter(':'); - assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.CharMatcher); - - sub.setValueDelimiter("||"); - assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.StringMatcher); - sub.setValueDelimiter((String) null); - assertNull(sub.getValueDelimiterMatcher()); - - final StrMatcher matcher = StrMatcher.commaMatcher(); - sub.setValueDelimiterMatcher(matcher); - assertSame(matcher, sub.getValueDelimiterMatcher()); - sub.setValueDelimiterMatcher((StrMatcher) null); - assertNull(sub.getValueDelimiterMatcher()); - } - - //----------------------------------------------------------------------- - /** - * Tests static. - */ - @Test - public void testStaticReplace() { - final Map<String, String> map = new HashMap<>(); - map.put("name", "commons"); - assertEquals("Hi commons!", StrSubstitutor.replace("Hi ${name}!", map)); - } - - /** - * Tests static. - */ - @Test - public void testStaticReplacePrefixSuffix() { - final Map<String, String> map = new HashMap<>(); - map.put("name", "commons"); - assertEquals("Hi commons!", StrSubstitutor.replace("Hi <name>!", map, "<", ">")); - } - - /** - * Tests interpolation with system properties. - */ - @Test - public void testStaticReplaceSystemProperties() { - final StrBuilder buf = new StrBuilder(); - buf.append("Hi ").append(System.getProperty("user.name")); - buf.append(", you are working with "); - buf.append(System.getProperty("os.name")); - buf.append(", your home directory is "); - buf.append(System.getProperty("user.home")).append('.'); - assertEquals(buf.toString(), StrSubstitutor.replaceSystemProperties("Hi ${user.name}, you are " - + "working with ${os.name}, your home " - + "directory is ${user.home}.")); - } - - /** - * Test for LANG-1055: StrSubstitutor.replaceSystemProperties does not work consistently - */ - @Test - public void testLANG1055() { - System.setProperty("test_key", "test_value"); - - final String expected = StrSubstitutor.replace("test_key=${test_key}", System.getProperties()); - final String actual = StrSubstitutor.replaceSystemProperties("test_key=${test_key}"); - assertEquals(expected, actual); - } - - /** - * Test the replace of a properties object - */ - @Test - public void testSubstituteDefaultProperties() { - final String org = "${doesnotwork}"; - System.setProperty("doesnotwork", "It works!"); - - // create a new Properties object with the System.getProperties as default - final Properties props = new Properties(System.getProperties()); - - assertEquals("It works!", StrSubstitutor.replace(org, props)); - } - - @Test - public void testSamePrefixAndSuffix() { - final Map<String, String> map = new HashMap<>(); - map.put("greeting", "Hello"); - map.put(" there ", "XXX"); - map.put("name", "commons"); - assertEquals("Hi commons!", StrSubstitutor.replace("Hi @name@!", map, "@", "@")); - assertEquals("Hello there commons!", StrSubstitutor.replace("@greeting@ there @name@!", map, "@", "@")); - } - - @Test - public void testSubstitutePreserveEscape() { - final String org = "${not-escaped} $${escaped}"; - final Map<String, String> map = new HashMap<>(); - map.put("not-escaped", "value"); - - final StrSubstitutor sub = new StrSubstitutor(map, "${", "}", '$'); - assertFalse(sub.isPreserveEscapes()); - assertEquals("value ${escaped}", sub.replace(org)); - - sub.setPreserveEscapes(true); - assertTrue(sub.isPreserveEscapes()); - assertEquals("value $${escaped}", sub.replace(org)); - } - - private void doTestReplace(final String expectedResult, final String replaceTemplate, final boolean substring) { - final StrSubstitutor sub = new StrSubstitutor(values); - doTestReplace(sub, expectedResult, replaceTemplate, substring); - } - - //----------------------------------------------------------------------- - private void doTestReplace(final StrSubstitutor sub, final String expectedResult, final String replaceTemplate, - final boolean substring) { - final String expectedShortResult = expectedResult.substring(1, expectedResult.length() - 1); - - // replace using String - assertEquals(expectedResult, sub.replace(replaceTemplate)); - if (substring) { - assertEquals(expectedShortResult, sub.replace(replaceTemplate, 1, replaceTemplate.length() - 2)); - } - - // replace using char[] - final char[] chars = replaceTemplate.toCharArray(); - assertEquals(expectedResult, sub.replace(chars)); - if (substring) { - assertEquals(expectedShortResult, sub.replace(chars, 1, chars.length - 2)); - } - - // replace using StringBuffer - StringBuffer buf = new StringBuffer(replaceTemplate); - assertEquals(expectedResult, sub.replace(buf)); - if (substring) { - assertEquals(expectedShortResult, sub.replace(buf, 1, buf.length() - 2)); - } - - // replace using StringBuilder - StringBuilder builder = new StringBuilder(replaceTemplate); - assertEquals(expectedResult, sub.replace(builder)); - if (substring) { - assertEquals(expectedShortResult, sub.replace(builder, 1, builder.length() - 2)); - } - - // replace using StrBuilder - StrBuilder bld = new StrBuilder(replaceTemplate); - assertEquals(expectedResult, sub.replace(bld)); - if (substring) { - assertEquals(expectedShortResult, sub.replace(bld, 1, bld.length() - 2)); - } - - // replace using object - final MutableObject<String> obj = new MutableObject<>(replaceTemplate); // toString returns template - assertEquals(expectedResult, sub.replace(obj)); - - // replace in StringBuffer - buf = new StringBuffer(replaceTemplate); - assertTrue(sub.replaceIn(buf)); - assertEquals(expectedResult, buf.toString()); - if (substring) { - buf = new StringBuffer(replaceTemplate); - assertTrue(sub.replaceIn(buf, 1, buf.length() - 2)); - assertEquals(expectedResult, buf.toString()); // expect full result as remainder is untouched - } - - // replace in StringBuilder - builder = new StringBuilder(replaceTemplate); - assertTrue(sub.replaceIn(builder)); - assertEquals(expectedResult, builder.toString()); - if (substring) { - builder = new StringBuilder(replaceTemplate); - assertTrue(sub.replaceIn(builder, 1, builder.length() - 2)); - assertEquals(expectedResult, builder.toString()); // expect full result as remainder is untouched - } - - // replace in StrBuilder - bld = new StrBuilder(replaceTemplate); - assertTrue(sub.replaceIn(bld)); - assertEquals(expectedResult, bld.toString()); - if (substring) { - bld = new StrBuilder(replaceTemplate); - assertTrue(sub.replaceIn(bld, 1, bld.length() - 2)); - assertEquals(expectedResult, bld.toString()); // expect full result as remainder is untouched - } - } - - private void doTestNoReplace(final String replaceTemplate) { - final StrSubstitutor sub = new StrSubstitutor(values); - - if (replaceTemplate == null) { - assertNull(sub.replace((String) null)); - assertNull(sub.replace((String) null, 0, 100)); - assertNull(sub.replace((char[]) null)); - assertNull(sub.replace((char[]) null, 0, 100)); - assertNull(sub.replace((StringBuffer) null)); - assertNull(sub.replace((StringBuffer) null, 0, 100)); - assertNull(sub.replace((StrBuilder) null)); - assertNull(sub.replace((StrBuilder) null, 0, 100)); - assertNull(sub.replace((Object) null)); - assertFalse(sub.replaceIn((StringBuffer) null)); - assertFalse(sub.replaceIn((StringBuffer) null, 0, 100)); - assertFalse(sub.replaceIn((StrBuilder) null)); - assertFalse(sub.replaceIn((StrBuilder) null, 0, 100)); - } else { - assertEquals(replaceTemplate, sub.replace(replaceTemplate)); - final StrBuilder bld = new StrBuilder(replaceTemplate); - assertFalse(sub.replaceIn(bld)); - assertEquals(replaceTemplate, bld.toString()); - } - } - - @Test - public void testReplaceInTakingTwoAndThreeIntsReturningFalse() { - final Map<String, Object> hashMap = new HashMap<>(); - final StringLookup mapStringLookup = StringLookupFactory.INSTANCE.mapStringLookup(hashMap); - final StrMatcher strMatcher = StrMatcher.tabMatcher(); - final StrSubstitutor strSubstitutor = - new StrSubstitutor(mapStringLookup, strMatcher, strMatcher, 'b', strMatcher); - - assertFalse(strSubstitutor.replaceIn((StringBuilder) null, 1315, (-1369))); - assertEquals('b', strSubstitutor.getEscapeChar()); - assertFalse(strSubstitutor.isPreserveEscapes()); - } - - @Test - public void testReplaceInTakingTwoAndThreeIntsReturningFalse_deprecated() { - final Map<String, Object> hashMap = new HashMap<>(); - final StrLookup.MapStrLookup<Object> mapStrLookup = new StrLookup.MapStrLookup<>(hashMap); - final StrMatcher strMatcher = StrMatcher.tabMatcher(); - final StrSubstitutor strSubstitutor = - new StrSubstitutor(mapStrLookup, strMatcher, strMatcher, 'b', strMatcher); - - assertFalse(strSubstitutor.replaceIn((StringBuilder) null, 1315, (-1369))); - assertEquals('b', strSubstitutor.getEscapeChar()); - assertFalse(strSubstitutor.isPreserveEscapes()); - } - - @Test - public void testReplaceInTakingStringBuilderWithNonNull() { - final StringLookup strLookup = StringLookupFactory.INSTANCE.systemPropertyStringLookup(); - final StrSubstitutor strSubstitutor = new StrSubstitutor(strLookup, "b<H", "b<H", '\''); - final StringBuilder stringBuilder = new StringBuilder((CharSequence) "b<H"); - - assertEquals('\'', strSubstitutor.getEscapeChar()); - assertFalse(strSubstitutor.replaceIn(stringBuilder)); - } - - @Test - public void testReplaceInTakingStringBuilderWithNonNull_deprecated() { - final StrLookup<String> strLookup = StrLookup.systemPropertiesLookup(); - final StrSubstitutor strSubstitutor = new StrSubstitutor(strLookup, "b<H", "b<H", '\''); - final StringBuilder stringBuilder = new StringBuilder((CharSequence) "b<H"); - - assertEquals('\'', strSubstitutor.getEscapeChar()); - assertFalse(strSubstitutor.replaceIn(stringBuilder)); - } - - @Test - public void testReplaceInTakingStringBufferWithNonNull() { - final StrSubstitutor strSubstitutor = - new StrSubstitutor(new HashMap<String, String>(), "WV@i#y?N*[", "WV@i#y?N*[", '*'); - - assertFalse(strSubstitutor.isPreserveEscapes()); - assertFalse(strSubstitutor.replaceIn(new StringBuffer("WV@i#y?N*["))); - assertEquals('*', strSubstitutor.getEscapeChar()); - } - - @Test - public void testCreatesStrSubstitutorTakingStrLookupAndCallsReplaceTakingTwoAndThreeInts() { - final Map<String, CharacterPredicates> map = new HashMap<>(); - final StringLookup mapStringLookup = StringLookupFactory.INSTANCE.mapStringLookup(map); - final StrSubstitutor strSubstitutor = new StrSubstitutor(mapStringLookup); - - assertNull(strSubstitutor.replace((CharSequence) null, 0, 0)); - assertEquals('$', strSubstitutor.getEscapeChar()); - } - - @Test - public void testCreatesStrSubstitutorTakingStrLookupAndCallsReplaceTakingTwoAndThreeInts_deprecated() { - final Map<String, CharacterPredicates> map = new HashMap<>(); - final StrLookup.MapStrLookup<CharacterPredicates> mapStrLookup = new StrLookup.MapStrLookup<>(map); - final StrSubstitutor strSubstitutor = new StrSubstitutor(mapStrLookup); - - assertNull(strSubstitutor.replace((CharSequence) null, 0, 0)); - assertEquals('$', strSubstitutor.getEscapeChar()); - } - - @Test - public void testReplaceTakingCharSequenceReturningNull() { - final StrSubstitutor strSubstitutor = new StrSubstitutor((StringLookup) null); - - assertNull(strSubstitutor.replace((CharSequence) null)); - assertFalse(strSubstitutor.isPreserveEscapes()); - assertEquals('$', strSubstitutor.getEscapeChar()); - } - - @Test - public void testReplaceTakingCharSequenceReturningNull_deprecated() { - final StrSubstitutor strSubstitutor = new StrSubstitutor((StrLookup<?>) null); - - assertNull(strSubstitutor.replace((CharSequence) null)); - assertFalse(strSubstitutor.isPreserveEscapes()); - assertEquals('$', strSubstitutor.getEscapeChar()); - } - - @Test(expected = NullPointerException.class) - public void testReplaceTakingThreeArgumentsThrowsNullPointerException() { - StrSubstitutor.replace(null, (Properties) null); - } - - @Test - public void testReplaceInTakingStringBuilderWithNull() { - final Map<String, Object> map = new HashMap<>(); - final StrSubstitutor strSubstitutor = new StrSubstitutor(map, "", "", 'T', "K+<'f"); - - assertFalse(strSubstitutor.replaceIn((StringBuilder) null)); - } - -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.text; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.lang3.mutable.MutableObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Test class for {@link StrSubstitutor}. + */ +public class StrSubstitutorTest { + + private Map<String, String> values; + + @Before + public void setUp() throws Exception { + values = new HashMap<>(); + values.put("animal", "quick brown fox"); + values.put("target", "lazy dog"); + } + + @After + public void tearDown() throws Exception { + values = null; + } + + //----------------------------------------------------------------------- + /** + * Tests simple key replace. + */ + @Test + public void testReplaceSimple() { + doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true); + } + + /** + * Tests simple key replace. + */ + @Test + public void testReplaceSolo() { + doTestReplace("quick brown fox", "${animal}", false); + } + + /** + * Tests replace with no variables. + */ + @Test + public void testReplaceNoVariables() { + doTestNoReplace("The balloon arrived."); + } + + /** + * Tests replace with null. + */ + @Test + public void testReplaceNull() { + doTestNoReplace(null); + } + + /** + * Tests replace with null. + */ + @Test + public void testReplaceEmpty() { + doTestNoReplace(""); + } + + /** + * Tests key replace changing map after initialization (not recommended). + */ + @Test + public void testReplaceChangedMap() { + final StrSubstitutor sub = new StrSubstitutor(values); + values.put("target", "moon"); + assertEquals("The quick brown fox jumps over the moon.", + sub.replace("The ${animal} jumps over the ${target}.")); + } + + /** + * Tests unknown key replace. + */ + @Test + public void testReplaceUnknownKey() { + doTestReplace("The ${person} jumps over the lazy dog.", "The ${person} jumps over the ${target}.", true); + doTestReplace("The ${person} jumps over the lazy dog. 1234567890.", + "The ${person} jumps over the ${target}. ${undefined.number:-1234567890}.", true); + } + + /** + * Tests adjacent keys. + */ + @Test + public void testReplaceAdjacentAtStart() { + values.put("code", "GBP"); + values.put("amount", "12.50"); + final StrSubstitutor sub = new StrSubstitutor(values); + assertEquals("GBP12.50 charged", sub.replace("${code}${amount} charged")); + } + + /** + * Tests adjacent keys. + */ + @Test + public void testReplaceAdjacentAtEnd() { + values.put("code", "GBP"); + values.put("amount", "12.50"); + final StrSubstitutor sub = new StrSubstitutor(values); + assertEquals("Amount is GBP12.50", sub.replace("Amount is ${code}${amount}")); + } + + /** + * Tests simple recursive replace. + */ + @Test + public void testReplaceRecursive() { + values.put("animal", "${critter}"); + values.put("target", "${pet}"); + values.put("pet", "${petCharacteristic} dog"); + values.put("petCharacteristic", "lazy"); + values.put("critter", "${critterSpeed} ${critterColor} ${critterType}"); + values.put("critterSpeed", "quick"); + values.put("critterColor", "brown"); + values.put("critterType", "fox"); + doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true); + + values.put("pet", "${petCharacteristicUnknown:-lazy} dog"); + doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true); + } + + @Test + public void testDisableSubstitutionInValues() { + final StrSubstitutor sub = new StrSubstitutor(values); + sub.setDisableSubstitutionInValues(true); + values.put("animal", "${critter}"); + values.put("target", "${pet}"); + values.put("pet", "${petCharacteristic} dog"); + values.put("petCharacteristic", "lazy"); + values.put("critter", "${critterSpeed} ${critterColor} ${critterType}"); + values.put("critterSpeed", "quick"); + values.put("critterColor", "brown"); + values.put("critterType", "fox"); + doTestReplace(sub, "The ${critter} jumps over the ${pet}.", "The ${animal} jumps over the ${target}.", true); + } + + /** + * Tests escaping. + */ + @Test + public void testReplaceEscaping() { + doTestReplace("The ${animal} jumps over the lazy dog.", "The $${animal} jumps over the ${target}.", true); + } + + /** + * Tests escaping. + */ + @Test + public void testReplaceSoloEscaping() { + doTestReplace("${animal}", "$${animal}", false); + } + + /** + * Tests complex escaping. + */ + @Test + public void testReplaceComplexEscaping() { + doTestReplace("The ${quick brown fox} jumps over the lazy dog.", + "The $${${animal}} jumps over the ${target}.", true); + doTestReplace("The ${quick brown fox} jumps over the lazy dog. ${1234567890}.", + "The $${${animal}} jumps over the ${target}. $${${undefined.number:-1234567890}}.", true); + } + + /** + * Tests when no prefix or suffix. + */ + @Test + public void testReplaceNoPrefixNoSuffix() { + doTestReplace("The animal jumps over the lazy dog.", "The animal jumps over the ${target}.", true); + } + + /** + * Tests when no incomplete prefix. + */ + @Test + public void testReplaceIncompletePrefix() { + doTestReplace("The {animal} jumps over the lazy dog.", "The {animal} jumps over the ${target}.", true); + } + + /** + * Tests when prefix but no suffix. + */ + @Test + public void testReplacePrefixNoSuffix() { + doTestReplace("The ${animal jumps over the ${target} lazy dog.", + "The ${animal jumps over the ${target} ${target}.", true); + } + + /** + * Tests when suffix but no prefix. + */ + @Test + public void testReplaceNoPrefixSuffix() { + doTestReplace("The animal} jumps over the lazy dog.", "The animal} jumps over the ${target}.", true); + } + + /** + * Tests when no variable name. + */ + @Test + public void testReplaceEmptyKeys() { + doTestReplace("The ${} jumps over the lazy dog.", "The ${} jumps over the ${target}.", true); + doTestReplace("The animal jumps over the lazy dog.", "The ${:-animal} jumps over the ${target}.", true); + } + + /** + * Tests replace creates output same as input. + */ + @Test + public void testReplaceToIdentical() { + values.put("animal", "$${${thing}}"); + values.put("thing", "animal"); + doTestReplace("The ${animal} jumps.", "The ${animal} jumps.", true); + } + + /** + * Tests a cyclic replace operation. + * The cycle should be detected and cause an exception to be thrown. + */ + @Test + public void testCyclicReplacement() { + final Map<String, String> map = new HashMap<>(); + map.put("animal", "${critter}"); + map.put("target", "${pet}"); + map.put("pet", "${petCharacteristic} dog"); + map.put("petCharacteristic", "lazy"); + map.put("critter", "${critterSpeed} ${critterColor} ${critterType}"); + map.put("critterSpeed", "quick"); + map.put("critterColor", "brown"); + map.put("critterType", "${animal}"); + StrSubstitutor sub = new StrSubstitutor(map); + try { + sub.replace("The ${animal} jumps over the ${target}."); + fail("Cyclic replacement was not detected!"); + } catch (final IllegalStateException ex) { + // expected + } + + // also check even when default value is set. + map.put("critterType", "${animal:-fox}"); + sub = new StrSubstitutor(map); + try { + sub.replace("The ${animal} jumps over the ${target}."); + fail("Cyclic replacement was not detected!"); + } catch (final IllegalStateException ex) { + // expected + } + } + + /** + * Tests interpolation with weird boundary patterns. + */ + @Test + public void testReplaceWeirdPattens() { + doTestNoReplace(""); + doTestNoReplace("${}"); + doTestNoReplace("${ }"); + doTestNoReplace("${\t}"); + doTestNoReplace("${\n}"); + doTestNoReplace("${\b}"); + doTestNoReplace("${"); + doTestNoReplace("$}"); + doTestNoReplace("}"); + doTestNoReplace("${}$"); + doTestNoReplace("${${"); + doTestNoReplace("${${}}"); + doTestNoReplace("${$${}}"); + doTestNoReplace("${$$${}}"); + doTestNoReplace("${$$${$}}"); + doTestNoReplace("${${}}"); + doTestNoReplace("${${ }}"); + } + + /** + * Tests simple key replace. + */ + @Test + public void testReplacePartialString_noReplace() { + final StrSubstitutor sub = new StrSubstitutor(); + assertEquals("${animal} jumps", sub.replace("The ${animal} jumps over the ${target}.", 4, 15)); + } + + /** + * Tests whether a variable can be replaced in a variable name. + */ + @Test + public void testReplaceInVariable() { + values.put("animal.1", "fox"); + values.put("animal.2", "mouse"); + values.put("species", "2"); + final StrSubstitutor sub = new StrSubstitutor(values); + sub.setEnableSubstitutionInVariables(true); + assertEquals( + "Wrong result (1)", + "The mouse jumps over the lazy dog.", + sub.replace("The ${animal.${species}} jumps over the ${target}.")); + values.put("species", "1"); + assertEquals( + "Wrong result (2)", + "The fox jumps over the lazy dog.", + sub.replace("The ${animal.${species}} jumps over the ${target}.")); + assertEquals( + "Wrong result (3)", + "The fox jumps over the lazy dog.", + sub.replace("The ${unknown.animal.${unknown.species:-1}:-fox} " + + "jumps over the ${unknow.target:-lazy dog}.")); + } + + /** + * Tests whether substitution in variable names is disabled per default. + */ + @Test + public void testReplaceInVariableDisabled() { + values.put("animal.1", "fox"); + values.put("animal.2", "mouse"); + values.put("species", "2"); + final StrSubstitutor sub = new StrSubstitutor(values); + assertEquals( + "Wrong result (1)", + "The ${animal.${species}} jumps over the lazy dog.", + sub.replace("The ${animal.${species}} jumps over the ${target}.")); + assertEquals( + "Wrong result (2)", + "The ${animal.${species:-1}} jumps over the lazy dog.", + sub.replace("The ${animal.${species:-1}} jumps over the ${target}.")); + } + + /** + * Tests complex and recursive substitution in variable names. + */ + @Test + public void testReplaceInVariableRecursive() { + values.put("animal.2", "brown fox"); + values.put("animal.1", "white mouse"); + values.put("color", "white"); + values.put("species.white", "1"); + values.put("species.brown", "2"); + final StrSubstitutor sub = new StrSubstitutor(values); + sub.setEnableSubstitutionInVariables(true); + assertEquals( + "Wrong result (1)", + "The white mouse jumps over the lazy dog.", + sub.replace("The ${animal.${species.${color}}} jumps over the ${target}.")); + assertEquals( + "Wrong result (2)", + "The brown fox jumps over the lazy dog.", + sub.replace("The ${animal.${species.${unknownColor:-brown}}} jumps over the ${target}.")); + } + + @Test + public void testDefaultValueDelimiters() { + final Map<String, String> map = new HashMap<>(); + map.put("animal", "fox"); + map.put("target", "dog"); + + StrSubstitutor sub = new StrSubstitutor(map, "${", "}", '$'); + assertEquals("The fox jumps over the lazy dog. 1234567890.", + sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number:-1234567890}.")); + + sub = new StrSubstitutor(map, "${", "}", '$', "?:"); + assertEquals("The fox jumps over the lazy dog. 1234567890.", + sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number?:1234567890}.")); + + sub = new StrSubstitutor(map, "${", "}", '$', "||"); + assertEquals("The fox jumps over the lazy dog. 1234567890.", + sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number||1234567890}.")); + + sub = new StrSubstitutor(map, "${", "}", '$', "!"); + assertEquals("The fox jumps over the lazy dog. 1234567890.", + sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}.")); + + sub = new StrSubstitutor(map, "${", "}", '$', ""); + sub.setValueDelimiterMatcher(null); + assertEquals("The fox jumps over the lazy dog. ${undefined.number!1234567890}.", + sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}.")); + + sub = new StrSubstitutor(map, "${", "}", '$'); + sub.setValueDelimiterMatcher(null); + assertEquals("The fox jumps over the lazy dog. ${undefined.number!1234567890}.", + sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}.")); + } + + //----------------------------------------------------------------------- + /** + * Tests protected. + */ + @Test + public void testResolveVariable() { + final StrBuilder builder = new StrBuilder("Hi ${name}!"); + final Map<String, String> map = new HashMap<>(); + map.put("name", "commons"); + final StrSubstitutor sub = new StrSubstitutor(map) { + @Override + protected String resolveVariable(final String variableName, final StrBuilder buf, final int startPos, + final int endPos) { + assertEquals("name", variableName); + assertSame(builder, buf); + assertEquals(3, startPos); + assertEquals(10, endPos); + return "jakarta"; + } + }; + sub.replaceIn(builder); + assertEquals("Hi jakarta!", builder.toString()); + } + + //----------------------------------------------------------------------- + /** + * Tests constructor. + */ + @Test + public void testConstructorNoArgs() { + final StrSubstitutor sub = new StrSubstitutor(); + assertEquals("Hi ${name}", sub.replace("Hi ${name}")); + } + + /** + * Tests constructor. + */ + @Test + public void testConstructorMapPrefixSuffix() { + final Map<String, String> map = new HashMap<>(); + map.put("name", "commons"); + final StrSubstitutor sub = new StrSubstitutor(map, "<", ">"); + assertEquals("Hi < commons", sub.replace("Hi $< <name>")); + } + + /** + * Tests constructor. + */ + @Test + public void testConstructorMapFull() { + final Map<String, String> map = new HashMap<>(); + map.put("name", "commons"); + StrSubstitutor sub = new StrSubstitutor(map, "<", ">", '!'); + assertEquals("Hi < commons", sub.replace("Hi !< <name>")); + sub = new StrSubstitutor(map, "<", ">", '!', "||"); + assertEquals("Hi < commons", sub.replace("Hi !< <name2||commons>")); + } + + //----------------------------------------------------------------------- + /** + * Tests get set. + */ + @Test + public void testGetSetEscape() { + final StrSubstitutor sub = new StrSubstitutor(); + assertEquals('$', sub.getEscapeChar()); + sub.setEscapeChar('<'); + assertEquals('<', sub.getEscapeChar()); + } + + /** + * Tests get set. + */ + @Test + public void testGetSetPrefix() { + final StrSubstitutor sub = new StrSubstitutor(); + assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher); + sub.setVariablePrefix('<'); + assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.CharMatcher); + + sub.setVariablePrefix("<<"); + assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher); + try { + sub.setVariablePrefix((String) null); + fail(); + } catch (final IllegalArgumentException ex) { + // expected + } + assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher); + + final StrMatcher matcher = StrMatcher.commaMatcher(); + sub.setVariablePrefixMatcher(matcher); + assertSame(matcher, sub.getVariablePrefixMatcher()); + try { + sub.setVariablePrefixMatcher((StrMatcher) null); + fail(); + } catch (final IllegalArgumentException ex) { + // expected + } + assertSame(matcher, sub.getVariablePrefixMatcher()); + } + + /** + * Tests get set. + */ + @Test + public void testGetSetSuffix() { + final StrSubstitutor sub = new StrSubstitutor(); + assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher); + sub.setVariableSuffix('<'); + assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.CharMatcher); + + sub.setVariableSuffix("<<"); + assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher); + try { + sub.setVariableSuffix((String) null); + fail(); + } catch (final IllegalArgumentException ex) { + // expected + } + assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher); + + final StrMatcher matcher = StrMatcher.commaMatcher(); + sub.setVariableSuffixMatcher(matcher); + assertSame(matcher, sub.getVariableSuffixMatcher()); + try { + sub.setVariableSuffixMatcher((StrMatcher) null); + fail(); + } catch (final IllegalArgumentException ex) { + // expected + } + assertSame(matcher, sub.getVariableSuffixMatcher()); + } + + /** + * Tests get set. + */ + @Test + public void testGetSetValueDelimiter() { + final StrSubstitutor sub = new StrSubstitutor(); + assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.StringMatcher); + sub.setValueDelimiter(':'); + assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.CharMatcher); + + sub.setValueDelimiter("||"); + assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.StringMatcher); + sub.setValueDelimiter((String) null); + assertNull(sub.getValueDelimiterMatcher()); + + final StrMatcher matcher = StrMatcher.commaMatcher(); + sub.setValueDelimiterMatcher(matcher); + assertSame(matcher, sub.getValueDelimiterMatcher()); + sub.setValueDelimiterMatcher((StrMatcher) null); + assertNull(sub.getValueDelimiterMatcher()); + } + + //----------------------------------------------------------------------- + /** + * Tests static. + */ + @Test + public void testStaticReplace() { + final Map<String, String> map = new HashMap<>(); + map.put("name", "commons"); + assertEquals("Hi commons!", StrSubstitutor.replace("Hi ${name}!", map)); + } + + /** + * Tests static. + */ + @Test + public void testStaticReplacePrefixSuffix() { + final Map<String, String> map = new HashMap<>(); + map.put("name", "commons"); + assertEquals("Hi commons!", StrSubstitutor.replace("Hi <name>!", map, "<", ">")); + } + + /** + * Tests interpolation with system properties. + */ + @Test + public void testStaticReplaceSystemProperties() { + final StrBuilder buf = new StrBuilder(); + buf.append("Hi ").append(System.getProperty("user.name")); + buf.append(", you are working with "); + buf.append(System.getProperty("os.name")); + buf.append(", your home directory is "); + buf.append(System.getProperty("user.home")).append('.'); + assertEquals(buf.toString(), StrSubstitutor.replaceSystemProperties("Hi ${user.name}, you are " + + "working with ${os.name}, your home " + + "directory is ${user.home}.")); + } + + /** + * Test for LANG-1055: StrSubstitutor.replaceSystemProperties does not work consistently + */ + @Test + public void testLANG1055() { + System.setProperty("test_key", "test_value"); + + final String expected = StrSubstitutor.replace("test_key=${test_key}", System.getProperties()); + final String actual = StrSubstitutor.replaceSystemProperties("test_key=${test_key}"); + assertEquals(expected, actual); + } + + /** + * Test the replace of a properties object + */ + @Test + public void testSubstituteDefaultProperties() { + final String org = "${doesnotwork}"; + System.setProperty("doesnotwork", "It works!"); + + // create a new Properties object with the System.getProperties as default + final Properties props = new Properties(System.getProperties()); + + assertEquals("It works!", StrSubstitutor.replace(org, props)); + } + + @Test + public void testSamePrefixAndSuffix() { + final Map<String, String> map = new HashMap<>(); + map.put("greeting", "Hello"); + map.put(" there ", "XXX"); + map.put("name", "commons"); + assertEquals("Hi commons!", StrSubstitutor.replace("Hi @name@!", map, "@", "@")); + assertEquals("Hello there commons!", StrSubstitutor.replace("@greeting@ there @name@!", map, "@", "@")); + } + + @Test + public void testSubstitutePreserveEscape() { + final String org = "${not-escaped} $${escaped}"; + final Map<String, String> map = new HashMap<>(); + map.put("not-escaped", "value"); + + final StrSubstitutor sub = new StrSubstitutor(map, "${", "}", '$'); + assertFalse(sub.isPreserveEscapes()); + assertEquals("value ${escaped}", sub.replace(org)); + + sub.setPreserveEscapes(true); + assertTrue(sub.isPreserveEscapes()); + assertEquals("value $${escaped}", sub.replace(org)); + } + + private void doTestReplace(final String expectedResult, final String replaceTemplate, final boolean substring) { + final StrSubstitutor sub = new StrSubstitutor(values); + doTestReplace(sub, expectedResult, replaceTemplate, substring); + } + + //----------------------------------------------------------------------- + private void doTestReplace(final StrSubstitutor sub, final String expectedResult, final String replaceTemplate, + final boolean substring) { + final String expectedShortResult = expectedResult.substring(1, expectedResult.length() - 1); + + // replace using String + assertEquals(expectedResult, sub.replace(replaceTemplate)); + if (substring) { + assertEquals(expectedShortResult, sub.replace(replaceTemplate, 1, replaceTemplate.length() - 2)); + } + + // replace using char[] + final char[] chars = replaceTemplate.toCharArray(); + assertEquals(expectedResult, sub.replace(chars)); + if (substring) { + assertEquals(expectedShortResult, sub.replace(chars, 1, chars.length - 2)); + } + + // replace using StringBuffer + StringBuffer buf = new StringBuffer(replaceTemplate); + assertEquals(expectedResult, sub.replace(buf)); + if (substring) { + assertEquals(expectedShortResult, sub.replace(buf, 1, buf.length() - 2)); + } + + // replace using StringBuilder + StringBuilder builder = new StringBuilder(replaceTemplate); + assertEquals(expectedResult, sub.replace(builder)); + if (substring) { + assertEquals(expectedShortResult, sub.replace(builder, 1, builder.length() - 2)); + } + + // replace using StrBuilder + StrBuilder bld = new StrBuilder(replaceTemplate); + assertEquals(expectedResult, sub.replace(bld)); + if (substring) { + assertEquals(expectedShortResult, sub.replace(bld, 1, bld.length() - 2)); + } + + // replace using object + final MutableObject<String> obj = new MutableObject<>(replaceTemplate); // toString returns template + assertEquals(expectedResult, sub.replace(obj)); + + // replace in StringBuffer + buf = new StringBuffer(replaceTemplate); + assertTrue(sub.replaceIn(buf)); + assertEquals(expectedResult, buf.toString()); + if (substring) { + buf = new StringBuffer(replaceTemplate); + assertTrue(sub.replaceIn(buf, 1, buf.length() - 2)); + assertEquals(expectedResult, buf.toString()); // expect full result as remainder is untouched + } + + // replace in StringBuilder + builder = new StringBuilder(replaceTemplate); + assertTrue(sub.replaceIn(builder)); + assertEquals(expectedResult, builder.toString()); + if (substring) { + builder = new StringBuilder(replaceTemplate); + assertTrue(sub.replaceIn(builder, 1, builder.length() - 2)); + assertEquals(expectedResult, builder.toString()); // expect full result as remainder is untouched + } + + // replace in StrBuilder + bld = new StrBuilder(replaceTemplate); + assertTrue(sub.replaceIn(bld)); + assertEquals(expectedResult, bld.toString()); + if (substring) { + bld = new StrBuilder(replaceTemplate); + assertTrue(sub.replaceIn(bld, 1, bld.length() - 2)); + assertEquals(expectedResult, bld.toString()); // expect full result as remainder is untouched + } + } + + private void doTestNoReplace(final String replaceTemplate) { + final StrSubstitutor sub = new StrSubstitutor(values); + + if (replaceTemplate == null) { + assertNull(sub.replace((String) null)); + assertNull(sub.replace((String) null, 0, 100)); + assertNull(sub.replace((char[]) null)); + assertNull(sub.replace((char[]) null, 0, 100)); + assertNull(sub.replace((StringBuffer) null)); + assertNull(sub.replace((StringBuffer) null, 0, 100)); + assertNull(sub.replace((StrBuilder) null)); + assertNull(sub.replace((StrBuilder) null, 0, 100)); + assertNull(sub.replace((Object) null)); + assertFalse(sub.replaceIn((StringBuffer) null)); + assertFalse(sub.replaceIn((StringBuffer) null, 0, 100)); + assertFalse(sub.replaceIn((StrBuilder) null)); + assertFalse(sub.replaceIn((StrBuilder) null, 0, 100)); + } else { + assertEquals(replaceTemplate, sub.replace(replaceTemplate)); + final StrBuilder bld = new StrBuilder(replaceTemplate); + assertFalse(sub.replaceIn(bld)); + assertEquals(replaceTemplate, bld.toString()); + } + } + + @Test + public void testReplaceInTakingTwoAndThreeIntsReturningFalse() { + final Map<String, Object> hashMap = new HashMap<>(); + final StrLookup.MapStrLookup<Object> strLookupMapStrLookup = new StrLookup.MapStrLookup<>(hashMap); + final StrMatcher strMatcher = StrMatcher.tabMatcher(); + final StrSubstitutor strSubstitutor = + new StrSubstitutor(strLookupMapStrLookup, strMatcher, strMatcher, 'b', strMatcher); + + assertFalse(strSubstitutor.replaceIn((StringBuilder) null, 1315, (-1369))); + assertEquals('b', strSubstitutor.getEscapeChar()); + assertFalse(strSubstitutor.isPreserveEscapes()); + } + + @Test + public void testReplaceInTakingStringBuilderWithNonNull() { + final StrLookup<String> strLookup = StrLookup.systemPropertiesLookup(); + final StrSubstitutor strSubstitutor = new StrSubstitutor(strLookup, "b<H", "b<H", '\''); + final StringBuilder stringBuilder = new StringBuilder((CharSequence) "b<H"); + + assertEquals('\'', strSubstitutor.getEscapeChar()); + assertFalse(strSubstitutor.replaceIn(stringBuilder)); + } + + @Test + public void testReplaceInTakingStringBufferWithNonNull() { + final StrSubstitutor strSubstitutor = + new StrSubstitutor(new HashMap<String, String>(), "WV@i#y?N*[", "WV@i#y?N*[", '*'); + + assertFalse(strSubstitutor.isPreserveEscapes()); + assertFalse(strSubstitutor.replaceIn(new StringBuffer("WV@i#y?N*["))); + assertEquals('*', strSubstitutor.getEscapeChar()); + } + + @Test + public void testCreatesStrSubstitutorTakingStrLookupAndCallsReplaceTakingTwoAndThreeInts() { + final Map<String, CharacterPredicates> map = new HashMap<>(); + final StrLookup.MapStrLookup<CharacterPredicates> strLookupMapStrLookup = new StrLookup.MapStrLookup<>(map); + final StrSubstitutor strSubstitutor = new StrSubstitutor(strLookupMapStrLookup); + + assertNull(strSubstitutor.replace((CharSequence) null, 0, 0)); + assertEquals('$', strSubstitutor.getEscapeChar()); + } + + @Test + public void testReplaceTakingCharSequenceReturningNull() { + final StrSubstitutor strSubstitutor = new StrSubstitutor((StrLookup<?>) null); + + assertNull(strSubstitutor.replace((CharSequence) null)); + assertFalse(strSubstitutor.isPreserveEscapes()); + assertEquals('$', strSubstitutor.getEscapeChar()); + } + + @Test(expected = NullPointerException.class) + public void testReplaceTakingThreeArgumentsThrowsNullPointerException() { + StrSubstitutor.replace(null, (Properties) null); + } + + @Test + public void testReplaceInTakingStringBuilderWithNull() { + final Map<String, Object> map = new HashMap<>(); + final StrSubstitutor strSubstitutor = new StrSubstitutor(map, "", "", 'T', "K+<'f"); + + assertFalse(strSubstitutor.replaceIn((StringBuilder) null)); + } + +}
http://git-wip-us.apache.org/repos/asf/commons-text/blob/4b67dd51/src/test/java/org/apache/commons/text/StrSubstitutorWithInterpolatorStringLookupTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/text/StrSubstitutorWithInterpolatorStringLookupTest.java b/src/test/java/org/apache/commons/text/StrSubstitutorWithInterpolatorStringLookupTest.java deleted file mode 100644 index d50d3b7..0000000 --- a/src/test/java/org/apache/commons/text/StrSubstitutorWithInterpolatorStringLookupTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.text; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.text.lookup.StringLookupFactory; -import org.junit.Assert; -import org.junit.Test; - -public class StrSubstitutorWithInterpolatorStringLookupTest { - - @Test - public void testMapAndSystemProperty() { - final String key = "key"; - final String value = "value"; - final Map<String, String> map = new HashMap<>(); - map.put(key, value); - final StrSubstitutor strSubst = new StrSubstitutor(StringLookupFactory.INSTANCE.interpolatorStringLookup(map)); - final String spKey = "user.name"; - Assert.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}")); - Assert.assertEquals(value, strSubst.replace("${" + key + "}")); - } - - @Test - public void testSystemProperty() { - final StrSubstitutor strSubst = new StrSubstitutor(StringLookupFactory.INSTANCE.interpolatorStringLookup()); - final String spKey = "user.name"; - Assert.assertEquals(System.getProperty(spKey), strSubst.replace("${sys:" + spKey + "}")); - } -}