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.cts.isolatedsplitapp; 18 19 import static org.hamcrest.CoreMatchers.*; 20 import static org.junit.Assert.*; 21 22 import android.app.Activity; 23 import android.content.BroadcastReceiver; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.res.Configuration; 28 import android.content.res.Resources; 29 import android.os.Bundle; 30 31 import androidx.test.InstrumentationRegistry; 32 import androidx.test.rule.ActivityTestRule; 33 import androidx.test.runner.AndroidJUnit4; 34 35 import org.junit.Rule; 36 import org.junit.Test; 37 import org.junit.rules.TestRule; 38 import org.junit.runner.Description; 39 import org.junit.runner.RunWith; 40 import org.junit.runners.model.Statement; 41 42 import java.util.Locale; 43 import java.util.concurrent.CompletableFuture; 44 import java.util.concurrent.TimeUnit; 45 46 @RunWith(AndroidJUnit4.class) 47 public class SplitAppTest { 48 private static final String PACKAGE = "com.android.cts.isolatedsplitapp"; 49 50 private static final ComponentName FEATURE_A_ACTIVITY = 51 ComponentName.createRelative(PACKAGE, ".feature_a.FeatureAActivity"); 52 private static final ComponentName FEATURE_B_ACTIVITY = 53 ComponentName.createRelative(PACKAGE, ".feature_b.FeatureBActivity"); 54 private static final ComponentName FEATURE_C_ACTIVITY = 55 ComponentName.createRelative(PACKAGE, ".feature_c.FeatureCActivity"); 56 57 private static final String FEATURE_A_STRING = 58 "com.android.cts.isolatedsplitapp.feature_a:string/feature_a_string"; 59 private static final String FEATURE_B_STRING = 60 "com.android.cts.isolatedsplitapp.feature_b:string/feature_b_string"; 61 private static final String FEATURE_C_STRING = 62 "com.android.cts.isolatedsplitapp.feature_c:string/feature_c_string"; 63 64 private static final Configuration PL = new Configuration(); 65 static { 66 PL.setLocale(Locale.forLanguageTag("pl")); 67 } 68 69 @Rule 70 public ActivityTestRule<BaseActivity> mBaseActivityRule = 71 new ActivityTestRule<>(BaseActivity.class); 72 73 // Do not launch this activity lazily. We use this rule to launch all feature Activities, 74 // so we use #launchActivity() with the correct Intent. 75 @Rule 76 public ActivityTestRule<Activity> mFeatureActivityRule = 77 new ActivityTestRule<>(Activity.class, true /*initialTouchMode*/, 78 false /*launchActivity*/); 79 80 @Rule 81 public AppContextTestRule mAppContextTestRule = new AppContextTestRule(); 82 83 @Test shouldLoadDefault()84 public void shouldLoadDefault() throws Exception { 85 final Context context = mBaseActivityRule.getActivity(); 86 final Resources resources = context.getResources(); 87 assertThat(resources, notNullValue()); 88 89 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 90 91 // The base does not depend on any splits so no splits should be accessible. 92 assertActivitiesDoNotExist(context, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY, 93 FEATURE_C_ACTIVITY); 94 assertResourcesDoNotExist(context, FEATURE_A_STRING, FEATURE_B_STRING, FEATURE_C_STRING); 95 } 96 97 @Test shouldLoadPolishLocale()98 public void shouldLoadPolishLocale() throws Exception { 99 final Context context = mBaseActivityRule.getActivity().createConfigurationContext(PL); 100 final Resources resources = context.getResources(); 101 assertThat(resources, notNullValue()); 102 103 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 104 105 // The base does not depend on any splits so no splits should be accessible. 106 assertActivitiesDoNotExist(context, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY, 107 FEATURE_C_ACTIVITY); 108 assertResourcesDoNotExist(context, FEATURE_A_STRING, FEATURE_B_STRING, FEATURE_C_STRING); 109 } 110 111 @Test shouldLoadFeatureADefault()112 public void shouldLoadFeatureADefault() throws Exception { 113 final Context context = mFeatureActivityRule.launchActivity( 114 new Intent().setComponent(FEATURE_A_ACTIVITY)); 115 final Resources resources = context.getResources(); 116 assertThat(resources, notNullValue()); 117 118 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 119 120 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 121 assertThat(resources.getString(resourceId), equalTo("Feature A String Default")); 122 123 assertActivitiesDoNotExist(context, FEATURE_B_ACTIVITY, FEATURE_C_ACTIVITY); 124 assertResourcesDoNotExist(context, FEATURE_B_STRING, FEATURE_C_STRING); 125 } 126 127 @Test shouldLoadFeatureAPolishLocale()128 public void shouldLoadFeatureAPolishLocale() throws Exception { 129 final Context context = mFeatureActivityRule.launchActivity( 130 new Intent().setComponent(FEATURE_A_ACTIVITY)).createConfigurationContext(PL); 131 final Resources resources = context.getResources(); 132 assertThat(resources, notNullValue()); 133 134 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 135 136 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 137 assertThat(resources.getString(resourceId), equalTo("Feature A String Polish")); 138 139 assertActivitiesDoNotExist(context, FEATURE_B_ACTIVITY, FEATURE_C_ACTIVITY); 140 assertResourcesDoNotExist(context, FEATURE_B_STRING, FEATURE_C_STRING); 141 } 142 143 @Test shouldLoadFeatureAReceivers()144 public void shouldLoadFeatureAReceivers() throws Exception { 145 final Context context = mAppContextTestRule.getContext(); 146 final ExtrasResultReceiver receiver = sendOrderedBroadcast(context); 147 final Bundle results = receiver.get(); 148 assertThat(results.getString("base"), equalTo("Base String Default")); 149 assertThat(results.getString("feature_a"), equalTo("Feature A String Default")); 150 assertThat(results.getString("feature_b"), nullValue()); 151 assertThat(results.getString("feature_c"), nullValue()); 152 } 153 154 @Test shouldLoadFeatureBDefault()155 public void shouldLoadFeatureBDefault() throws Exception { 156 // Feature B depends on A, so we expect both to be available. 157 final Context context = mFeatureActivityRule.launchActivity( 158 new Intent().setComponent(FEATURE_B_ACTIVITY)); 159 final Resources resources = context.getResources(); 160 assertThat(resources, notNullValue()); 161 162 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 163 164 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 165 assertThat(resources.getString(resourceId), equalTo("Feature A String Default")); 166 167 resourceId = resources.getIdentifier(FEATURE_B_STRING, null, null); 168 assertThat(resources.getString(resourceId), equalTo("Feature B String Default")); 169 170 assertActivitiesDoNotExist(context, FEATURE_C_ACTIVITY); 171 assertResourcesDoNotExist(context, FEATURE_C_STRING); 172 } 173 174 @Test shouldLoadFeatureBPolishLocale()175 public void shouldLoadFeatureBPolishLocale() throws Exception { 176 final Context context = mFeatureActivityRule.launchActivity( 177 new Intent().setComponent(FEATURE_B_ACTIVITY)).createConfigurationContext(PL); 178 final Resources resources = context.getResources(); 179 assertThat(resources, notNullValue()); 180 181 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 182 183 int resourceId = resources.getIdentifier(FEATURE_A_STRING, null, null); 184 assertThat(resources.getString(resourceId), equalTo("Feature A String Polish")); 185 186 resourceId = resources.getIdentifier(FEATURE_B_STRING, null, null); 187 assertThat(resources.getString(resourceId), equalTo("Feature B String Polish")); 188 189 assertActivitiesDoNotExist(context, FEATURE_C_ACTIVITY); 190 assertResourcesDoNotExist(context, FEATURE_C_STRING); 191 } 192 193 @Test shouldLoadFeatureAAndBReceivers()194 public void shouldLoadFeatureAAndBReceivers() throws Exception { 195 final Context context = mAppContextTestRule.getContext(); 196 final ExtrasResultReceiver receiver = sendOrderedBroadcast(context); 197 final Bundle results = receiver.get(); 198 assertThat(results.getString("base"), equalTo("Base String Default")); 199 assertThat(results.getString("feature_a"), equalTo("Feature A String Default")); 200 assertThat(results.getString("feature_b"), equalTo("Feature B String Default")); 201 assertThat(results.getString("feature_c"), nullValue()); 202 } 203 204 @Test shouldLoadFeatureCDefault()205 public void shouldLoadFeatureCDefault() throws Exception { 206 final Context context = mFeatureActivityRule.launchActivity( 207 new Intent().setComponent(FEATURE_C_ACTIVITY)); 208 final Resources resources = context.getResources(); 209 assertThat(resources, notNullValue()); 210 211 assertThat(resources.getString(R.string.base_string), equalTo("Base String Default")); 212 213 int resourceId = resources.getIdentifier(FEATURE_C_STRING, null, null); 214 assertThat(resources.getString(resourceId), equalTo("Feature C String Default")); 215 216 assertActivitiesDoNotExist(context, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY); 217 assertResourcesDoNotExist(context, FEATURE_A_STRING, FEATURE_B_STRING); 218 } 219 220 @Test shouldLoadFeatureCPolishLocale()221 public void shouldLoadFeatureCPolishLocale() throws Exception { 222 final Context context = mFeatureActivityRule.launchActivity( 223 new Intent().setComponent(FEATURE_C_ACTIVITY)).createConfigurationContext(PL); 224 final Resources resources = context.getResources(); 225 assertThat(resources, notNullValue()); 226 227 assertThat(resources.getString(R.string.base_string), equalTo("Base String Polish")); 228 229 int resourceId = resources.getIdentifier(FEATURE_C_STRING, null, null); 230 assertThat(resources.getString(resourceId), equalTo("Feature C String Polish")); 231 232 assertActivitiesDoNotExist(context, FEATURE_A_ACTIVITY, FEATURE_B_ACTIVITY); 233 assertResourcesDoNotExist(context, FEATURE_A_STRING, FEATURE_B_STRING); 234 } 235 236 @Test shouldLoadFeatureAAndBAndCReceivers()237 public void shouldLoadFeatureAAndBAndCReceivers() throws Exception { 238 final Context context = mAppContextTestRule.getContext(); 239 final ExtrasResultReceiver receiver = sendOrderedBroadcast(context); 240 final Bundle results = receiver.get(); 241 assertThat(results.getString("base"), equalTo("Base String Default")); 242 assertThat(results.getString("feature_a"), equalTo("Feature A String Default")); 243 assertThat(results.getString("feature_b"), equalTo("Feature B String Default")); 244 assertThat(results.getString("feature_c"), equalTo("Feature C String Default")); 245 } 246 assertActivitiesDoNotExist(Context context, ComponentName... activities)247 private static void assertActivitiesDoNotExist(Context context, ComponentName... activities) { 248 for (ComponentName activity : activities) { 249 try { 250 Class.forName(activity.getClassName(), true, context.getClassLoader()); 251 fail("Class " + activity.getClassName() + " is accessible"); 252 } catch (ClassNotFoundException e) { 253 // Pass. 254 } 255 } 256 } 257 assertResourcesDoNotExist(Context context, String... resourceNames)258 private static void assertResourcesDoNotExist(Context context, String... resourceNames) { 259 final Resources resources = context.getResources(); 260 for (String resourceName : resourceNames) { 261 final int resid = resources.getIdentifier(resourceName, null, null); 262 if (resid != 0) { 263 fail("Found resource '" + resourceName + "' with ID " + Integer.toHexString(resid)); 264 } 265 } 266 } 267 268 private static class ExtrasResultReceiver extends BroadcastReceiver { 269 private final CompletableFuture<Bundle> mResult = new CompletableFuture<>(); 270 271 @Override onReceive(Context context, Intent intent)272 public void onReceive(Context context, Intent intent) { 273 mResult.complete(getResultExtras(true)); 274 } 275 get()276 public Bundle get() throws Exception { 277 return mResult.get(5000, TimeUnit.SECONDS); 278 } 279 } 280 sendOrderedBroadcast(Context context)281 private static ExtrasResultReceiver sendOrderedBroadcast(Context context) { 282 final ExtrasResultReceiver resultReceiver = new ExtrasResultReceiver(); 283 context.sendOrderedBroadcast(new Intent(PACKAGE + ".ACTION").setPackage(PACKAGE), null, 284 resultReceiver, null, 0, null, null); 285 return resultReceiver; 286 } 287 288 private static class AppContextTestRule implements TestRule { 289 private Context mContext; 290 291 @Override apply(final Statement base, Description description)292 public Statement apply(final Statement base, Description description) { 293 return new Statement() { 294 @Override 295 public void evaluate() throws Throwable { 296 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 297 base.evaluate(); 298 } 299 }; 300 } 301 getContext()302 public Context getContext() { 303 return mContext; 304 } 305 } 306 } 307