1 /* 2 * Copyright (C) 2014 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 com.android.inputmethod.compat; 18 19 import android.graphics.Typeface; 20 import android.os.Build; 21 import android.test.AndroidTestCase; 22 import android.test.suitebuilder.annotation.SmallTest; 23 import android.text.SpannableString; 24 import android.text.Spanned; 25 import android.text.style.StyleSpan; 26 27 import java.util.Locale; 28 29 @SmallTest 30 public class LocaleSpanCompatUtilsTests extends AndroidTestCase { testInstantiatable()31 public void testInstantiatable() { 32 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 33 // LocaleSpan isn't yet available. 34 return; 35 } 36 assertTrue(LocaleSpanCompatUtils.isLocaleSpanAvailable()); 37 final Object japaneseLocaleSpan = LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE); 38 assertNotNull(japaneseLocaleSpan); 39 assertEquals(Locale.JAPANESE, 40 LocaleSpanCompatUtils.getLocaleFromLocaleSpan(japaneseLocaleSpan)); 41 } 42 assertLocaleSpan(final Spanned spanned, final int index, final int expectedStart, final int expectedEnd, final Locale expectedLocale, final int expectedSpanFlags)43 private static void assertLocaleSpan(final Spanned spanned, final int index, 44 final int expectedStart, final int expectedEnd, 45 final Locale expectedLocale, final int expectedSpanFlags) { 46 final Object span = spanned.getSpans(0, spanned.length(), Object.class)[index]; 47 assertEquals(expectedLocale, LocaleSpanCompatUtils.getLocaleFromLocaleSpan(span)); 48 assertEquals(expectedStart, spanned.getSpanStart(span)); 49 assertEquals(expectedEnd, spanned.getSpanEnd(span)); 50 assertEquals(expectedSpanFlags, spanned.getSpanFlags(span)); 51 } 52 assertSpanEquals(final Object expectedSpan, final Spanned spanned, final int index)53 private static void assertSpanEquals(final Object expectedSpan, final Spanned spanned, 54 final int index) { 55 final Object[] spans = spanned.getSpans(0, spanned.length(), Object.class); 56 assertEquals(expectedSpan, spans[index]); 57 } 58 assertSpanCount(final int expectedCount, final Spanned spanned)59 private static void assertSpanCount(final int expectedCount, final Spanned spanned) { 60 final Object[] spans = spanned.getSpans(0, spanned.length(), Object.class); 61 assertEquals(expectedCount, spans.length); 62 } 63 testUpdateLocaleSpan()64 public void testUpdateLocaleSpan() { 65 if (!LocaleSpanCompatUtils.isLocaleSpanAvailable()) { 66 return; 67 } 68 69 // Test if the simplest case works. 70 { 71 final SpannableString text = new SpannableString("0123456789"); 72 LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE); 73 assertSpanCount(1, text); 74 assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 75 } 76 77 // Test if only LocaleSpans are updated. 78 { 79 final SpannableString text = new SpannableString("0123456789"); 80 final StyleSpan styleSpan = new StyleSpan(Typeface.BOLD); 81 text.setSpan(styleSpan, 0, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 82 LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE); 83 assertSpanCount(2, text); 84 assertSpanEquals(styleSpan, text, 0); 85 assertLocaleSpan(text, 1, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 86 } 87 88 // Test if two jointed spans are merged into one span. 89 { 90 final SpannableString text = new SpannableString("0123456789"); 91 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3, 92 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 93 LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE); 94 assertSpanCount(1, text); 95 assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 96 } 97 98 // Test if two overlapped spans are merged into one span. 99 { 100 final SpannableString text = new SpannableString("0123456789"); 101 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4, 102 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 103 LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE); 104 assertSpanCount(1, text); 105 assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 106 } 107 108 // Test if three overlapped spans are merged into one span. 109 { 110 final SpannableString text = new SpannableString("0123456789"); 111 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4, 112 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 113 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6, 114 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 115 LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 8, Locale.JAPANESE); 116 assertSpanCount(1, text); 117 assertLocaleSpan(text, 0, 1, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 118 } 119 120 // Test if disjoint spans remain disjoint. 121 { 122 final SpannableString text = new SpannableString("0123456789"); 123 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3, 124 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 125 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6, 126 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 127 LocaleSpanCompatUtils.updateLocaleSpan(text, 8, 9, Locale.JAPANESE); 128 assertSpanCount(3, text); 129 assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 130 assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 131 assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 132 } 133 134 // Test if existing span flags are preserved during merge. 135 { 136 final SpannableString text = new SpannableString("0123456789"); 137 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5, 138 Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE); 139 LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 4, Locale.JAPANESE); 140 assertSpanCount(1, text); 141 assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, 142 Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE); 143 } 144 145 // Test if existing span flags are preserved even when partially overlapped (leading edge). 146 { 147 final SpannableString text = new SpannableString("0123456789"); 148 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5, 149 Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE); 150 LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 7, Locale.JAPANESE); 151 assertSpanCount(1, text); 152 assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, 153 Spanned.SPAN_INCLUSIVE_EXCLUSIVE | Spanned.SPAN_INTERMEDIATE); 154 } 155 156 // Test if existing span flags are preserved even when partially overlapped (trailing edge). 157 { 158 final SpannableString text = new SpannableString("0123456789"); 159 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 3, 7, 160 Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE); 161 LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE); 162 assertSpanCount(1, text); 163 assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, 164 Spanned.SPAN_EXCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE); 165 } 166 167 // Test if existing locale span will be removed when the locale doesn't match. 168 { 169 final SpannableString text = new SpannableString("0123456789"); 170 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 5, 171 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 172 LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 7, Locale.JAPANESE); 173 assertSpanCount(1, text); 174 assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 175 } 176 177 // Test if existing locale span will be removed when the locale doesn't match. (case 2) 178 { 179 final SpannableString text = new SpannableString("0123456789"); 180 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7, 181 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 182 LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 6, Locale.JAPANESE); 183 assertSpanCount(3, text); 184 assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 185 assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 186 assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 187 } 188 189 // Test if existing locale span will be removed when the locale doesn't match. (case 3) 190 { 191 final SpannableString text = new SpannableString("0123456789"); 192 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7, 193 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 194 LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 5, Locale.JAPANESE); 195 assertSpanCount(2, text); 196 assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 197 assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 198 } 199 200 // Test if existing locale span will be removed when the locale doesn't match. (case 3) 201 { 202 final SpannableString text = new SpannableString("0123456789"); 203 text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7, 204 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 205 LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 8, Locale.JAPANESE); 206 assertSpanCount(2, text); 207 assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 208 assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 209 } 210 } 211 } 212