TextClassificationManagerTest.java revision 86ef9827dabc05832997898e8d85504e007a206b
1/* 2 * Copyright (C) 2017 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 17package android.view.textclassifier; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertThat; 21import static org.mockito.Mockito.mock; 22 23import android.os.LocaleList; 24import android.support.test.InstrumentationRegistry; 25import android.support.test.filters.SmallTest; 26import android.support.test.runner.AndroidJUnit4; 27 28import org.hamcrest.BaseMatcher; 29import org.hamcrest.Description; 30import org.hamcrest.Matcher; 31import org.junit.Before; 32import org.junit.Test; 33import org.junit.runner.RunWith; 34 35import java.util.List; 36import java.util.Locale; 37 38@SmallTest 39@RunWith(AndroidJUnit4.class) 40public class TextClassificationManagerTest { 41 42 private static final LocaleList LOCALES = LocaleList.forLanguageTags("en"); 43 private static final String NO_TYPE = null; 44 45 private TextClassificationManager mTcm; 46 private TextClassifier mClassifier; 47 48 @Before 49 public void setup() { 50 mTcm = InstrumentationRegistry.getTargetContext() 51 .getSystemService(TextClassificationManager.class); 52 mTcm.setTextClassifier(null); 53 mClassifier = mTcm.getTextClassifier(); 54 } 55 56 @Test 57 public void testSmartSelection() { 58 if (isTextClassifierDisabled()) return; 59 60 String text = "Contact me at droid@android.com"; 61 String selected = "droid"; 62 String suggested = "droid@android.com"; 63 int startIndex = text.indexOf(selected); 64 int endIndex = startIndex + selected.length(); 65 int smartStartIndex = text.indexOf(suggested); 66 int smartEndIndex = smartStartIndex + suggested.length(); 67 68 assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES), 69 isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL)); 70 } 71 72 @Test 73 public void testSmartSelection_nullLocaleList() { 74 if (isTextClassifierDisabled()) return; 75 76 String text = "Contact me at droid@android.com"; 77 String selected = "droid"; 78 String suggested = "droid@android.com"; 79 int startIndex = text.indexOf(selected); 80 int endIndex = startIndex + selected.length(); 81 int smartStartIndex = text.indexOf(suggested); 82 int smartEndIndex = smartStartIndex + suggested.length(); 83 LocaleList nullLocales = null; 84 85 assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, nullLocales), 86 isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL)); 87 } 88 89 @Test 90 public void testSmartSelection_url() { 91 if (isTextClassifierDisabled()) return; 92 93 String text = "Visit http://www.android.com for more information"; 94 String selected = "http"; 95 String suggested = "http://www.android.com"; 96 int startIndex = text.indexOf(selected); 97 int endIndex = startIndex + selected.length(); 98 int smartStartIndex = text.indexOf(suggested); 99 int smartEndIndex = smartStartIndex + suggested.length(); 100 101 assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES), 102 isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_URL)); 103 } 104 105 @Test 106 public void testSmartSelection_withEmoji() { 107 if (isTextClassifierDisabled()) return; 108 109 String text = "\uD83D\uDE02 Hello."; 110 String selected = "Hello"; 111 int startIndex = text.indexOf(selected); 112 int endIndex = startIndex + selected.length(); 113 114 assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES), 115 isTextSelection(startIndex, endIndex, NO_TYPE)); 116 } 117 118 @Test 119 public void testClassifyText() { 120 if (isTextClassifierDisabled()) return; 121 122 String text = "Contact me at droid@android.com"; 123 String classifiedText = "droid@android.com"; 124 int startIndex = text.indexOf(classifiedText); 125 int endIndex = startIndex + classifiedText.length(); 126 assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES), 127 isTextClassification( 128 classifiedText, 129 TextClassifier.TYPE_EMAIL, 130 "mailto:" + classifiedText)); 131 } 132 133 @Test 134 public void testTextClassifyText_url() { 135 if (isTextClassifierDisabled()) return; 136 137 String text = "Visit www.android.com for more information"; 138 String classifiedText = "www.android.com"; 139 int startIndex = text.indexOf(classifiedText); 140 int endIndex = startIndex + classifiedText.length(); 141 assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES), 142 isTextClassification( 143 classifiedText, 144 TextClassifier.TYPE_URL, 145 "http://" + classifiedText)); 146 } 147 148 @Test 149 public void testTextClassifyText_url_inCaps() { 150 if (isTextClassifierDisabled()) return; 151 152 String text = "Visit HTTP://ANDROID.COM for more information"; 153 String classifiedText = "HTTP://ANDROID.COM"; 154 int startIndex = text.indexOf(classifiedText); 155 int endIndex = startIndex + classifiedText.length(); 156 assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES), 157 isTextClassification( 158 classifiedText, 159 TextClassifier.TYPE_URL, 160 "http://ANDROID.COM")); 161 } 162 163 @Test 164 public void testTextClassifyText_nullLocaleList() { 165 if (isTextClassifierDisabled()) return; 166 167 String text = "Contact me at droid@android.com"; 168 String classifiedText = "droid@android.com"; 169 int startIndex = text.indexOf(classifiedText); 170 int endIndex = startIndex + classifiedText.length(); 171 LocaleList nullLocales = null; 172 assertThat(mClassifier.classifyText(text, startIndex, endIndex, nullLocales), 173 isTextClassification( 174 classifiedText, 175 TextClassifier.TYPE_EMAIL, 176 "mailto:" + classifiedText)); 177 } 178 179 @Test 180 public void testLanguageDetection() { 181 if (isTextClassifierDisabled()) return; 182 183 String text = "This is a piece of English text"; 184 assertThat(mTcm.detectLanguages(text), isDetectedLanguage("en")); 185 186 text = "Das ist ein deutscher Text"; 187 assertThat(mTcm.detectLanguages(text), isDetectedLanguage("de")); 188 189 text = "これは日本語のテキストです"; 190 assertThat(mTcm.detectLanguages(text), isDetectedLanguage("ja")); 191 } 192 193 @Test 194 public void testSetTextClassifier() { 195 TextClassifier classifier = mock(TextClassifier.class); 196 mTcm.setTextClassifier(classifier); 197 assertEquals(classifier, mTcm.getTextClassifier()); 198 } 199 200 private boolean isTextClassifierDisabled() { 201 return mClassifier == TextClassifier.NO_OP; 202 } 203 204 private static Matcher<TextSelection> isTextSelection( 205 final int startIndex, final int endIndex, final String type) { 206 return new BaseMatcher<TextSelection>() { 207 @Override 208 public boolean matches(Object o) { 209 if (o instanceof TextSelection) { 210 TextSelection selection = (TextSelection) o; 211 return startIndex == selection.getSelectionStartIndex() 212 && endIndex == selection.getSelectionEndIndex() 213 && typeMatches(selection, type); 214 } 215 return false; 216 } 217 218 private boolean typeMatches(TextSelection selection, String type) { 219 return type == null 220 || (selection.getEntityCount() > 0 221 && type.trim().equalsIgnoreCase(selection.getEntity(0))); 222 } 223 224 @Override 225 public void describeTo(Description description) { 226 description.appendValue( 227 String.format("%d, %d, %s", startIndex, endIndex, type)); 228 } 229 }; 230 } 231 232 private static Matcher<TextClassification> isTextClassification( 233 final String text, final String type, final String intentUri) { 234 return new BaseMatcher<TextClassification>() { 235 @Override 236 public boolean matches(Object o) { 237 if (o instanceof TextClassification) { 238 TextClassification result = (TextClassification) o; 239 final boolean typeRequirementSatisfied; 240 String scheme; 241 switch (type) { 242 case TextClassifier.TYPE_EMAIL: 243 scheme = result.getIntent().getData().getScheme(); 244 typeRequirementSatisfied = "mailto".equals(scheme); 245 break; 246 case TextClassifier.TYPE_URL: 247 scheme = result.getIntent().getData().getScheme(); 248 typeRequirementSatisfied = "http".equals(scheme) 249 || "https".equals(scheme); 250 break; 251 default: 252 typeRequirementSatisfied = true; 253 } 254 255 return typeRequirementSatisfied 256 && text.equals(result.getText()) 257 && result.getEntityCount() > 0 258 && type.equals(result.getEntity(0)) 259 && intentUri.equals(result.getIntent().getDataString()); 260 // TODO: Include other properties. 261 } 262 return false; 263 } 264 265 @Override 266 public void describeTo(Description description) { 267 description.appendText("text=").appendValue(text) 268 .appendText(", type=").appendValue(type) 269 .appendText(", intent.data=").appendValue(intentUri); 270 } 271 }; 272 } 273 274 private static Matcher<List<TextLanguage>> isDetectedLanguage(final String language) { 275 return new BaseMatcher<List<TextLanguage>>() { 276 @Override 277 public boolean matches(Object o) { 278 if (o instanceof List) { 279 List languages = (List) o; 280 if (!languages.isEmpty()) { 281 Object o1 = languages.get(0); 282 if (o1 instanceof TextLanguage) { 283 TextLanguage lang = (TextLanguage) o1; 284 return lang.getLanguageCount() > 0 285 && new Locale(language).getLanguage() 286 .equals(lang.getLanguage(0).getLanguage()); 287 } 288 } 289 } 290 return false; 291 } 292 293 @Override 294 public void describeTo(Description description) { 295 description.appendValue(String.format("%s", language)); 296 } 297 }; 298 } 299} 300