blob: 48dcb5c90cf008229a3aaea7be2648bab80cc20c [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* 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.gwt.emultest.java.lang;
import com.google.gwt.junit.client.GWTTestCase;
/**
* TODO: COMPILER OPTIMIZATIONS HAVE MADE THIS TEST NOT ACTUALLY TEST ANYTHING!
* NEED A VERSION THAT DOESN'T USE STATICALLY DETERMINABLE STRINGS!
*
* See individual method TODOs for ones that still need work -- the ones without
* comments are already protected against optimization.
*/
public class StringTest extends GWTTestCase {
@Override
public String getModuleName() {
return "com.google.gwt.emultest.EmulSuite";
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testCharAt() {
assertEquals("abc".charAt(1), 'b');
}
public void testCodePoint() {
String testPlain = hideFromCompiler("CAT");
String testUnicode = hideFromCompiler("C\uD801\uDF00T");
assertEquals("CAT", new String(new int[] { 'C', 'A', 'T' }, 0, 3));
assertEquals("C\uD801\uDF00T", new String(new int[] { 'C', 67328, 'T' }, 0, 3));
assertEquals("\uD801\uDF00", new String(new int[] { 'C', 67328, 'T' }, 1, 1));
assertEquals(65, testPlain.codePointAt(1));
assertEquals("codePointAt fails on surrogate pair", 67328, testUnicode.codePointAt(1));
assertEquals(65, testPlain.codePointBefore(2));
assertEquals("codePointBefore fails on surrogate pair", 67328, testUnicode.codePointBefore(3));
assertEquals("codePointCount(plain): ", 3, testPlain.codePointCount(0, 3));
assertEquals("codePointCount(unicode): ", 3, testUnicode.codePointCount(0, 4));
assertEquals(1, testPlain.codePointCount(1, 2));
assertEquals(1, testUnicode.codePointCount(1, 2));
assertEquals(2, testUnicode.codePointCount(2, 4));
assertEquals(1, testUnicode.offsetByCodePoints(0, 1));
assertEquals("offsetByCodePoints(1,1): ", 3, testUnicode.offsetByCodePoints(1, 1));
assertEquals("offsetByCodePoints(2,1): ", 3, testUnicode.offsetByCodePoints(2, 1));
assertEquals(4, testUnicode.offsetByCodePoints(3, 1));
assertEquals(1, testUnicode.offsetByCodePoints(2, -1));
assertEquals(1, testUnicode.offsetByCodePoints(3, -1));
assertEquals("offsetByCodePoints(4.-1): ", 3, testUnicode.offsetByCodePoints(4, -1));
assertEquals(0, testUnicode.offsetByCodePoints(3, -2));
/*
* The next line contains a Unicode character outside the base multilingual
* plane -- it may not show properly depending on your fonts, etc. The
* character is the Gothic letter Faihu, or U+10346. We use it to verify
* that multi-char UTF16 characters are handled properly.
*
* In Windows 2000, registry changes are required to support non-BMP characters
* (or surrogates in general) -- surrogates are not supported before Win2k and
* they are enabled by default in WinXP and later.
*
* [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\LanguagePack]
* SURROGATE=(REG_DWORD)0x00000002
*
* [HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\International\Scripts\42]
* IEFixedFontName=[Surrogate Font Face Name]
* IEPropFontName=[Surrogate Font Face Name]
*/
String nonBmpChar = hideFromCompiler("𐍆");
assertEquals("\uD800\uDF46", nonBmpChar);
assertEquals(0x10346, nonBmpChar.codePointAt(0));
assertEquals(2, nonBmpChar.length());
assertEquals(1, nonBmpChar.codePointCount(0, 2));
}
public void testConcat() {
String abc = String.valueOf(new char[] {'a', 'b', 'c'});
String def = String.valueOf(new char[] {'d', 'e', 'f'});
String empty = String.valueOf(new char[] {});
assertEquals("abcdef", abc + def);
assertEquals("abcdef", abc.concat(def));
assertEquals("", empty.concat(empty));
char c = def.charAt(0);
String s = abc;
assertEquals("abcd", abc + 'd');
assertEquals("abcd", abc + c);
assertEquals("abcd", s + 'd');
assertEquals("abcd", s + c);
s += c;
assertEquals("abcd", s);
}
public void testConstructor() {
char[] chars = {'a', 'b', 'c', 'd', 'e', 'f'};
String constant = String.valueOf(new char[] {'a', 'b', 'c', 'd', 'e', 'f'});
String shortString = String.valueOf(new char[] {'c', 'd', 'e'});
assertEquals(constant, new String(hideFromCompiler(constant)));
assertEquals(constant, new String(chars), constant);
assertEquals(shortString, new String(chars, 2, 3), shortString);
assertEquals("", new String(hideFromCompiler("")));
assertEquals("", new String(new String(new String(new String(hideFromCompiler(""))))));
assertEquals("", new String(new char[] {}));
StringBuffer buf = new StringBuffer();
buf.append('c');
buf.append('a');
buf.append('t');
assertEquals("cat", new String(buf));
StringBuilder sb = new StringBuilder();
sb.append('c');
sb.append('a');
sb.append('t');
assertEquals("cat", new String(sb));
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
* (StringBuffer tests are ok)
*/
public void testContains() {
// at the beginning
assertTrue("abcdef".contains("ab"));
assertTrue("abcdef".contains(new StringBuffer("ab")));
// at the end
assertTrue("abcdef".contains("ef"));
assertTrue("abcdef".contains(new StringBuffer("ef")));
// in the middle
assertTrue("abcdef".contains("cd"));
assertTrue("abcdef".contains(new StringBuffer("cd")));
// the same
assertTrue("abcdef".contains("abcdef"));
assertTrue("abcdef".contains(new StringBuffer("abcdef")));
// not present
assertFalse("abcdef".contains("z"));
assertFalse("abcdef".contains(new StringBuffer("z")));
}
public void testEndsWith() {
String haystack = "abcdefghi";
assertTrue("a", haystack.endsWith("defghi"));
assertTrue("b", haystack.endsWith(haystack));
assertFalse("c", haystack.endsWith(haystack + "j"));
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testEquals() {
assertFalse("ABC".equals("abc"));
assertFalse("abc".equals("ABC"));
assertTrue("abc".equals("abc"));
assertTrue("ABC".equals("ABC"));
assertFalse("AbC".equals("aBC"));
assertFalse("AbC".equals("aBC"));
assertTrue("".equals(""));
assertFalse("".equals(null));
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testEqualsIgnoreCase() {
assertTrue("ABC".equalsIgnoreCase("abc"));
assertTrue("abc".equalsIgnoreCase("ABC"));
assertTrue("abc".equalsIgnoreCase("abc"));
assertTrue("ABC".equalsIgnoreCase("ABC"));
assertTrue("AbC".equalsIgnoreCase("aBC"));
assertTrue("AbC".equalsIgnoreCase("aBC"));
assertTrue("".equalsIgnoreCase(""));
assertFalse("".equalsIgnoreCase(null));
}
/**
* Tests hashing with strings.
*
* The specific strings used in this test used to trigger failures because we
* use a JavaScript object as a hash map to cache the computed hash codes.
* This conflicts with built-in properties defined on objects -- see issue
* #631.
*
*/
public void testHashCode() {
String[] testStrings = {
"watch", "unwatch", "toString", "toSource", "eval", "valueOf",
"constructor", "__proto__"};
int[] savedHash = new int[testStrings.length];
for (int i = 0; i < testStrings.length; ++i) {
savedHash[i] = testStrings[i].hashCode();
/*
* Verify that the resulting hash code is numeric, since this is not
* enforced in web mode.
*/
String str = Integer.toString(savedHash[i]);
for (int j = 0; j < str.length(); ++j) {
char ch = str.charAt(j);
assertTrue("Bad character '" + ch + "' (U+0" + Integer.toHexString(ch)
+ ")", ch == '-' || ch == ' ' || Character.isDigit(ch));
}
}
// verify the hash codes are constant for a given string
for (int i = 0; i < testStrings.length; ++i) {
assertEquals(savedHash[i], testStrings[i].hashCode());
}
}
public void testIndexOf() {
String haystack = "abcdefghi";
assertEquals(haystack.indexOf("q"), -1);
assertEquals(haystack.indexOf('q'), -1);
assertEquals(haystack.indexOf("a"), 0);
assertEquals(haystack.indexOf('a'), 0);
assertEquals(haystack.indexOf('a', 1), -1);
assertEquals(haystack.indexOf("bc"), 1);
assertEquals(haystack.indexOf(""), 0);
}
public void testIntern() {
String s1 = String.valueOf(new char[] {'a', 'b', 'c', 'd', 'e', 'f'});
String s2 = String.valueOf(new char[] {'a', 'b', 'c', 'd', 'e', 'f'});
assertTrue("strings not equal", s1.equals(s2));
assertSame("interns are not the same reference", s1.intern(), s2.intern());
}
public void testLastIndexOf() {
String x = "abcdeabcdef";
assertEquals(9, x.lastIndexOf("e"));
assertEquals(10, x.lastIndexOf("f"));
assertEquals(-1, x.lastIndexOf("f", 1));
}
public void testLength() {
String abc = String.valueOf(new char[] {'a', 'b', 'c'});
assertEquals(3, abc.length());
String str = "x";
for (int i = 0; i < 16; i++) {
str = str + str;
}
assertEquals(1 << 16, str.length());
String cat = String.valueOf(new char[] {'C', '\uD801', '\uDF00', 'T'});
assertEquals(4, cat.length());
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testLowerCase() {
assertEquals("abc", "AbC".toLowerCase());
assertEquals("abc", "abc".toLowerCase());
assertEquals("", "".toLowerCase());
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testMatch() {
assertFalse("1f", "abbbbcd".matches("b*"));
assertFalse("2f", "abbbbcd".matches("b+"));
assertTrue("3t", "abbbbcd".matches("ab*bcd"));
assertTrue("4t", "abbbbcd".matches("ab+cd"));
assertTrue("5t", "abbbbcd".matches("ab+bcd"));
assertFalse("6f", "abbbbcd".matches(""));
assertTrue("7t", "abbbbcd".matches("a.*d"));
assertFalse("8f", "abbbbcd".matches("a.*e"));
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testNull() {
assertNull(returnNull());
String a = returnNull() + returnNull();
assertEquals("nullnull", a);
}
public void testRegionMatches() {
String test = String.valueOf(new char[] {'a', 'b', 'c', 'd', 'e', 'f'});
assertTrue(test.regionMatches(1, "bcd", 0, 3));
assertTrue(test.regionMatches(1, "bcdx", 0, 3));
assertFalse(test.regionMatches(1, "bcdx", 0, 4));
assertFalse(test.regionMatches(1, "bcdx", 1, 3));
assertTrue(test.regionMatches(true, 0, "XAbCd", 1, 4));
assertTrue(test.regionMatches(true, 1, "BcD", 0, 3));
assertTrue(test.regionMatches(true, 1, "bCdx", 0, 3));
assertFalse(test.regionMatches(true, 1, "bCdx", 0, 4));
assertFalse(test.regionMatches(true, 1, "bCdx", 1, 3));
assertTrue(test.regionMatches(true, 0, "xaBcd", 1, 4));
test = test.toUpperCase();
assertTrue(test.regionMatches(true, 0, "XAbCd", 1, 4));
assertTrue(test.regionMatches(true, 1, "BcD", 0, 3));
assertTrue(test.regionMatches(true, 1, "bCdx", 0, 3));
assertFalse(test.regionMatches(true, 1, "bCdx", 0, 4));
assertFalse(test.regionMatches(true, 1, "bCdx", 1, 3));
assertTrue(test.regionMatches(true, 0, "xaBcd", 1, 4));
}
public void testReplace() {
String axax = String.valueOf(new char[] {'a', 'x', 'a', 'x'});
String aaaa = String.valueOf(new char[] {'a', 'a', 'a', 'a'});
assertEquals("aaaa", axax.replace('x', 'a'));
assertEquals("aaaa", aaaa.replace('x', 'a'));
for (char from = 32; from < 250; ++from) {
char to = (char) (from + 5);
assertEquals(toS(to), toS(from).replace(from, to));
}
for (char to = 32; to < 250; ++to) {
char from = (char) (to + 5);
assertEquals(toS(to), toS(from).replace(from, to));
}
// issue 1480
String exampleXd
= String.valueOf(new char[] {'e', 'x', 'a', 'm', 'p', 'l', 'e', ' ', 'x', 'd'});
assertEquals("example xd", exampleXd.replace('\r', ' ').replace('\n', ' '));
String dogFood = String.valueOf(new char[] {'d', 'o', 'g', '\u0120', 'f', 'o', 'o', 'd'});
assertEquals("dog food", dogFood.replace('\u0120', ' '));
String testStr = String.valueOf(new char[] {'\u1111', 'B', '\u1111', 'B', '\u1111', 'B'});
assertEquals("ABABAB", testStr.replace('\u1111', 'A'));
// assertEquals("foobar", hideFromCompiler("bazbar").replace("baz", "foo"));
// assertEquals("$0bar", hideFromCompiler("foobar").replace("foo", "$0"));
// assertEquals("+1", hideFromCompiler("*[)1").replace("*[)", "+"));
}
public void testReplaceAll() {
String regex = hideFromCompiler("*[").replaceAll("([/\\\\\\.\\*\\+\\?\\|\\(\\)\\[\\]\\{\\}])",
"\\\\$1");
assertEquals("\\*\\[", regex);
assertEquals("+1", hideFromCompiler("*[1").replaceAll(regex, "+"));
String x1 = String.valueOf(new char[] {'x', 'x', 'x', 'a', 'b', 'c', 'x', 'x', 'd', 'e', 'x',
'f'});
assertEquals("abcdef", x1.replaceAll("x*", ""));
String x2 = String.valueOf(new char[] {'1', 'a', 'b', 'c', '1', '2', '3', 'd', 'e', '1', '2',
'3', '4', 'f'});
assertEquals("1\\1abc123\\123de1234\\1234f", x2.replaceAll(
"([1234]+)", "$1\\\\$1"));
String x3 = String.valueOf(new char[] {'x', ' ', ' ', 'x'});
assertEquals("\n \n", x3.replaceAll("x", "\n"));
String x4 = String.valueOf(new char[] {'\n', ' ', ' ', '\n'});
assertEquals("x x", x4.replaceAll("\\\n", "x"));
String x5 = String.valueOf(new char[] {'x'});
assertEquals("x\"\\", x5.replaceAll("x", "\\x\\\"\\\\"));
assertEquals("$$x$", x5.replaceAll("(x)", "\\$\\$$1\\$"));
}
public void testSplit() {
compareList("fullSplit", new String[] {"abc", "", "", "de", "f"},
"abcxxxdexfxx".split("x"));
compareList("emptyRegexSplit", new String[] {
"", "a", "b", "c", "x", "x", "d", "e", "x", "f", "x"},
"abcxxdexfx".split(""));
compareList("2:", "boo:and:foo".split(":", 2), new String[] {
"boo", "and:foo"});
compareList("5:", "boo:and:foo".split(":", 5), new String[] {
"boo", "and", "foo"});
compareList("-2:", "boo:and:foo".split(":", -2), new String[] {
"boo", "and", "foo"});
compareList("5o", "boo:and:foo".split("o", 5), new String[] {
"b", "", ":and:f", "", ""});
compareList("-2o", "boo:and:foo".split("o", -2), new String[] {
"b", "", ":and:f", "", ""});
compareList("0o", "boo:and:foo".split("o", 0), new String[] {
"b", "", ":and:f"});
compareList("0:", "boo:and:foo".split(":", 0), new String[] {
"boo", "and", "foo"});
}
public void testStartsWith() {
String haystack = "abcdefghi";
assertTrue(haystack.startsWith("abc"));
assertTrue(haystack.startsWith("bc", 1));
assertTrue(haystack.startsWith(haystack));
assertFalse(haystack.startsWith(haystack + "j"));
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testSubstring() {
String haystack = "abcdefghi";
assertEquals("cd", haystack.substring(2, 4));
assertEquals("bc", "abcdef".substring(1, 3));
assertEquals("bcdef", "abcdef".substring(1));
}
public void testToCharArray() {
char[] a1 = "abc".toCharArray();
char[] a2 = new char[] {'a', 'b', 'c'};
for (int i = 0; i < a1.length; i++) {
assertEquals(a1[i], a2[i]);
}
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testTrim() {
trimRightAssertEquals("abc", " \t abc \n ");
trimRightAssertEquals("abc", "abc".trim());
trimRightAssertSame("abc", "abc");
String s = '\u0023' + "hi";
trimRightAssertSame(s, s);
trimRightAssertEquals("abc", " abc".trim());
trimRightAssertEquals("abc", "abc ".trim());
trimRightAssertEquals("", "".trim());
trimRightAssertEquals("", " \t ".trim());
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testUpperCase() {
assertEquals("abc", "AbC".toLowerCase());
assertEquals("abc", "abc".toLowerCase());
assertEquals("", "".toLowerCase());
}
/*
* TODO: needs rewriting to avoid compiler optimizations.
*/
public void testValueOf() {
assertTrue(String.valueOf(C.FLOAT_VALUE).startsWith(C.FLOAT_STRING));
assertEquals(C.INT_STRING, String.valueOf(C.INT_VALUE));
assertEquals(C.LONG_STRING, String.valueOf(C.LONG_VALUE));
assertTrue(String.valueOf(C.DOUBLE_VALUE).startsWith(C.DOUBLE_STRING));
assertEquals(C.CHAR_STRING, String.valueOf(C.CHAR_VALUE));
assertEquals(C.CHAR_ARRAY_STRING, String.valueOf(C.CHAR_ARRAY_VALUE));
assertEquals(C.CHAR_ARRAY_STRING_SUB, String.valueOf(C.CHAR_ARRAY_VALUE, 1,
4));
assertEquals(C.FALSE_STRING, String.valueOf(C.FALSE_VALUE));
assertEquals(C.TRUE_STRING, String.valueOf(C.TRUE_VALUE));
}
/**
* Helper method for testTrim to avoid compiler optimizations.
*
* TODO: insufficient, compiler now inlines.
*/
public void trimRightAssertEquals(String left, String right) {
assertEquals(left, right.trim());
}
/**
* Helper method for testTrim to avoid compiler optimizations.
*
* TODO: insufficient, compiler now inlines.
*/
public void trimRightAssertSame(String left, String right) {
assertSame(left, right.trim());
}
private void compareList(String category, String[] desired, String[] got) {
assertEquals(category + " length", desired.length, got.length);
for (int i = 0; i < desired.length; i++) {
assertEquals(category + " " + i, desired[i], got[i]);
}
}
private String returnNull() {
return null;
}
private String toS(char from) {
return Character.toString(from);
}
}