blob: 472b3e2cd20d752bb4ec3c222646964309547ad1 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Neal Nguyen1a44d5d2010-01-13 10:42:43 -080017package android.text;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +010019import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertNotNull;
22import static org.junit.Assert.assertNull;
Roozbeh Pournader205a9932017-06-08 00:23:42 -070023import static org.junit.Assert.assertSame;
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +010024import static org.junit.Assert.assertTrue;
25import static org.junit.Assert.fail;
26
Martin Wallgrencee20512011-04-07 14:45:43 +020027import android.os.Parcel;
Siyamed Sinir68089c82016-06-29 16:55:35 -070028import android.support.test.filters.LargeTest;
29import android.support.test.filters.SmallTest;
Roozbeh Pournader205a9932017-06-08 00:23:42 -070030import android.support.test.runner.AndroidJUnit4;
Siyamed Sinir68089c82016-06-29 16:55:35 -070031import android.test.MoreAsserts;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.text.style.StyleSpan;
The Android Open Source Projectee7e6a72010-06-03 09:03:58 -070033import android.text.util.Rfc822Token;
34import android.text.util.Rfc822Tokenizer;
Roozbeh Pournader463b4822015-08-06 16:04:45 -070035import android.view.View;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036
Roozbeh Pournader205a9932017-06-08 00:23:42 -070037import com.google.android.collect.Lists;
38
39import org.junit.Test;
40import org.junit.runner.RunWith;
41
Gilles Debunne1e3ac182011-03-08 14:22:34 -080042import java.util.ArrayList;
43import java.util.List;
Roozbeh Pournader463b4822015-08-06 16:04:45 -070044import java.util.Locale;
Paul Westbrook7762d932009-12-11 14:13:48 -080045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046/**
47 * TextUtilsTest tests {@link TextUtils}.
48 */
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +010049@SmallTest
50@RunWith(AndroidJUnit4.class)
51public class TextUtilsTest {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +010053 @Test
54 public void testBasic() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 assertEquals("", TextUtils.concat());
56 assertEquals("foo", TextUtils.concat("foo"));
57 assertEquals("foobar", TextUtils.concat("foo", "bar"));
58 assertEquals("foobarbaz", TextUtils.concat("foo", "bar", "baz"));
59
60 SpannableString foo = new SpannableString("foo");
61 foo.setSpan("foo", 1, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
62
63 SpannableString bar = new SpannableString("bar");
64 bar.setSpan("bar", 1, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
65
66 SpannableString baz = new SpannableString("baz");
67 baz.setSpan("baz", 1, 2, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
68
69 assertEquals("foo", TextUtils.concat(foo).toString());
70 assertEquals("foobar", TextUtils.concat(foo, bar).toString());
71 assertEquals("foobarbaz", TextUtils.concat(foo, bar, baz).toString());
72
73 assertEquals(1, ((Spanned) TextUtils.concat(foo)).getSpanStart("foo"));
74
75 assertEquals(1, ((Spanned) TextUtils.concat(foo, bar)).getSpanStart("foo"));
76 assertEquals(4, ((Spanned) TextUtils.concat(foo, bar)).getSpanStart("bar"));
77
78 assertEquals(1, ((Spanned) TextUtils.concat(foo, bar, baz)).getSpanStart("foo"));
79 assertEquals(4, ((Spanned) TextUtils.concat(foo, bar, baz)).getSpanStart("bar"));
80 assertEquals(7, ((Spanned) TextUtils.concat(foo, bar, baz)).getSpanStart("baz"));
81
82 assertTrue(TextUtils.concat("foo", "bar") instanceof String);
83 assertTrue(TextUtils.concat(foo, bar) instanceof SpannedString);
84 }
85
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +010086 @Test
87 public void testTemplateString() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 CharSequence result;
89
90 result = TextUtils.expandTemplate("This is a ^1 of the ^2 broadcast ^3.",
91 "test", "emergency", "system");
92 assertEquals("This is a test of the emergency broadcast system.",
93 result.toString());
94
95 result = TextUtils.expandTemplate("^^^1^^^2^3^a^1^^b^^^c",
96 "one", "two", "three");
97 assertEquals("^one^twothree^aone^b^^c",
98 result.toString());
99
100 result = TextUtils.expandTemplate("^");
101 assertEquals("^", result.toString());
102
103 result = TextUtils.expandTemplate("^^");
104 assertEquals("^", result.toString());
105
106 result = TextUtils.expandTemplate("^^^");
107 assertEquals("^^", result.toString());
108
109 result = TextUtils.expandTemplate("shorter ^1 values ^2.", "a", "");
110 assertEquals("shorter a values .", result.toString());
111
112 try {
113 TextUtils.expandTemplate("Only ^1 value given, but ^2 used.", "foo");
114 fail();
115 } catch (IllegalArgumentException e) {
116 }
117
118 try {
119 TextUtils.expandTemplate("^1 value given, and ^0 used.", "foo");
120 fail();
121 } catch (IllegalArgumentException e) {
122 }
123
124 result = TextUtils.expandTemplate("^1 value given, and ^9 used.",
125 "one", "two", "three", "four", "five",
126 "six", "seven", "eight", "nine");
127 assertEquals("one value given, and nine used.", result.toString());
128
129 try {
130 TextUtils.expandTemplate("^1 value given, and ^10 used.",
131 "one", "two", "three", "four", "five",
132 "six", "seven", "eight", "nine", "ten");
133 fail();
134 } catch (IllegalArgumentException e) {
135 }
136
137 // putting carets in the values: expansion is not recursive.
138
139 result = TextUtils.expandTemplate("^2", "foo", "^^");
140 assertEquals("^^", result.toString());
141
142 result = TextUtils.expandTemplate("^^2", "foo", "1");
143 assertEquals("^2", result.toString());
144
145 result = TextUtils.expandTemplate("^1", "value with ^2 in it", "foo");
146 assertEquals("value with ^2 in it", result.toString());
147 }
148
149 /** Fail unless text+spans contains a span 'spanName' with the given start and end. */
150 private void checkContains(Spanned text, String[] spans, String spanName,
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100151 int start, int end) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 for (String i: spans) {
153 if (i.equals(spanName)) {
154 assertEquals(start, text.getSpanStart(i));
155 assertEquals(end, text.getSpanEnd(i));
156 return;
157 }
158 }
159 fail();
160 }
161
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100162 @Test
163 public void testTemplateSpan() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 SpannableString template;
165 Spanned result;
166 String[] spans;
167
168 // ordinary replacement
169
170 template = new SpannableString("a^1b");
171 template.setSpan("before", 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
172 template.setSpan("during", 1, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
173 template.setSpan("after", 3, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
174 template.setSpan("during+after", 1, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
175
176 result = (Spanned) TextUtils.expandTemplate(template, "foo");
177 assertEquals(5, result.length());
178 spans = result.getSpans(0, result.length(), String.class);
179
180 // value is one character longer, so span endpoints should change.
181 assertEquals(4, spans.length);
182 checkContains(result, spans, "before", 0, 1);
183 checkContains(result, spans, "during", 1, 4);
184 checkContains(result, spans, "after", 4, 5);
185 checkContains(result, spans, "during+after", 1, 5);
186
187
188 // replacement with empty string
189
190 result = (Spanned) TextUtils.expandTemplate(template, "");
191 assertEquals(2, result.length());
192 spans = result.getSpans(0, result.length(), String.class);
193
194 // the "during" span should disappear.
195 assertEquals(3, spans.length);
196 checkContains(result, spans, "before", 0, 1);
197 checkContains(result, spans, "after", 1, 2);
198 checkContains(result, spans, "during+after", 1, 2);
199 }
200
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100201 @Test
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 public void testStringSplitterSimple() {
203 stringSplitterTestHelper("a,b,cde", new String[] {"a", "b", "cde"});
204 }
205
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100206 @Test
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 public void testStringSplitterEmpty() {
208 stringSplitterTestHelper("", new String[] {});
209 }
210
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100211 @Test
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 public void testStringSplitterWithLeadingEmptyString() {
213 stringSplitterTestHelper(",a,b,cde", new String[] {"", "a", "b", "cde"});
214 }
215
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100216 @Test
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 public void testStringSplitterWithInternalEmptyString() {
218 stringSplitterTestHelper("a,b,,cde", new String[] {"a", "b", "", "cde"});
219 }
220
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100221 @Test
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 public void testStringSplitterWithTrailingEmptyString() {
223 // A single trailing emtpy string should be ignored.
224 stringSplitterTestHelper("a,b,cde,", new String[] {"a", "b", "cde"});
225 }
226
227 private void stringSplitterTestHelper(String string, String[] expectedStrings) {
228 TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
229 splitter.setString(string);
230 List<String> strings = Lists.newArrayList();
231 for (String s : splitter) {
232 strings.add(s);
233 }
234 MoreAsserts.assertEquals(expectedStrings, strings.toArray(new String[]{}));
235 }
236
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100237 @Test
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 public void testTrim() {
239 String[] strings = { "abc", " abc", " abc", "abc ", "abc ",
240 " abc ", " abc ", "\nabc\n", "\nabc", "abc\n" };
241
242 for (String s : strings) {
243 assertEquals(s.trim().length(), TextUtils.getTrimmedLength(s));
244 }
245 }
246
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100247 @Test
The Android Open Source Projectee7e6a72010-06-03 09:03:58 -0700248 public void testRfc822TokenizerFullAddress() {
249 Rfc822Token[] tokens = Rfc822Tokenizer.tokenize("Foo Bar (something) <foo@google.com>");
250 assertNotNull(tokens);
251 assertEquals(1, tokens.length);
252 assertEquals("foo@google.com", tokens[0].getAddress());
253 assertEquals("Foo Bar", tokens[0].getName());
254 assertEquals("something",tokens[0].getComment());
255 }
256
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100257 @Test
The Android Open Source Projectee7e6a72010-06-03 09:03:58 -0700258 public void testRfc822TokenizeItemWithError() {
259 Rfc822Token[] tokens = Rfc822Tokenizer.tokenize("\"Foo Bar\\");
260 assertNotNull(tokens);
261 assertEquals(1, tokens.length);
262 assertEquals("Foo Bar", tokens[0].getAddress());
263 }
264
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100265 @Test
Mattias Niklewski114f98a2011-01-18 14:27:23 +0100266 public void testRfc822FindToken() {
267 Rfc822Tokenizer tokenizer = new Rfc822Tokenizer();
268 // 0 1 2 3 4
269 // 0 1234 56789012345678901234 5678 90123456789012345
270 String address = "\"Foo\" <foo@google.com>, \"Bar\" <bar@google.com>";
271 assertEquals(0, tokenizer.findTokenStart(address, 21));
272 assertEquals(22, tokenizer.findTokenEnd(address, 21));
273 assertEquals(24, tokenizer.findTokenStart(address, 25));
274 assertEquals(46, tokenizer.findTokenEnd(address, 25));
275 }
276
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100277 @Test
Mattias Niklewski114f98a2011-01-18 14:27:23 +0100278 public void testRfc822FindTokenWithError() {
279 assertEquals(9, new Rfc822Tokenizer().findTokenEnd("\"Foo Bar\\", 0));
280 }
281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 @LargeTest
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100283 @Test
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 public void testEllipsize() {
285 CharSequence s1 = "The quick brown fox jumps over \u00FEhe lazy dog.";
286 CharSequence s2 = new Wrapper(s1);
287 Spannable s3 = new SpannableString(s1);
288 s3.setSpan(new StyleSpan(0), 5, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
289 TextPaint p = new TextPaint();
Eric Fischer1f0dac32009-07-01 18:03:09 -0700290 p.setFlags(p.getFlags() & ~p.DEV_KERN_TEXT_FLAG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
292 for (int i = 0; i < 100; i++) {
293 for (int j = 0; j < 3; j++) {
294 TextUtils.TruncateAt kind = null;
295
296 switch (j) {
297 case 0:
298 kind = TextUtils.TruncateAt.START;
299 break;
300
301 case 1:
302 kind = TextUtils.TruncateAt.END;
303 break;
304
305 case 2:
306 kind = TextUtils.TruncateAt.MIDDLE;
307 break;
308 }
309
310 String out1 = TextUtils.ellipsize(s1, p, i, kind).toString();
311 String out2 = TextUtils.ellipsize(s2, p, i, kind).toString();
312 String out3 = TextUtils.ellipsize(s3, p, i, kind).toString();
313
314 String keep1 = TextUtils.ellipsize(s1, p, i, kind, true, null).toString();
315 String keep2 = TextUtils.ellipsize(s2, p, i, kind, true, null).toString();
316 String keep3 = TextUtils.ellipsize(s3, p, i, kind, true, null).toString();
317
318 String trim1 = keep1.replace("\uFEFF", "");
319
320 // Are all normal output strings identical?
321 assertEquals("wid " + i + " pass " + j, out1, out2);
322 assertEquals("wid " + i + " pass " + j, out2, out3);
323
324 // Are preserved output strings identical?
325 assertEquals("wid " + i + " pass " + j, keep1, keep2);
326 assertEquals("wid " + i + " pass " + j, keep2, keep3);
327
328 // Does trimming padding from preserved yield normal?
329 assertEquals("wid " + i + " pass " + j, out1, trim1);
330
331 // Did preserved output strings preserve length?
332 assertEquals("wid " + i + " pass " + j, keep1.length(), s1.length());
333
334 // Does the output string actually fit in the space?
335 assertTrue("wid " + i + " pass " + j, p.measureText(out1) <= i);
336
337 // Is the padded output the same width as trimmed output?
338 assertTrue("wid " + i + " pass " + j, p.measureText(keep1) == p.measureText(out1));
339 }
340 }
341 }
342
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100343 @Test
Brad Fitzpatrick11fe1812010-09-10 16:07:52 -0700344 public void testDelimitedStringContains() {
345 assertFalse(TextUtils.delimitedStringContains("", ',', null));
346 assertFalse(TextUtils.delimitedStringContains(null, ',', ""));
347 // Whole match
348 assertTrue(TextUtils.delimitedStringContains("gps", ',', "gps"));
349 // At beginning.
350 assertTrue(TextUtils.delimitedStringContains("gps,gpsx,network,mock", ',', "gps"));
351 assertTrue(TextUtils.delimitedStringContains("gps,network,mock", ',', "gps"));
352 // In middle, both without, before & after a false match.
353 assertTrue(TextUtils.delimitedStringContains("network,gps,mock", ',', "gps"));
354 assertTrue(TextUtils.delimitedStringContains("network,gps,gpsx,mock", ',', "gps"));
355 assertTrue(TextUtils.delimitedStringContains("network,gpsx,gps,mock", ',', "gps"));
356 // At the end.
357 assertTrue(TextUtils.delimitedStringContains("network,mock,gps", ',', "gps"));
358 assertTrue(TextUtils.delimitedStringContains("network,mock,gpsx,gps", ',', "gps"));
359 // Not present (but with a false match)
360 assertFalse(TextUtils.delimitedStringContains("network,mock,gpsx", ',', "gps"));
361 }
362
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100363 @Test
Martin Wallgrencee20512011-04-07 14:45:43 +0200364 public void testCharSequenceCreator() {
365 Parcel p = Parcel.obtain();
Roozbeh Pournaderc38d3902017-07-06 17:07:39 -0700366 CharSequence text;
367 try {
368 TextUtils.writeToParcel(null, p, 0);
369 text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
370 assertNull("null CharSequence should generate null from parcel", text);
371 } finally {
372 p.recycle();
373 }
Martin Wallgrencee20512011-04-07 14:45:43 +0200374 p = Parcel.obtain();
Roozbeh Pournaderc38d3902017-07-06 17:07:39 -0700375 try {
376 TextUtils.writeToParcel("test", p, 0);
377 p.setDataPosition(0);
378 text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
379 assertEquals("conversion to/from parcel failed", "test", text);
380 } finally {
381 p.recycle();
382 }
Martin Wallgrencee20512011-04-07 14:45:43 +0200383 }
384
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100385 @Test
Martin Wallgrencee20512011-04-07 14:45:43 +0200386 public void testCharSequenceCreatorNull() {
387 Parcel p;
388 CharSequence text;
389 p = Parcel.obtain();
Roozbeh Pournaderc38d3902017-07-06 17:07:39 -0700390 try {
391 TextUtils.writeToParcel(null, p, 0);
392 p.setDataPosition(0);
393 text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
394 assertNull("null CharSequence should generate null from parcel", text);
395 } finally {
396 p.recycle();
397 }
Martin Wallgrencee20512011-04-07 14:45:43 +0200398 }
399
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100400 @Test
Martin Wallgrencee20512011-04-07 14:45:43 +0200401 public void testCharSequenceCreatorSpannable() {
402 Parcel p;
403 CharSequence text;
404 p = Parcel.obtain();
Roozbeh Pournaderc38d3902017-07-06 17:07:39 -0700405 try {
406 TextUtils.writeToParcel(new SpannableString("test"), p, 0);
407 p.setDataPosition(0);
408 text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
409 assertEquals("conversion to/from parcel failed", "test", text.toString());
410 } finally {
411 p.recycle();
412 }
Martin Wallgrencee20512011-04-07 14:45:43 +0200413 }
414
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100415 @Test
Martin Wallgrencee20512011-04-07 14:45:43 +0200416 public void testCharSequenceCreatorString() {
417 Parcel p;
418 CharSequence text;
419 p = Parcel.obtain();
Roozbeh Pournaderc38d3902017-07-06 17:07:39 -0700420 try {
421 TextUtils.writeToParcel("test", p, 0);
422 p.setDataPosition(0);
423 text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
424 assertEquals("conversion to/from parcel failed", "test", text.toString());
425 } finally {
426 p.recycle();
427 }
Martin Wallgrencee20512011-04-07 14:45:43 +0200428 }
429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 /**
431 * CharSequence wrapper for testing the cases where text is copied into
432 * a char array instead of working from a String or a Spanned.
433 */
434 private static class Wrapper implements CharSequence {
435 private CharSequence mString;
436
437 public Wrapper(CharSequence s) {
438 mString = s;
439 }
440
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100441 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 public int length() {
443 return mString.length();
444 }
445
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100446 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 public char charAt(int off) {
448 return mString.charAt(off);
449 }
450
Gilles Debunne1e3ac182011-03-08 14:22:34 -0800451 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 public String toString() {
453 return mString.toString();
454 }
455
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100456 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 public CharSequence subSequence(int start, int end) {
458 return new Wrapper(mString.subSequence(start, end));
459 }
460 }
Gilles Debunne1e3ac182011-03-08 14:22:34 -0800461
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100462 @Test
Gilles Debunne1e3ac182011-03-08 14:22:34 -0800463 public void testRemoveEmptySpans() {
464 MockSpanned spanned = new MockSpanned();
465
466 spanned.test();
467 spanned.addSpan().test();
468 spanned.addSpan().test();
469 spanned.addSpan().test();
470 spanned.addEmptySpan().test();
471 spanned.addSpan().test();
472 spanned.addEmptySpan().test();
473 spanned.addEmptySpan().test();
474 spanned.addSpan().test();
475
476 spanned.clear();
477 spanned.addEmptySpan().test();
478 spanned.addEmptySpan().test();
479 spanned.addEmptySpan().test();
480 spanned.addSpan().test();
481 spanned.addEmptySpan().test();
482 spanned.addSpan().test();
483
484 spanned.clear();
485 spanned.addSpan().test();
486 spanned.addEmptySpan().test();
487 spanned.addSpan().test();
488 spanned.addEmptySpan().test();
489 spanned.addSpan().test();
490 spanned.addSpan().test();
491 }
492
493 protected static class MockSpanned implements Spanned {
494
495 private List<Object> allSpans = new ArrayList<Object>();
496 private List<Object> nonEmptySpans = new ArrayList<Object>();
497
498 public void clear() {
499 allSpans.clear();
500 nonEmptySpans.clear();
501 }
502
503 public MockSpanned addSpan() {
504 Object o = new Object();
505 allSpans.add(o);
506 nonEmptySpans.add(o);
507 return this;
508 }
509
510 public MockSpanned addEmptySpan() {
511 Object o = new Object();
512 allSpans.add(o);
513 return this;
514 }
515
516 public void test() {
517 Object[] nonEmpty = TextUtils.removeEmptySpans(allSpans.toArray(), this, Object.class);
518 assertEquals("Mismatched array size", nonEmptySpans.size(), nonEmpty.length);
519 for (int i=0; i<nonEmpty.length; i++) {
520 assertEquals("Span differ", nonEmptySpans.get(i), nonEmpty[i]);
521 }
522 }
523
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100524 @Override
Gilles Debunne1e3ac182011-03-08 14:22:34 -0800525 public char charAt(int arg0) {
526 return 0;
527 }
528
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100529 @Override
Gilles Debunne1e3ac182011-03-08 14:22:34 -0800530 public int length() {
531 return 0;
532 }
533
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100534 @Override
Gilles Debunne1e3ac182011-03-08 14:22:34 -0800535 public CharSequence subSequence(int arg0, int arg1) {
536 return null;
537 }
538
539 @Override
540 public <T> T[] getSpans(int start, int end, Class<T> type) {
541 return null;
542 }
543
544 @Override
545 public int getSpanStart(Object tag) {
546 return 0;
547 }
548
549 @Override
550 public int getSpanEnd(Object tag) {
551 return nonEmptySpans.contains(tag) ? 1 : 0;
552 }
553
554 @Override
555 public int getSpanFlags(Object tag) {
556 return 0;
557 }
558
559 @Override
560 public int nextSpanTransition(int start, int limit, Class type) {
561 return 0;
562 }
563 }
Roozbeh Pournader463b4822015-08-06 16:04:45 -0700564
Andrei Stingaceanue1a7d0d2017-04-24 16:53:17 +0100565 @Test
Roozbeh Pournader463b4822015-08-06 16:04:45 -0700566 public void testGetLayoutDirectionFromLocale() {
567 assertEquals(View.LAYOUT_DIRECTION_LTR, TextUtils.getLayoutDirectionFromLocale(null));
568 assertEquals(View.LAYOUT_DIRECTION_LTR,
569 TextUtils.getLayoutDirectionFromLocale(Locale.ROOT));
570 assertEquals(View.LAYOUT_DIRECTION_LTR,
571 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("en")));
572 assertEquals(View.LAYOUT_DIRECTION_LTR,
573 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("en-US")));
574 assertEquals(View.LAYOUT_DIRECTION_LTR,
575 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az")));
576 assertEquals(View.LAYOUT_DIRECTION_LTR,
577 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-AZ")));
578 assertEquals(View.LAYOUT_DIRECTION_LTR,
579 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-Latn")));
580 assertEquals(View.LAYOUT_DIRECTION_LTR,
581 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("en-EG")));
582 assertEquals(View.LAYOUT_DIRECTION_LTR,
583 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("ar-Latn")));
584
585 assertEquals(View.LAYOUT_DIRECTION_RTL,
586 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("ar")));
587 assertEquals(View.LAYOUT_DIRECTION_RTL,
588 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("fa")));
589 assertEquals(View.LAYOUT_DIRECTION_RTL,
590 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("he")));
591 assertEquals(View.LAYOUT_DIRECTION_RTL,
592 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("iw")));
593 assertEquals(View.LAYOUT_DIRECTION_RTL,
594 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("ur")));
595 assertEquals(View.LAYOUT_DIRECTION_RTL,
596 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("dv")));
597 assertEquals(View.LAYOUT_DIRECTION_RTL,
598 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-Arab")));
599 assertEquals(View.LAYOUT_DIRECTION_RTL,
600 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("az-IR")));
601 assertEquals(View.LAYOUT_DIRECTION_RTL,
602 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("fa-US")));
603 assertEquals(View.LAYOUT_DIRECTION_RTL,
604 TextUtils.getLayoutDirectionFromLocale(Locale.forLanguageTag("tr-Arab")));
605 }
Roozbeh Pournader205a9932017-06-08 00:23:42 -0700606
607 @Test
608 public void testToUpperCase() {
609 {
610 final CharSequence result = TextUtils.toUpperCase(null, "abc", false);
611 assertEquals(StringBuilder.class, result.getClass());
612 assertEquals("ABC", result.toString());
613 }
614 {
615 final SpannableString str = new SpannableString("abc");
616 Object span = new Object();
617 str.setSpan(span, 1, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
618
619 final CharSequence result = TextUtils.toUpperCase(null, str, true /* copySpans */);
620 assertEquals(SpannableStringBuilder.class, result.getClass());
621 assertEquals("ABC", result.toString());
622 final Spanned spanned = (Spanned) result;
623 final Object[] resultSpans = spanned.getSpans(0, result.length(), Object.class);
624 assertEquals(1, resultSpans.length);
625 assertSame(span, resultSpans[0]);
626 assertEquals(1, spanned.getSpanStart(span));
627 assertEquals(2, spanned.getSpanEnd(span));
628 assertEquals(Spanned.SPAN_INCLUSIVE_INCLUSIVE, spanned.getSpanFlags(span));
629 }
630 {
631 final Locale turkish = new Locale("tr", "TR");
632 final CharSequence result = TextUtils.toUpperCase(turkish, "i", false);
633 assertEquals(StringBuilder.class, result.getClass());
634 assertEquals("İ", result.toString());
635 }
636 {
637 final String str = "ABC";
638 assertSame(str, TextUtils.toUpperCase(null, str, false));
639 }
640 {
641 final SpannableString str = new SpannableString("ABC");
642 str.setSpan(new Object(), 1, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
643 assertSame(str, TextUtils.toUpperCase(null, str, true /* copySpans */));
644 }
645 }
646
647 // Copied from cts/tests/tests/widget/src/android/widget/cts/TextViewTest.java and modified
648 // for the TextUtils.toUpperCase method.
649 @Test
650 public void testToUpperCase_SpansArePreserved() {
651 final Locale greek = new Locale("el", "GR");
652 final String lowerString = "ι\u0301ριδα"; // ίριδα with first letter decomposed
653 final String upperString = "ΙΡΙΔΑ"; // uppercased
654 // expected lowercase to uppercase index map
655 final int[] indexMap = {0, 1, 1, 2, 3, 4, 5};
656 final int flags = Spanned.SPAN_INCLUSIVE_INCLUSIVE;
657
658 final Spannable source = new SpannableString(lowerString);
659 source.setSpan(new Object(), 0, 1, flags);
660 source.setSpan(new Object(), 1, 2, flags);
661 source.setSpan(new Object(), 2, 3, flags);
662 source.setSpan(new Object(), 3, 4, flags);
663 source.setSpan(new Object(), 4, 5, flags);
664 source.setSpan(new Object(), 5, 6, flags);
665 source.setSpan(new Object(), 0, 2, flags);
666 source.setSpan(new Object(), 1, 3, flags);
667 source.setSpan(new Object(), 2, 4, flags);
668 source.setSpan(new Object(), 0, 6, flags);
669 final Object[] sourceSpans = source.getSpans(0, source.length(), Object.class);
670
671 final CharSequence uppercase = TextUtils.toUpperCase(greek, source, true /* copySpans */);
672 assertEquals(SpannableStringBuilder.class, uppercase.getClass());
673 final Spanned result = (Spanned) uppercase;
674
675 assertEquals(upperString, result.toString());
676 final Object[] resultSpans = result.getSpans(0, result.length(), Object.class);
677 assertEquals(sourceSpans.length, resultSpans.length);
678 for (int i = 0; i < sourceSpans.length; i++) {
679 assertSame(sourceSpans[i], resultSpans[i]);
680 final Object span = sourceSpans[i];
681 assertEquals(indexMap[source.getSpanStart(span)], result.getSpanStart(span));
682 assertEquals(indexMap[source.getSpanEnd(span)], result.getSpanEnd(span));
683 assertEquals(source.getSpanFlags(span), result.getSpanFlags(span));
684 }
685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686}