1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.text.cts; 18 19 import dalvik.annotation.TestLevel; 20 import dalvik.annotation.TestTargetClass; 21 import dalvik.annotation.TestTargetNew; 22 import dalvik.annotation.ToBeFixed; 23 24 import android.content.res.ColorStateList; 25 import android.graphics.Canvas; 26 import android.graphics.Color; 27 import android.graphics.Paint; 28 import android.graphics.Typeface; 29 import android.graphics.Paint.FontMetricsInt; 30 import android.os.Parcel; 31 import android.os.Parcelable; 32 import android.test.AndroidTestCase; 33 import android.text.GetChars; 34 import android.text.Spannable; 35 import android.text.SpannableString; 36 import android.text.SpannableStringBuilder; 37 import android.text.Spanned; 38 import android.text.SpannedString; 39 import android.text.TextPaint; 40 import android.text.TextUtils; 41 import android.text.TextUtils.EllipsizeCallback; 42 import android.text.TextUtils.TruncateAt; 43 import android.text.style.BackgroundColorSpan; 44 import android.text.style.ReplacementSpan; 45 import android.text.style.TextAppearanceSpan; 46 import android.text.style.URLSpan; 47 import android.util.StringBuilderPrinter; 48 49 import java.util.ArrayList; 50 import java.util.regex.Pattern; 51 52 /** 53 * Test {@link TextUtils}. 54 */ 55 @TestTargetClass(TextUtils.class) 56 public class TextUtilsTest extends AndroidTestCase { 57 private static String mEllipsis; 58 private int mStart; 59 private int mEnd; 60 61 @Override setUp()62 protected void setUp() throws Exception { 63 super.setUp(); 64 mEllipsis = getEllipsis(); 65 resetRange(); 66 } 67 resetRange()68 private void resetRange() { 69 mStart = -1; 70 mEnd = -1; 71 } 72 73 /** 74 * Get the ellipsis from system. 75 * @return the string of ellipsis. 76 */ getEllipsis()77 private String getEllipsis() { 78 String text = "xxxxx"; 79 TextPaint p = new TextPaint(); 80 float width = p.measureText(text.substring(1)); 81 String re = TextUtils.ellipsize(text, p, width, TruncateAt.START).toString(); 82 return re.substring(0, re.indexOf("x")); 83 } 84 85 @TestTargetNew( 86 level = TestLevel.COMPLETE, 87 method = "commaEllipsize", 88 args = {CharSequence.class, TextPaint.class, float.class, String.class, String.class} 89 ) 90 @ToBeFixed(bug = "1688347 ", explanation = "The javadoc for commaEllipsize() " + 91 "does not discuss any of the corner cases") testCommaEllipsize()92 public void testCommaEllipsize() { 93 TextPaint p = new TextPaint(); 94 String text = "long, string, to, truncate"; 95 96 float textWidth = p.measureText("long, 3 plus"); 97 // avail is shorter than text width for only one item plus the appropriate ellipsis. 98 // issue 1688347, the expected result for this case does not be described 99 // in the javadoc of commaEllipsize(). 100 assertEquals("", 101 TextUtils.commaEllipsize(text, p, textWidth - 1, "plus 1", "%d plus").toString()); 102 // avail is long enough for only one item plus the appropriate ellipsis. 103 assertEquals("long, 3 plus", 104 TextUtils.commaEllipsize(text, p, textWidth, "plus 1", "%d plus").toString()); 105 106 // avail is long enough for two item plus the appropriate ellipsis. 107 textWidth = p.measureText("long, string, 2 more"); 108 assertEquals("long, string, 2 more", 109 TextUtils.commaEllipsize(text, p, textWidth, "more 1", "%d more").toString()); 110 111 // avail is long enough for the whole sentence. 112 textWidth = p.measureText("long, string, to, truncate"); 113 assertEquals("long, string, to, truncate", 114 TextUtils.commaEllipsize(text, p, textWidth, "more 1", "%d more").toString()); 115 116 // the sentence is extended, avail is NOT long enough for the whole sentence. 117 assertEquals("long, string, to, more 1", TextUtils.commaEllipsize( 118 text + "-extended", p, textWidth, "more 1", "%d more").toString()); 119 120 // exceptional value 121 assertEquals("", TextUtils.commaEllipsize(text, p, -1f, "plus 1", "%d plus").toString()); 122 123 assertEquals(text, TextUtils.commaEllipsize( 124 text, p, Float.MAX_VALUE, "more 1", "%d more").toString()); 125 126 assertEquals("long, string, to, null", TextUtils.commaEllipsize( 127 text + "-extended", p, textWidth, null, "%d more").toString()); 128 129 try { 130 TextUtils.commaEllipsize(null, p, textWidth, "plus 1", "%d plus"); 131 fail("Should throw NullPointerException"); 132 } catch (NullPointerException e) { 133 // issue 1688347, not clear what is supposed to happen if the text to truncate is null. 134 } 135 136 try { 137 TextUtils.commaEllipsize(text, null, textWidth, "plus 1", "%d plus"); 138 fail("Should throw NullPointerException"); 139 } catch (NullPointerException e) { 140 // issue 1688347, not clear what is supposed to happen if TextPaint is null. 141 } 142 143 try { 144 TextUtils.commaEllipsize(text, p, textWidth, "plus 1", null); 145 fail("Should throw NullPointerException"); 146 } catch (NullPointerException e) { 147 // issue 1688347, not clear what is supposed to happen 148 // if the string for "%d more" in the current locale is null. 149 } 150 } 151 152 @TestTargetNew( 153 level = TestLevel.COMPLETE, 154 method = "concat", 155 args = {CharSequence[].class} 156 ) 157 @ToBeFixed(bug = "1695243", explanation = "the javadoc for concat() is incomplete." + 158 "1. doesn't explain @param and @return" + 159 "2. doesn't describe the expected result when parameter is empty" + 160 "3. doesn't discuss the case that parameter is expectional.") testConcat()161 public void testConcat() { 162 // issue 1695243 163 // the javadoc for concat() doesn't describe the expected result when parameter is empty. 164 assertEquals("", TextUtils.concat().toString()); 165 166 assertEquals("first", TextUtils.concat("first").toString()); 167 168 assertEquals("first, second", TextUtils.concat("first", ", ", "second").toString()); 169 170 SpannableString string1 = new SpannableString("first"); 171 SpannableString string2 = new SpannableString("second"); 172 final String url = "www.test_url.com"; 173 URLSpan urlSpan = new URLSpan(url); 174 string1.setSpan(urlSpan, 0, string1.length() - 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE); 175 BackgroundColorSpan bgColorSpan = new BackgroundColorSpan(Color.GREEN); 176 string2.setSpan(bgColorSpan, 0, string2.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 177 178 final String comma = ", "; 179 Spanned strResult = (Spanned) TextUtils.concat(string1, comma, string2); 180 assertEquals(string1.toString() + comma + string2.toString(), strResult.toString()); 181 Object spans[] = strResult.getSpans(0, strResult.length(), Object.class); 182 assertEquals(2, spans.length); 183 assertTrue(spans[0] instanceof URLSpan); 184 assertEquals(url, ((URLSpan) spans[0]).getURL()); 185 assertTrue(spans[1] instanceof BackgroundColorSpan); 186 assertEquals(Color.GREEN, ((BackgroundColorSpan) spans[1]).getBackgroundColor()); 187 assertEquals(0, strResult.getSpanStart(urlSpan)); 188 assertEquals(string1.length() - 1, strResult.getSpanEnd(urlSpan)); 189 assertEquals(string1.length() + comma.length(), strResult.getSpanStart(bgColorSpan)); 190 assertEquals(strResult.length() - 1, strResult.getSpanEnd(bgColorSpan)); 191 192 assertEquals(string1, TextUtils.concat(string1)); 193 194 // issue 1695243, the javadoc for concat() doesn't describe 195 // the expected result when parameters are null. 196 assertEquals(null, TextUtils.concat((CharSequence) null)); 197 198 try { 199 TextUtils.concat((CharSequence[]) null); 200 fail("Should throw NullPointerException"); 201 } catch (NullPointerException e) { 202 // expected 203 } 204 } 205 206 @TestTargetNew( 207 level = TestLevel.COMPLETE, 208 method = "copySpansFrom", 209 args = {Spanned.class, int.class, int.class, Class.class, Spannable.class, int.class} 210 ) 211 @ToBeFixed(bug = "1688347", explanation = "the javadoc for copySpansFrom() does not exist.") testCopySpansFrom()212 public void testCopySpansFrom() { 213 Object[] spans; 214 String text = "content"; 215 SpannableString source1 = new SpannableString(text); 216 int midPos = source1.length() / 2; 217 final String url = "www.test_url.com"; 218 URLSpan urlSpan = new URLSpan(url); 219 source1.setSpan(urlSpan, 0, midPos, Spanned.SPAN_INCLUSIVE_INCLUSIVE); 220 BackgroundColorSpan bgColorSpan = new BackgroundColorSpan(Color.GREEN); 221 source1.setSpan(bgColorSpan, midPos - 1, 222 source1.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 223 224 // normal test 225 SpannableString dest1 = new SpannableString(text); 226 TextUtils.copySpansFrom(source1, 0, source1.length(), Object.class, dest1, 0); 227 spans = dest1.getSpans(0, dest1.length(), Object.class); 228 assertEquals(2, spans.length); 229 assertTrue(spans[0] instanceof URLSpan); 230 assertEquals(url, ((URLSpan) spans[0]).getURL()); 231 assertTrue(spans[1] instanceof BackgroundColorSpan); 232 assertEquals(Color.GREEN, ((BackgroundColorSpan) spans[1]).getBackgroundColor()); 233 assertEquals(0, dest1.getSpanStart(urlSpan)); 234 assertEquals(midPos, dest1.getSpanEnd(urlSpan)); 235 assertEquals(Spanned.SPAN_INCLUSIVE_INCLUSIVE, dest1.getSpanFlags(urlSpan)); 236 assertEquals(midPos - 1, dest1.getSpanStart(bgColorSpan)); 237 assertEquals(source1.length() - 1, dest1.getSpanEnd(bgColorSpan)); 238 assertEquals(Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, dest1.getSpanFlags(bgColorSpan)); 239 240 SpannableString source2 = new SpannableString(text); 241 source2.setSpan(urlSpan, 0, source2.length() - 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE); 242 SpannableString dest2 = new SpannableString(text); 243 TextUtils.copySpansFrom(source2, 0, source2.length(), Object.class, dest2, 0); 244 spans = dest2.getSpans(0, dest2.length(), Object.class); 245 assertEquals(1, spans.length); 246 assertTrue(spans[0] instanceof URLSpan); 247 assertEquals(url, ((URLSpan) spans[0]).getURL()); 248 assertEquals(0, dest2.getSpanStart(urlSpan)); 249 assertEquals(source2.length() - 1, dest2.getSpanEnd(urlSpan)); 250 assertEquals(Spanned.SPAN_EXCLUSIVE_INCLUSIVE, dest2.getSpanFlags(urlSpan)); 251 252 SpannableString dest3 = new SpannableString(text); 253 TextUtils.copySpansFrom(source2, 0, source2.length(), BackgroundColorSpan.class, dest3, 0); 254 spans = dest3.getSpans(0, dest3.length(), Object.class); 255 assertEquals(0, spans.length); 256 TextUtils.copySpansFrom(source2, 0, source2.length(), URLSpan.class, dest3, 0); 257 spans = dest3.getSpans(0, dest3.length(), Object.class); 258 assertEquals(1, spans.length); 259 260 SpannableString dest4 = new SpannableString("short"); 261 try { 262 TextUtils.copySpansFrom(source2, 0, source2.length(), Object.class, dest4, 0); 263 fail("Should throw IndexOutOfBoundsException"); 264 } catch (IndexOutOfBoundsException e) { 265 // expected 266 } 267 TextUtils.copySpansFrom(source2, 0, dest4.length(), Object.class, dest4, 0); 268 spans = dest4.getSpans(0, dest4.length(), Object.class); 269 assertEquals(1, spans.length); 270 assertEquals(0, dest4.getSpanStart(spans[0])); 271 // issue 1688347, not clear the expected result when 'start ~ end' only 272 // covered a part of the span. 273 assertEquals(dest4.length(), dest4.getSpanEnd(spans[0])); 274 275 SpannableString dest5 = new SpannableString("longer content"); 276 TextUtils.copySpansFrom(source2, 0, source2.length(), Object.class, dest5, 0); 277 spans = dest5.getSpans(0, 1, Object.class); 278 assertEquals(1, spans.length); 279 280 dest5 = new SpannableString("longer content"); 281 TextUtils.copySpansFrom(source2, 0, source2.length(), Object.class, dest5, 2); 282 spans = dest5.getSpans(0, 1, Object.class); 283 assertEquals(0, spans.length); 284 spans = dest5.getSpans(2, dest5.length(), Object.class); 285 assertEquals(1, spans.length); 286 try { 287 TextUtils.copySpansFrom(source2, 0, source2.length(), 288 Object.class, dest5, dest5.length() - source2.length() + 2); 289 fail("Should throw IndexOutOfBoundsException"); 290 } catch (IndexOutOfBoundsException e) { 291 // expected 292 } 293 294 // issue 1688347, no javadoc about the expected behavior of the exceptional argument. 295 // exceptional source start 296 SpannableString dest6 = new SpannableString("exceptional test"); 297 TextUtils.copySpansFrom(source2, -1, source2.length(), Object.class, dest6, 0); 298 spans = dest6.getSpans(0, dest6.length(), Object.class); 299 assertEquals(1, spans.length); 300 dest6 = new SpannableString("exceptional test"); 301 TextUtils.copySpansFrom(source2, Integer.MAX_VALUE, source2.length() - 1, 302 Object.class, dest6, 0); 303 spans = dest6.getSpans(0, dest6.length(), Object.class); 304 assertEquals(0, spans.length); 305 306 // exceptional source end 307 dest6 = new SpannableString("exceptional test"); 308 TextUtils.copySpansFrom(source2, 0, -1, Object.class, dest6, 0); 309 spans = dest6.getSpans(0, dest6.length(), Object.class); 310 assertEquals(0, spans.length); 311 TextUtils.copySpansFrom(source2, 0, Integer.MAX_VALUE, Object.class, dest6, 0); 312 spans = dest6.getSpans(0, dest6.length(), Object.class); 313 assertEquals(1, spans.length); 314 315 // exceptional class kind 316 dest6 = new SpannableString("exceptional test"); 317 TextUtils.copySpansFrom(source2, 0, source2.length(), null, dest6, 0); 318 spans = dest6.getSpans(0, dest6.length(), Object.class); 319 assertEquals(1, spans.length); 320 321 // exceptional destination offset 322 dest6 = new SpannableString("exceptional test"); 323 try { 324 TextUtils.copySpansFrom(source2, 0, source2.length(), Object.class, dest6, -1); 325 fail("Should throw IndexOutOfBoundsException"); 326 } catch (IndexOutOfBoundsException e) { 327 // expect 328 } 329 try { 330 TextUtils.copySpansFrom(source2, 0, source2.length(), 331 Object.class, dest6, Integer.MAX_VALUE); 332 fail("Should throw IndexOutOfBoundsException"); 333 } catch (IndexOutOfBoundsException e) { 334 // expect 335 } 336 337 // exceptional source 338 try { 339 TextUtils.copySpansFrom(null, 0, source2.length(), Object.class, dest6, 0); 340 fail("Should throw NullPointerException"); 341 } catch (NullPointerException e) { 342 // expect 343 } 344 345 // exceptional destination 346 try { 347 TextUtils.copySpansFrom(source2, 0, source2.length(), Object.class, null, 0); 348 fail("Should throw NullPointerException"); 349 } catch (NullPointerException e) { 350 // expect 351 } 352 } 353 354 @TestTargetNew( 355 level = TestLevel.COMPLETE, 356 method = "ellipsize", 357 args = {CharSequence.class, TextPaint.class, float.class, TruncateAt.class} 358 ) 359 @ToBeFixed(bug = "1688347", explanation = "" + 360 "1. the javadoc for ellipsize() is incomplete." + 361 " - doesn't explain @param and @return" + 362 " - doesn't describe expected behavior if user pass an exceptional argument." + 363 "2. ellipsize() is not defined for TruncateAt.MARQUEE. " + 364 " In the code it looks like this does the same as MIDDLE. " + 365 " In other methods, MARQUEE is equivalent to END, except for the first line.") testEllipsize()366 public void testEllipsize() { 367 TextPaint p = new TextPaint(); 368 369 // turn off kerning. with kerning enabled, different methods of measuring the same text 370 // produce different results. 371 p.setFlags(p.getFlags() & ~p.DEV_KERN_TEXT_FLAG); 372 373 CharSequence text = "long string to truncate"; 374 375 float textWidth = p.measureText(mEllipsis + "uncate"); 376 assertEquals(mEllipsis + "uncate", 377 TextUtils.ellipsize(text, p, textWidth, TruncateAt.START).toString()); 378 379 textWidth = p.measureText("long str" + mEllipsis); 380 assertEquals("long str" + mEllipsis, 381 TextUtils.ellipsize(text, p, textWidth, TruncateAt.END).toString()); 382 383 textWidth = p.measureText("long" + mEllipsis + "ate"); 384 assertEquals("long" + mEllipsis + "ate", 385 TextUtils.ellipsize(text, p, textWidth, TruncateAt.MIDDLE).toString()); 386 387 // issue 1688347, ellipsize() is not defined for TruncateAt.MARQUEE. 388 // In the code it looks like this does the same as MIDDLE. 389 // In other methods, MARQUEE is equivalent to END, except for the first line. 390 assertEquals("long" + mEllipsis + "ate", 391 TextUtils.ellipsize(text, p, textWidth, TruncateAt.MARQUEE).toString()); 392 393 textWidth = p.measureText(mEllipsis); 394 assertEquals(mEllipsis, TextUtils.ellipsize(text, p, textWidth, TruncateAt.END).toString()); 395 assertEquals("", TextUtils.ellipsize(text, p, textWidth - 1, TruncateAt.END).toString()); 396 assertEquals("", TextUtils.ellipsize(text, p, -1f, TruncateAt.END).toString()); 397 assertEquals(text, 398 TextUtils.ellipsize(text, p, Float.MAX_VALUE, TruncateAt.END).toString()); 399 400 assertEquals(mEllipsis, 401 TextUtils.ellipsize(text, p, textWidth, TruncateAt.START).toString()); 402 assertEquals(mEllipsis, 403 TextUtils.ellipsize(text, p, textWidth, TruncateAt.MIDDLE).toString()); 404 405 try { 406 TextUtils.ellipsize(text, null, textWidth, TruncateAt.MIDDLE); 407 fail("Should throw NullPointerException"); 408 } catch (NullPointerException e) { 409 // expected 410 } 411 412 try { 413 TextUtils.ellipsize(null, p, textWidth, TruncateAt.MIDDLE); 414 fail("Should throw NullPointerException"); 415 } catch (NullPointerException e) { 416 // expected 417 } 418 } 419 420 @TestTargetNew( 421 level = TestLevel.COMPLETE, 422 method = "ellipsize", 423 args = {CharSequence.class, TextPaint.class, float.class, TruncateAt.class, 424 boolean.class, EllipsizeCallback.class} 425 ) 426 @ToBeFixed(bug = "1688347", explanation = "" + 427 "1. the javadoc for ellipsize() is incomplete." + 428 " - doesn't explain @param and @return" + 429 " - doesn't describe expected behavior if user pass an exceptional argument." + 430 "2. ellipsize() is not defined for TruncateAt.MARQUEE. " + 431 " In the code it looks like this does the same as MIDDLE. " + 432 " In other methods, MARQUEE is equivalent to END, except for the first line.") testEllipsizeCallback()433 public void testEllipsizeCallback() { 434 TextPaint p = new TextPaint(); 435 436 // turn off kerning. with kerning enabled, different methods of measuring the same text 437 // produce different results. 438 p.setFlags(p.getFlags() & ~p.DEV_KERN_TEXT_FLAG); 439 440 TextUtils.EllipsizeCallback callback = new TextUtils.EllipsizeCallback() { 441 public void ellipsized(final int start, final int end) { 442 mStart = start; 443 mEnd = end; 444 } 445 }; 446 447 String text = "long string to truncate"; 448 449 // TruncateAt.START, does not specify preserveLength 450 resetRange(); 451 float textWidth = p.measureText(mEllipsis + "uncate"); 452 assertEquals(mEllipsis + "uncate", 453 TextUtils.ellipsize(text, p, textWidth, TruncateAt.START, false, 454 callback).toString()); 455 assertEquals(0, mStart); 456 assertEquals(text.length() - "uncate".length(), mEnd); 457 458 // TruncateAt.START, specify preserveLength 459 resetRange(); 460 int ellipsisNum = text.length() - "uncate".length(); 461 assertEquals(getBlankString(true, ellipsisNum) + "uncate", 462 TextUtils.ellipsize(text, p, textWidth, TruncateAt.START, true, 463 callback).toString()); 464 assertEquals(0, mStart); 465 assertEquals(text.length() - "uncate".length(), mEnd); 466 467 // TruncateAt.END, specify preserveLength 468 resetRange(); 469 textWidth = p.measureText("long str" + mEllipsis); 470 ellipsisNum = text.length() - "long str".length(); 471 assertEquals("long str" + getBlankString(true, ellipsisNum), 472 TextUtils.ellipsize(text, p, textWidth, TruncateAt.END, true, callback).toString()); 473 assertEquals("long str".length(), mStart); 474 assertEquals(text.length(), mEnd); 475 476 // TruncateAt.MIDDLE, specify preserveLength 477 resetRange(); 478 textWidth = p.measureText("long" + mEllipsis + "ate"); 479 ellipsisNum = text.length() - "long".length() - "ate".length(); 480 assertEquals("long" + getBlankString(true, ellipsisNum) + "ate", 481 TextUtils.ellipsize(text, p, textWidth, TruncateAt.MIDDLE, true, 482 callback).toString()); 483 assertEquals("long".length(), mStart); 484 assertEquals(text.length() - "ate".length(), mEnd); 485 486 // TruncateAt.MIDDLE, specify preserveLength, but does not specify callback. 487 resetRange(); 488 assertEquals("long" + getBlankString(true, ellipsisNum) + "ate", 489 TextUtils.ellipsize(text, p, textWidth, TruncateAt.MIDDLE, true, 490 null).toString()); 491 assertEquals(-1, mStart); 492 assertEquals(-1, mEnd); 493 494 // TruncateAt.MARQUEE, specify preserveLength 495 // issue 1688347, ellipsize() is not defined for TruncateAt.MARQUEE. 496 // In the code it looks like this does the same as MIDDLE. 497 // In other methods, MARQUEE is equivalent to END, except for the first line. 498 resetRange(); 499 textWidth = p.measureText("long" + mEllipsis + "ate"); 500 ellipsisNum = text.length() - "long".length() - "ate".length(); 501 assertEquals("long" + getBlankString(true, ellipsisNum) + "ate", 502 TextUtils.ellipsize(text, p, textWidth, TruncateAt.MARQUEE, true, 503 callback).toString()); 504 assertEquals("long".length(), mStart); 505 assertEquals(text.length() - "ate".length(), mEnd); 506 507 // avail is not long enough for ELLIPSIS, and preserveLength is specified. 508 resetRange(); 509 textWidth = p.measureText(mEllipsis); 510 assertEquals(getBlankString(false, text.length()), 511 TextUtils.ellipsize(text, p, textWidth - 1f, TruncateAt.END, true, 512 callback).toString()); 513 assertEquals(0, mStart); 514 assertEquals(text.length(), mEnd); 515 516 // avail is not long enough for ELLIPSIS, and preserveLength doesn't be specified. 517 resetRange(); 518 assertEquals("", 519 TextUtils.ellipsize(text, p, textWidth - 1f, TruncateAt.END, false, 520 callback).toString()); 521 assertEquals(0, mStart); 522 assertEquals(text.length(), mEnd); 523 524 // avail is long enough for ELLIPSIS, and preserveLength is specified. 525 resetRange(); 526 assertEquals(getBlankString(true, text.length()), 527 TextUtils.ellipsize(text, p, textWidth, TruncateAt.END, true, callback).toString()); 528 assertEquals(0, mStart); 529 assertEquals(text.length(), mEnd); 530 531 // avail is long enough for ELLIPSIS, and preserveLength doesn't be specified. 532 resetRange(); 533 assertEquals(mEllipsis, 534 TextUtils.ellipsize(text, p, textWidth, TruncateAt.END, false, 535 callback).toString()); 536 assertEquals(0, mStart); 537 assertEquals(text.length(), mEnd); 538 539 // avail is long enough for the whole sentence. 540 resetRange(); 541 assertEquals(text, 542 TextUtils.ellipsize(text, p, Float.MAX_VALUE, TruncateAt.END, true, 543 callback).toString()); 544 assertEquals(0, mStart); 545 assertEquals(0, mEnd); 546 547 textWidth = p.measureText("long str" + mEllipsis); 548 try { 549 TextUtils.ellipsize(text, null, textWidth, TruncateAt.END, true, callback); 550 } catch (NullPointerException e) { 551 // expected 552 } 553 554 try { 555 TextUtils.ellipsize(null, p, textWidth, TruncateAt.END, true, callback); 556 } catch (NullPointerException e) { 557 // expected 558 } 559 } 560 561 /** 562 * Get a blank string which is filled up by '\uFEFF'. 563 * 564 * @param isNeedStart - boolean whether need to start with char '\u2026' in the string. 565 * @param len - int length of string. 566 * @return a blank string which is filled up by '\uFEFF'. 567 */ getBlankString(boolean isNeedStart, int len)568 private String getBlankString(boolean isNeedStart, int len) { 569 StringBuilder buf = new StringBuilder(); 570 571 int i = 0; 572 if (isNeedStart) { 573 buf.append('\u2026'); 574 i++; 575 } 576 for (; i < len; i++) { 577 buf.append('\uFEFF'); 578 } 579 580 return buf.toString(); 581 } 582 583 @TestTargetNew( 584 level = TestLevel.COMPLETE, 585 method = "equals", 586 args = {CharSequence.class, CharSequence.class} 587 ) testEquals()588 public void testEquals() { 589 // compare with itself. 590 // String is a subclass of CharSequence and overrides equals(). 591 String string = "same object"; 592 assertTrue(TextUtils.equals(string, string)); 593 594 // SpannableString is a subclass of CharSequence and does NOT override equals(). 595 SpannableString spanString = new SpannableString("same object"); 596 final String url = "www.test_url.com"; 597 spanString.setSpan(new URLSpan(url), 0, spanString.length(), 598 Spanned.SPAN_INCLUSIVE_INCLUSIVE); 599 assertTrue(TextUtils.equals(spanString, spanString)); 600 601 // compare with other objects which have same content. 602 assertTrue(TextUtils.equals("different object", "different object")); 603 604 SpannableString urlSpanString = new SpannableString("same content"); 605 SpannableString bgColorSpanString = new SpannableString( 606 "same content"); 607 URLSpan urlSpan = new URLSpan(url); 608 urlSpanString.setSpan(urlSpan, 0, urlSpanString.length(), 609 Spanned.SPAN_INCLUSIVE_INCLUSIVE); 610 BackgroundColorSpan bgColorSpan = new BackgroundColorSpan(Color.GREEN); 611 bgColorSpanString.setSpan(bgColorSpan, 0, bgColorSpanString.length(), 612 Spanned.SPAN_INCLUSIVE_INCLUSIVE); 613 614 assertTrue(TextUtils.equals(bgColorSpanString, urlSpanString)); 615 616 // compare with other objects which have different content. 617 assertFalse(TextUtils.equals("different content A", "different content B")); 618 assertFalse(TextUtils.equals(spanString, urlSpanString)); 619 assertFalse(TextUtils.equals(spanString, bgColorSpanString)); 620 621 // compare with null 622 assertTrue(TextUtils.equals(null, null)); 623 assertFalse(TextUtils.equals(spanString, null)); 624 assertFalse(TextUtils.equals(null, string)); 625 } 626 627 @TestTargetNew( 628 level = TestLevel.COMPLETE, 629 method = "expandTemplate", 630 args = {CharSequence.class, CharSequence[].class} 631 ) 632 @ToBeFixed(bug = "1695243", explanation = 633 "the javadoc for expandTemplate() is incomplete." + 634 "1. not clear what is supposed to happen if template or values is null." + 635 "2. doesn't discuss the case that ^0 in template string.") testExpandTemplate()636 public void testExpandTemplate() { 637 // ^1 at the start of template string. 638 assertEquals("value1 template to be expanded", 639 TextUtils.expandTemplate("^1 template to be expanded", "value1").toString()); 640 // ^1 at the end of template string. 641 assertEquals("template to be expanded value1", 642 TextUtils.expandTemplate("template to be expanded ^1", "value1").toString()); 643 // ^1 in the middle of template string. 644 assertEquals("template value1 to be expanded", 645 TextUtils.expandTemplate("template ^1 to be expanded", "value1").toString()); 646 // ^1 followed by a '0' 647 assertEquals("template value10 to be expanded", 648 TextUtils.expandTemplate("template ^10 to be expanded", "value1").toString()); 649 // ^1 followed by a 'a' 650 assertEquals("template value1a to be expanded", 651 TextUtils.expandTemplate("template ^1a to be expanded", "value1").toString()); 652 // no ^1 653 assertEquals("template ^a to be expanded", 654 TextUtils.expandTemplate("template ^a to be expanded", "value1").toString()); 655 assertEquals("template to be expanded", 656 TextUtils.expandTemplate("template to be expanded", "value1").toString()); 657 // two consecutive ^ in the input to produce a single ^ in the output. 658 assertEquals("template ^ to be expanded", 659 TextUtils.expandTemplate("template ^^ to be expanded", "value1").toString()); 660 // two ^ with a space in the middle. 661 assertEquals("template ^ ^ to be expanded", 662 TextUtils.expandTemplate("template ^ ^ to be expanded", "value1").toString()); 663 // ^1 follow a '^' 664 assertEquals("template ^1 to be expanded", 665 TextUtils.expandTemplate("template ^^1 to be expanded", "value1").toString()); 666 // ^1 followed by a '^' 667 assertEquals("template value1^ to be expanded", 668 TextUtils.expandTemplate("template ^1^ to be expanded", "value1").toString()); 669 670 // 9 replacement values 671 final int MAX_SUPPORTED_VALUES_NUM = 9; 672 CharSequence values[] = createCharSequenceArray(MAX_SUPPORTED_VALUES_NUM); 673 String expected = "value1 value2 template value3 value4 to value5 value6" + 674 " be value7 value8 expanded value9"; 675 String template = "^1 ^2 template ^3 ^4 to ^5 ^6 be ^7 ^8 expanded ^9"; 676 assertEquals(expected, TextUtils.expandTemplate(template, values).toString()); 677 678 // only up to 9 replacement values are supported 679 values = createCharSequenceArray(MAX_SUPPORTED_VALUES_NUM + 1); 680 try { 681 TextUtils.expandTemplate(template, values); 682 fail("Should throw IllegalArgumentException!"); 683 } catch (IllegalArgumentException e) { 684 // expect 685 } 686 687 // template string is ^0 688 try { 689 TextUtils.expandTemplate("template ^0 to be expanded", "value1"); 690 } catch (IllegalArgumentException e) { 691 // issue 1695243, doesn't discuss the case that ^0 in template string. 692 } 693 694 // template string is ^0 695 try { 696 TextUtils.expandTemplate("template ^0 to be expanded"); 697 } catch (IllegalArgumentException e) { 698 // issue 1695243, doesn't discuss the case that ^0 in template string. 699 } 700 701 // the template requests 2 values but only 1 is provided 702 try { 703 TextUtils.expandTemplate("template ^2 to be expanded", "value1"); 704 fail("Should throw IllegalArgumentException!"); 705 } catch (IllegalArgumentException e) { 706 // expect 707 } 708 709 // values is null 710 try { 711 TextUtils.expandTemplate("template ^2 to be expanded", (CharSequence[]) null); 712 } catch (NullPointerException e) { 713 // expected 714 } 715 716 // the template requests 2 values but only one null value is provided 717 try { 718 TextUtils.expandTemplate("template ^2 to be expanded", (CharSequence) null); 719 fail("Should throw IllegalArgumentException!"); 720 } catch (IllegalArgumentException e) { 721 // expect 722 } 723 724 // the template requests 2 values and 2 values is provided, but all values are null. 725 try { 726 TextUtils.expandTemplate("template ^2 to be expanded", 727 (CharSequence) null, (CharSequence) null); 728 } catch (NullPointerException e) { 729 // expected 730 } 731 732 // the template requests 2 values but no value is provided. 733 try { 734 TextUtils.expandTemplate("template ^2 to be expanded"); 735 fail("Should throw IllegalArgumentException!"); 736 } catch (IllegalArgumentException e) { 737 // expected 738 } 739 740 // template is null 741 try { 742 TextUtils.expandTemplate(null, "value1"); 743 } catch (NullPointerException e) { 744 // expected 745 } 746 } 747 748 /** 749 * Create a char sequence array with the specified length 750 * @param len the length of the array 751 * @return The char sequence array with the specified length. 752 * The value of each item is "value[index+1]" 753 */ createCharSequenceArray(int len)754 private CharSequence[] createCharSequenceArray(int len) { 755 CharSequence array[] = new CharSequence[len]; 756 757 for (int i = 0; i < len; i++) { 758 array[i] = "value" + (i + 1); 759 } 760 761 return array; 762 } 763 764 @TestTargetNew( 765 level = TestLevel.COMPLETE, 766 method = "getChars", 767 args = {CharSequence.class, int.class, int.class, char[].class, int.class} 768 ) 769 @ToBeFixed(bug = "1695243", explanation = "the javadoc for getChars() does not exist.") testGetChars()770 public void testGetChars() { 771 char[] destOriginal = "destination".toCharArray(); 772 char[] destResult = destOriginal.clone(); 773 774 // check whether GetChars.getChars() is called and with the proper parameters. 775 MockGetChars mockGetChars = new MockGetChars(); 776 int start = 1; 777 int end = destResult.length; 778 int destOff = 2; 779 TextUtils.getChars(mockGetChars, start, end, destResult, destOff); 780 assertTrue(mockGetChars.hasCalledGetChars()); 781 assertEquals(start, mockGetChars.ReadGetCharsParams().start); 782 assertEquals(end, mockGetChars.ReadGetCharsParams().end); 783 assertEquals(destResult, mockGetChars.ReadGetCharsParams().dest); 784 assertEquals(destOff, mockGetChars.ReadGetCharsParams().destoff); 785 786 // use MockCharSequence to do the test includes corner cases. 787 MockCharSequence mockCharSequence = new MockCharSequence("source string mock"); 788 // get chars to place at the beginning of the destination except the latest one char. 789 destResult = destOriginal.clone(); 790 start = 0; 791 end = destResult.length - 1; 792 destOff = 0; 793 TextUtils.getChars(mockCharSequence, start, end, destResult, destOff); 794 // chars before end are copied from the mockCharSequence. 795 for (int i = 0; i < end - start; i++) { 796 assertEquals(mockCharSequence.charAt(start + i), destResult[destOff + i]); 797 } 798 // chars after end doesn't be changed. 799 for (int i = destOff + (end - start); i < destOriginal.length; i++) { 800 assertEquals(destOriginal[i], destResult[i]); 801 } 802 803 // get chars to place at the end of the destination except the earliest two chars. 804 destResult = destOriginal.clone(); 805 start = 0; 806 end = destResult.length - 2; 807 destOff = 2; 808 TextUtils.getChars(mockCharSequence, start, end, destResult, destOff); 809 // chars before start doesn't be changed. 810 for (int i = 0; i < destOff; i++) { 811 assertEquals(destOriginal[i], destResult[i]); 812 } 813 // chars after start are copied from the mockCharSequence. 814 for (int i = 0; i < end - start; i++) { 815 assertEquals(mockCharSequence.charAt(start + i), destResult[destOff + i]); 816 } 817 818 // get chars to place at the end of the destination except the earliest two chars 819 // and the latest one word. 820 destResult = destOriginal.clone(); 821 start = 1; 822 end = destResult.length - 2; 823 destOff = 0; 824 TextUtils.getChars(mockCharSequence, start, end, destResult, destOff); 825 for (int i = 0; i < destOff; i++) { 826 assertEquals(destOriginal[i], destResult[i]); 827 } 828 for (int i = 0; i < end - start; i++) { 829 assertEquals(mockCharSequence.charAt(start + i), destResult[destOff + i]); 830 } 831 for (int i = destOff + (end - start); i < destOriginal.length; i++) { 832 assertEquals(destOriginal[i], destResult[i]); 833 } 834 835 // get chars to place the whole of the destination 836 destResult = destOriginal.clone(); 837 start = 0; 838 end = destResult.length; 839 destOff = 0; 840 TextUtils.getChars(mockCharSequence, start, end, destResult, destOff); 841 for (int i = 0; i < end - start; i++) { 842 assertEquals(mockCharSequence.charAt(start + i), destResult[destOff + i]); 843 } 844 845 // exceptional start. 846 end = 2; 847 destOff = 0; 848 destResult = destOriginal.clone(); 849 try { 850 TextUtils.getChars(mockCharSequence, -1, end, destResult, destOff); 851 fail("Should throw IndexOutOfBoundsException!"); 852 } catch (IndexOutOfBoundsException e) { 853 // expected 854 } 855 856 destResult = destOriginal.clone(); 857 TextUtils.getChars(mockCharSequence, Integer.MAX_VALUE, end, destResult, destOff); 858 for (int i = 0; i < destResult.length; i++) { 859 assertEquals(destOriginal[i], destResult[i]); 860 } 861 862 // exceptional end. 863 destResult = destOriginal.clone(); 864 start = 0; 865 destOff = 0; 866 try { 867 TextUtils.getChars(mockCharSequence, start, destResult.length + 1, destResult, destOff); 868 fail("Should throw IndexOutOfBoundsException!"); 869 } catch (IndexOutOfBoundsException e) { 870 // expected 871 } 872 873 destResult = destOriginal.clone(); 874 TextUtils.getChars(mockCharSequence, start, -1, destResult, destOff); 875 for (int i = 0; i < destResult.length; i++) { 876 assertEquals(destOriginal[i], destResult[i]); 877 } 878 879 // exceptional destOff. 880 destResult = destOriginal.clone(); 881 start = 0; 882 end = 2; 883 try { 884 TextUtils.getChars(mockCharSequence, start, end, destResult, Integer.MAX_VALUE); 885 fail("Should throw IndexOutOfBoundsException!"); 886 } catch (IndexOutOfBoundsException e) { 887 // expect 888 } 889 try { 890 TextUtils.getChars(mockCharSequence, start, end, destResult, Integer.MIN_VALUE); 891 fail("Should throw IndexOutOfBoundsException!"); 892 } catch (IndexOutOfBoundsException e) { 893 // expect 894 } 895 896 // exceptional source 897 start = 0; 898 end = 2; 899 destOff =0; 900 try { 901 TextUtils.getChars(null, start, end, destResult, destOff); 902 fail("Should throw NullPointerException!"); 903 } catch (NullPointerException e) { 904 // expected 905 } 906 907 // exceptional destination 908 try { 909 TextUtils.getChars(mockCharSequence, start, end, null, destOff); 910 fail("Should throw NullPointerException!"); 911 } catch (NullPointerException e) { 912 // expected 913 } 914 } 915 916 /** 917 * MockGetChars for test. 918 */ 919 private class MockGetChars implements GetChars { 920 private boolean mHasCalledGetChars; 921 private GetCharsParams mGetCharsParams = new GetCharsParams(); 922 923 class GetCharsParams { 924 int start; 925 int end; 926 char[] dest; 927 int destoff; 928 } 929 hasCalledGetChars()930 public boolean hasCalledGetChars() { 931 return mHasCalledGetChars; 932 } 933 reset()934 public void reset() { 935 mHasCalledGetChars = false; 936 } 937 ReadGetCharsParams()938 public GetCharsParams ReadGetCharsParams() { 939 return mGetCharsParams; 940 } 941 getChars(int start, int end, char[] dest, int destoff)942 public void getChars(int start, int end, char[] dest, int destoff) { 943 mHasCalledGetChars = true; 944 mGetCharsParams.start = start; 945 mGetCharsParams.end = end; 946 mGetCharsParams.dest = dest; 947 mGetCharsParams.destoff = destoff; 948 } 949 charAt(int arg0)950 public char charAt(int arg0) { 951 return 0; 952 } 953 length()954 public int length() { 955 return 100; 956 } 957 subSequence(int arg0, int arg1)958 public CharSequence subSequence(int arg0, int arg1) { 959 return null; 960 } 961 } 962 963 /** 964 * MockCharSequence for test. 965 */ 966 private class MockCharSequence implements CharSequence { 967 private char mText[]; 968 MockCharSequence()969 public MockCharSequence() { 970 this(""); 971 } 972 MockCharSequence(String text)973 public MockCharSequence(String text) { 974 mText = text.toCharArray(); 975 } 976 charAt(int arg0)977 public char charAt(int arg0) { 978 if (arg0 >= 0 && arg0 < mText.length) { 979 return mText[arg0]; 980 } 981 throw new IndexOutOfBoundsException(); 982 } 983 length()984 public int length() { 985 return mText.length; 986 } 987 subSequence(int arg0, int arg1)988 public CharSequence subSequence(int arg0, int arg1) { 989 return null; 990 } 991 } 992 993 @TestTargetNew( 994 level = TestLevel.COMPLETE, 995 method = "getOffsetAfter", 996 args = {CharSequence.class, int.class} 997 ) 998 @ToBeFixed(bug = "1695243", explanation = "the javadoc for getOffsetAfter() does not exist.") testGetOffsetAfter()999 public void testGetOffsetAfter() { 1000 // the first '\uD800' is index 9, the second 'uD800' is index 16 1001 // the '\uDBFF' is index 26 1002 final int POS_FIRST_D800 = 9; // the position of the first '\uD800'. 1003 final int POS_SECOND_D800 = 16; 1004 final int POS_FIRST_DBFF = 26; 1005 final int SUPPLEMENTARY_CHARACTERS_OFFSET = 2; // the offset for a supplementary characters 1006 final int NORMAL_CHARACTERS_OFFSET = 1; 1007 SpannableString text = new SpannableString( 1008 "string to\uD800\uDB00 get \uD800\uDC00 offset \uDBFF\uDFFF after"); 1009 assertEquals(0 + 1, TextUtils.getOffsetAfter(text, 0)); 1010 assertEquals(text.length(), TextUtils.getOffsetAfter(text, text.length())); 1011 assertEquals(text.length(), TextUtils.getOffsetAfter(text, text.length() - 1)); 1012 assertEquals(POS_FIRST_D800 + NORMAL_CHARACTERS_OFFSET, 1013 TextUtils.getOffsetAfter(text, POS_FIRST_D800)); 1014 assertEquals(POS_SECOND_D800 + SUPPLEMENTARY_CHARACTERS_OFFSET, 1015 TextUtils.getOffsetAfter(text, POS_SECOND_D800)); 1016 assertEquals(POS_FIRST_DBFF + SUPPLEMENTARY_CHARACTERS_OFFSET, 1017 TextUtils.getOffsetAfter(text, POS_FIRST_DBFF)); 1018 1019 // the CharSequence string has a span. 1020 MockReplacementSpan mockReplacementSpan = new MockReplacementSpan(); 1021 text.setSpan(mockReplacementSpan, POS_FIRST_D800 - 1, text.length() - 1, 1022 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 1023 assertEquals(text.length() - 1, TextUtils.getOffsetAfter(text, POS_FIRST_D800)); 1024 1025 try { 1026 TextUtils.getOffsetAfter(text, -1); 1027 fail("Should throw IndexOutOfBoundsException!"); 1028 } catch (IndexOutOfBoundsException e) { 1029 } 1030 1031 try { 1032 TextUtils.getOffsetAfter(text, Integer.MAX_VALUE); 1033 fail("Should throw IndexOutOfBoundsException!"); 1034 } catch (IndexOutOfBoundsException e) { 1035 } 1036 1037 try { 1038 TextUtils.getOffsetAfter(null, 0); 1039 fail("Should throw NullPointerException!"); 1040 } catch (NullPointerException e) { 1041 // expected 1042 } 1043 } 1044 1045 /** 1046 * MockReplacementSpan for test. 1047 */ 1048 private class MockReplacementSpan extends ReplacementSpan { 1049 @Override draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)1050 public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, 1051 int y, int bottom, Paint paint) { 1052 } 1053 1054 @Override getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm)1055 public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) { 1056 return 0; 1057 } 1058 } 1059 1060 @TestTargetNew( 1061 level = TestLevel.COMPLETE, 1062 method = "getOffsetBefore", 1063 args = {CharSequence.class, int.class} 1064 ) 1065 @ToBeFixed(bug = "1695243", explanation = "the javadoc for getOffsetBefore() does not exist.") testGetOffsetBefore()1066 public void testGetOffsetBefore() { 1067 // the first '\uDC00' is index 10, the second 'uDC00' is index 17 1068 // the '\uDFFF' is index 27 1069 final int POS_FIRST_DC00 = 10; 1070 final int POS_SECOND_DC00 = 17; 1071 final int POS_FIRST_DFFF = 27; 1072 final int SUPPLYMENTARY_CHARACTERS_OFFSET = 2; 1073 final int NORMAL_CHARACTERS_OFFSET = 1; 1074 SpannableString text = new SpannableString( 1075 "string to\uD700\uDC00 get \uD800\uDC00 offset \uDBFF\uDFFF before"); 1076 assertEquals(0, TextUtils.getOffsetBefore(text, 0)); 1077 assertEquals(0, TextUtils.getOffsetBefore(text, 1)); 1078 assertEquals(text.length() - 1, TextUtils.getOffsetBefore(text, text.length())); 1079 assertEquals(POS_FIRST_DC00 + 1 - NORMAL_CHARACTERS_OFFSET, 1080 TextUtils.getOffsetBefore(text, POS_FIRST_DC00 + 1)); 1081 assertEquals(POS_SECOND_DC00 + 1 - SUPPLYMENTARY_CHARACTERS_OFFSET, 1082 TextUtils.getOffsetBefore(text, POS_SECOND_DC00 + 1)); 1083 assertEquals(POS_FIRST_DFFF + 1 - SUPPLYMENTARY_CHARACTERS_OFFSET, 1084 TextUtils.getOffsetBefore(text, POS_FIRST_DFFF + 1)); 1085 1086 // the CharSequence string has a span. 1087 MockReplacementSpan mockReplacementSpan = new MockReplacementSpan(); 1088 text.setSpan(mockReplacementSpan, 0, POS_FIRST_DC00 + 1, 1089 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 1090 assertEquals(0, TextUtils.getOffsetBefore(text, POS_FIRST_DC00)); 1091 1092 try { 1093 TextUtils.getOffsetBefore(text, -1); 1094 fail("Should throw IndexOutOfBoundsException!"); 1095 } catch (IndexOutOfBoundsException e) { 1096 } 1097 1098 try { 1099 TextUtils.getOffsetBefore(text, Integer.MAX_VALUE); 1100 fail("Should throw IndexOutOfBoundsException!"); 1101 } catch (IndexOutOfBoundsException e) { 1102 } 1103 1104 try { 1105 TextUtils.getOffsetBefore(null, POS_FIRST_DC00); 1106 fail("Should throw NullPointerException!"); 1107 } catch (NullPointerException e) { 1108 // expected 1109 } 1110 } 1111 1112 @TestTargetNew( 1113 level = TestLevel.COMPLETE, 1114 method = "getReverse", 1115 args = {CharSequence.class, int.class, int.class} 1116 ) 1117 @ToBeFixed(bug = "1695243", explanation = "the javadoc for getReverse() does not exist.") testGetReverse()1118 public void testGetReverse() { 1119 String source = "string to be reversed"; 1120 assertEquals("gnirts", TextUtils.getReverse(source, 0, "string".length()).toString()); 1121 assertEquals("desrever", 1122 TextUtils.getReverse(source, source.length() - "reversed".length(), 1123 source.length()).toString()); 1124 assertEquals("", TextUtils.getReverse(source, 0, 0).toString()); 1125 1126 // issue 1695243, exception is thrown after the result of some cases 1127 // convert to a string, is this expected? 1128 CharSequence result = TextUtils.getReverse(source, -1, "string".length()); 1129 try { 1130 result.toString(); 1131 fail("Should throw IndexOutOfBoundsException!"); 1132 } catch (IndexOutOfBoundsException e) { 1133 } 1134 1135 TextUtils.getReverse(source, 0, source.length() + 1); 1136 try { 1137 result.toString(); 1138 fail("Should throw IndexOutOfBoundsException!"); 1139 } catch (IndexOutOfBoundsException e) { 1140 } 1141 1142 TextUtils.getReverse(source, "string".length(), 0); 1143 try { 1144 result.toString(); 1145 fail("Should throw IndexOutOfBoundsException!"); 1146 } catch (IndexOutOfBoundsException e) { 1147 } 1148 1149 TextUtils.getReverse(source, 0, Integer.MAX_VALUE); 1150 try { 1151 result.toString(); 1152 fail("Should throw IndexOutOfBoundsException!"); 1153 } catch (IndexOutOfBoundsException e) { 1154 } 1155 1156 TextUtils.getReverse(source, Integer.MIN_VALUE, "string".length()); 1157 try { 1158 result.toString(); 1159 fail("Should throw IndexOutOfBoundsException!"); 1160 } catch (IndexOutOfBoundsException e) { 1161 } 1162 1163 TextUtils.getReverse(null, 0, "string".length()); 1164 try { 1165 result.toString(); 1166 fail("Should throw IndexOutOfBoundsException!"); 1167 } catch (IndexOutOfBoundsException e) { 1168 // expected 1169 } 1170 } 1171 1172 @TestTargetNew( 1173 level = TestLevel.COMPLETE, 1174 method = "getTrimmedLength", 1175 args = {CharSequence.class} 1176 ) 1177 @ToBeFixed(bug = "1695243", explanation = "the javadoc for getReverse() is incomplete." + 1178 "1. doesn't explain @param and @return." + 1179 "2. doesn't discuss the case that parameter is expectional.") testGetTrimmedLength()1180 public void testGetTrimmedLength() { 1181 assertEquals("normalstring".length(), TextUtils.getTrimmedLength("normalstring")); 1182 assertEquals("normal string".length(), TextUtils.getTrimmedLength("normal string")); 1183 assertEquals("blank before".length(), TextUtils.getTrimmedLength(" \t blank before")); 1184 assertEquals("blank after".length(), TextUtils.getTrimmedLength("blank after \n ")); 1185 assertEquals("blank both".length(), TextUtils.getTrimmedLength(" \t blank both \n ")); 1186 1187 char[] allTrimmedChars = new char[] { 1188 '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007', 1189 '\u0008', '\u0009', '\u0010', '\u0011', '\u0012', '\u0013', '\u0014', '\u0015', 1190 '\u0016', '\u0017', '\u0018', '\u0019', '\u0020' 1191 }; 1192 assertEquals(0, TextUtils.getTrimmedLength(String.valueOf(allTrimmedChars))); 1193 1194 try { 1195 TextUtils.getTrimmedLength(null); 1196 fail("Should throw NullPointerException!"); 1197 } catch (NullPointerException e) { 1198 // expected 1199 } 1200 } 1201 1202 @TestTargetNew( 1203 level = TestLevel.COMPLETE, 1204 method = "htmlEncode", 1205 args = {String.class} 1206 ) 1207 @ToBeFixed(bug = "1695243", explanation = "the javadoc for htmlEncode() is incomplete." + 1208 "1. doesn't discuss the case that parameter is expectional.") testHtmlEncode()1209 public void testHtmlEncode() { 1210 assertEquals("<_html_>\\ &"'string'"", 1211 TextUtils.htmlEncode("<_html_>\\ &\"'string'\"")); 1212 1213 try { 1214 TextUtils.htmlEncode(null); 1215 fail("Should throw NullPointerException!"); 1216 } catch (NullPointerException e) { 1217 // expected 1218 } 1219 } 1220 1221 @TestTargetNew( 1222 level = TestLevel.COMPLETE, 1223 method = "indexOf", 1224 args = {CharSequence.class, char.class} 1225 ) 1226 @ToBeFixed(bug = "1695243", explanation = "the javadoc for indexOf() does not exist.") testIndexOf1()1227 public void testIndexOf1() { 1228 String searchString = "string to be searched"; 1229 final int INDEX_OF_FIRST_R = 2; // first occurrence of 'r' 1230 final int INDEX_OF_FIRST_T = 1; 1231 final int INDEX_OF_FIRST_D = searchString.length() - 1; 1232 1233 assertEquals(INDEX_OF_FIRST_T, TextUtils.indexOf(searchString, 't')); 1234 assertEquals(INDEX_OF_FIRST_R, TextUtils.indexOf(searchString, 'r')); 1235 assertEquals(INDEX_OF_FIRST_D, TextUtils.indexOf(searchString, 'd')); 1236 assertEquals(-1, TextUtils.indexOf(searchString, 'f')); 1237 1238 StringBuffer stringBuffer = new StringBuffer(searchString); 1239 assertEquals(INDEX_OF_FIRST_R, TextUtils.indexOf(stringBuffer, 'r')); 1240 1241 StringBuilder stringBuilder = new StringBuilder(searchString); 1242 assertEquals(INDEX_OF_FIRST_R, TextUtils.indexOf(stringBuilder, 'r')); 1243 1244 MockGetChars mockGetChars = new MockGetChars(); 1245 assertFalse(mockGetChars.hasCalledGetChars()); 1246 TextUtils.indexOf(mockGetChars, 'r'); 1247 assertTrue(mockGetChars.hasCalledGetChars()); 1248 1249 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1250 assertEquals(INDEX_OF_FIRST_R, TextUtils.indexOf(mockCharSequence, 'r')); 1251 } 1252 1253 @TestTargetNew( 1254 level = TestLevel.COMPLETE, 1255 method = "indexOf", 1256 args = {CharSequence.class, char.class, int.class} 1257 ) 1258 @ToBeFixed(bug = "1695243", explanation = "the javadoc for indexOf() does not exist.") testIndexOf2()1259 public void testIndexOf2() { 1260 String searchString = "string to be searched"; 1261 final int INDEX_OF_FIRST_R = 2; 1262 final int INDEX_OF_SECOND_R = 16; 1263 1264 assertEquals(INDEX_OF_FIRST_R, TextUtils.indexOf(searchString, 'r', 0)); 1265 assertEquals(INDEX_OF_SECOND_R, TextUtils.indexOf(searchString, 'r', INDEX_OF_FIRST_R + 1)); 1266 assertEquals(-1, TextUtils.indexOf(searchString, 'r', searchString.length())); 1267 assertEquals(INDEX_OF_FIRST_R, TextUtils.indexOf(searchString, 'r', Integer.MIN_VALUE)); 1268 assertEquals(-1, TextUtils.indexOf(searchString, 'r', Integer.MAX_VALUE)); 1269 1270 StringBuffer stringBuffer = new StringBuffer(searchString); 1271 assertEquals(INDEX_OF_SECOND_R, TextUtils.indexOf(stringBuffer, 'r', INDEX_OF_FIRST_R + 1)); 1272 try { 1273 TextUtils.indexOf(stringBuffer, 'r', Integer.MIN_VALUE); 1274 fail("Should throw IndexOutOfBoundsException!"); 1275 } catch (IndexOutOfBoundsException e) { 1276 // expect 1277 } 1278 assertEquals(-1, TextUtils.indexOf(stringBuffer, 'r', Integer.MAX_VALUE)); 1279 1280 StringBuilder stringBuilder = new StringBuilder(searchString); 1281 assertEquals(INDEX_OF_SECOND_R, 1282 TextUtils.indexOf(stringBuilder, 'r', INDEX_OF_FIRST_R + 1)); 1283 1284 MockGetChars mockGetChars = new MockGetChars(); 1285 TextUtils.indexOf(mockGetChars, 'r', INDEX_OF_FIRST_R + 1); 1286 assertTrue(mockGetChars.hasCalledGetChars()); 1287 1288 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1289 assertEquals(INDEX_OF_SECOND_R, TextUtils.indexOf(mockCharSequence, 'r', 1290 INDEX_OF_FIRST_R + 1)); 1291 } 1292 1293 @TestTargetNew( 1294 level = TestLevel.COMPLETE, 1295 method = "indexOf", 1296 args = {CharSequence.class, char.class, int.class, int.class} 1297 ) 1298 @ToBeFixed(bug = "1695243", explanation = "the javadoc for indexOf() does not exist.") testIndexOf3()1299 public void testIndexOf3() { 1300 String searchString = "string to be searched"; 1301 final int INDEX_OF_FIRST_R = 2; 1302 final int INDEX_OF_SECOND_R = 16; 1303 1304 assertEquals(INDEX_OF_FIRST_R, 1305 TextUtils.indexOf(searchString, 'r', 0, searchString.length())); 1306 assertEquals(INDEX_OF_SECOND_R, TextUtils.indexOf(searchString, 'r', 1307 INDEX_OF_FIRST_R + 1, searchString.length())); 1308 assertEquals(-1, TextUtils.indexOf(searchString, 'r', 1309 INDEX_OF_FIRST_R + 1, INDEX_OF_SECOND_R)); 1310 1311 try { 1312 TextUtils.indexOf(searchString, 'r', Integer.MIN_VALUE, INDEX_OF_SECOND_R); 1313 fail("Should throw IndexOutOfBoundsException!"); 1314 } catch (IndexOutOfBoundsException e) { 1315 // expect 1316 } 1317 assertEquals(-1, 1318 TextUtils.indexOf(searchString, 'r', Integer.MAX_VALUE, INDEX_OF_SECOND_R)); 1319 assertEquals(-1, TextUtils.indexOf(searchString, 'r', 0, Integer.MIN_VALUE)); 1320 try { 1321 TextUtils.indexOf(searchString, 'r', 0, Integer.MAX_VALUE); 1322 fail("Should throw IndexOutOfBoundsException!"); 1323 } catch (IndexOutOfBoundsException e) { 1324 // expect 1325 } 1326 1327 StringBuffer stringBuffer = new StringBuffer(searchString); 1328 assertEquals(INDEX_OF_SECOND_R, TextUtils.indexOf(stringBuffer, 'r', 1329 INDEX_OF_FIRST_R + 1, searchString.length())); 1330 1331 StringBuilder stringBuilder = new StringBuilder(searchString); 1332 assertEquals(INDEX_OF_SECOND_R, TextUtils.indexOf(stringBuilder, 'r', 1333 INDEX_OF_FIRST_R + 1, searchString.length())); 1334 1335 MockGetChars mockGetChars = new MockGetChars(); 1336 TextUtils.indexOf(mockGetChars, 'r', INDEX_OF_FIRST_R + 1, searchString.length()); 1337 assertTrue(mockGetChars.hasCalledGetChars()); 1338 1339 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1340 assertEquals(INDEX_OF_SECOND_R, TextUtils.indexOf(mockCharSequence, 'r', 1341 INDEX_OF_FIRST_R + 1, searchString.length())); 1342 } 1343 1344 @TestTargetNew( 1345 level = TestLevel.COMPLETE, 1346 method = "indexOf", 1347 args = {CharSequence.class, CharSequence.class} 1348 ) 1349 @ToBeFixed(bug = "1695243", explanation = "the javadoc for indexOf() does not exist.") testIndexOf4()1350 public void testIndexOf4() { 1351 String searchString = "string to be searched by string"; 1352 final int SEARCH_INDEX = 13; 1353 1354 assertEquals(0, TextUtils.indexOf(searchString, "string")); 1355 assertEquals(SEARCH_INDEX, TextUtils.indexOf(searchString, "search")); 1356 assertEquals(-1, TextUtils.indexOf(searchString, "tobe")); 1357 assertEquals(0, TextUtils.indexOf(searchString, "")); 1358 1359 StringBuffer stringBuffer = new StringBuffer(searchString); 1360 assertEquals(SEARCH_INDEX, TextUtils.indexOf(stringBuffer, "search")); 1361 1362 StringBuilder stringBuilder = new StringBuilder(searchString); 1363 assertEquals(SEARCH_INDEX, TextUtils.indexOf(stringBuilder, "search")); 1364 1365 MockGetChars mockGetChars = new MockGetChars(); 1366 TextUtils.indexOf(mockGetChars, "search"); 1367 assertTrue(mockGetChars.hasCalledGetChars()); 1368 1369 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1370 assertEquals(SEARCH_INDEX, TextUtils.indexOf(mockCharSequence, "search")); 1371 } 1372 1373 @TestTargetNew( 1374 level = TestLevel.COMPLETE, 1375 method = "indexOf", 1376 args = {CharSequence.class, CharSequence.class, int.class} 1377 ) 1378 @ToBeFixed(bug = "1695243", explanation = "the javadoc for indexOf() does not exist.") testIndexOf5()1379 public void testIndexOf5() { 1380 String searchString = "string to be searched by string"; 1381 final int INDEX_OF_FIRST_STRING = 0; 1382 final int INDEX_OF_SECOND_STRING = 25; 1383 1384 assertEquals(INDEX_OF_FIRST_STRING, TextUtils.indexOf(searchString, "string", 0)); 1385 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(searchString, "string", 1386 INDEX_OF_FIRST_STRING + 1)); 1387 assertEquals(-1, TextUtils.indexOf(searchString, "string", INDEX_OF_SECOND_STRING + 1)); 1388 assertEquals(INDEX_OF_FIRST_STRING, TextUtils.indexOf(searchString, "string", 1389 Integer.MIN_VALUE)); 1390 assertEquals(-1, TextUtils.indexOf(searchString, "string", Integer.MAX_VALUE)); 1391 1392 assertEquals(1, TextUtils.indexOf(searchString, "", 1)); 1393 assertEquals(Integer.MAX_VALUE, TextUtils.indexOf(searchString, "", Integer.MAX_VALUE)); 1394 1395 assertEquals(0, TextUtils.indexOf(searchString, searchString, 0)); 1396 assertEquals(-1, TextUtils.indexOf(searchString, searchString + "longer needle", 0)); 1397 1398 StringBuffer stringBuffer = new StringBuffer(searchString); 1399 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(stringBuffer, "string", 1400 INDEX_OF_FIRST_STRING + 1)); 1401 try { 1402 TextUtils.indexOf(stringBuffer, "string", Integer.MIN_VALUE); 1403 fail("Should throw IndexOutOfBoundsException!"); 1404 } catch (IndexOutOfBoundsException e) { 1405 // expect 1406 } 1407 assertEquals(-1, TextUtils.indexOf(stringBuffer, "string", Integer.MAX_VALUE)); 1408 1409 StringBuilder stringBuilder = new StringBuilder(searchString); 1410 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(stringBuilder, "string", 1411 INDEX_OF_FIRST_STRING + 1)); 1412 1413 MockGetChars mockGetChars = new MockGetChars(); 1414 assertFalse(mockGetChars.hasCalledGetChars()); 1415 TextUtils.indexOf(mockGetChars, "string", INDEX_OF_FIRST_STRING + 1); 1416 assertTrue(mockGetChars.hasCalledGetChars()); 1417 1418 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1419 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(mockCharSequence, "string", 1420 INDEX_OF_FIRST_STRING + 1)); 1421 } 1422 1423 @TestTargetNew( 1424 level = TestLevel.COMPLETE, 1425 method = "indexOf", 1426 args = {CharSequence.class, CharSequence.class, int.class, int.class} 1427 ) 1428 @ToBeFixed(bug = "1695243", explanation = "the javadoc for indexOf() does not exist.") testIndexOf6()1429 public void testIndexOf6() { 1430 String searchString = "string to be searched by string"; 1431 final int INDEX_OF_FIRST_STRING = 0; 1432 final int INDEX_OF_SECOND_STRING = 25; 1433 1434 assertEquals(INDEX_OF_FIRST_STRING, TextUtils.indexOf(searchString, "string", 0, 1435 searchString.length())); 1436 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(searchString, "string", 1437 INDEX_OF_FIRST_STRING + 1, searchString.length())); 1438 assertEquals(-1, TextUtils.indexOf(searchString, "string", INDEX_OF_FIRST_STRING + 1, 1439 INDEX_OF_SECOND_STRING - 1)); 1440 assertEquals(INDEX_OF_FIRST_STRING, TextUtils.indexOf(searchString, "string", 1441 Integer.MIN_VALUE, INDEX_OF_SECOND_STRING - 1)); 1442 assertEquals(-1, TextUtils.indexOf(searchString, "string", Integer.MAX_VALUE, 1443 INDEX_OF_SECOND_STRING - 1)); 1444 1445 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(searchString, "string", 1446 INDEX_OF_FIRST_STRING + 1, Integer.MIN_VALUE)); 1447 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(searchString, "string", 1448 INDEX_OF_FIRST_STRING + 1, Integer.MAX_VALUE)); 1449 1450 StringBuffer stringBuffer = new StringBuffer(searchString); 1451 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(stringBuffer, "string", 1452 INDEX_OF_FIRST_STRING + 1, searchString.length())); 1453 try { 1454 TextUtils.indexOf(stringBuffer, "string", Integer.MIN_VALUE, 1455 INDEX_OF_SECOND_STRING - 1); 1456 fail("Should throw IndexOutOfBoundsException!"); 1457 } catch (IndexOutOfBoundsException e) { 1458 // expect 1459 } 1460 assertEquals(-1, TextUtils.indexOf(stringBuffer, "string", Integer.MAX_VALUE, 1461 searchString.length())); 1462 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(stringBuffer, 1463 "string", INDEX_OF_FIRST_STRING + 1, Integer.MIN_VALUE)); 1464 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(stringBuffer, 1465 "string", INDEX_OF_FIRST_STRING + 1, Integer.MAX_VALUE)); 1466 1467 StringBuilder stringBuilder = new StringBuilder(searchString); 1468 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(stringBuilder, "string", 1469 INDEX_OF_FIRST_STRING + 1, searchString.length())); 1470 1471 MockGetChars mockGetChars = new MockGetChars(); 1472 TextUtils.indexOf(mockGetChars, "string", INDEX_OF_FIRST_STRING + 1, searchString.length()); 1473 assertTrue(mockGetChars.hasCalledGetChars()); 1474 1475 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1476 assertEquals(INDEX_OF_SECOND_STRING, TextUtils.indexOf(mockCharSequence, "string", 1477 INDEX_OF_FIRST_STRING + 1, searchString.length())); 1478 } 1479 1480 @TestTargetNew( 1481 level = TestLevel.COMPLETE, 1482 method = "isDigitsOnly", 1483 args = {CharSequence.class} 1484 ) 1485 @ToBeFixed(bug = "1695243", explanation = "the javadoc for isDigitsOnly() is incomplete.") testIsDigitsOnly()1486 public void testIsDigitsOnly() { 1487 assertFalse(TextUtils.isDigitsOnly("no digit")); 1488 assertFalse(TextUtils.isDigitsOnly("character and 56 digits")); 1489 assertTrue(TextUtils.isDigitsOnly("0123456789")); 1490 assertFalse(TextUtils.isDigitsOnly("1234 56789")); 1491 1492 try { 1493 TextUtils.isDigitsOnly(null); 1494 fail("Should throw NullPointerException!"); 1495 } catch (NullPointerException e) { 1496 // issue 1695243, not clear what is supposed result if the CharSequence is null. 1497 } 1498 } 1499 1500 @TestTargetNew( 1501 level = TestLevel.COMPLETE, 1502 method = "isEmpty", 1503 args = {CharSequence.class} 1504 ) testIsEmpty()1505 public void testIsEmpty() { 1506 assertFalse(TextUtils.isEmpty("not empty")); 1507 assertFalse(TextUtils.isEmpty(" ")); 1508 assertTrue(TextUtils.isEmpty("")); 1509 assertTrue(TextUtils.isEmpty(null)); 1510 } 1511 1512 @TestTargetNew( 1513 level = TestLevel.COMPLETE, 1514 method = "isGraphic", 1515 args = {char.class} 1516 ) 1517 @ToBeFixed(bug = "1695243", explanation = "the javadoc for isGraphic() is incomplete.") testIsGraphicChar()1518 public void testIsGraphicChar() { 1519 assertTrue(TextUtils.isGraphic('a')); 1520 assertTrue(TextUtils.isGraphic("\uBA00")); 1521 1522 // LINE_SEPARATOR 1523 assertFalse(TextUtils.isGraphic('\u2028')); 1524 1525 // PARAGRAPH_SEPARATOR 1526 assertFalse(TextUtils.isGraphic('\u2029')); 1527 1528 // CONTROL 1529 assertFalse(TextUtils.isGraphic('\u0085')); 1530 1531 // UNASSIGNED 1532 assertFalse(TextUtils.isGraphic('\u0D00')); 1533 1534 // SURROGATE 1535 assertFalse(TextUtils.isGraphic('\uD800')); 1536 1537 // SPACE_SEPARATOR 1538 assertFalse(TextUtils.isGraphic('\u0020')); 1539 1540 try { 1541 assertFalse(TextUtils.isGraphic((Character) null)); 1542 fail("Should throw NullPointerException!"); 1543 } catch (NullPointerException e) { 1544 // expected 1545 } 1546 } 1547 1548 @TestTargetNew( 1549 level = TestLevel.COMPLETE, 1550 method = "isGraphic", 1551 args = {CharSequence.class} 1552 ) 1553 @ToBeFixed(bug = "1695243", explanation = "the javadoc for isGraphic() is incomplete.") testIsGraphicCharSequence()1554 public void testIsGraphicCharSequence() { 1555 assertTrue(TextUtils.isGraphic("printable characters")); 1556 1557 assertFalse(TextUtils.isGraphic("\u2028\u2029\u0085\u0D00\uD800\u0020")); 1558 1559 assertTrue(TextUtils.isGraphic("a\u2028\u2029\u0085\u0D00\uD800\u0020")); 1560 1561 try { 1562 TextUtils.isGraphic(null); 1563 fail("Should throw NullPointerException!"); 1564 } catch (NullPointerException e) { 1565 // expected 1566 } 1567 } 1568 1569 @SuppressWarnings("unchecked") 1570 @TestTargetNew( 1571 level = TestLevel.COMPLETE, 1572 method = "join", 1573 args = {CharSequence.class, Iterable.class} 1574 ) 1575 @ToBeFixed(bug = "1695243", explanation = "the javadoc for join() is incomplete.") testJoin1()1576 public void testJoin1() { 1577 ArrayList<CharSequence> charTokens = new ArrayList<CharSequence>(); 1578 charTokens.add("string1"); 1579 charTokens.add("string2"); 1580 charTokens.add("string3"); 1581 assertEquals("string1|string2|string3", TextUtils.join("|", charTokens)); 1582 assertEquals("string1; string2; string3", TextUtils.join("; ", charTokens)); 1583 assertEquals("string1string2string3", TextUtils.join("", charTokens)); 1584 1585 // issue 1695243, not clear what is supposed result if the delimiter or tokens are null. 1586 assertEquals("string1nullstring2nullstring3", TextUtils.join(null, charTokens)); 1587 try { 1588 TextUtils.join("|", (Iterable) null); 1589 fail("Should throw NullPointerException!"); 1590 } catch (NullPointerException e) { 1591 // expect 1592 } 1593 1594 ArrayList<SpannableString> spannableStringTokens = new ArrayList<SpannableString>(); 1595 spannableStringTokens.add(new SpannableString("span 1")); 1596 spannableStringTokens.add(new SpannableString("span 2")); 1597 spannableStringTokens.add(new SpannableString("span 3")); 1598 assertEquals("span 1;span 2;span 3", TextUtils.join(";", spannableStringTokens)); 1599 } 1600 1601 @TestTargetNew( 1602 level = TestLevel.COMPLETE, 1603 method = "join", 1604 args = {CharSequence.class, Object[].class} 1605 ) 1606 @ToBeFixed(bug = "1695243", explanation = "the javadoc for join() is incomplete.") testJoin2()1607 public void testJoin2() { 1608 CharSequence[] charTokens = new CharSequence[] { "string1", "string2", "string3" }; 1609 assertEquals("string1|string2|string3", TextUtils.join("|", charTokens)); 1610 assertEquals("string1; string2; string3", TextUtils.join("; ", charTokens)); 1611 assertEquals("string1string2string3", TextUtils.join("", charTokens)); 1612 1613 // issue 1695243, not clear what is supposed result if the delimiter or tokens are null. 1614 assertEquals("string1nullstring2nullstring3", TextUtils.join(null, charTokens)); 1615 try { 1616 TextUtils.join("|", (Object[]) null); 1617 fail("Should throw NullPointerException!"); 1618 } catch (NullPointerException e) { 1619 // expect 1620 } 1621 1622 SpannableString[] spannableStringTokens = new SpannableString[] { 1623 new SpannableString("span 1"), 1624 new SpannableString("span 2"), 1625 new SpannableString("span 3") }; 1626 assertEquals("span 1;span 2;span 3", TextUtils.join(";", spannableStringTokens)); 1627 } 1628 1629 @TestTargetNew( 1630 level = TestLevel.COMPLETE, 1631 method = "lastIndexOf", 1632 args = {CharSequence.class, char.class} 1633 ) 1634 @ToBeFixed(bug = "1695243", explanation = "the javadoc for lastIndexOf() does not exist.") testLastIndexOf1()1635 public void testLastIndexOf1() { 1636 String searchString = "string to be searched"; 1637 final int INDEX_OF_LAST_R = 16; 1638 final int INDEX_OF_LAST_T = 7; 1639 final int INDEX_OF_LAST_D = searchString.length() - 1; 1640 1641 assertEquals(INDEX_OF_LAST_T, TextUtils.lastIndexOf(searchString, 't')); 1642 assertEquals(INDEX_OF_LAST_R, TextUtils.lastIndexOf(searchString, 'r')); 1643 assertEquals(INDEX_OF_LAST_D, TextUtils.lastIndexOf(searchString, 'd')); 1644 assertEquals(-1, TextUtils.lastIndexOf(searchString, 'f')); 1645 1646 StringBuffer stringBuffer = new StringBuffer(searchString); 1647 assertEquals(INDEX_OF_LAST_R, TextUtils.lastIndexOf(stringBuffer, 'r')); 1648 1649 StringBuilder stringBuilder = new StringBuilder(searchString); 1650 assertEquals(INDEX_OF_LAST_R, TextUtils.lastIndexOf(stringBuilder, 'r')); 1651 1652 MockGetChars mockGetChars = new MockGetChars(); 1653 TextUtils.lastIndexOf(mockGetChars, 'r'); 1654 assertTrue(mockGetChars.hasCalledGetChars()); 1655 1656 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1657 assertEquals(INDEX_OF_LAST_R, TextUtils.lastIndexOf(mockCharSequence, 'r')); 1658 } 1659 1660 @TestTargetNew( 1661 level = TestLevel.COMPLETE, 1662 method = "lastIndexOf", 1663 args = {CharSequence.class, char.class, int.class} 1664 ) 1665 @ToBeFixed(bug = "1695243", explanation = "the javadoc for lastIndexOf() does not exist.") testLastIndexOf2()1666 public void testLastIndexOf2() { 1667 String searchString = "string to be searched"; 1668 final int INDEX_OF_FIRST_R = 2; 1669 final int INDEX_OF_SECOND_R = 16; 1670 1671 assertEquals(INDEX_OF_SECOND_R, 1672 TextUtils.lastIndexOf(searchString, 'r', searchString.length())); 1673 assertEquals(-1, TextUtils.lastIndexOf(searchString, 'r', 0)); 1674 assertEquals(INDEX_OF_FIRST_R, 1675 TextUtils.lastIndexOf(searchString, 'r', INDEX_OF_FIRST_R)); 1676 assertEquals(-1, TextUtils.lastIndexOf(searchString, 'r', Integer.MIN_VALUE)); 1677 assertEquals(INDEX_OF_SECOND_R, 1678 TextUtils.lastIndexOf(searchString, 'r', Integer.MAX_VALUE)); 1679 1680 StringBuffer stringBuffer = new StringBuffer(searchString); 1681 assertEquals(INDEX_OF_FIRST_R, 1682 TextUtils.lastIndexOf(stringBuffer, 'r', INDEX_OF_FIRST_R)); 1683 assertEquals(-1, TextUtils.lastIndexOf(stringBuffer, 'r', Integer.MIN_VALUE)); 1684 assertEquals(INDEX_OF_SECOND_R, 1685 TextUtils.lastIndexOf(stringBuffer, 'r', Integer.MAX_VALUE)); 1686 1687 StringBuilder stringBuilder = new StringBuilder(searchString); 1688 assertEquals(INDEX_OF_FIRST_R, 1689 TextUtils.lastIndexOf(stringBuilder, 'r', INDEX_OF_FIRST_R)); 1690 1691 MockGetChars mockGetChars = new MockGetChars(); 1692 TextUtils.lastIndexOf(mockGetChars, 'r', INDEX_OF_FIRST_R); 1693 assertTrue(mockGetChars.hasCalledGetChars()); 1694 1695 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1696 assertEquals(INDEX_OF_FIRST_R, 1697 TextUtils.lastIndexOf(mockCharSequence, 'r', INDEX_OF_FIRST_R)); 1698 } 1699 1700 @TestTargetNew( 1701 level = TestLevel.COMPLETE, 1702 method = "lastIndexOf", 1703 args = {CharSequence.class, char.class, int.class, int.class} 1704 ) 1705 @ToBeFixed(bug = "1695243", explanation = "the javadoc for lastIndexOf() does not exist.") testLastIndexOf3()1706 public void testLastIndexOf3() { 1707 String searchString = "string to be searched"; 1708 final int INDEX_OF_FIRST_R = 2; 1709 final int INDEX_OF_SECOND_R = 16; 1710 1711 assertEquals(INDEX_OF_SECOND_R, TextUtils.lastIndexOf(searchString, 'r', 0, 1712 searchString.length())); 1713 assertEquals(INDEX_OF_FIRST_R, TextUtils.lastIndexOf(searchString, 'r', 0, 1714 INDEX_OF_SECOND_R - 1)); 1715 assertEquals(-1, TextUtils.lastIndexOf(searchString, 'r', 0, INDEX_OF_FIRST_R - 1)); 1716 1717 try { 1718 TextUtils.lastIndexOf(searchString, 'r', Integer.MIN_VALUE, INDEX_OF_SECOND_R - 1); 1719 fail("Should throw IndexOutOfBoundsException!"); 1720 } catch (IndexOutOfBoundsException e) { 1721 // expect 1722 } 1723 assertEquals(-1, TextUtils.lastIndexOf(searchString, 'r', Integer.MAX_VALUE, 1724 INDEX_OF_SECOND_R - 1)); 1725 assertEquals(-1, TextUtils.lastIndexOf(searchString, 'r', 0, Integer.MIN_VALUE)); 1726 assertEquals(INDEX_OF_SECOND_R, TextUtils.lastIndexOf(searchString, 'r', 0, 1727 Integer.MAX_VALUE)); 1728 1729 StringBuffer stringBuffer = new StringBuffer(searchString); 1730 assertEquals(INDEX_OF_FIRST_R, TextUtils.lastIndexOf(stringBuffer, 'r', 0, 1731 INDEX_OF_SECOND_R - 1)); 1732 1733 StringBuilder stringBuilder = new StringBuilder(searchString); 1734 assertEquals(INDEX_OF_FIRST_R, TextUtils.lastIndexOf(stringBuilder, 'r', 0, 1735 INDEX_OF_SECOND_R - 1)); 1736 1737 MockGetChars mockGetChars = new MockGetChars(); 1738 TextUtils.lastIndexOf(mockGetChars, 'r', 0, INDEX_OF_SECOND_R - 1); 1739 assertTrue(mockGetChars.hasCalledGetChars()); 1740 1741 MockCharSequence mockCharSequence = new MockCharSequence(searchString); 1742 assertEquals(INDEX_OF_FIRST_R, TextUtils.lastIndexOf(mockCharSequence, 'r', 0, 1743 INDEX_OF_SECOND_R - 1)); 1744 } 1745 1746 @TestTargetNew( 1747 level = TestLevel.COMPLETE, 1748 method = "regionMatches", 1749 args = {CharSequence.class, int.class, CharSequence.class, int.class, int.class} 1750 ) 1751 @ToBeFixed(bug = "1695243", explanation = "the javadoc for regionMatches() does not exist.") testRegionMatches()1752 public void testRegionMatches() { 1753 assertFalse(TextUtils.regionMatches("one", 0, "two", 0, "one".length())); 1754 assertTrue(TextUtils.regionMatches("one", 0, "one", 0, "one".length())); 1755 try { 1756 TextUtils.regionMatches("one", 0, "one", 0, "one".length() + 1); 1757 fail("Should throw IndexOutOfBoundsException!"); 1758 } catch (IndexOutOfBoundsException e) { 1759 } 1760 1761 String one = "Hello Android, hello World!"; 1762 String two = "Hello World"; 1763 // match "Hello" 1764 assertTrue(TextUtils.regionMatches(one, 0, two, 0, "Hello".length())); 1765 1766 // match "Hello A" and "Hello W" 1767 assertFalse(TextUtils.regionMatches(one, 0, two, 0, "Hello A".length())); 1768 1769 // match "World" 1770 assertTrue(TextUtils.regionMatches(one, "Hello Android, hello ".length(), 1771 two, "Hello ".length(), "World".length())); 1772 assertFalse(TextUtils.regionMatches(one, "Hello Android, hello ".length(), 1773 two, 0, "World".length())); 1774 1775 try { 1776 TextUtils.regionMatches(one, Integer.MIN_VALUE, two, 0, "Hello".length()); 1777 fail("Should throw IndexOutOfBoundsException!"); 1778 } catch (IndexOutOfBoundsException e) { 1779 } 1780 try { 1781 TextUtils.regionMatches(one, Integer.MAX_VALUE, two, 0, "Hello".length()); 1782 fail("Should throw IndexOutOfBoundsException!"); 1783 } catch (IndexOutOfBoundsException e) { 1784 } 1785 1786 try { 1787 TextUtils.regionMatches(one, 0, two, Integer.MIN_VALUE, "Hello".length()); 1788 fail("Should throw IndexOutOfBoundsException!"); 1789 } catch (IndexOutOfBoundsException e) { 1790 } 1791 try { 1792 TextUtils.regionMatches(one, 0, two, Integer.MAX_VALUE, "Hello".length()); 1793 fail("Should throw IndexOutOfBoundsException!"); 1794 } catch (IndexOutOfBoundsException e) { 1795 } 1796 1797 try { 1798 TextUtils.regionMatches(one, 0, two, 0, Integer.MIN_VALUE); 1799 fail("Should throw IndexOutOfBoundsException!"); 1800 } catch (IndexOutOfBoundsException e) { 1801 } 1802 try { 1803 TextUtils.regionMatches(one, 0, two, 0, Integer.MAX_VALUE); 1804 fail("Should throw IndexOutOfBoundsException!"); 1805 } catch (IndexOutOfBoundsException e) { 1806 } 1807 1808 try { 1809 TextUtils.regionMatches(null, 0, two, 0, "Hello".length()); 1810 fail("Should throw NullPointerException!"); 1811 } catch (NullPointerException e) { 1812 // expect 1813 } 1814 try { 1815 TextUtils.regionMatches(one, 0, null, 0, "Hello".length()); 1816 fail("Should throw NullPointerException!"); 1817 } catch (NullPointerException e) { 1818 // expect 1819 } 1820 } 1821 1822 @TestTargetNew( 1823 level = TestLevel.COMPLETE, 1824 method = "replace", 1825 args = {CharSequence.class, String[].class, CharSequence[].class} 1826 ) 1827 @ToBeFixed(bug = "1695243", explanation = "the javadoc for replace() is incomplete.") testReplace()1828 public void testReplace() { 1829 String template = "this is a string to be as the template for replacement"; 1830 1831 String sources[] = new String[] { "string" }; 1832 CharSequence destinations[] = new CharSequence[] { "text" }; 1833 SpannableStringBuilder replacedString = (SpannableStringBuilder) TextUtils.replace(template, 1834 sources, destinations); 1835 assertEquals("this is a text to be as the template for replacement", 1836 replacedString.toString()); 1837 1838 sources = new String[] {"is", "the", "for replacement"}; 1839 destinations = new CharSequence[] {"was", "", "to be replaced"}; 1840 replacedString = (SpannableStringBuilder)TextUtils.replace(template, sources, destinations); 1841 assertEquals("thwas is a string to be as template to be replaced", 1842 replacedString.toString()); 1843 1844 sources = new String[] {"is", "for replacement"}; 1845 destinations = new CharSequence[] {"was", "", "to be replaced"}; 1846 replacedString = (SpannableStringBuilder)TextUtils.replace(template, sources, destinations); 1847 assertEquals("thwas is a string to be as the template ", replacedString.toString()); 1848 1849 sources = new String[] {"is", "the", "for replacement"}; 1850 destinations = new CharSequence[] {"was", "to be replaced"}; 1851 try { 1852 TextUtils.replace(template, sources, destinations); 1853 fail("Should throw ArrayIndexOutOfBoundsException!"); 1854 } catch (ArrayIndexOutOfBoundsException e) { 1855 // expected 1856 } 1857 1858 try { 1859 TextUtils.replace(null, sources, destinations); 1860 fail("Should throw NullPointerException!"); 1861 } catch (NullPointerException e) { 1862 // expected 1863 } 1864 try { 1865 TextUtils.replace(template, null, destinations); 1866 fail("Should throw NullPointerException!"); 1867 } catch (NullPointerException e) { 1868 // expected 1869 } 1870 try { 1871 TextUtils.replace(template, sources, null); 1872 fail("Should throw NullPointerException!"); 1873 } catch (NullPointerException e) { 1874 // expected 1875 } 1876 } 1877 1878 @TestTargetNew( 1879 level = TestLevel.COMPLETE, 1880 method = "split", 1881 args = {String.class, Pattern.class} 1882 ) 1883 @ToBeFixed(bug = "1695243", explanation = "the javadoc for split() is incomplete." + 1884 "1. not clear what is supposed result if the pattern string is empty.") testSplitPattern()1885 public void testSplitPattern() { 1886 String testString = "abccbadecdebz"; 1887 assertEquals(calculateCharsCount(testString, "c") + 1, 1888 TextUtils.split(testString, Pattern.compile("c")).length); 1889 assertEquals(calculateCharsCount(testString, "a") + 1, 1890 TextUtils.split(testString, Pattern.compile("a")).length); 1891 assertEquals(calculateCharsCount(testString, "z") + 1, 1892 TextUtils.split(testString, Pattern.compile("z")).length); 1893 assertEquals(calculateCharsCount(testString, "de") + 1, 1894 TextUtils.split(testString, Pattern.compile("de")).length); 1895 int totalCount = 1 + calculateCharsCount(testString, "a") 1896 + calculateCharsCount(testString, "b") + calculateCharsCount(testString, "c"); 1897 assertEquals(totalCount, 1898 TextUtils.split(testString, Pattern.compile("[a-c]")).length); 1899 assertEquals(0, TextUtils.split("", Pattern.compile("a")).length); 1900 // issue 1695243, not clear what is supposed result if the pattern string is empty. 1901 assertEquals(testString.length() + 2, 1902 TextUtils.split(testString, Pattern.compile("")).length); 1903 1904 try { 1905 TextUtils.split(null, Pattern.compile("a")); 1906 fail("Should throw NullPointerException!"); 1907 } catch (NullPointerException e) { 1908 // expect 1909 } 1910 try { 1911 TextUtils.split("abccbadecdebz", (Pattern) null); 1912 fail("Should throw NullPointerException!"); 1913 } catch (NullPointerException e) { 1914 // expect 1915 } 1916 } 1917 1918 /* 1919 * return the appearance count of searched chars in text. 1920 */ calculateCharsCount(CharSequence text, CharSequence searches)1921 private int calculateCharsCount(CharSequence text, CharSequence searches) { 1922 int count = 0; 1923 int start = TextUtils.indexOf(text, searches, 0); 1924 1925 while (start != -1) { 1926 count++; 1927 start = TextUtils.indexOf(text, searches, start + 1); 1928 } 1929 return count; 1930 } 1931 1932 @TestTargetNew( 1933 level = TestLevel.COMPLETE, 1934 method = "split", 1935 args = {String.class, String.class} 1936 ) 1937 @ToBeFixed(bug = "1695243", explanation = "the javadoc for split() is incomplete." + 1938 "1. not clear what is supposed result if the pattern string is empty.") testSplitString()1939 public void testSplitString() { 1940 String testString = "abccbadecdebz"; 1941 assertEquals(calculateCharsCount(testString, "c") + 1, 1942 TextUtils.split("abccbadecdebz", "c").length); 1943 assertEquals(calculateCharsCount(testString, "a") + 1, 1944 TextUtils.split("abccbadecdebz", "a").length); 1945 assertEquals(calculateCharsCount(testString, "z") + 1, 1946 TextUtils.split("abccbadecdebz", "z").length); 1947 assertEquals(calculateCharsCount(testString, "de") + 1, 1948 TextUtils.split("abccbadecdebz", "de").length); 1949 assertEquals(0, TextUtils.split("", "a").length); 1950 // issue 1695243, not clear what is supposed result if the pattern string is empty. 1951 assertEquals(testString.length() + 2, 1952 TextUtils.split("abccbadecdebz", "").length); 1953 1954 try { 1955 TextUtils.split(null, "a"); 1956 fail("Should throw NullPointerException!"); 1957 } catch (NullPointerException e) { 1958 // expect 1959 } 1960 try { 1961 TextUtils.split("abccbadecdebz", (String) null); 1962 fail("Should throw NullPointerException!"); 1963 } catch (NullPointerException e) { 1964 // expect 1965 } 1966 } 1967 1968 @TestTargetNew( 1969 level = TestLevel.COMPLETE, 1970 method = "stringOrSpannedString", 1971 args = {CharSequence.class} 1972 ) 1973 @ToBeFixed(bug = "1695243", explanation = "the javadoc for" + 1974 " stringOrSpannedString() does not exist.") testStringOrSpannedString()1975 public void testStringOrSpannedString() { 1976 assertNull(TextUtils.stringOrSpannedString(null)); 1977 1978 SpannedString spannedString = new SpannedString("Spanned String"); 1979 assertSame(spannedString, TextUtils.stringOrSpannedString(spannedString)); 1980 1981 SpannableString spannableString = new SpannableString("Spannable String"); 1982 assertEquals("Spannable String", 1983 TextUtils.stringOrSpannedString(spannableString).toString()); 1984 assertEquals(SpannedString.class, 1985 TextUtils.stringOrSpannedString(spannableString).getClass()); 1986 1987 StringBuffer stringBuffer = new StringBuffer("String Buffer"); 1988 assertEquals("String Buffer", 1989 TextUtils.stringOrSpannedString(stringBuffer).toString()); 1990 assertEquals(String.class, 1991 TextUtils.stringOrSpannedString(stringBuffer).getClass()); 1992 } 1993 1994 @TestTargetNew( 1995 level = TestLevel.COMPLETE, 1996 method = "substring", 1997 args = {CharSequence.class, int.class, int.class} 1998 ) 1999 @ToBeFixed(bug = "1695243", explanation = "the javadoc for substring() is incomplete." + 2000 "1. doesn't explain @param and @return" + 2001 "2. not clear what is supposed to happen if source is null." + 2002 "3. doesn't explain the thrown IndexOutOfBoundsException") testSubString()2003 public void testSubString() { 2004 String string = "String"; 2005 assertSame(string, TextUtils.substring(string, 0, string.length())); 2006 assertEquals("Strin", TextUtils.substring(string, 0, string.length() - 1)); 2007 assertEquals("", TextUtils.substring(string, 1, 1)); 2008 2009 try { 2010 TextUtils.substring(string, string.length(), 0); 2011 fail("Should throw IndexOutOfBoundsException!"); 2012 } catch (IndexOutOfBoundsException e) { 2013 // expected 2014 } 2015 2016 try { 2017 TextUtils.substring(string, -1, string.length()); 2018 fail("Should throw IndexOutOfBoundsException!"); 2019 } catch (IndexOutOfBoundsException e) { 2020 // expected 2021 } 2022 2023 try { 2024 TextUtils.substring(string, Integer.MAX_VALUE, string.length()); 2025 fail("Should throw IndexOutOfBoundsException!"); 2026 } catch (IndexOutOfBoundsException e) { 2027 // expected 2028 } 2029 2030 try { 2031 TextUtils.substring(string, 0, -1); 2032 fail("Should throw IndexOutOfBoundsException!"); 2033 } catch (IndexOutOfBoundsException e) { 2034 // expected 2035 } 2036 2037 try { 2038 TextUtils.substring(string, 0, Integer.MAX_VALUE); 2039 fail("Should throw IndexOutOfBoundsException!"); 2040 } catch (IndexOutOfBoundsException e) { 2041 // expected 2042 } 2043 2044 try { 2045 TextUtils.substring(null, 0, string.length()); 2046 fail("Should throw NullPointerException!"); 2047 } catch (NullPointerException e) { 2048 // expected 2049 } 2050 2051 StringBuffer stringBuffer = new StringBuffer("String Buffer"); 2052 assertEquals("Strin", TextUtils.substring(stringBuffer, 0, string.length() - 1)); 2053 assertEquals("", TextUtils.substring(stringBuffer, 1, 1)); 2054 2055 MockGetChars mockGetChars = new MockGetChars(); 2056 TextUtils.substring(mockGetChars, 0, string.length()); 2057 assertTrue(mockGetChars.hasCalledGetChars()); 2058 } 2059 2060 @TestTargetNew( 2061 level = TestLevel.COMPLETE, 2062 method = "writeToParcel", 2063 args = {CharSequence.class, Parcel.class, int.class} 2064 ) 2065 @ToBeFixed(bug = "1695243", explanation = "the javadoc for writeToParcel() is incomplete." + 2066 "1. doesn't explain @param and @return" + 2067 "2. not clear is it the supposed result when the CharSequence is null.") testWriteToParcel()2068 public void testWriteToParcel() { 2069 Parcel p = Parcel.obtain(); 2070 2071 Parcelable.Creator<CharSequence> creator = TextUtils.CHAR_SEQUENCE_CREATOR; 2072 2073 String string = "String"; 2074 TextUtils.writeToParcel(string, p, 0); 2075 p.setDataPosition(0); 2076 assertEquals(string, creator.createFromParcel(p).toString()); 2077 p.recycle(); 2078 2079 p = Parcel.obtain(); 2080 TextUtils.writeToParcel(null, p, 0); 2081 p.setDataPosition(0); 2082 assertNull(creator.createFromParcel(p)); 2083 p.recycle(); 2084 2085 p = Parcel.obtain(); 2086 SpannableString spannableString = new SpannableString("Spannable String"); 2087 URLSpan urlSpan = new URLSpan("URL Span"); 2088 int urlSpanStart = spannableString.length() >> 1; 2089 int urlSpanEnd = spannableString.length(); 2090 spannableString.setSpan(urlSpan, urlSpanStart, urlSpanEnd, 2091 Spanned.SPAN_INCLUSIVE_INCLUSIVE); 2092 TextUtils.writeToParcel(spannableString, p, 0); 2093 p.setDataPosition(0); 2094 SpannableString ret = (SpannableString) creator.createFromParcel(p); 2095 assertEquals("Spannable String", ret.toString()); 2096 Object[] spans = ret.getSpans(0, ret.length(), Object.class); 2097 assertEquals(1, spans.length); 2098 assertEquals("URL Span", ((URLSpan) spans[0]).getURL()); 2099 assertEquals(urlSpanStart, ret.getSpanStart(spans[0])); 2100 assertEquals(urlSpanEnd, ret.getSpanEnd(spans[0])); 2101 assertEquals(Spanned.SPAN_INCLUSIVE_INCLUSIVE, ret.getSpanFlags(spans[0])); 2102 p.recycle(); 2103 2104 p = Parcel.obtain(); 2105 ColorStateList colors = new ColorStateList(new int[][] { 2106 new int[] {android.R.attr.state_focused}, new int[0]}, 2107 new int[] {Color.rgb(0, 255, 0), Color.BLACK}); 2108 int textSize = 20; 2109 TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan( 2110 null, Typeface.ITALIC, textSize, colors, null); 2111 int textAppearanceSpanStart = 0; 2112 int textAppearanceSpanEnd = spannableString.length() >> 1; 2113 spannableString.setSpan(textAppearanceSpan, textAppearanceSpanStart, 2114 textAppearanceSpanEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 2115 TextUtils.writeToParcel(spannableString, p, -1); 2116 p.setDataPosition(0); 2117 ret = (SpannableString) creator.createFromParcel(p); 2118 assertEquals("Spannable String", ret.toString()); 2119 spans = ret.getSpans(0, ret.length(), Object.class); 2120 assertEquals(2, spans.length); 2121 assertEquals("URL Span", ((URLSpan) spans[0]).getURL()); 2122 assertEquals(urlSpanStart, ret.getSpanStart(spans[0])); 2123 assertEquals(urlSpanEnd, ret.getSpanEnd(spans[0])); 2124 assertEquals(Spanned.SPAN_INCLUSIVE_INCLUSIVE, ret.getSpanFlags(spans[0])); 2125 assertEquals(null, ((TextAppearanceSpan) spans[1]).getFamily()); 2126 2127 assertEquals(Typeface.ITALIC, ((TextAppearanceSpan) spans[1]).getTextStyle()); 2128 assertEquals(textSize, ((TextAppearanceSpan) spans[1]).getTextSize()); 2129 2130 assertEquals(colors.toString(), ((TextAppearanceSpan) spans[1]).getTextColor().toString()); 2131 assertEquals(null, ((TextAppearanceSpan) spans[1]).getLinkTextColor()); 2132 assertEquals(textAppearanceSpanStart, ret.getSpanStart(spans[1])); 2133 assertEquals(textAppearanceSpanEnd, ret.getSpanEnd(spans[1])); 2134 assertEquals(Spanned.SPAN_INCLUSIVE_EXCLUSIVE, ret.getSpanFlags(spans[1])); 2135 p.recycle(); 2136 2137 try { 2138 TextUtils.writeToParcel(spannableString, null, 0); 2139 fail("Should throw NullPointerException!"); 2140 } catch (NullPointerException e) { 2141 // expected 2142 } 2143 } 2144 2145 @TestTargetNew( 2146 level = TestLevel.COMPLETE, 2147 method = "getCapsMode", 2148 args = {CharSequence.class, int.class, int.class} 2149 ) 2150 @ToBeFixed(bug = "1586346", explanation = "return cap mode which is NOT set in reqModes") testGetCapsMode()2151 public void testGetCapsMode() { 2152 final int CAP_MODE_ALL = TextUtils.CAP_MODE_CHARACTERS 2153 | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES; 2154 final int CAP_MODE_CHARACTERS_AND_WORD = 2155 TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS; 2156 String testString = "Start. Sentence word!No space before\n\t" + 2157 "Paragraph? (\"\'skip begin\'\"). skip end"; 2158 2159 // CAP_MODE_SENTENCES should be in effect in the whole text. 2160 for (int i = 0; i < testString.length(); i++) { 2161 assertEquals(TextUtils.CAP_MODE_CHARACTERS, 2162 TextUtils.getCapsMode(testString, i, TextUtils.CAP_MODE_CHARACTERS)); 2163 } 2164 2165 // all modes should be in effect at the start of the text. 2166 assertEquals(TextUtils.CAP_MODE_WORDS, 2167 TextUtils.getCapsMode(testString, 0, TextUtils.CAP_MODE_WORDS)); 2168 // issue 1586346 2169 assertEquals(TextUtils.CAP_MODE_WORDS, 2170 TextUtils.getCapsMode(testString, 0, TextUtils.CAP_MODE_SENTENCES)); 2171 assertEquals(CAP_MODE_CHARACTERS_AND_WORD, 2172 TextUtils.getCapsMode(testString, 0, CAP_MODE_ALL)); 2173 2174 // all mode should be in effect at the position after "." or "?" or "!" + " ". 2175 int offset = testString.indexOf("Sentence word!"); 2176 assertEquals(TextUtils.CAP_MODE_WORDS, 2177 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_WORDS)); 2178 assertEquals(TextUtils.CAP_MODE_SENTENCES, 2179 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_SENTENCES)); 2180 // issue 1586346 2181 assertEquals(CAP_MODE_CHARACTERS_AND_WORD, 2182 TextUtils.getCapsMode(testString, 0, CAP_MODE_ALL)); 2183 2184 // CAP_MODE_SENTENCES should NOT be in effect at the position after other words + " ". 2185 offset = testString.indexOf("word!"); 2186 assertEquals(TextUtils.CAP_MODE_WORDS, 2187 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_WORDS)); 2188 assertEquals(0, 2189 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_SENTENCES)); 2190 // issue 1586346 2191 assertEquals(TextUtils.CAP_MODE_CHARACTERS, 2192 TextUtils.getCapsMode(testString, offset, CAP_MODE_ALL)); 2193 2194 // if no space after "." or "?" or "!", CAP_MODE_SENTENCES and CAP_MODE_WORDS 2195 // should NOT be in effect. 2196 offset = testString.indexOf("No space before"); 2197 assertEquals(0, 2198 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_WORDS)); 2199 assertEquals(0, 2200 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_SENTENCES)); 2201 assertEquals(TextUtils.CAP_MODE_CHARACTERS, 2202 TextUtils.getCapsMode(testString, offset, CAP_MODE_ALL)); 2203 2204 // all mode should be in effect at a beginning of a new paragraph. 2205 offset = testString.indexOf("Paragraph"); 2206 assertEquals(TextUtils.CAP_MODE_WORDS, 2207 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_WORDS)); 2208 // issue 1586346 2209 assertEquals(TextUtils.CAP_MODE_WORDS, 2210 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_SENTENCES)); 2211 assertEquals(CAP_MODE_CHARACTERS_AND_WORD, 2212 TextUtils.getCapsMode(testString, offset, CAP_MODE_ALL)); 2213 2214 // some special word which means the start of a sentence should be skipped. 2215 offset = testString.indexOf("skip begin"); 2216 assertEquals(TextUtils.CAP_MODE_WORDS, 2217 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_WORDS)); 2218 assertEquals(TextUtils.CAP_MODE_SENTENCES, 2219 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_SENTENCES)); 2220 // issue 1586346 2221 assertEquals(TextUtils.CAP_MODE_SENTENCES | TextUtils.CAP_MODE_CHARACTERS, 2222 TextUtils.getCapsMode(testString, offset, CAP_MODE_ALL)); 2223 2224 // some special word which means the end of a sentence should be skipped. 2225 offset = testString.indexOf("skip end"); 2226 assertEquals(TextUtils.CAP_MODE_WORDS, 2227 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_WORDS)); 2228 assertEquals(TextUtils.CAP_MODE_SENTENCES, 2229 TextUtils.getCapsMode(testString, offset, TextUtils.CAP_MODE_SENTENCES)); 2230 // issue 1586346 2231 assertEquals(TextUtils.CAP_MODE_SENTENCES | TextUtils.CAP_MODE_CHARACTERS, 2232 TextUtils.getCapsMode(testString, offset, CAP_MODE_ALL)); 2233 } 2234 2235 @TestTargetNew( 2236 level = TestLevel.COMPLETE, 2237 method = "getCapsMode", 2238 args = {CharSequence.class, int.class, int.class} 2239 ) 2240 @ToBeFixed(bug = "1695243", explanation = "the javadoc for substring() is incomplete." + 2241 "1. doesn't describe the expected result when parameter is exceptional.") testGetCapsModeException()2242 public void testGetCapsModeException() { 2243 String testString = "Start. Sentence word!No space before\n\t" + 2244 "Paragraph? (\"\'skip begin\'\"). skip end"; 2245 2246 int offset = testString.indexOf("Sentence word!"); 2247 assertEquals(TextUtils.CAP_MODE_CHARACTERS, 2248 TextUtils.getCapsMode(null, offset, TextUtils.CAP_MODE_CHARACTERS)); 2249 2250 try { 2251 TextUtils.getCapsMode(null, offset, TextUtils.CAP_MODE_SENTENCES); 2252 fail("Should throw NullPointerException!"); 2253 } catch (NullPointerException e) { 2254 // expected 2255 } 2256 2257 try { 2258 TextUtils.getCapsMode(testString, -1, TextUtils.CAP_MODE_SENTENCES); 2259 fail("Should throw IndexOutOfBoundsException!"); 2260 } catch (IndexOutOfBoundsException e) { 2261 // expected 2262 } 2263 2264 try { 2265 TextUtils.getCapsMode(testString, testString.length() + 1, 2266 TextUtils.CAP_MODE_SENTENCES); 2267 fail("Should throw IndexOutOfBoundsException!"); 2268 } catch (IndexOutOfBoundsException e) { 2269 // expected 2270 } 2271 } 2272 2273 @TestTargetNew( 2274 level = TestLevel.COMPLETE, 2275 method = "dumpSpans", 2276 args = {java.lang.CharSequence.class, android.util.Printer.class, java.lang.String.class} 2277 ) testDumpSpans()2278 public void testDumpSpans() { 2279 StringBuilder builder = new StringBuilder(); 2280 StringBuilderPrinter printer = new StringBuilderPrinter(builder); 2281 CharSequence source = "test dump spans"; 2282 String prefix = "prefix"; 2283 2284 assertEquals(0, builder.length()); 2285 TextUtils.dumpSpans(source, printer, prefix); 2286 assertTrue(builder.length() > 0); 2287 2288 builder = new StringBuilder(); 2289 printer = new StringBuilderPrinter(builder); 2290 assertEquals(0, builder.length()); 2291 SpannableString spanned = new SpannableString(source); 2292 spanned.setSpan(new Object(), 0, source.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); 2293 TextUtils.dumpSpans(spanned, printer, prefix); 2294 assertTrue(builder.length() > 0); 2295 } 2296 } 2297