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