/* Copyright 2013 Jonatan Jönsson
*
* Licensed 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 se.softhouse.common.strings;
import static java.util.Arrays.asList;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
import static se.softhouse.common.strings.StringsUtil.closestMatch;
import static se.softhouse.common.strings.StringsUtil.closestMatches;
import static se.softhouse.common.strings.StringsUtil.numberToPositionalString;
import static se.softhouse.common.strings.StringsUtil.pointingAtIndex;
import static se.softhouse.common.strings.StringsUtil.spaces;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import se.softhouse.common.testlib.Explanation;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.NullPointerTester.Visibility;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Tests for {@link StringsUtil}
*/
public class StringsUtilTest
{
@Test
public void testThatSpacesCreatesFiveSpaces()
{
assertThat(spaces(5)).isEqualTo(" ");
}
@Test
public void testLevenshteinDistance()
{
assertThat(StringsUtil.levenshteinDistance("", "")).isZero();
assertThat(StringsUtil.levenshteinDistance("", "a")).isEqualTo(1);
assertThat(StringsUtil.levenshteinDistance("aaapppp", "")).isEqualTo(7);
assertThat(StringsUtil.levenshteinDistance("frog", "fog")).isEqualTo(1);
assertThat(StringsUtil.levenshteinDistance("fly", "ant")).isEqualTo(3);
assertThat(StringsUtil.levenshteinDistance("elephant", "hippo")).isEqualTo(7);
assertThat(StringsUtil.levenshteinDistance("hippo", "elephant")).isEqualTo(7);
assertThat(StringsUtil.levenshteinDistance("hippo", "zzzzzzzz")).isEqualTo(8);
assertThat(StringsUtil.levenshteinDistance("hello", "hallo")).isEqualTo(1);
}
@Test
public void testLevenshteinDistanceWithADistance()
{
assertThat(StringsUtil.levenshteinDistance("", "", 1)).isZero();
assertThat(StringsUtil.levenshteinDistance("", "a", 1)).isEqualTo(1);
assertThat(StringsUtil.levenshteinDistance("aaapppp", "", 8)).isEqualTo(7);
assertThat(StringsUtil.levenshteinDistance("frog", "fog", 3)).isEqualTo(1);
assertThat(StringsUtil.levenshteinDistance("elephantelephantelephantelephantelephantelephant", "hippo", 4)).isEqualTo(4);
}
@Test(expected = IllegalArgumentException.class)
public void testLevenshteinDistanceWithADistanceMustBePositive()
{
StringsUtil.levenshteinDistance("", "", -1);
}
@Test
public void testClosestMatch()
{
List<String> strings = asList("logging", "help", "status");
assertThat(closestMatch("stats", strings)).isEqualTo("status");
}
@Test
public void testThatShortestStringIsReturnedForEmptyInput()
{
List<String> strings = asList("logging", "help", "status");
assertThat(closestMatch("", strings)).isEqualTo("help");
}
@Test
public void testThatTheFirstOfTwoEquallyGoodMatchesIsChosen()
{
List<String> strings = asList("logg", "kogg", "sogg");
assertThat(closestMatch("bogg", strings)).isEqualTo("logg");
}
@Test
public void testThatEmptyStringIsReturnedForSmallInput()
{
List<String> strings = asList("--logging", "--help", "");
assertThat(closestMatch("s", strings)).isEqualTo("");
}
@Test(expected = IllegalArgumentException.class)
@SuppressFBWarnings(value = "RV_RETURN_VALUE_IGNORED", justification = Explanation.FAIL_FAST)
public void testThatNoValidOptionsIsIllegal()
{
List<String> strings = asList();
closestMatch("", strings);
}
@Test
public void testSortedListOfCloseMatches()
{
List<String> strings = asList("stageasds", "state", "status");
assertThat(closestMatches("statos", strings, 3)).isEqualTo(Arrays.asList("status", "state"));
assertThat(closestMatches("foo", Collections.<String>emptyList(), 5)).isEmpty();
}
@Test
public void testTextsForPositionalNumbers()
{
assertThat(numberToPositionalString(0)).isEqualTo("zeroth");
assertThat(numberToPositionalString(1)).isEqualTo("first");
assertThat(numberToPositionalString(2)).isEqualTo("second");
assertThat(numberToPositionalString(3)).isEqualTo("third");
assertThat(numberToPositionalString(4)).isEqualTo("fourth");
assertThat(numberToPositionalString(5)).isEqualTo("fifth");
assertThat(numberToPositionalString(6)).isEqualTo("6th");
}
@Test
public void testThatPointingAtIndexProducesSpacesBeforeThePointer()
{
assertThat(pointingAtIndex(0)).isEqualTo("^");
assertThat(pointingAtIndex(1)).isEqualTo(" ^");
assertThat(pointingAtIndex(2)).isEqualTo(" ^");
try
{
pointingAtIndex(-1);
fail("-1 should be an invalid index to point at");
}
catch(IllegalArgumentException expected)
{
}
}
@Test(expected = IllegalArgumentException.class)
public void testThatNegativeNumberCantBePositional()
{
numberToPositionalString(-1);
}
@Test
public void testThatFindingNeedleInHaystackReturnsTheCorrectStartingIndex() throws Exception
{
// Find the 1st "b" in "abba"
assertThat(StringsUtil.indexOfNth(1, "b", "abba")).isEqualTo(1);
assertThat(StringsUtil.indexOfNth(2, "a", "abba")).isEqualTo(3);
assertThat(StringsUtil.indexOfNth(3, "ab", "abcabcabc")).isEqualTo(6);
// Trying to find more occurrences than there exists
assertThat(StringsUtil.indexOfNth(4, "ab", "ababab")).isEqualTo(-1);
// Missing the string altogether
assertThat(StringsUtil.indexOfNth(3, "abc", "ababab")).isEqualTo(-1);
}
@Test
public void testThatAtLeastOneOccurenceIsMinimum()
{
try
{
StringsUtil.indexOfNth(0, "b", "abba");
fail("0 should be an invalid nth parameter");
}
catch(IllegalArgumentException expected)
{
assertThat(expected).hasMessage("nth must be at least 1 (was 0)");
}
}
@Test
public void testStartsWithAndMore() throws Exception
{
assertThat(StringsUtil.startsWithAndHasMore("foo", "foo")).as("foo is equal to foo so should not have more").isFalse();
assertThat(StringsUtil.startsWithAndHasMore("foos", "foo")).as("foos starts with foo and should have more (the s)").isTrue();
assertThat(StringsUtil.startsWithAndHasMore("bar", "foo")).isFalse();
}
@Test
public void testThatNullContractsAreFollowed() throws Exception
{
new NullPointerTester().testStaticMethods(StringsUtil.class, Visibility.PACKAGE);
}
}