• 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.util.Log;
22 import android.view.textclassifier.TextClassification;
23 import android.view.textclassifier.TextClassification.Request;
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
smokeTest()73   public void smokeTest() throws Exception {
74     extServicesTextClassifierRule.addDeviceConfigOverride(
75         "manifest_url_annotator_en", V804_EN_ANNOTATOR_MANIFEST_URL);
76 
77     assertWithRetries(() -> verifyActiveEnglishModel(V804_EN_TAG));
78   }
79 
80   @Test
downgradeModel()81   public void downgradeModel() throws Exception {
82     // Download an experimental model.
83     extServicesTextClassifierRule.addDeviceConfigOverride(
84         "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL);
85 
86     assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG));
87 
88     // Downgrade to an older model.
89     extServicesTextClassifierRule.addDeviceConfigOverride(
90         "manifest_url_annotator_en", V804_EN_ANNOTATOR_MANIFEST_URL);
91 
92     assertWithRetries(() -> verifyActiveEnglishModel(V804_EN_TAG));
93   }
94 
95   @Test
upgradeModel()96   public void upgradeModel() throws Exception {
97     // Download a model.
98     extServicesTextClassifierRule.addDeviceConfigOverride(
99         "manifest_url_annotator_en", V804_EN_ANNOTATOR_MANIFEST_URL);
100 
101     assertWithRetries(() -> verifyActiveEnglishModel(V804_EN_TAG));
102 
103     // Upgrade to an experimental model.
104     extServicesTextClassifierRule.addDeviceConfigOverride(
105         "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL);
106 
107     assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG));
108   }
109 
110   @Test
clearFlag()111   public void clearFlag() throws Exception {
112     // Download a new model.
113     extServicesTextClassifierRule.addDeviceConfigOverride(
114         "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL);
115 
116     assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG));
117 
118     // Revert the flag.
119     extServicesTextClassifierRule.addDeviceConfigOverride("manifest_url_annotator_en", "");
120     // Fallback to use the universal model.
121     assertWithRetries(
122         () -> verifyActiveModel(/* text= */ "abc", /* expectedVersion= */ FACTORY_MODEL_TAG));
123   }
124 
125   @Test
modelsForMultipleLanguagesDownloaded()126   public void modelsForMultipleLanguagesDownloaded() throws Exception {
127     extServicesTextClassifierRule.addDeviceConfigOverride("multi_language_support_enabled", "true");
128     extServicesTextClassifierRule.addDeviceConfigOverride(
129         "testing_locale_list_override", "en-US,ru-RU");
130 
131     // download en model
132     extServicesTextClassifierRule.addDeviceConfigOverride(
133         "manifest_url_annotator_en", EXPERIMENTAL_EN_ANNOTATOR_MANIFEST_URL);
134 
135     // download ru model
136     extServicesTextClassifierRule.addDeviceConfigOverride(
137         "manifest_url_annotator_ru", V804_RU_ANNOTATOR_MANIFEST_URL);
138     assertWithRetries(() -> verifyActiveEnglishModel(EXPERIMENTAL_EN_TAG));
139 
140     assertWithRetries(this::verifyActiveRussianModel);
141 
142     assertWithRetries(
143         () -> verifyActiveModel(/* text= */ "français", /* expectedVersion= */ FACTORY_MODEL_TAG));
144   }
145 
assertWithRetries(Runnable assertRunnable)146   private void assertWithRetries(Runnable assertRunnable) throws Exception {
147     for (int i = 0; i < ASSERT_MAX_ATTEMPTS; i++) {
148       try {
149         extServicesTextClassifierRule.overrideDeviceConfig();
150         assertRunnable.run();
151         break; // success. Bail out.
152       } catch (AssertionError ex) {
153         if (i == ASSERT_MAX_ATTEMPTS - 1) { // last attempt, give up.
154           extServicesTextClassifierRule.dumpDefaultTextClassifierService();
155           throw ex;
156         } else {
157           Thread.sleep(ASSERT_SLEEP_BEFORE_RETRY_MS);
158         }
159       } catch (Exception unknownException) {
160         throw unknownException;
161       }
162     }
163   }
164 
verifyActiveModel(String text, String expectedVersion)165   private void verifyActiveModel(String text, String expectedVersion) {
166     TextClassification textClassification =
167         extServicesTextClassifierRule
168             .getTextClassifier()
169             .classifyText(new Request.Builder(text, 0, text.length()).build());
170     // The result id contains the name of the just used model.
171     Log.d(TAG, "verifyActiveModel. TextClassification ID: " + textClassification.getId());
172     assertThat(textClassification.getId()).contains(expectedVersion);
173   }
174 
verifyActiveEnglishModel(String expectedVersion)175   private void verifyActiveEnglishModel(String expectedVersion) {
176     verifyActiveModel("abc", expectedVersion);
177   }
178 
verifyActiveRussianModel()179   private void verifyActiveRussianModel() {
180     verifyActiveModel("привет", V804_RU_TAG);
181   }
182 }
183