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