1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package test.java.lang.String; 25 26 /* @test 27 * @bug 8058779 8054307 28 * @library /test/lib 29 * @build jdk.test.lib.RandomFactory 30 * @run testng LiteralReplace 31 * @summary Basic tests of String.replace(CharSequence, CharSequence) 32 * @key randomness 33 */ 34 35 import java.util.ArrayList; 36 import java.util.Arrays; 37 import java.util.Iterator; 38 import java.util.regex.Matcher; 39 import java.util.regex.Pattern; 40 import java.util.Random; 41 42 import org.testng.annotations.Test; 43 import org.testng.annotations.DataProvider; 44 import static org.testng.Assert.fail; 45 46 public class LiteralReplace { 47 48 @Test(dataProvider="sourceTargetReplacementExpected") testExpected(String source, String target, String replacement, String expected)49 public void testExpected(String source, String target, 50 String replacement, String expected) 51 { 52 String canonical = canonicalReplace(source, target, replacement); 53 if (!canonical.equals(expected)) { 54 fail("Canonical: " + canonical + " != " + expected); 55 } 56 test0(source, target, replacement, expected); 57 } 58 59 @Test(dataProvider="sourceTargetReplacement") testCanonical(String source, String target, String replacement)60 public void testCanonical(String source, String target, 61 String replacement) 62 { 63 String canonical = canonicalReplace(source, target, replacement); 64 test0(source, target, replacement, canonical); 65 } 66 test0(String source, String target, String replacement, String expected)67 private void test0(String source, String target, String replacement, 68 String expected) 69 { 70 String result = source.replace(target, replacement); 71 if (!result.equals(expected)) { 72 fail(result + " != " + expected); 73 } 74 } 75 76 @Test(dataProvider="sourceTargetReplacementWithNull", 77 expectedExceptions = {NullPointerException.class}) testNPE(String source, String target, String replacement)78 public void testNPE(String source, String target, String replacement) { 79 source.replace(target, replacement); 80 } 81 82 83 @DataProvider sourceTargetReplacementExpected()84 public static Object[][] sourceTargetReplacementExpected() { 85 return new Object[][] { 86 {"aaa", "aa", "b", "ba"}, 87 {"abcdefgh", "def", "DEF", "abcDEFgh"}, 88 {"abcdefgh", "123", "DEF", "abcdefgh"}, 89 {"abcdefgh", "abcdefghi", "DEF", "abcdefgh"}, 90 {"abcdefghabc", "abc", "DEF", "DEFdefghDEF"}, 91 {"abcdefghdef", "def", "", "abcgh"}, 92 {"abcdefgh", "", "_", "_a_b_c_d_e_f_g_h_"}, 93 {"", "", "", ""}, 94 {"", "a", "b", ""}, 95 {"", "", "abc", "abc"}, 96 {"abcdefgh", "abcdefgh", "abcdefgh", "abcdefgh"}, 97 {"abcdefgh", "abcdefgh", "abcdefghi", "abcdefghi"}, 98 {"abcdefgh", "abcdefgh", "", ""}, 99 {"abcdabcd", "abcd", "", ""}, 100 {"aaaaaaaaa", "aa", "_X_", "_X__X__X__X_a"}, 101 {"aaaaaaaaa", "aa", "aaa", "aaaaaaaaaaaaa"}, 102 {"aaaaaaaaa", "aa", "aa", "aaaaaaaaa"}, 103 {"a.c.e.g.", ".", "-", "a-c-e-g-"}, 104 {"abcdefgh", "[a-h]", "X", "abcdefgh"}, 105 {"aa+", "a+", "", "a"}, 106 {"^abc$", "abc", "x", "^x$"}, 107 108 // more with non-latin1 characters 109 {"\u4e00\u4e00\u4e00", 110 "\u4e00\u4e00", 111 "\u4e01", 112 "\u4e01\u4e00"}, 113 114 {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08", 115 "\u4e03\u4e04\u4e05", 116 "\u4e10\u4e11\u4e12", 117 "\u4e00\u4e01\u4e02\u4e10\u4e11\u4e12\u4e06\u4e07\u4e08"}, 118 119 {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08", 120 "ABC", 121 "\u4e10\u4e11\u4e12", 122 "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"}, 123 124 {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08", 125 "\u4e02\u4e03", 126 "\u4e12\u4e13", 127 "\u4e00\u4e01\u4e12\u4e13\u4e04\u4e12\u4e13\u4e07\u4e08"}, 128 129 {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08", 130 "\u4e02\u4e03", 131 "ab", 132 "\u4e00\u4e01ab\u4e04ab\u4e07\u4e08"}, 133 134 {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07", 135 "", 136 "_", 137 "_\u4e00_\u4e01_\u4e02_\u4e03_\u4e04_\u4e05_\u4e06_\u4e07_"}, 138 {"^\u4e00\u4e01\u4e02$", 139 "\u4e00\u4e01\u4e02", 140 "\u4e03", 141 "^\u4e03$"}, 142 143 {"", "\u4e00", "\u4e01", ""}, 144 {"", "", "\u4e00\u4e01\u4e02", "\u4e00\u4e01\u4e02"}, 145 146 {"^\u4e00\u4e01\u4e02$", 147 "\u4e00\u4e01\u4e02", 148 "X", 149 "^X$"}, 150 151 {"abcdefgh", 152 "def", 153 "\u4e01", 154 "abc\u4e01gh"}, 155 156 {"abcdefgh", 157 "def", 158 "\u4e01\u4e02", 159 "abc\u4e01\u4e02gh"}, 160 161 {"abcdefabcgh", 162 "abc", 163 "\u4e01\u4e02", 164 "\u4e01\u4e02def\u4e01\u4e02gh"}, 165 166 {"abcdefabcghabc", 167 "abc", 168 "\u4e01\u4e02", 169 "\u4e01\u4e02def\u4e01\u4e02gh\u4e01\u4e02"}, 170 171 {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", 172 "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", 173 "abcd", 174 "abcd"}, 175 176 {"\u4e00\u4e01", 177 "\u4e00\u4e01", 178 "abcdefg", 179 "abcdefg"}, 180 181 {"\u4e00\u4e01xyz", 182 "\u4e00\u4e01", 183 "abcdefg", 184 "abcdefgxyz"}, 185 186 {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00", 187 "\u4e00\u4e00", 188 "\u4e00\u4e00\u4e00", 189 "\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00"}, 190 191 {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00", 192 "\u4e00\u4e00\u4e00", 193 "\u4e00\u4e00", 194 "\u4e00\u4e00\u4e00\u4e00"}, 195 196 {"\u4e00.\u4e01.\u4e02.\u4e03.\u4e04.", 197 ".", 198 "-", 199 "\u4e00-\u4e01-\u4e02-\u4e03-\u4e04-"}, 200 201 {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00", 202 "\u4e00", 203 "", 204 ""}, 205 206 {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", 207 "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", 208 "", 209 ""}, 210 }; 211 } 212 213 @DataProvider sourceTargetReplacement()214 public static Iterator<Object[]> sourceTargetReplacement() { 215 ArrayList<Object[]> list = new ArrayList<>(); 216 for (int maxSrcLen = 1; maxSrcLen <= (1 << 10); maxSrcLen <<= 1) { 217 for (int maxTrgLen = 1; maxTrgLen <= (1 << 10); maxTrgLen <<= 1) { 218 for (int maxPrlLen = 1; maxPrlLen <= (1 << 10); maxPrlLen <<= 1) { 219 list.add(makeArray(makeRandomString(maxSrcLen), 220 makeRandomString(maxTrgLen), 221 makeRandomString(maxPrlLen))); 222 223 String source = makeRandomString(maxSrcLen); 224 list.add(makeArray(source, 225 mekeRandomSubstring(source, maxTrgLen), 226 makeRandomString(maxPrlLen))); 227 } 228 } 229 } 230 return list.iterator(); 231 } 232 233 @DataProvider sourceTargetReplacementWithNull()234 public static Iterator<Object[]> sourceTargetReplacementWithNull() { 235 ArrayList<Object[]> list = new ArrayList<>(); 236 Object[] arr = {null, "", "a", "b", "string", "str", "ababstrstr"}; 237 for (int i = 0; i < arr.length; ++i) { 238 for (int j = 0; j < arr.length; ++j) { 239 for (int k = 0; k < arr.length; ++k) { 240 if (arr[i] != null && (arr[j] == null || arr[k] == null)) { 241 list.add(makeArray(arr[i], arr[j], arr[k])); 242 } 243 } 244 } 245 } 246 return list.iterator(); 247 } 248 249 // utilities 250 251 /** 252 * How the String.replace(CharSequence, CharSequence) used to be implemented 253 */ canonicalReplace(String source, String target, String replacement)254 private static String canonicalReplace(String source, String target, String replacement) { 255 return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( 256 source).replaceAll(Matcher.quoteReplacement(replacement.toString())); 257 } 258 259 private static final Random random = new Random(); 260 261 private static final char[] CHARS = ("qwertyuiop[]12345678" + 262 "90-=\\`asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+|QWERTYUIOP{" + 263 "}ASDFGHJKL:\"ZXCVBNM<>?\n\r\t\u0444\u044B\u0432\u0430").toCharArray(); 264 makeRandomString(int maxLen)265 private static String makeRandomString(int maxLen) { 266 int len = random.nextInt(maxLen); 267 char[] buf = new char[len]; 268 for (int i = 0; i < len; ++i) { 269 buf[i] = CHARS[random.nextInt(CHARS.length)]; 270 } 271 return new String(buf); 272 } 273 mekeRandomSubstring(String source, int maxLen)274 private static String mekeRandomSubstring(String source, int maxLen) { 275 if (source.isEmpty()) { 276 return source; 277 } 278 int pos = random.nextInt(source.length()); 279 int len = Integer.min(source.length() - pos, 280 random.nextInt(maxLen)); 281 return source.substring(pos, pos + len); 282 } 283 makeArray(Object... array)284 private static Object[] makeArray(Object... array) { 285 return array; 286 } 287 } 288