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