1 /* 2 * Copyright (C) 2018 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.textclassifier.downloader; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.view.textclassifier.TextClassification; 22 import android.view.textclassifier.TextClassification.Request; 23 import androidx.test.filters.FlakyTest; 24 import com.android.textclassifier.testing.ExtServicesTextClassifierRule; 25 import org.junit.After; 26 import org.junit.Before; 27 import org.junit.Ignore; 28 import org.junit.Rule; 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 import org.junit.runners.JUnit4; 32 33 @Ignore("b/358423172") 34 @RunWith(JUnit4.class) 35 public class ModelDownloaderIntegrationTest { 36 private static final String TAG = "ModelDownloaderTest"; 37 private static final String EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL = 38 "https://www.gstatic.com/android/text_classifier/r/experimental/v999999999/en.fb.manifest"; 39 private static final String EXPERIMENTAL_EN_TAG = "en_v999999999"; 40 private static final String V804_EN_ANNOTATOR_MANIFEST_URL = 41 "https://www.gstatic.com/android/text_classifier/r/v804/en.fb.manifest"; 42 private static final String V804_RU_ANNOTATOR_MANIFEST_URL = 43 "https://www.gstatic.com/android/text_classifier/r/v804/ru.fb.manifest"; 44 private static final String V804_EN_TAG = "en_v804"; 45 private static final String V804_RU_TAG = "ru_v804"; 46 private static final String FACTORY_MODEL_TAG = "*"; 47 private static final int ASSERT_MAX_ATTEMPTS = 20; 48 private static final int ASSERT_SLEEP_BEFORE_RETRY_MS = 1000; 49 50 @Rule 51 public final ExtServicesTextClassifierRule extServicesTextClassifierRule = 52 new ExtServicesTextClassifierRule(); 53 54 @Before setup()55 public void setup() throws Exception { 56 extServicesTextClassifierRule.addDeviceConfigOverride("config_updater_model_enabled", "false"); 57 extServicesTextClassifierRule.addDeviceConfigOverride("model_download_manager_enabled", "true"); 58 extServicesTextClassifierRule.addDeviceConfigOverride( 59 "model_download_backoff_delay_in_millis", "5"); 60 extServicesTextClassifierRule.addDeviceConfigOverride("testing_locale_list_override", "en-US"); 61 extServicesTextClassifierRule.overrideDeviceConfig(); 62 63 extServicesTextClassifierRule.enableVerboseLogging(); 64 // Verbose logging only takes effect after restarting ExtServices 65 extServicesTextClassifierRule.forceStopExtServices(); 66 } 67 68 @After tearDown()69 public void tearDown() throws Exception { 70 // This is to reset logging/locale_override for ExtServices. 71 extServicesTextClassifierRule.forceStopExtServices(); 72 } 73 74 @Test 75 @FlakyTest(bugId = 284901878) smokeTest()76 public void smokeTest() throws Exception { 77 extServicesTextClassifierRule.addDeviceConfigOverride( 78 "manifest_url_annotator_en", V804_EN_ANNOTATOR_MANIFEST_URL); 79 80 assertWithRetries(() -> verifyActiveEnglishModel(V804_EN_TAG)); 81 } 82 83 @Test 84 @FlakyTest(bugId = 284901878) downgradeModel()85 public void downgradeModel() throws Exception { 86 // Download an experimental model. 87 extServicesTextClassifierRule.addDeviceConfigOverride( 88 "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL); 89 90 assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG)); 91 92 // Downgrade to an older model. 93 extServicesTextClassifierRule.addDeviceConfigOverride( 94 "manifest_url_annotator_en", V804_EN_ANNOTATOR_MANIFEST_URL); 95 96 assertWithRetries(() -> verifyActiveEnglishModel(V804_EN_TAG)); 97 } 98 99 @Test 100 @FlakyTest(bugId = 284901878) upgradeModel()101 public void upgradeModel() throws Exception { 102 // Download a model. 103 extServicesTextClassifierRule.addDeviceConfigOverride( 104 "manifest_url_annotator_en", V804_EN_ANNOTATOR_MANIFEST_URL); 105 106 assertWithRetries(() -> verifyActiveEnglishModel(V804_EN_TAG)); 107 108 // Upgrade to an experimental model. 109 extServicesTextClassifierRule.addDeviceConfigOverride( 110 "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL); 111 112 assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG)); 113 } 114 115 @Test 116 @FlakyTest(bugId = 284901878) clearFlag()117 public void clearFlag() throws Exception { 118 // Download a new model. 119 extServicesTextClassifierRule.addDeviceConfigOverride( 120 "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL); 121 122 assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG)); 123 124 // Revert the flag. 125 extServicesTextClassifierRule.addDeviceConfigOverride("manifest_url_annotator_en", ""); 126 // Fallback to use the universal model. 127 assertWithRetries( 128 () -> verifyActiveModel(/* text= */ "abc", /* expectedVersion= */ FACTORY_MODEL_TAG)); 129 } 130 131 @Test 132 @FlakyTest(bugId = 267344737) modelsForMultipleLanguagesDownloaded()133 public void modelsForMultipleLanguagesDownloaded() throws Exception { 134 extServicesTextClassifierRule.addDeviceConfigOverride("multi_language_support_enabled", "true"); 135 extServicesTextClassifierRule.addDeviceConfigOverride( 136 "testing_locale_list_override", "en-US,ru-RU"); 137 138 // download en model 139 extServicesTextClassifierRule.addDeviceConfigOverride( 140 "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL); 141 142 // download ru model 143 extServicesTextClassifierRule.addDeviceConfigOverride( 144 "manifest_url_annotator_ru", V804_RU_ANNOTATOR_MANIFEST_URL); 145 assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG)); 146 147 assertWithRetries(this::verifyActiveRussianModel); 148 149 assertWithRetries( 150 () -> verifyActiveModel(/* text= */ "français", /* expectedVersion= */ FACTORY_MODEL_TAG)); 151 } 152 assertWithRetries(Runnable assertRunnable)153 private void assertWithRetries(Runnable assertRunnable) throws Exception { 154 for (int i = 0; i < ASSERT_MAX_ATTEMPTS; i++) { 155 try { 156 extServicesTextClassifierRule.overrideDeviceConfig(); 157 assertRunnable.run(); 158 break; // success. Bail out. 159 } catch (AssertionError ex) { 160 if (i == ASSERT_MAX_ATTEMPTS - 1) { // last attempt, give up. 161 extServicesTextClassifierRule.dumpDefaultTextClassifierService(); 162 throw ex; 163 } else { 164 Thread.sleep(ASSERT_SLEEP_BEFORE_RETRY_MS); 165 } 166 } catch (Exception unknownException) { 167 throw unknownException; 168 } 169 } 170 } 171 verifyActiveModel(String text, String expectedVersion)172 private void verifyActiveModel(String text, String expectedVersion) { 173 TextClassification textClassification = 174 extServicesTextClassifierRule 175 .getTextClassifier() 176 .classifyText(new Request.Builder(text, 0, text.length()).build()); 177 // The result id contains the name of the just used model. 178 assertThat(textClassification.getId()).contains(expectedVersion); 179 } 180 verifyActiveEnglishModel(String expectedVersion)181 private void verifyActiveEnglishModel(String expectedVersion) { 182 verifyActiveModel("abc", expectedVersion); 183 } 184 verifyActiveRussianModel()185 private void verifyActiveRussianModel() { 186 verifyActiveModel("привет", V804_RU_TAG); 187 } 188 } 189