761 lines
30 KiB
Java
761 lines
30 KiB
Java
/*
|
|
* Copyright (C) 2008 The Guava Authors
|
|
*
|
|
* 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 com.google.common.base;
|
|
|
|
import static com.google.common.base.CharMatcher.anyOf;
|
|
import static com.google.common.base.CharMatcher.breakingWhitespace;
|
|
import static com.google.common.base.CharMatcher.forPredicate;
|
|
import static com.google.common.base.CharMatcher.inRange;
|
|
import static com.google.common.base.CharMatcher.is;
|
|
import static com.google.common.base.CharMatcher.isNot;
|
|
import static com.google.common.base.CharMatcher.noneOf;
|
|
import static com.google.common.base.CharMatcher.whitespace;
|
|
|
|
import com.google.common.annotations.GwtCompatible;
|
|
import com.google.common.annotations.GwtIncompatible;
|
|
import com.google.common.collect.Sets;
|
|
import com.google.common.testing.NullPointerTester;
|
|
import java.util.Arrays;
|
|
import java.util.BitSet;
|
|
import java.util.HashSet;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
import junit.framework.AssertionFailedError;
|
|
import junit.framework.TestCase;
|
|
|
|
/**
|
|
* Unit test for {@link CharMatcher}.
|
|
*
|
|
* @author Kevin Bourrillion
|
|
*/
|
|
@GwtCompatible(emulated = true)
|
|
public class CharMatcherTest extends TestCase {
|
|
|
|
@GwtIncompatible // NullPointerTester
|
|
public void testStaticNullPointers() throws Exception {
|
|
NullPointerTester tester = new NullPointerTester();
|
|
tester.testAllPublicStaticMethods(CharMatcher.class);
|
|
tester.testAllPublicInstanceMethods(CharMatcher.any());
|
|
tester.testAllPublicInstanceMethods(CharMatcher.anyOf("abc"));
|
|
}
|
|
|
|
private static final CharMatcher WHATEVER =
|
|
new CharMatcher() {
|
|
@Override
|
|
public boolean matches(char c) {
|
|
throw new AssertionFailedError("You weren't supposed to actually invoke me!");
|
|
}
|
|
};
|
|
|
|
public void testAnyAndNone_logicalOps() throws Exception {
|
|
// These are testing behavior that's never promised by the API, but since
|
|
// we're lucky enough that these do pass, it saves us from having to write
|
|
// more excruciating tests! Hooray!
|
|
|
|
assertSame(CharMatcher.any(), CharMatcher.none().negate());
|
|
assertSame(CharMatcher.none(), CharMatcher.any().negate());
|
|
|
|
assertSame(WHATEVER, CharMatcher.any().and(WHATEVER));
|
|
assertSame(CharMatcher.any(), CharMatcher.any().or(WHATEVER));
|
|
|
|
assertSame(CharMatcher.none(), CharMatcher.none().and(WHATEVER));
|
|
assertSame(WHATEVER, CharMatcher.none().or(WHATEVER));
|
|
}
|
|
|
|
// The rest of the behavior of ANY and DEFAULT will be covered in the tests for
|
|
// the text processing methods below.
|
|
|
|
public void testWhitespaceBreakingWhitespaceSubset() throws Exception {
|
|
for (int c = 0; c <= Character.MAX_VALUE; c++) {
|
|
if (breakingWhitespace().matches((char) c)) {
|
|
assertTrue(Integer.toHexString(c), whitespace().matches((char) c));
|
|
}
|
|
}
|
|
}
|
|
|
|
// The next tests require ICU4J and have, at least for now, been sliced out
|
|
// of the open-source view of the tests.
|
|
|
|
@GwtIncompatible // Character.isISOControl
|
|
public void testJavaIsoControl() {
|
|
for (int c = 0; c <= Character.MAX_VALUE; c++) {
|
|
assertEquals(
|
|
"" + c, Character.isISOControl(c), CharMatcher.javaIsoControl().matches((char) c));
|
|
}
|
|
}
|
|
|
|
// Omitting tests for the rest of the JAVA_* constants as these are defined
|
|
// as extremely straightforward pass-throughs to the JDK methods.
|
|
|
|
// We're testing the is(), isNot(), anyOf(), noneOf() and inRange() methods
|
|
// below by testing their text-processing methods.
|
|
|
|
// The organization of this test class is unusual, as it's not done by
|
|
// method, but by overall "scenario". Also, the variety of actual tests we
|
|
// do borders on absurd overkill. Better safe than sorry, though?
|
|
|
|
@GwtIncompatible // java.util.BitSet
|
|
public void testSetBits() {
|
|
doTestSetBits(CharMatcher.any());
|
|
doTestSetBits(CharMatcher.none());
|
|
doTestSetBits(is('a'));
|
|
doTestSetBits(isNot('a'));
|
|
doTestSetBits(anyOf(""));
|
|
doTestSetBits(anyOf("x"));
|
|
doTestSetBits(anyOf("xy"));
|
|
doTestSetBits(anyOf("CharMatcher"));
|
|
doTestSetBits(noneOf("CharMatcher"));
|
|
doTestSetBits(inRange('n', 'q'));
|
|
doTestSetBits(forPredicate(Predicates.equalTo('c')));
|
|
doTestSetBits(CharMatcher.ascii());
|
|
doTestSetBits(CharMatcher.digit());
|
|
doTestSetBits(CharMatcher.invisible());
|
|
doTestSetBits(CharMatcher.whitespace());
|
|
doTestSetBits(inRange('A', 'Z').and(inRange('F', 'K').negate()));
|
|
}
|
|
|
|
@GwtIncompatible // java.util.BitSet
|
|
private void doTestSetBits(CharMatcher matcher) {
|
|
BitSet bitset = new BitSet();
|
|
matcher.setBits(bitset);
|
|
for (int i = Character.MIN_VALUE; i <= Character.MAX_VALUE; i++) {
|
|
assertEquals(matcher.matches((char) i), bitset.get(i));
|
|
}
|
|
}
|
|
|
|
public void testEmpty() throws Exception {
|
|
doTestEmpty(CharMatcher.any());
|
|
doTestEmpty(CharMatcher.none());
|
|
doTestEmpty(is('a'));
|
|
doTestEmpty(isNot('a'));
|
|
doTestEmpty(anyOf(""));
|
|
doTestEmpty(anyOf("x"));
|
|
doTestEmpty(anyOf("xy"));
|
|
doTestEmpty(anyOf("CharMatcher"));
|
|
doTestEmpty(noneOf("CharMatcher"));
|
|
doTestEmpty(inRange('n', 'q'));
|
|
doTestEmpty(forPredicate(Predicates.equalTo('c')));
|
|
}
|
|
|
|
@GwtIncompatible // NullPointerTester
|
|
public void testNull() throws Exception {
|
|
doTestNull(CharMatcher.any());
|
|
doTestNull(CharMatcher.none());
|
|
doTestNull(is('a'));
|
|
doTestNull(isNot('a'));
|
|
doTestNull(anyOf(""));
|
|
doTestNull(anyOf("x"));
|
|
doTestNull(anyOf("xy"));
|
|
doTestNull(anyOf("CharMatcher"));
|
|
doTestNull(noneOf("CharMatcher"));
|
|
doTestNull(inRange('n', 'q'));
|
|
doTestNull(forPredicate(Predicates.equalTo('c')));
|
|
}
|
|
|
|
private void doTestEmpty(CharMatcher matcher) throws Exception {
|
|
reallyTestEmpty(matcher);
|
|
reallyTestEmpty(matcher.negate());
|
|
reallyTestEmpty(matcher.precomputed());
|
|
}
|
|
|
|
private void reallyTestEmpty(CharMatcher matcher) throws Exception {
|
|
assertEquals(-1, matcher.indexIn(""));
|
|
assertEquals(-1, matcher.indexIn("", 0));
|
|
try {
|
|
matcher.indexIn("", 1);
|
|
fail();
|
|
} catch (IndexOutOfBoundsException expected) {
|
|
}
|
|
try {
|
|
matcher.indexIn("", -1);
|
|
fail();
|
|
} catch (IndexOutOfBoundsException expected) {
|
|
}
|
|
assertEquals(-1, matcher.lastIndexIn(""));
|
|
assertFalse(matcher.matchesAnyOf(""));
|
|
assertTrue(matcher.matchesAllOf(""));
|
|
assertTrue(matcher.matchesNoneOf(""));
|
|
assertEquals("", matcher.removeFrom(""));
|
|
assertEquals("", matcher.replaceFrom("", 'z'));
|
|
assertEquals("", matcher.replaceFrom("", "ZZ"));
|
|
assertEquals("", matcher.trimFrom(""));
|
|
assertEquals(0, matcher.countIn(""));
|
|
}
|
|
|
|
@GwtIncompatible // NullPointerTester
|
|
private static void doTestNull(CharMatcher matcher) throws Exception {
|
|
NullPointerTester tester = new NullPointerTester();
|
|
tester.testAllPublicInstanceMethods(matcher);
|
|
}
|
|
|
|
public void testNoMatches() {
|
|
doTestNoMatches(CharMatcher.none(), "blah");
|
|
doTestNoMatches(is('a'), "bcde");
|
|
doTestNoMatches(isNot('a'), "aaaa");
|
|
doTestNoMatches(anyOf(""), "abcd");
|
|
doTestNoMatches(anyOf("x"), "abcd");
|
|
doTestNoMatches(anyOf("xy"), "abcd");
|
|
doTestNoMatches(anyOf("CharMatcher"), "zxqy");
|
|
doTestNoMatches(noneOf("CharMatcher"), "ChMa");
|
|
doTestNoMatches(inRange('p', 'x'), "mom");
|
|
doTestNoMatches(forPredicate(Predicates.equalTo('c')), "abe");
|
|
doTestNoMatches(inRange('A', 'Z').and(inRange('F', 'K').negate()), "F1a");
|
|
doTestNoMatches(CharMatcher.digit(), "\tAz()");
|
|
doTestNoMatches(CharMatcher.javaDigit(), "\tAz()");
|
|
doTestNoMatches(CharMatcher.digit().and(CharMatcher.ascii()), "\tAz()");
|
|
doTestNoMatches(CharMatcher.singleWidth(), "\u05bf\u3000");
|
|
}
|
|
|
|
private void doTestNoMatches(CharMatcher matcher, String s) {
|
|
reallyTestNoMatches(matcher, s);
|
|
reallyTestAllMatches(matcher.negate(), s);
|
|
reallyTestNoMatches(matcher.precomputed(), s);
|
|
reallyTestAllMatches(matcher.negate().precomputed(), s);
|
|
reallyTestAllMatches(matcher.precomputed().negate(), s);
|
|
reallyTestNoMatches(forPredicate(matcher), s);
|
|
|
|
reallyTestNoMatches(matcher, new StringBuilder(s));
|
|
}
|
|
|
|
public void testAllMatches() {
|
|
doTestAllMatches(CharMatcher.any(), "blah");
|
|
doTestAllMatches(isNot('a'), "bcde");
|
|
doTestAllMatches(is('a'), "aaaa");
|
|
doTestAllMatches(noneOf("CharMatcher"), "zxqy");
|
|
doTestAllMatches(anyOf("x"), "xxxx");
|
|
doTestAllMatches(anyOf("xy"), "xyyx");
|
|
doTestAllMatches(anyOf("CharMatcher"), "ChMa");
|
|
doTestAllMatches(inRange('m', 'p'), "mom");
|
|
doTestAllMatches(forPredicate(Predicates.equalTo('c')), "ccc");
|
|
doTestAllMatches(CharMatcher.digit(), "0123456789\u0ED0\u1B59");
|
|
doTestAllMatches(CharMatcher.javaDigit(), "0123456789");
|
|
doTestAllMatches(CharMatcher.digit().and(CharMatcher.ascii()), "0123456789");
|
|
doTestAllMatches(CharMatcher.singleWidth(), "\t0123ABCdef~\u00A0\u2111");
|
|
}
|
|
|
|
private void doTestAllMatches(CharMatcher matcher, String s) {
|
|
reallyTestAllMatches(matcher, s);
|
|
reallyTestNoMatches(matcher.negate(), s);
|
|
reallyTestAllMatches(matcher.precomputed(), s);
|
|
reallyTestNoMatches(matcher.negate().precomputed(), s);
|
|
reallyTestNoMatches(matcher.precomputed().negate(), s);
|
|
reallyTestAllMatches(forPredicate(matcher), s);
|
|
|
|
reallyTestAllMatches(matcher, new StringBuilder(s));
|
|
}
|
|
|
|
private void reallyTestNoMatches(CharMatcher matcher, CharSequence s) {
|
|
assertFalse(matcher.matches(s.charAt(0)));
|
|
assertEquals(-1, matcher.indexIn(s));
|
|
assertEquals(-1, matcher.indexIn(s, 0));
|
|
assertEquals(-1, matcher.indexIn(s, 1));
|
|
assertEquals(-1, matcher.indexIn(s, s.length()));
|
|
try {
|
|
matcher.indexIn(s, s.length() + 1);
|
|
fail();
|
|
} catch (IndexOutOfBoundsException expected) {
|
|
}
|
|
try {
|
|
matcher.indexIn(s, -1);
|
|
fail();
|
|
} catch (IndexOutOfBoundsException expected) {
|
|
}
|
|
assertEquals(-1, matcher.lastIndexIn(s));
|
|
assertFalse(matcher.matchesAnyOf(s));
|
|
assertFalse(matcher.matchesAllOf(s));
|
|
assertTrue(matcher.matchesNoneOf(s));
|
|
|
|
assertEquals(s.toString(), matcher.removeFrom(s));
|
|
assertEquals(s.toString(), matcher.replaceFrom(s, 'z'));
|
|
assertEquals(s.toString(), matcher.replaceFrom(s, "ZZ"));
|
|
assertEquals(s.toString(), matcher.trimFrom(s));
|
|
assertEquals(0, matcher.countIn(s));
|
|
}
|
|
|
|
private void reallyTestAllMatches(CharMatcher matcher, CharSequence s) {
|
|
assertTrue(matcher.matches(s.charAt(0)));
|
|
assertEquals(0, matcher.indexIn(s));
|
|
assertEquals(0, matcher.indexIn(s, 0));
|
|
assertEquals(1, matcher.indexIn(s, 1));
|
|
assertEquals(-1, matcher.indexIn(s, s.length()));
|
|
assertEquals(s.length() - 1, matcher.lastIndexIn(s));
|
|
assertTrue(matcher.matchesAnyOf(s));
|
|
assertTrue(matcher.matchesAllOf(s));
|
|
assertFalse(matcher.matchesNoneOf(s));
|
|
assertEquals("", matcher.removeFrom(s));
|
|
assertEquals(Strings.repeat("z", s.length()), matcher.replaceFrom(s, 'z'));
|
|
assertEquals(Strings.repeat("ZZ", s.length()), matcher.replaceFrom(s, "ZZ"));
|
|
assertEquals("", matcher.trimFrom(s));
|
|
assertEquals(s.length(), matcher.countIn(s));
|
|
}
|
|
|
|
public void testGeneral() {
|
|
doTestGeneral(is('a'), 'a', 'b');
|
|
doTestGeneral(isNot('a'), 'b', 'a');
|
|
doTestGeneral(anyOf("x"), 'x', 'z');
|
|
doTestGeneral(anyOf("xy"), 'y', 'z');
|
|
doTestGeneral(anyOf("CharMatcher"), 'C', 'z');
|
|
doTestGeneral(noneOf("CharMatcher"), 'z', 'C');
|
|
doTestGeneral(inRange('p', 'x'), 'q', 'z');
|
|
}
|
|
|
|
private void doTestGeneral(CharMatcher matcher, char match, char noMatch) {
|
|
doTestOneCharMatch(matcher, "" + match);
|
|
doTestOneCharNoMatch(matcher, "" + noMatch);
|
|
doTestMatchThenNoMatch(matcher, "" + match + noMatch);
|
|
doTestNoMatchThenMatch(matcher, "" + noMatch + match);
|
|
}
|
|
|
|
private void doTestOneCharMatch(CharMatcher matcher, String s) {
|
|
reallyTestOneCharMatch(matcher, s);
|
|
reallyTestOneCharNoMatch(matcher.negate(), s);
|
|
reallyTestOneCharMatch(matcher.precomputed(), s);
|
|
reallyTestOneCharNoMatch(matcher.negate().precomputed(), s);
|
|
reallyTestOneCharNoMatch(matcher.precomputed().negate(), s);
|
|
}
|
|
|
|
private void doTestOneCharNoMatch(CharMatcher matcher, String s) {
|
|
reallyTestOneCharNoMatch(matcher, s);
|
|
reallyTestOneCharMatch(matcher.negate(), s);
|
|
reallyTestOneCharNoMatch(matcher.precomputed(), s);
|
|
reallyTestOneCharMatch(matcher.negate().precomputed(), s);
|
|
reallyTestOneCharMatch(matcher.precomputed().negate(), s);
|
|
}
|
|
|
|
private void doTestMatchThenNoMatch(CharMatcher matcher, String s) {
|
|
reallyTestMatchThenNoMatch(matcher, s);
|
|
reallyTestNoMatchThenMatch(matcher.negate(), s);
|
|
reallyTestMatchThenNoMatch(matcher.precomputed(), s);
|
|
reallyTestNoMatchThenMatch(matcher.negate().precomputed(), s);
|
|
reallyTestNoMatchThenMatch(matcher.precomputed().negate(), s);
|
|
}
|
|
|
|
private void doTestNoMatchThenMatch(CharMatcher matcher, String s) {
|
|
reallyTestNoMatchThenMatch(matcher, s);
|
|
reallyTestMatchThenNoMatch(matcher.negate(), s);
|
|
reallyTestNoMatchThenMatch(matcher.precomputed(), s);
|
|
reallyTestMatchThenNoMatch(matcher.negate().precomputed(), s);
|
|
reallyTestMatchThenNoMatch(matcher.precomputed().negate(), s);
|
|
}
|
|
|
|
@SuppressWarnings("deprecation") // intentionally testing apply() method
|
|
private void reallyTestOneCharMatch(CharMatcher matcher, String s) {
|
|
assertTrue(matcher.matches(s.charAt(0)));
|
|
assertTrue(matcher.apply(s.charAt(0)));
|
|
assertEquals(0, matcher.indexIn(s));
|
|
assertEquals(0, matcher.indexIn(s, 0));
|
|
assertEquals(-1, matcher.indexIn(s, 1));
|
|
assertEquals(0, matcher.lastIndexIn(s));
|
|
assertTrue(matcher.matchesAnyOf(s));
|
|
assertTrue(matcher.matchesAllOf(s));
|
|
assertFalse(matcher.matchesNoneOf(s));
|
|
assertEquals("", matcher.removeFrom(s));
|
|
assertEquals("z", matcher.replaceFrom(s, 'z'));
|
|
assertEquals("ZZ", matcher.replaceFrom(s, "ZZ"));
|
|
assertEquals("", matcher.trimFrom(s));
|
|
assertEquals(1, matcher.countIn(s));
|
|
}
|
|
|
|
@SuppressWarnings("deprecation") // intentionally testing apply() method
|
|
private void reallyTestOneCharNoMatch(CharMatcher matcher, String s) {
|
|
assertFalse(matcher.matches(s.charAt(0)));
|
|
assertFalse(matcher.apply(s.charAt(0)));
|
|
assertEquals(-1, matcher.indexIn(s));
|
|
assertEquals(-1, matcher.indexIn(s, 0));
|
|
assertEquals(-1, matcher.indexIn(s, 1));
|
|
assertEquals(-1, matcher.lastIndexIn(s));
|
|
assertFalse(matcher.matchesAnyOf(s));
|
|
assertFalse(matcher.matchesAllOf(s));
|
|
assertTrue(matcher.matchesNoneOf(s));
|
|
|
|
assertSame(s, matcher.removeFrom(s));
|
|
assertSame(s, matcher.replaceFrom(s, 'z'));
|
|
assertSame(s, matcher.replaceFrom(s, "ZZ"));
|
|
assertSame(s, matcher.trimFrom(s));
|
|
assertSame(0, matcher.countIn(s));
|
|
}
|
|
|
|
private void reallyTestMatchThenNoMatch(CharMatcher matcher, String s) {
|
|
assertEquals(0, matcher.indexIn(s));
|
|
assertEquals(0, matcher.indexIn(s, 0));
|
|
assertEquals(-1, matcher.indexIn(s, 1));
|
|
assertEquals(-1, matcher.indexIn(s, 2));
|
|
assertEquals(0, matcher.lastIndexIn(s));
|
|
assertTrue(matcher.matchesAnyOf(s));
|
|
assertFalse(matcher.matchesAllOf(s));
|
|
assertFalse(matcher.matchesNoneOf(s));
|
|
assertEquals(s.substring(1), matcher.removeFrom(s));
|
|
assertEquals("z" + s.substring(1), matcher.replaceFrom(s, 'z'));
|
|
assertEquals("ZZ" + s.substring(1), matcher.replaceFrom(s, "ZZ"));
|
|
assertEquals(s.substring(1), matcher.trimFrom(s));
|
|
assertEquals(1, matcher.countIn(s));
|
|
}
|
|
|
|
private void reallyTestNoMatchThenMatch(CharMatcher matcher, String s) {
|
|
assertEquals(1, matcher.indexIn(s));
|
|
assertEquals(1, matcher.indexIn(s, 0));
|
|
assertEquals(1, matcher.indexIn(s, 1));
|
|
assertEquals(-1, matcher.indexIn(s, 2));
|
|
assertEquals(1, matcher.lastIndexIn(s));
|
|
assertTrue(matcher.matchesAnyOf(s));
|
|
assertFalse(matcher.matchesAllOf(s));
|
|
assertFalse(matcher.matchesNoneOf(s));
|
|
assertEquals(s.substring(0, 1), matcher.removeFrom(s));
|
|
assertEquals(s.substring(0, 1) + "z", matcher.replaceFrom(s, 'z'));
|
|
assertEquals(s.substring(0, 1) + "ZZ", matcher.replaceFrom(s, "ZZ"));
|
|
assertEquals(s.substring(0, 1), matcher.trimFrom(s));
|
|
assertEquals(1, matcher.countIn(s));
|
|
}
|
|
|
|
/**
|
|
* Checks that expected is equals to out, and further, if in is equals to expected, then out is
|
|
* successfully optimized to be identical to in, i.e. that "in" is simply returned.
|
|
*/
|
|
private void assertEqualsSame(String expected, String in, String out) {
|
|
if (expected.equals(in)) {
|
|
assertSame(in, out);
|
|
} else {
|
|
assertEquals(expected, out);
|
|
}
|
|
}
|
|
|
|
// Test collapse() a little differently than the rest, as we really want to
|
|
// cover lots of different configurations of input text
|
|
public void testCollapse() {
|
|
// collapsing groups of '-' into '_' or '-'
|
|
doTestCollapse("-", "_");
|
|
doTestCollapse("x-", "x_");
|
|
doTestCollapse("-x", "_x");
|
|
doTestCollapse("--", "_");
|
|
doTestCollapse("x--", "x_");
|
|
doTestCollapse("--x", "_x");
|
|
doTestCollapse("-x-", "_x_");
|
|
doTestCollapse("x-x", "x_x");
|
|
doTestCollapse("---", "_");
|
|
doTestCollapse("--x-", "_x_");
|
|
doTestCollapse("--xx", "_xx");
|
|
doTestCollapse("-x--", "_x_");
|
|
doTestCollapse("-x-x", "_x_x");
|
|
doTestCollapse("-xx-", "_xx_");
|
|
doTestCollapse("x--x", "x_x");
|
|
doTestCollapse("x-x-", "x_x_");
|
|
doTestCollapse("x-xx", "x_xx");
|
|
doTestCollapse("x-x--xx---x----x", "x_x_xx_x_x");
|
|
|
|
doTestCollapseWithNoChange("");
|
|
doTestCollapseWithNoChange("x");
|
|
doTestCollapseWithNoChange("xx");
|
|
}
|
|
|
|
private void doTestCollapse(String in, String out) {
|
|
// Try a few different matchers which all match '-' and not 'x'
|
|
// Try replacement chars that both do and do not change the value.
|
|
for (char replacement : new char[] {'_', '-'}) {
|
|
String expected = out.replace('_', replacement);
|
|
assertEqualsSame(expected, in, is('-').collapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, is('-').collapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, is('-').or(is('#')).collapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, isNot('x').collapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, is('x').negate().collapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, anyOf("-").collapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, anyOf("-#").collapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, anyOf("-#123").collapseFrom(in, replacement));
|
|
}
|
|
}
|
|
|
|
private void doTestCollapseWithNoChange(String inout) {
|
|
assertSame(inout, is('-').collapseFrom(inout, '_'));
|
|
assertSame(inout, is('-').or(is('#')).collapseFrom(inout, '_'));
|
|
assertSame(inout, isNot('x').collapseFrom(inout, '_'));
|
|
assertSame(inout, is('x').negate().collapseFrom(inout, '_'));
|
|
assertSame(inout, anyOf("-").collapseFrom(inout, '_'));
|
|
assertSame(inout, anyOf("-#").collapseFrom(inout, '_'));
|
|
assertSame(inout, anyOf("-#123").collapseFrom(inout, '_'));
|
|
assertSame(inout, CharMatcher.none().collapseFrom(inout, '_'));
|
|
}
|
|
|
|
public void testCollapse_any() {
|
|
assertEquals("", CharMatcher.any().collapseFrom("", '_'));
|
|
assertEquals("_", CharMatcher.any().collapseFrom("a", '_'));
|
|
assertEquals("_", CharMatcher.any().collapseFrom("ab", '_'));
|
|
assertEquals("_", CharMatcher.any().collapseFrom("abcd", '_'));
|
|
}
|
|
|
|
public void testTrimFrom() {
|
|
// trimming -
|
|
doTestTrimFrom("-", "");
|
|
doTestTrimFrom("x-", "x");
|
|
doTestTrimFrom("-x", "x");
|
|
doTestTrimFrom("--", "");
|
|
doTestTrimFrom("x--", "x");
|
|
doTestTrimFrom("--x", "x");
|
|
doTestTrimFrom("-x-", "x");
|
|
doTestTrimFrom("x-x", "x-x");
|
|
doTestTrimFrom("---", "");
|
|
doTestTrimFrom("--x-", "x");
|
|
doTestTrimFrom("--xx", "xx");
|
|
doTestTrimFrom("-x--", "x");
|
|
doTestTrimFrom("-x-x", "x-x");
|
|
doTestTrimFrom("-xx-", "xx");
|
|
doTestTrimFrom("x--x", "x--x");
|
|
doTestTrimFrom("x-x-", "x-x");
|
|
doTestTrimFrom("x-xx", "x-xx");
|
|
doTestTrimFrom("x-x--xx---x----x", "x-x--xx---x----x");
|
|
// additional testing using the doc example
|
|
assertEquals("cat", anyOf("ab").trimFrom("abacatbab"));
|
|
}
|
|
|
|
private void doTestTrimFrom(String in, String out) {
|
|
// Try a few different matchers which all match '-' and not 'x'
|
|
assertEquals(out, is('-').trimFrom(in));
|
|
assertEquals(out, is('-').or(is('#')).trimFrom(in));
|
|
assertEquals(out, isNot('x').trimFrom(in));
|
|
assertEquals(out, is('x').negate().trimFrom(in));
|
|
assertEquals(out, anyOf("-").trimFrom(in));
|
|
assertEquals(out, anyOf("-#").trimFrom(in));
|
|
assertEquals(out, anyOf("-#123").trimFrom(in));
|
|
}
|
|
|
|
public void testTrimLeadingFrom() {
|
|
// trimming -
|
|
doTestTrimLeadingFrom("-", "");
|
|
doTestTrimLeadingFrom("x-", "x-");
|
|
doTestTrimLeadingFrom("-x", "x");
|
|
doTestTrimLeadingFrom("--", "");
|
|
doTestTrimLeadingFrom("x--", "x--");
|
|
doTestTrimLeadingFrom("--x", "x");
|
|
doTestTrimLeadingFrom("-x-", "x-");
|
|
doTestTrimLeadingFrom("x-x", "x-x");
|
|
doTestTrimLeadingFrom("---", "");
|
|
doTestTrimLeadingFrom("--x-", "x-");
|
|
doTestTrimLeadingFrom("--xx", "xx");
|
|
doTestTrimLeadingFrom("-x--", "x--");
|
|
doTestTrimLeadingFrom("-x-x", "x-x");
|
|
doTestTrimLeadingFrom("-xx-", "xx-");
|
|
doTestTrimLeadingFrom("x--x", "x--x");
|
|
doTestTrimLeadingFrom("x-x-", "x-x-");
|
|
doTestTrimLeadingFrom("x-xx", "x-xx");
|
|
doTestTrimLeadingFrom("x-x--xx---x----x", "x-x--xx---x----x");
|
|
// additional testing using the doc example
|
|
assertEquals("catbab", anyOf("ab").trimLeadingFrom("abacatbab"));
|
|
}
|
|
|
|
private void doTestTrimLeadingFrom(String in, String out) {
|
|
// Try a few different matchers which all match '-' and not 'x'
|
|
assertEquals(out, is('-').trimLeadingFrom(in));
|
|
assertEquals(out, is('-').or(is('#')).trimLeadingFrom(in));
|
|
assertEquals(out, isNot('x').trimLeadingFrom(in));
|
|
assertEquals(out, is('x').negate().trimLeadingFrom(in));
|
|
assertEquals(out, anyOf("-#").trimLeadingFrom(in));
|
|
assertEquals(out, anyOf("-#123").trimLeadingFrom(in));
|
|
}
|
|
|
|
public void testTrimTrailingFrom() {
|
|
// trimming -
|
|
doTestTrimTrailingFrom("-", "");
|
|
doTestTrimTrailingFrom("x-", "x");
|
|
doTestTrimTrailingFrom("-x", "-x");
|
|
doTestTrimTrailingFrom("--", "");
|
|
doTestTrimTrailingFrom("x--", "x");
|
|
doTestTrimTrailingFrom("--x", "--x");
|
|
doTestTrimTrailingFrom("-x-", "-x");
|
|
doTestTrimTrailingFrom("x-x", "x-x");
|
|
doTestTrimTrailingFrom("---", "");
|
|
doTestTrimTrailingFrom("--x-", "--x");
|
|
doTestTrimTrailingFrom("--xx", "--xx");
|
|
doTestTrimTrailingFrom("-x--", "-x");
|
|
doTestTrimTrailingFrom("-x-x", "-x-x");
|
|
doTestTrimTrailingFrom("-xx-", "-xx");
|
|
doTestTrimTrailingFrom("x--x", "x--x");
|
|
doTestTrimTrailingFrom("x-x-", "x-x");
|
|
doTestTrimTrailingFrom("x-xx", "x-xx");
|
|
doTestTrimTrailingFrom("x-x--xx---x----x", "x-x--xx---x----x");
|
|
// additional testing using the doc example
|
|
assertEquals("abacat", anyOf("ab").trimTrailingFrom("abacatbab"));
|
|
}
|
|
|
|
private void doTestTrimTrailingFrom(String in, String out) {
|
|
// Try a few different matchers which all match '-' and not 'x'
|
|
assertEquals(out, is('-').trimTrailingFrom(in));
|
|
assertEquals(out, is('-').or(is('#')).trimTrailingFrom(in));
|
|
assertEquals(out, isNot('x').trimTrailingFrom(in));
|
|
assertEquals(out, is('x').negate().trimTrailingFrom(in));
|
|
assertEquals(out, anyOf("-#").trimTrailingFrom(in));
|
|
assertEquals(out, anyOf("-#123").trimTrailingFrom(in));
|
|
}
|
|
|
|
public void testTrimAndCollapse() {
|
|
// collapsing groups of '-' into '_' or '-'
|
|
doTestTrimAndCollapse("", "");
|
|
doTestTrimAndCollapse("x", "x");
|
|
doTestTrimAndCollapse("-", "");
|
|
doTestTrimAndCollapse("x-", "x");
|
|
doTestTrimAndCollapse("-x", "x");
|
|
doTestTrimAndCollapse("--", "");
|
|
doTestTrimAndCollapse("x--", "x");
|
|
doTestTrimAndCollapse("--x", "x");
|
|
doTestTrimAndCollapse("-x-", "x");
|
|
doTestTrimAndCollapse("x-x", "x_x");
|
|
doTestTrimAndCollapse("---", "");
|
|
doTestTrimAndCollapse("--x-", "x");
|
|
doTestTrimAndCollapse("--xx", "xx");
|
|
doTestTrimAndCollapse("-x--", "x");
|
|
doTestTrimAndCollapse("-x-x", "x_x");
|
|
doTestTrimAndCollapse("-xx-", "xx");
|
|
doTestTrimAndCollapse("x--x", "x_x");
|
|
doTestTrimAndCollapse("x-x-", "x_x");
|
|
doTestTrimAndCollapse("x-xx", "x_xx");
|
|
doTestTrimAndCollapse("x-x--xx---x----x", "x_x_xx_x_x");
|
|
}
|
|
|
|
private void doTestTrimAndCollapse(String in, String out) {
|
|
// Try a few different matchers which all match '-' and not 'x'
|
|
for (char replacement : new char[] {'_', '-'}) {
|
|
String expected = out.replace('_', replacement);
|
|
assertEqualsSame(expected, in, is('-').trimAndCollapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, is('-').or(is('#')).trimAndCollapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, isNot('x').trimAndCollapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, is('x').negate().trimAndCollapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, anyOf("-").trimAndCollapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, anyOf("-#").trimAndCollapseFrom(in, replacement));
|
|
assertEqualsSame(expected, in, anyOf("-#123").trimAndCollapseFrom(in, replacement));
|
|
}
|
|
}
|
|
|
|
public void testReplaceFrom() {
|
|
assertEquals("yoho", is('a').replaceFrom("yaha", 'o'));
|
|
assertEquals("yh", is('a').replaceFrom("yaha", ""));
|
|
assertEquals("yoho", is('a').replaceFrom("yaha", "o"));
|
|
assertEquals("yoohoo", is('a').replaceFrom("yaha", "oo"));
|
|
assertEquals("12 > 5", is('>').replaceFrom("12 > 5", ">"));
|
|
}
|
|
|
|
public void testPrecomputedOptimizations() {
|
|
// These are testing behavior that's never promised by the API.
|
|
// Some matchers are so efficient that it is a waste of effort to
|
|
// build a precomputed version.
|
|
CharMatcher m1 = is('x');
|
|
assertSame(m1, m1.precomputed());
|
|
assertEquals(m1.toString(), m1.precomputed().toString());
|
|
|
|
CharMatcher m2 = anyOf("Az");
|
|
assertSame(m2, m2.precomputed());
|
|
assertEquals(m2.toString(), m2.precomputed().toString());
|
|
|
|
CharMatcher m3 = inRange('A', 'Z');
|
|
assertSame(m3, m3.precomputed());
|
|
assertEquals(m3.toString(), m3.precomputed().toString());
|
|
|
|
assertSame(CharMatcher.none(), CharMatcher.none().precomputed());
|
|
assertSame(CharMatcher.any(), CharMatcher.any().precomputed());
|
|
}
|
|
|
|
@GwtIncompatible // java.util.BitSet
|
|
private static BitSet bitSet(String chars) {
|
|
return bitSet(chars.toCharArray());
|
|
}
|
|
|
|
@GwtIncompatible // java.util.BitSet
|
|
private static BitSet bitSet(char[] chars) {
|
|
BitSet tmp = new BitSet();
|
|
for (char c : chars) {
|
|
tmp.set(c);
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
@GwtIncompatible // java.util.Random, java.util.BitSet
|
|
public void testSmallCharMatcher() {
|
|
CharMatcher len1 = SmallCharMatcher.from(bitSet("#"), "#");
|
|
CharMatcher len2 = SmallCharMatcher.from(bitSet("ab"), "ab");
|
|
CharMatcher len3 = SmallCharMatcher.from(bitSet("abc"), "abc");
|
|
CharMatcher len4 = SmallCharMatcher.from(bitSet("abcd"), "abcd");
|
|
assertTrue(len1.matches('#'));
|
|
assertFalse(len1.matches('!'));
|
|
assertTrue(len2.matches('a'));
|
|
assertTrue(len2.matches('b'));
|
|
for (char c = 'c'; c < 'z'; c++) {
|
|
assertFalse(len2.matches(c));
|
|
}
|
|
assertTrue(len3.matches('a'));
|
|
assertTrue(len3.matches('b'));
|
|
assertTrue(len3.matches('c'));
|
|
for (char c = 'd'; c < 'z'; c++) {
|
|
assertFalse(len3.matches(c));
|
|
}
|
|
assertTrue(len4.matches('a'));
|
|
assertTrue(len4.matches('b'));
|
|
assertTrue(len4.matches('c'));
|
|
assertTrue(len4.matches('d'));
|
|
for (char c = 'e'; c < 'z'; c++) {
|
|
assertFalse(len4.matches(c));
|
|
}
|
|
|
|
Random rand = new Random(1234);
|
|
for (int testCase = 0; testCase < 100; testCase++) {
|
|
char[] chars = randomChars(rand, rand.nextInt(63) + 1);
|
|
CharMatcher m = SmallCharMatcher.from(bitSet(chars), new String(chars));
|
|
checkExactMatches(m, chars);
|
|
}
|
|
}
|
|
|
|
static void checkExactMatches(CharMatcher m, char[] chars) {
|
|
Set<Character> positive = Sets.newHashSetWithExpectedSize(chars.length);
|
|
for (char c : chars) {
|
|
positive.add(c);
|
|
}
|
|
for (int c = 0; c <= Character.MAX_VALUE; c++) {
|
|
assertFalse(positive.contains(new Character((char) c)) ^ m.matches((char) c));
|
|
}
|
|
}
|
|
|
|
static char[] randomChars(Random rand, int size) {
|
|
Set<Character> chars = new HashSet<>(size);
|
|
for (int i = 0; i < size; i++) {
|
|
char c;
|
|
do {
|
|
c = (char) rand.nextInt(Character.MAX_VALUE - Character.MIN_VALUE + 1);
|
|
} while (chars.contains(c));
|
|
chars.add(c);
|
|
}
|
|
char[] retValue = new char[chars.size()];
|
|
int i = 0;
|
|
for (char c : chars) {
|
|
retValue[i++] = c;
|
|
}
|
|
Arrays.sort(retValue);
|
|
return retValue;
|
|
}
|
|
|
|
public void testToString() {
|
|
assertToStringWorks("CharMatcher.none()", CharMatcher.anyOf(""));
|
|
assertToStringWorks("CharMatcher.is('\\u0031')", CharMatcher.anyOf("1"));
|
|
assertToStringWorks("CharMatcher.isNot('\\u0031')", CharMatcher.isNot('1'));
|
|
assertToStringWorks("CharMatcher.anyOf(\"\\u0031\\u0032\")", CharMatcher.anyOf("12"));
|
|
assertToStringWorks("CharMatcher.anyOf(\"\\u0031\\u0032\\u0033\")", CharMatcher.anyOf("321"));
|
|
assertToStringWorks("CharMatcher.inRange('\\u0031', '\\u0033')", CharMatcher.inRange('1', '3'));
|
|
}
|
|
|
|
private static void assertToStringWorks(String expected, CharMatcher matcher) {
|
|
assertEquals(expected, matcher.toString());
|
|
assertEquals(expected, matcher.precomputed().toString());
|
|
assertEquals(expected, matcher.negate().negate().toString());
|
|
assertEquals(expected, matcher.negate().precomputed().negate().toString());
|
|
assertEquals(expected, matcher.negate().precomputed().negate().precomputed().toString());
|
|
}
|
|
}
|