| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.tradefed.targetprep; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.anyBoolean; |
| import static org.mockito.ArgumentMatchers.anyString; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.Mockito.atLeastOnce; |
| import static org.mockito.Mockito.doReturn; |
| import static org.mockito.Mockito.inOrder; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import com.android.tradefed.build.IBuildInfo; |
| import com.android.tradefed.command.remote.DeviceDescriptor; |
| import com.android.tradefed.config.OptionSetter; |
| import com.android.tradefed.device.DeviceNotAvailableException; |
| import com.android.tradefed.device.ITestDevice; |
| import com.android.tradefed.device.ITestDevice.ApexInfo; |
| import com.android.tradefed.invoker.IInvocationContext; |
| import com.android.tradefed.invoker.InvocationContext; |
| import com.android.tradefed.invoker.TestInformation; |
| import com.android.tradefed.util.BundletoolUtil; |
| import com.android.tradefed.util.CommandResult; |
| import com.android.tradefed.util.CommandStatus; |
| import com.android.tradefed.util.FileUtil; |
| |
| import com.google.common.collect.ImmutableSet; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| import org.mockito.InOrder; |
| import org.mockito.Mock; |
| import org.mockito.Mockito; |
| import org.mockito.MockitoAnnotations; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| /** Unit test for {@link InstallApexModuleTargetPreparer} */ |
| @RunWith(JUnit4.class) |
| public class InstallApexModuleTargetPreparerTest { |
| |
| private static final String SERIAL = "serial"; |
| private InstallApexModuleTargetPreparer mInstallApexModuleTargetPreparer; |
| @Mock |
| IBuildInfo mMockBuildInfo; |
| @Mock |
| ITestDevice mMockDevice; |
| private TestInformation mTestInfo; |
| private BundletoolUtil mMockBundletoolUtil; |
| private File mFakeApex; |
| private File mFakeApex2; |
| private File mFakeApex3; |
| private File mFakeApk; |
| private File mFakeApk2; |
| private File mFakePersistentApk; |
| private File mFakeApkApks; |
| private File mFakeApexApks; |
| private File mBundletoolJar; |
| private OptionSetter mSetter; |
| private static final String APEX_PACKAGE_NAME = "com.android.FAKE_APEX_PACKAGE_NAME"; |
| private static final String APEX2_PACKAGE_NAME = "com.android.FAKE_APEX2_PACKAGE_NAME"; |
| private static final String APEX3_PACKAGE_NAME = "com.android.FAKE_APEX3_PACKAGE_NAME"; |
| private static final String APK_PACKAGE_NAME = "com.android.FAKE_APK_PACKAGE_NAME"; |
| private static final String APK2_PACKAGE_NAME = "com.android.FAKE_APK2_PACKAGE_NAME"; |
| private static final String PERSISTENT_APK_PACKAGE_NAME = "com.android.PERSISTENT_PACKAGE_NAME"; |
| private static final String SPLIT_APEX_PACKAGE_NAME = |
| "com.android.SPLIT_FAKE_APEX_PACKAGE_NAME"; |
| private static final String SPLIT_APK_PACKAGE_NAME = "com.android.SPLIT_FAKE_APK_PACKAGE_NAME"; |
| private static final String APEX_PACKAGE_KEYWORD = "FAKE_APEX_PACKAGE_NAME"; |
| private static final long APEX_VERSION = 1; |
| private static final String APEX_NAME = "fakeApex.apex"; |
| private static final String APEX2_NAME = "fakeApex_2.apex"; |
| private static final String APK_NAME = "fakeApk.apk"; |
| private static final String APK2_NAME = "fakeSecondApk.apk"; |
| private static final String PERSISTENT_APK_NAME = "fakePersistentApk.apk"; |
| private static final String SPLIT_APEX_APKS_NAME = "fakeApex.apks"; |
| private static final String SPLIT_APK__APKS_NAME = "fakeApk.apks"; |
| private static final String BUNDLETOOL_JAR_NAME = "bundletool.jar"; |
| private static final String APEX_DATA_DIR = "/data/apex/active/"; |
| private static final String STAGING_DATA_DIR = "/data/app-staging/"; |
| private static final String SESSION_DATA_DIR = "/data/apex/sessions/"; |
| private static final String APEX_STAGING_WAIT_TIME = "10"; |
| private static final String MODULE_PUSH_REMOTE_PATH = "/data/local/tmp/"; |
| protected static final String PARENT_SESSION_CREATION_CMD = "pm install-create --multi-package --staged --enable-rollback | egrep -o -e '[0-9]+'"; |
| protected static final String CHILD_SESSION_CREATION_CMD_APEX = "pm install-create --apex --staged --enable-rollback | egrep -o -e '[0-9]+'"; |
| protected static final String CHILD_SESSION_CREATION_CMD_APK = "pm install-create --staged --enable-rollback | egrep -o -e '[0-9]+'"; |
| protected static final String PARENT_SESSION_CREATION_ROLLBACK_NO_ENABLE_CMD= "pm install-create --multi-package --staged | egrep -o -e '[0-9]+'"; |
| protected static final String CHILD_SESSION_CREATION_ROLLBACK_NO_ENABLE_CMD_APEX = "pm install-create --apex --staged | egrep -o -e '[0-9]+'"; |
| |
| @Before |
| public void setUp() throws Exception { |
| MockitoAnnotations.initMocks(this); |
| |
| mFakeApex = FileUtil.createTempFile("fakeApex", ".apex"); |
| mFakeApex2 = FileUtil.createTempFile("fakeApex_2", ".apex"); |
| mFakeApex3 = FileUtil.createTempFile("fakeApex_3", ".apex"); |
| mFakeApk = FileUtil.createTempFile("fakeApk", ".apk"); |
| mFakeApk2 = FileUtil.createTempFile("fakeSecondApk", ".apk"); |
| mFakePersistentApk = FileUtil.createTempFile("fakePersistentApk", ".apk"); |
| |
| when(mMockDevice.getSerialNumber()).thenReturn(SERIAL); |
| when(mMockDevice.getDeviceDescriptor()).thenReturn(null); |
| when(mMockDevice.checkApiLevelAgainstNextRelease(30)).thenReturn(true); |
| IInvocationContext context = new InvocationContext(); |
| context.addAllocatedDevice("device", mMockDevice); |
| context.addDeviceBuildInfo("device", mMockBuildInfo); |
| mTestInfo = TestInformation.newBuilder().setInvocationContext(context).build(); |
| |
| mInstallApexModuleTargetPreparer = |
| new InstallApexModuleTargetPreparer() { |
| @Override |
| protected String getModuleKeywordFromApexPackageName(String packageName) { |
| return APEX_PACKAGE_KEYWORD; |
| } |
| |
| @Override |
| protected String getBundletoolFileName() { |
| return BUNDLETOOL_JAR_NAME; |
| } |
| |
| @Override |
| protected BundletoolUtil getBundletoolUtil() { |
| return mMockBundletoolUtil; |
| } |
| |
| @Override |
| protected File getLocalPathForFilename( |
| TestInformation testInfo, String appFileName) throws TargetSetupError { |
| if (appFileName.endsWith(".apex")) { |
| if (appFileName.contains("fakeApex_2")) { |
| return mFakeApex2; |
| } else if (appFileName.contains("fakeApex_3")) { |
| return mFakeApex3; |
| } |
| return mFakeApex; |
| } |
| if (appFileName.endsWith(".apk")) { |
| if (appFileName.contains("Second")) { |
| return mFakeApk2; |
| } else if (appFileName.contains("Persistent")) { |
| return mFakePersistentApk; |
| } else { |
| return mFakeApk; |
| } |
| } |
| if (SPLIT_APEX_APKS_NAME.equals(appFileName)) { |
| return mFakeApexApks; |
| } |
| if (SPLIT_APK__APKS_NAME.equals(appFileName)) { |
| return mFakeApkApks; |
| } |
| if (appFileName.endsWith(".jar")) { |
| return mBundletoolJar; |
| } |
| return null; |
| } |
| |
| @Override |
| protected String parsePackageName( |
| File testAppFile, DeviceDescriptor deviceDescriptor) { |
| if (testAppFile.getName().endsWith(".apex")) { |
| if (testAppFile.getName().contains("fakeApex_2")) { |
| return APEX2_PACKAGE_NAME; |
| } else if (testAppFile.getName().contains("fakeApex_3")) { |
| return APEX3_PACKAGE_NAME; |
| } else if (testAppFile.getName().contains("Split")) { |
| return SPLIT_APEX_PACKAGE_NAME; |
| } else if (testAppFile.getName().contains("Persistent")) { |
| return PERSISTENT_APK_PACKAGE_NAME; |
| } |
| return APEX_PACKAGE_NAME; |
| } |
| if (testAppFile.getName().endsWith(".apk") |
| && !testAppFile.getName().contains("Split")) { |
| if (testAppFile.getName().contains("Second")) { |
| return APK2_PACKAGE_NAME; |
| } else if (testAppFile.getName().contains("Persistent")) { |
| return PERSISTENT_APK_PACKAGE_NAME; |
| } else { |
| return APK_PACKAGE_NAME; |
| } |
| } |
| if (testAppFile.getName().endsWith(".apk") |
| && testAppFile.getName().contains("Split")) { |
| return SPLIT_APK_PACKAGE_NAME; |
| } |
| if (testAppFile.getName().endsWith(".apks") |
| && testAppFile.getName().contains("fakeApk")) { |
| return SPLIT_APK_PACKAGE_NAME; |
| } |
| return null; |
| } |
| |
| @Override |
| protected ApexInfo retrieveApexInfo( |
| File apex, DeviceDescriptor deviceDescriptor) { |
| ApexInfo apexInfo; |
| if (apex.getName().contains("Split")) { |
| apexInfo = new ApexInfo(SPLIT_APEX_PACKAGE_NAME, APEX_VERSION); |
| } else if (apex.getName().contains("fakeApex_2")) { |
| apexInfo = new ApexInfo(APEX2_PACKAGE_NAME, APEX_VERSION); |
| } else { |
| apexInfo = new ApexInfo(APEX_PACKAGE_NAME, APEX_VERSION); |
| } |
| return apexInfo; |
| } |
| |
| @Override |
| protected boolean isPersistentApk(File filename, TestInformation testInfo) |
| throws TargetSetupError { |
| if (filename.getName().contains("Persistent")) { |
| return true; |
| } |
| return false; |
| } |
| }; |
| |
| mSetter = new OptionSetter(mInstallApexModuleTargetPreparer); |
| mSetter.setOptionValue("cleanup-apks", "true"); |
| mSetter.setOptionValue("apex-staging-wait-time", APEX_STAGING_WAIT_TIME); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| FileUtil.deleteFile(mFakeApex); |
| FileUtil.deleteFile(mFakeApex2); |
| FileUtil.deleteFile(mFakeApex3); |
| FileUtil.deleteFile(mFakeApk); |
| FileUtil.deleteFile(mFakeApk2); |
| FileUtil.deleteFile(mFakePersistentApk); |
| mMockBundletoolUtil = null; |
| } |
| |
| /** |
| * Test that it gets the correct apk files that are already installed on the /data directory. |
| */ |
| @Test |
| public void testGetApkModuleInData() throws Exception { |
| Set<String> expected = new HashSet<>(); |
| Set<String> result = new HashSet<>(); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| Set<ApexInfo> apexes = new HashSet<>(Arrays.asList(fakeApexData, fakeApexData2)); |
| |
| final String fakeName = "com.google.apk"; |
| final String fakeName2 = "com.google.apk2"; |
| final String fakeName3 = "com.google.apk3"; |
| final Set<String> mainlineModuleInfo = |
| new HashSet<>( |
| Arrays.asList( |
| fakeName, |
| fakeName2, |
| fakeName3, |
| APEX_PACKAGE_NAME, |
| APEX2_PACKAGE_NAME)); |
| |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(mainlineModuleInfo); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", fakeName))) |
| .thenReturn("package:/system/app/fakeApk/fakeApk.apk"); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", fakeName2))) |
| .thenReturn("package:/data/app/fakeApk2/fakeApk2.apk"); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", fakeName3))) |
| .thenReturn("package:/data/app/fakeApk3/fakeApk3.apk"); |
| |
| expected = new HashSet<>(Arrays.asList(fakeName2, fakeName3)); |
| result = mInstallApexModuleTargetPreparer.getApkModuleInData(apexes, mMockDevice); |
| assertEquals(2, result.size()); |
| assertEquals(expected, result); |
| } |
| |
| /** |
| * Test that it gets the correct apk files that the apex modules are excluded. |
| */ |
| @Test |
| public void testGetApkModules() throws Exception { |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| Set<String> modules = |
| new HashSet<>( |
| Arrays.asList( |
| APK_PACKAGE_NAME, |
| APK2_PACKAGE_NAME, |
| APEX_PACKAGE_NAME, |
| APEX2_PACKAGE_NAME)); |
| Set<ApexInfo> apexes = new HashSet<>(Arrays.asList(fakeApexData, fakeApexData2)); |
| Set<String> expected = new HashSet<>(Arrays.asList(APK_PACKAGE_NAME, APK2_PACKAGE_NAME)); |
| assertEquals(expected, mInstallApexModuleTargetPreparer.getApkModules(modules, apexes)); |
| } |
| |
| /** |
| * Test that it gets the correct apex files that are already installed on the /data directory. |
| */ |
| @Test |
| public void testGetApexInData() throws Exception { |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| Set<String> expectedApex = new HashSet<>(); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexSystem = |
| new ApexInfo( |
| "com.android.FAKE_APEX3_PACKAGE_NAME", |
| 1, |
| "/system/apex/com.android.FAKE_APEX3_PACKAGE_NAME@1.apex"); |
| |
| activatedApex = new HashSet<>(Arrays.asList(fakeApexData, fakeApexData2, fakeApexSystem)); |
| expectedApex = new HashSet<>(Arrays.asList(fakeApexData.name, fakeApexData2.name)); |
| assertEquals(2, mInstallApexModuleTargetPreparer.getApexInData(activatedApex).size()); |
| assertEquals(expectedApex, mInstallApexModuleTargetPreparer.getApexInData(activatedApex)); |
| |
| activatedApex = new HashSet<>(Arrays.asList(fakeApexSystem)); |
| assertEquals(0, mInstallApexModuleTargetPreparer.getApexInData(activatedApex).size()); |
| } |
| |
| /** |
| * Test that it returns the correct files to be installed and uninstalled. |
| */ |
| @Test |
| public void testGetModulesToUninstall_NoneUninstallAndInstallFiles() throws Exception { |
| Set<String> apexInData = new HashSet<>(); |
| List<File> testFiles = new ArrayList<>(); |
| testFiles.add(mFakeApex); |
| testFiles.add(mFakeApex2); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| apexInData.add(fakeApexData.name); |
| apexInData.add(fakeApexData2.name); |
| |
| Set<String> results = |
| mInstallApexModuleTargetPreparer.getModulesToUninstall( |
| apexInData, testFiles, mMockDevice); |
| |
| assertEquals(0, testFiles.size()); |
| assertEquals(0, results.size()); |
| } |
| |
| /** |
| * Test that it returns the correct files to be installed and uninstalled. |
| */ |
| @Test |
| public void testGetModulesToUninstall_UninstallAndInstallFiles() throws Exception { |
| Set<String> apexInData = new HashSet<>(); |
| List<File> testFiles = new ArrayList<>(); |
| testFiles.add(mFakeApex3); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| apexInData.add(fakeApexData.name); |
| apexInData.add(fakeApexData2.name); |
| |
| Set<String> results = |
| mInstallApexModuleTargetPreparer.getModulesToUninstall( |
| apexInData, testFiles, mMockDevice); |
| assertEquals(1, testFiles.size()); |
| assertEquals(mFakeApex3, testFiles.get(0)); |
| assertEquals(2, results.size()); |
| assertTrue(results.containsAll(apexInData)); |
| } |
| |
| /** |
| * Test that it returns the correct files to be installed and uninstalled. |
| */ |
| @Test |
| public void testGetModulesToUninstall_UninstallAndInstallFiles2() throws Exception { |
| Set<String> apexInData = new HashSet<>(); |
| List<File> testFiles = new ArrayList<>(); |
| testFiles.add(mFakeApex2); |
| testFiles.add(mFakeApex3); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| apexInData.add(fakeApexData.name); |
| apexInData.add(fakeApexData2.name); |
| |
| Set<String> results = |
| mInstallApexModuleTargetPreparer.getModulesToUninstall( |
| apexInData, testFiles, mMockDevice); |
| assertEquals(1, testFiles.size()); |
| assertEquals(mFakeApex3, testFiles.get(0)); |
| assertEquals(1, results.size()); |
| assertTrue(results.contains(fakeApexData.name)); |
| } |
| |
| /** |
| * Test the method behaves the same process when the files to be installed contain apk or apks. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_APEXANDAPK_NoReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| doReturn(new HashSet<>()) |
| .doReturn(new HashSet<>()) |
| .doReturn(new HashSet<>(Arrays.asList(fakeApexData))) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex, mFakeApk)); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifySuccessfulInstallMultiPackages(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| } |
| |
| /** |
| * Test the method will not install and reboot device as all apk/apex are installed already. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_APEXANDAPK_NoInstallAndReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<>(Arrays.asList(fakeApexData))); |
| when(mMockDevice.getMainlineModuleInfo()) |
| .thenReturn(new HashSet<>(Arrays.asList(APK_PACKAGE_NAME))); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", APK_PACKAGE_NAME))) |
| .thenReturn("package:/data/app/fakeApk/fakeApk.apk"); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getMainlineModuleInfo(); |
| } |
| |
| /** |
| * Test the method will install and reboot device as installing the persistent apk. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_APEXANDAPK_InstallAndReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(PERSISTENT_APK_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<>(Arrays.asList(fakeApexData))); |
| when(mMockDevice.getMainlineModuleInfo()) |
| .thenReturn(new HashSet<>(Arrays.asList(PERSISTENT_APK_PACKAGE_NAME))); |
| when(mMockDevice.executeShellCommand( |
| String.format("pm path %s", PERSISTENT_APK_PACKAGE_NAME))) |
| .thenReturn("package:/system/app/fakePersistentApk/fakePersistentApk.apk"); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakePersistentApk)); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(PERSISTENT_APK_PACKAGE_NAME); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakePersistentApk)); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getMainlineModuleInfo(); |
| } |
| |
| /** |
| * Test the method will install but not reboot device as installing non persistent apk. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_APEXANDAPK_InstallNoReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<>(Arrays.asList(fakeApexData))); |
| when(mMockDevice.getMainlineModuleInfo()) |
| .thenReturn(new HashSet<>(Arrays.asList(APK_PACKAGE_NAME))); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", APK_PACKAGE_NAME))) |
| .thenReturn("package:/system/app/fakeApk/fakeApk.apk"); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApk)); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getMainlineModuleInfo(); |
| } |
| |
| /** |
| * Test the method will proceed on tearDown as no module metadata on device. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_InstallAPK_No_ModuleMetadata() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<>()); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", APK_PACKAGE_NAME))) |
| .thenReturn("package:/system/app/fakeApk/fakeApk.apk"); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApk)); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| when(mMockDevice.uninstallPackage(APK_PACKAGE_NAME)).thenReturn(null); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| verify(mMockDevice, times(1)).uninstallPackage(APK_PACKAGE_NAME); |
| } |
| |
| /** |
| * Test the method will uninstall and reboot device as uninstalling apk modules. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_APEXANDAPK_UnInstallAPKAndReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<>(Arrays.asList(fakeApexData))); |
| when(mMockDevice.getMainlineModuleInfo()) |
| .thenReturn(new HashSet<>(Arrays.asList(APK_PACKAGE_NAME, APK2_PACKAGE_NAME))); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", APK_PACKAGE_NAME))) |
| .thenReturn("package:/data/app/fakeApk/fakeApk.apk"); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", APK2_PACKAGE_NAME))) |
| .thenReturn("package:/data/app/fakeSecondApk/fakeSecondApk.apk"); |
| Set<String> installableModules = new HashSet<>(); |
| when(mMockDevice.uninstallPackage(Mockito.any())).thenReturn(null); |
| |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getMainlineModuleInfo(); |
| verify(mMockDevice, times(2)).uninstallPackage(Mockito.any()); |
| verify(mMockDevice).reboot(); |
| } |
| |
| /** |
| * Test the method will uninstall and reboot device as uninstalling apex modules. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_APEXANDAPK_UnInstallAPEXANDReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK2_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<>(Arrays.asList(fakeApexData))); |
| when(mMockDevice.getMainlineModuleInfo()) |
| .thenReturn(new HashSet<>(Arrays.asList(APK_PACKAGE_NAME, APK2_PACKAGE_NAME))); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", APK_PACKAGE_NAME))) |
| .thenReturn("package:/data/app/fakeApk/fakeApk.apk"); |
| when(mMockDevice.executeShellCommand(String.format("pm path %s", APK2_PACKAGE_NAME))) |
| .thenReturn("package:/data/app/fakeSecondApk/fakeSecondApk.apk"); |
| Set<String> installableModules = new HashSet<>(); |
| when(mMockDevice.uninstallPackage(Mockito.any())).thenReturn(null); |
| |
| installableModules.add(APK2_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getMainlineModuleInfo(); |
| verify(mMockDevice, times(2)).uninstallPackage(Mockito.any()); |
| verify(mMockDevice).reboot(); |
| } |
| |
| /** |
| * Test the method will optimize the process and it will not reboot because the files to be |
| * installed are already installed on the device. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_MultipleAPEX_NoReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX2_NAME); |
| |
| Set<ApexInfo> apexInData = new HashSet<>(); |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| apexInData.add(fakeApexData); |
| apexInData.add(fakeApexData2); |
| when(mMockDevice.getActiveApexes()).thenReturn(apexInData); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(APEX2_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| } |
| |
| /** |
| * Test the method will uninstall the unused files and install the required files for the |
| * current test, and finally reboot the device. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_MultipleAPEX_UninstallThenInstallAndReboot() |
| throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX2_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| doReturn(new HashSet<>(Arrays.asList(fakeApexData))) |
| .doReturn(new HashSet<>(Arrays.asList(fakeApexData))) |
| .doReturn(new HashSet<>(Arrays.asList(fakeApexData2))) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX2_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| when(mMockDevice.uninstallPackage(Mockito.any())).thenReturn(null); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex2)); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex2)); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| verify(mMockDevice, times(1)).uninstallPackage(Mockito.any()); |
| } |
| |
| /** |
| * Test the method will uninstall the unused files for the current test, and finally reboot the |
| * device. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_MultipleAPEX_UninstallAndReboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX2_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| when(mMockDevice.getActiveApexes()) |
| .thenReturn(new HashSet<>(Arrays.asList(fakeApexData, fakeApexData2))); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX2_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| when(mMockDevice.uninstallPackage(Mockito.any())).thenReturn(null); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verify(mMockDevice, times(1)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| verify(mMockDevice, times(1)).uninstallPackage(Mockito.any()); |
| } |
| |
| /** |
| * Test the method will install the required files for the current test, and finally reboot the |
| * device. |
| */ |
| @Test |
| public void testSetupAndTearDown_Optimize_MultipleAPEX_Reboot() throws Exception { |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX2_NAME); |
| |
| Set<ApexInfo> apexInData = new HashSet<>(); |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| |
| ApexInfo fakeApexData2 = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| |
| apexInData.add(fakeApexData); |
| apexInData.add(fakeApexData2); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| doReturn(new HashSet<>(Arrays.asList(fakeApexData))) |
| .doReturn(apexInData) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(APEX2_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex2)); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex2)); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| } |
| |
| @Test |
| public void testSetupSuccess_removeExistingStagedApexSuccess() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| setActivatedApex(); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupSuccess_noDataUnderApexDataDirs() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| CommandResult res = new CommandResult(); |
| res.setStdout(""); |
| when(mMockDevice.executeShellV2Command("ls " + APEX_DATA_DIR)).thenReturn(res); |
| when(mMockDevice.executeShellV2Command("ls " + SESSION_DATA_DIR)).thenReturn(res); |
| when(mMockDevice.executeShellV2Command("ls " + STAGING_DATA_DIR)).thenReturn(res); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| setActivatedApex(); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupSuccess_getActivatedPackageSuccess() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| setActivatedApex(); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupSuccess_withAbsoluteTestFileName() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFile(mFakeApex); |
| |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| setActivatedApex(); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| |
| @Test(expected = TargetSetupError.class) |
| public void testSetupFail_getActivatedPackageSuccessThrowModuleNotPreloaded() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| setActivatedApex(); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(new HashSet<>()); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(1)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupFail_getActivatedPackageFail() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<ApexInfo>()); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| assertTrue( |
| expected.getMessage() |
| .contains("Failed to retrieve activated apex on device serial.")); |
| } finally { |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| } |
| |
| @Test |
| public void testSetupFail_apexActivationFailPackageNameWrong() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| "com.android.FAKE_APEX_PACKAGE_NAME_TO_FAIL", |
| 1, |
| "/system/apex/com.android.FAKE_APEX_PACKAGE_NAME_TO_FAIL.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| String failureMsg = |
| String.format( |
| "packageName: %s, versionCode: %d", APEX_PACKAGE_NAME, APEX_VERSION); |
| assertTrue(expected.getMessage().contains(failureMsg)); |
| } finally { |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| } |
| |
| @Test |
| public void testSetupFail_apexActivationFailVersionWrong() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| "com.android.FAKE_APEX_PACKAGE_NAME", |
| 0, |
| "/system/apex/com.android.FAKE_APEX_PACKAGE_NAME.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| String failureMsg = |
| String.format( |
| "packageName: %s, versionCode: %d", APEX_PACKAGE_NAME, APEX_VERSION); |
| assertTrue(expected.getMessage().contains(failureMsg)); |
| } finally { |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| } |
| |
| @Test |
| public void testSetupFail_apexActivationFailSourceDirWrong() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| "com.android.FAKE_APEX_PACKAGE_NAME", |
| 1, |
| "/system/apex/com.android.FAKE_APEX_PACKAGE_NAME.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| String failureMsg = |
| String.format( |
| "packageName: %s, versionCode: %d", APEX_PACKAGE_NAME, APEX_VERSION); |
| assertTrue(expected.getMessage().contains(failureMsg)); |
| } finally { |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| } |
| |
| @Test |
| public void testSetupSuccess_activatedSuccessOnQ() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| when(mMockDevice.checkApiLevelAgainstNextRelease(Mockito.anyInt())).thenReturn(false); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add(new ApexInfo("com.android.FAKE_APEX_PACKAGE_NAME", 1, "")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_SingleApk() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApk)); |
| when(mMockDevice.installPackage( |
| (File) Mockito.any(), |
| Mockito.eq(true), |
| Mockito.eq("--enable-rollback"), |
| Mockito.eq("--staged"))) |
| .thenReturn(null); |
| when(mMockDevice.uninstallPackage(APK_PACKAGE_NAME)).thenReturn(null); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| doReturn(new HashSet<ApexInfo>()) |
| .doReturn(ImmutableSet.of()) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(1)).reboot(); |
| verify(mMockDevice, times(1)).uninstallPackage(APK_PACKAGE_NAME); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_InstallMultipleApk() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK2_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| List<File> apks = new ArrayList<>(); |
| apks.add(mFakeApk); |
| apks.add(mFakeApk2); |
| mockSuccessfulInstallMultiPackages(apks); |
| when(mMockDevice.uninstallPackage(APK_PACKAGE_NAME)).thenReturn(null); |
| when(mMockDevice.uninstallPackage(APK2_PACKAGE_NAME)).thenReturn(null); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| installableModules.add(APK2_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| doReturn(new HashSet<ApexInfo>()) |
| .doReturn(ImmutableSet.of()) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(1)).reboot(); |
| verify(mMockDevice, times(1)).uninstallPackage(APK_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).uninstallPackage(APK2_PACKAGE_NAME); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_InstallMultipleApkContainingPersistentApk() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK2_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(PERSISTENT_APK_NAME); |
| |
| mockCleanInstalledApexPackages(); |
| List<File> apks = new ArrayList<>(); |
| apks.add(mFakeApk); |
| apks.add(mFakeApk2); |
| apks.add(mFakePersistentApk); |
| mockSuccessfulInstallMultiPackages(apks); |
| |
| when(mMockDevice.uninstallPackage(APK_PACKAGE_NAME)).thenReturn(null); |
| when(mMockDevice.uninstallPackage(APK2_PACKAGE_NAME)).thenReturn(null); |
| when(mMockDevice.uninstallPackage(PERSISTENT_APK_PACKAGE_NAME)).thenReturn(null); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| installableModules.add(APK2_PACKAGE_NAME); |
| installableModules.add(PERSISTENT_APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| doReturn(new HashSet<ApexInfo>()) |
| .doReturn(ImmutableSet.of()) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verifySuccessfulInstallPackages(apks); |
| verify(mMockDevice, times(1)).uninstallPackage(APK_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).uninstallPackage(APK2_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).uninstallPackage(PERSISTENT_APK_PACKAGE_NAME); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_ApkAndApks() throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APK__APKS_NAME); |
| mFakeApkApks = File.createTempFile("fakeApk", ".apks"); |
| |
| File fakeSplitApkApks = File.createTempFile("ApkSplits", ""); |
| fakeSplitApkApks.delete(); |
| fakeSplitApkApks.mkdir(); |
| File splitApk1 = File.createTempFile("fakeSplitApk1", ".apk", fakeSplitApkApks); |
| mBundletoolJar = File.createTempFile("bundletool", ".jar"); |
| File splitApk2 = File.createTempFile("fakeSplitApk2", ".apk", fakeSplitApkApks); |
| try { |
| mockCleanInstalledApexPackages(); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| |
| assertTrue(fakeSplitApkApks != null); |
| assertTrue(mFakeApkApks != null); |
| assertEquals(2, fakeSplitApkApks.listFiles().length); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApkApks); |
| |
| List<String> trainInstallCmd = new ArrayList<>(); |
| trainInstallCmd.add("install-multi-package"); |
| trainInstallCmd.add("--enable-rollback"); |
| trainInstallCmd.add(mFakeApk.getAbsolutePath()); |
| String cmd = ""; |
| for (File f : fakeSplitApkApks.listFiles()) { |
| if (!cmd.isEmpty()) { |
| cmd += ":" + f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } else { |
| cmd += f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } |
| } |
| trainInstallCmd.add(cmd); |
| when(mMockDevice.executeAdbCommand(trainInstallCmd.toArray(new String[0]))) |
| .thenReturn("Success"); |
| |
| when(mMockDevice.uninstallPackage(APK_PACKAGE_NAME)).thenReturn(null); |
| when(mMockDevice.uninstallPackage(SPLIT_APK_PACKAGE_NAME)).thenReturn(null); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APK_PACKAGE_NAME); |
| installableModules.add(SPLIT_APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| doReturn(new HashSet<ApexInfo>()) |
| .doReturn(ImmutableSet.of()) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| Mockito.verify(mMockBundletoolUtil, times(1)) |
| .generateDeviceSpecFile(Mockito.any(ITestDevice.class)); |
| // Extract splits 1 time to get the package name for the module, and again during |
| // installation. |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).reboot(); |
| verify(mMockDevice, times(1)).executeAdbCommand(trainInstallCmd.toArray(new String[0])); |
| verify(mMockDevice, times(1)).uninstallPackage(APK_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).uninstallPackage(SPLIT_APK_PACKAGE_NAME); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| assertTrue(!mInstallApexModuleTargetPreparer.getApkInstalled().isEmpty()); |
| } finally { |
| FileUtil.deleteFile(mFakeApexApks); |
| FileUtil.deleteFile(mFakeApkApks); |
| FileUtil.recursiveDelete(fakeSplitApkApks); |
| FileUtil.deleteFile(fakeSplitApkApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| } |
| |
| @Test |
| public void testSetupAndTearDown() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| setActivatedApex(); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME)) |
| .thenReturn("Success"); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifySuccessfulInstallPackages(Arrays.asList(mFakeApex)); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(3)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test |
| public void testGetModuleKeyword() { |
| mInstallApexModuleTargetPreparer = new InstallApexModuleTargetPreparer(); |
| final String testApex1PackageName = "com.android.foo"; |
| final String testApex2PackageName = "com.android.bar_test"; |
| assertEquals( |
| "foo", |
| mInstallApexModuleTargetPreparer.getModuleKeywordFromApexPackageName( |
| testApex1PackageName)); |
| assertEquals( |
| "bar_test", |
| mInstallApexModuleTargetPreparer.getModuleKeywordFromApexPackageName( |
| testApex2PackageName)); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_InstallApkAndApex() throws Exception { |
| mockCleanInstalledApexPackages(); |
| Set<String> installableModules = setupInstallableModulesSingleApexSingleApk(); |
| setActivatedApex(); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex, mFakeApk)); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verifySuccessfulInstallMultiPackages(); |
| verify(mMockDevice, times(3)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_FilePushFail() throws Exception { |
| mockCleanInstalledApexPackages(); |
| Set<String> installableModules = setupInstallableModulesSingleApexSingleApk(); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| for (File f : Arrays.asList(mFakeApk, mFakeApex)) { |
| when(mMockDevice.pushFile(f, MODULE_PUSH_REMOTE_PATH + f.getName())) |
| .thenReturn(Boolean.FALSE); |
| } |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| assertTrue( |
| expected.getMessage() |
| .contains("Failed to push local")); |
| } |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_ParentSessionCreationFail() throws Exception { |
| mockCleanInstalledApexPackages(); |
| Set<String> installableModules = setupInstallableModulesSingleApexSingleApk(); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| for (File f : Arrays.asList(mFakeApk, mFakeApex)) { |
| when(mMockDevice.pushFile(f, MODULE_PUSH_REMOTE_PATH + f.getName())) |
| .thenReturn(Boolean.TRUE); |
| } |
| CommandResult parent_session_creation_res = new CommandResult(); |
| parent_session_creation_res.setStatus(CommandStatus.FAILED); |
| parent_session_creation_res.setStderr("I am an error!"); |
| when(mMockDevice.executeShellV2Command(PARENT_SESSION_CREATION_CMD)).thenReturn(parent_session_creation_res); |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| assertTrue( |
| expected.getMessage() |
| .equals(String.format("Failed to create parent session. Error: %s", parent_session_creation_res.getStderr()))); |
| } |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_ChildSessionCreationFail() throws Exception { |
| mockCleanInstalledApexPackages(); |
| Set<String> installableModules = setupInstallableModulesSingleApexSingleApk(); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| for (File f : Arrays.asList(mFakeApk, mFakeApex)) { |
| when(mMockDevice.pushFile(f, MODULE_PUSH_REMOTE_PATH + f.getName())) |
| .thenReturn(Boolean.TRUE); |
| } |
| CommandResult parent_session_creation_res = new CommandResult(); |
| parent_session_creation_res.setStatus(CommandStatus.SUCCESS); |
| when(mMockDevice.executeShellV2Command(PARENT_SESSION_CREATION_CMD)).thenReturn(parent_session_creation_res); |
| CommandResult child_session_creation_res = new CommandResult(); |
| child_session_creation_res.setStatus(CommandStatus.FAILED); |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APEX)).thenReturn(child_session_creation_res); |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APK)).thenReturn(child_session_creation_res); |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| assertTrue( |
| expected.getMessage() |
| .contains("Failed to create child session for")); |
| } |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_FileWrittenToSessionFail() throws Exception { |
| mockCleanInstalledApexPackages(); |
| Set<String> installableModules = setupInstallableModulesSingleApexSingleApk(); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| for (File f : Arrays.asList(mFakeApk, mFakeApex)) { |
| when(mMockDevice.pushFile(f, MODULE_PUSH_REMOTE_PATH + f.getName())) |
| .thenReturn(Boolean.TRUE); |
| } |
| CommandResult session_creation_res = new CommandResult(); |
| session_creation_res.setStatus(CommandStatus.SUCCESS); |
| session_creation_res.setStdout("1"); |
| when(mMockDevice.executeShellV2Command(PARENT_SESSION_CREATION_CMD)).thenReturn(session_creation_res);; |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APEX)).thenReturn(session_creation_res); |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APK)).thenReturn(session_creation_res); |
| CommandResult write_to_session_res = new CommandResult(); |
| write_to_session_res.setStatus(CommandStatus.FAILED); |
| write_to_session_res.setStderr("I am an error!"); |
| when(mMockDevice.executeShellV2Command( |
| String.format( |
| "pm install-write -S %d %s %s %s", |
| mFakeApex.length(), |
| "1", |
| mInstallApexModuleTargetPreparer.parsePackageName(mFakeApex, mMockDevice.getDeviceDescriptor()), |
| MODULE_PUSH_REMOTE_PATH + mFakeApex.getName()))).thenReturn(write_to_session_res); |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| assertTrue( |
| expected.getMessage() |
| .equals(String.format("Failed to write %s to session 1. Error: %s", mFakeApex.getName(), write_to_session_res.getStderr()))); |
| } |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_AddChildSessionToParentSessionFail() throws Exception { |
| mockCleanInstalledApexPackages(); |
| Set<String> installableModules = setupInstallableModulesSingleApexSingleApk(); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| for (File f : Arrays.asList(mFakeApk, mFakeApex)) { |
| when(mMockDevice.pushFile(f, MODULE_PUSH_REMOTE_PATH + f.getName())) |
| .thenReturn(Boolean.TRUE); |
| } |
| CommandResult parent_session_creation_res = new CommandResult(); |
| parent_session_creation_res.setStatus(CommandStatus.SUCCESS); |
| parent_session_creation_res.setStdout("123"); |
| CommandResult child_session_creation_res = new CommandResult(); |
| child_session_creation_res.setStatus(CommandStatus.SUCCESS); |
| child_session_creation_res.setStdout("1"); |
| when(mMockDevice.executeShellV2Command(PARENT_SESSION_CREATION_CMD)).thenReturn(parent_session_creation_res);; |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APEX)).thenReturn(child_session_creation_res); |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APK)).thenReturn(child_session_creation_res); |
| CommandResult write_to_session_res = new CommandResult(); |
| write_to_session_res.setStatus(CommandStatus.SUCCESS); |
| CommandResult add_to_session_res = new CommandResult(); |
| add_to_session_res.setStatus(CommandStatus.FAILED); |
| add_to_session_res.setStderr("I am an error!"); |
| for (File f : Arrays.asList(mFakeApex, mFakeApk)) { |
| when(mMockDevice.executeShellV2Command( |
| String.format( |
| "pm install-write -S %d %s %s %s", |
| f.length(), |
| "1", |
| mInstallApexModuleTargetPreparer.parsePackageName(f, mMockDevice.getDeviceDescriptor()), |
| MODULE_PUSH_REMOTE_PATH + f.getName()))).thenReturn(write_to_session_res); |
| when(mMockDevice.executeShellV2Command( |
| String.format( |
| "pm install-add-session " + parent_session_creation_res.getStdout() + " 1"))).thenReturn(add_to_session_res); |
| } |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| assertTrue( |
| expected.getMessage() |
| .equals(String.format("Failed to add child session 1 to parent session 123. Error: %s", add_to_session_res.getStderr()))); |
| } |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_CommitParentSessionFail() throws Exception { |
| mockCleanInstalledApexPackages(); |
| Set<String> installableModules = setupInstallableModulesSingleApexSingleApk(); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| for (File f : Arrays.asList(mFakeApk, mFakeApex)) { |
| when(mMockDevice.pushFile(f, MODULE_PUSH_REMOTE_PATH + f.getName())) |
| .thenReturn(Boolean.TRUE); |
| } |
| CommandResult parent_session_creation_res = new CommandResult(); |
| parent_session_creation_res.setStatus(CommandStatus.SUCCESS); |
| parent_session_creation_res.setStdout("123"); |
| CommandResult child_session_creation_res = new CommandResult(); |
| child_session_creation_res.setStatus(CommandStatus.SUCCESS); |
| child_session_creation_res.setStdout("1"); |
| when(mMockDevice.executeShellV2Command(PARENT_SESSION_CREATION_CMD)).thenReturn(parent_session_creation_res);; |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APEX)).thenReturn(child_session_creation_res); |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APK)).thenReturn(child_session_creation_res); |
| CommandResult cmd_res = new CommandResult(); |
| cmd_res.setStatus(CommandStatus.SUCCESS); |
| for (File f : Arrays.asList(mFakeApex, mFakeApk)) { |
| when(mMockDevice.executeShellV2Command( |
| String.format( |
| "pm install-write -S %d %s %s %s", |
| f.length(), |
| "1", |
| mInstallApexModuleTargetPreparer.parsePackageName(f, mMockDevice.getDeviceDescriptor()), |
| MODULE_PUSH_REMOTE_PATH + f.getName()))).thenReturn(cmd_res); |
| when(mMockDevice.executeShellV2Command( |
| String.format( |
| "pm install-add-session " + parent_session_creation_res.getStdout() + " 1"))).thenReturn(cmd_res); |
| } |
| CommandResult commit_session_res = new CommandResult(); |
| commit_session_res.setStatus(CommandStatus.FAILED); |
| commit_session_res.setStderr("I am an error!"); |
| when(mMockDevice.executeShellV2Command("pm install-commit " + parent_session_creation_res.getStdout())).thenReturn(commit_session_res); |
| try { |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| fail("Should have thrown a TargetSetupError."); |
| } catch (TargetSetupError expected) { |
| assertTrue( |
| expected.getMessage() |
| .contains(String.format("Failed to commit"))); |
| } |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(2)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test(expected = RuntimeException.class) |
| public void testSetupAndTearDown_MultiInstallRollbackFail() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex, mFakeApk)); |
| setActivatedApex(); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME)) |
| .thenReturn("No available rollback"); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(APK_PACKAGE_NAME); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verifySuccessfulInstallMultiPackages(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| } |
| |
| @Test |
| public void testInstallUsingBundletool() throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APEX_APKS_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APK__APKS_NAME); |
| mFakeApexApks = File.createTempFile("fakeApex", ".apks"); |
| mFakeApkApks = File.createTempFile("fakeApk", ".apks"); |
| |
| File fakeSplitApexApks = File.createTempFile("ApexSplits", ""); |
| fakeSplitApexApks.delete(); |
| fakeSplitApexApks.mkdir(); |
| File splitApex = File.createTempFile("fakeSplitApex", ".apex", fakeSplitApexApks); |
| |
| File fakeSplitApkApks = File.createTempFile("ApkSplits", ""); |
| fakeSplitApkApks.delete(); |
| fakeSplitApkApks.mkdir(); |
| File splitApk1 = File.createTempFile("fakeSplitApk1", ".apk", fakeSplitApkApks); |
| mBundletoolJar = File.createTempFile("bundletool", ".jar"); |
| File splitApk2 = File.createTempFile("fakeSplitApk2", ".apk", fakeSplitApkApks); |
| try { |
| mockCleanInstalledApexPackages(); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| |
| assertTrue(fakeSplitApexApks != null); |
| assertTrue(fakeSplitApkApks != null); |
| assertTrue(mFakeApexApks != null); |
| assertTrue(mFakeApkApks != null); |
| assertEquals(1, fakeSplitApexApks.listFiles().length); |
| assertEquals(2, fakeSplitApkApks.listFiles().length); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApexApks); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApkApks); |
| |
| List<String> trainInstallCmd = new ArrayList<>(); |
| trainInstallCmd.add("install-multi-package"); |
| trainInstallCmd.add("--enable-rollback"); |
| trainInstallCmd.add(splitApex.getAbsolutePath()); |
| String cmd = ""; |
| for (File f : fakeSplitApkApks.listFiles()) { |
| if (!cmd.isEmpty()) { |
| cmd += ":" + f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } else { |
| cmd += f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } |
| } |
| trainInstallCmd.add(cmd); |
| when(mMockDevice.executeAdbCommand(trainInstallCmd.toArray(new String[0]))) |
| .thenReturn("Success"); |
| |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| SPLIT_APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME)) |
| .thenReturn("Success"); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(SPLIT_APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| Mockito.verify(mMockBundletoolUtil, times(1)) |
| .generateDeviceSpecFile(Mockito.any(ITestDevice.class)); |
| // Extract splits 1 time to get the package name for the module, and again during |
| // installation. |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| verify(mMockDevice, times(3)).reboot(); |
| verify(mMockDevice, times(1)).executeAdbCommand(trainInstallCmd.toArray(new String[0])); |
| verify(mMockDevice, times(1)) |
| .executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(2)).waitForDeviceAvailable(); |
| } finally { |
| FileUtil.deleteFile(mFakeApexApks); |
| FileUtil.deleteFile(mFakeApkApks); |
| FileUtil.recursiveDelete(fakeSplitApexApks); |
| FileUtil.deleteFile(fakeSplitApexApks); |
| FileUtil.recursiveDelete(fakeSplitApkApks); |
| FileUtil.deleteFile(fakeSplitApkApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| } |
| |
| @Test |
| public void testInstallUsingBundletool_AbsolutePath() throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APEX_APKS_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APK__APKS_NAME); |
| mFakeApexApks = File.createTempFile("fakeApex", ".apks"); |
| mFakeApkApks = File.createTempFile("fakeApk", ".apks"); |
| |
| File fakeSplitApexApks = File.createTempFile("ApexSplits", ""); |
| fakeSplitApexApks.delete(); |
| fakeSplitApexApks.mkdir(); |
| File splitApex = File.createTempFile("fakeSplitApex", ".apex", fakeSplitApexApks); |
| |
| File fakeSplitApkApks = File.createTempFile("ApkSplits", ""); |
| fakeSplitApkApks.delete(); |
| fakeSplitApkApks.mkdir(); |
| File splitApk1 = File.createTempFile("fakeSplitApk1", ".apk", fakeSplitApkApks); |
| mBundletoolJar = File.createTempFile("/fake/absolute/path/bundletool", ".jar"); |
| File splitApk2 = File.createTempFile("fakeSplitApk2", ".apk", fakeSplitApkApks); |
| try { |
| mockCleanInstalledApexPackages(); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| |
| assertTrue(fakeSplitApexApks != null); |
| assertTrue(fakeSplitApkApks != null); |
| assertTrue(mFakeApexApks != null); |
| assertTrue(mFakeApkApks != null); |
| assertEquals(1, fakeSplitApexApks.listFiles().length); |
| assertEquals(2, fakeSplitApkApks.listFiles().length); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApexApks); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApkApks); |
| |
| List<String> trainInstallCmd = new ArrayList<>(); |
| trainInstallCmd.add("install-multi-package"); |
| trainInstallCmd.add("--enable-rollback"); |
| trainInstallCmd.add(splitApex.getAbsolutePath()); |
| String cmd = ""; |
| for (File f : fakeSplitApkApks.listFiles()) { |
| if (!cmd.isEmpty()) { |
| cmd += ":" + f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } else { |
| cmd += f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } |
| } |
| trainInstallCmd.add(cmd); |
| when(mMockDevice.executeAdbCommand(trainInstallCmd.toArray(new String[0]))) |
| .thenReturn("Success"); |
| |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| SPLIT_APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME)) |
| .thenReturn("Success"); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(SPLIT_APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| Mockito.verify(mMockBundletoolUtil, times(1)) |
| .generateDeviceSpecFile(Mockito.any(ITestDevice.class)); |
| // Extract splits 1 time to get the package name for the module, and again during |
| // installation. |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| verify(mMockDevice, times(3)).reboot(); |
| verify(mMockDevice, times(1)).executeAdbCommand(trainInstallCmd.toArray(new String[0])); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)) |
| .executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(2)).waitForDeviceAvailable(); |
| } finally { |
| FileUtil.deleteFile(mFakeApexApks); |
| FileUtil.deleteFile(mFakeApkApks); |
| FileUtil.recursiveDelete(fakeSplitApexApks); |
| FileUtil.deleteFile(fakeSplitApexApks); |
| FileUtil.recursiveDelete(fakeSplitApkApks); |
| FileUtil.deleteFile(fakeSplitApkApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| } |
| |
| @Test |
| public void testInstallUsingBundletool_TrainFolder() throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| File trainFolder = File.createTempFile("tmpTrain", ""); |
| trainFolder.delete(); |
| trainFolder.mkdir(); |
| mSetter.setOptionValue("train-path", trainFolder.getAbsolutePath()); |
| mFakeApexApks = File.createTempFile("fakeApex", ".apks", trainFolder); |
| mFakeApkApks = File.createTempFile("fakeApk", ".apks", trainFolder); |
| |
| File fakeSplitApexApks = File.createTempFile("ApexSplits", ""); |
| fakeSplitApexApks.delete(); |
| fakeSplitApexApks.mkdir(); |
| File splitApex = File.createTempFile("fakeSplitApex", ".apex", fakeSplitApexApks); |
| |
| File fakeSplitApkApks = File.createTempFile("ApkSplits", ""); |
| fakeSplitApkApks.delete(); |
| fakeSplitApkApks.mkdir(); |
| File splitApk1 = File.createTempFile("fakeSplitApk1", ".apk", fakeSplitApkApks); |
| mBundletoolJar = File.createTempFile("bundletool", ".jar"); |
| File splitApk2 = File.createTempFile("fakeSplitApk2", ".apk", fakeSplitApkApks); |
| try { |
| mockCleanInstalledApexPackages(); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| |
| assertTrue(fakeSplitApexApks != null); |
| assertTrue(fakeSplitApkApks != null); |
| assertTrue(mFakeApexApks != null); |
| assertTrue(mFakeApkApks != null); |
| assertEquals(1, fakeSplitApexApks.listFiles().length); |
| assertEquals(2, fakeSplitApkApks.listFiles().length); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApexApks); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApkApks); |
| |
| List<String> trainInstallCmd = new ArrayList<>(); |
| trainInstallCmd.add("install-multi-package"); |
| trainInstallCmd.add("--enable-rollback"); |
| trainInstallCmd.add(splitApex.getAbsolutePath()); |
| String cmd = ""; |
| for (File f : fakeSplitApkApks.listFiles()) { |
| if (!cmd.isEmpty()) { |
| cmd += ":" + f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } else { |
| cmd += f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } |
| } |
| trainInstallCmd.add(cmd); |
| when(mMockDevice.executeAdbCommand(trainInstallCmd.toArray(new String[0]))) |
| .thenReturn("Success"); |
| |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| SPLIT_APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME)) |
| .thenReturn("Success"); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(SPLIT_APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| Mockito.verify(mMockBundletoolUtil, times(1)) |
| .generateDeviceSpecFile(Mockito.any(ITestDevice.class)); |
| // Extract splits 1 time to get the package name for the module, and again during |
| // installation. |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| verify(mMockDevice, times(3)).reboot(); |
| verify(mMockDevice, times(1)).executeAdbCommand(trainInstallCmd.toArray(new String[0])); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)) |
| .executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(2)).waitForDeviceAvailable(); |
| } finally { |
| FileUtil.recursiveDelete(trainFolder); |
| FileUtil.deleteFile(trainFolder); |
| FileUtil.deleteFile(mFakeApexApks); |
| FileUtil.deleteFile(mFakeApkApks); |
| FileUtil.recursiveDelete(fakeSplitApexApks); |
| FileUtil.deleteFile(fakeSplitApexApks); |
| FileUtil.recursiveDelete(fakeSplitApkApks); |
| FileUtil.deleteFile(fakeSplitApkApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| } |
| |
| @Test |
| public void testInstallUsingBundletool_AllFilesHaveAbsolutePath() throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| mFakeApexApks = File.createTempFile("fakeApex", ".apks"); |
| mFakeApkApks = File.createTempFile("fakeApk", ".apks"); |
| mInstallApexModuleTargetPreparer.addTestFile(mFakeApexApks); |
| mInstallApexModuleTargetPreparer.addTestFile(mFakeApkApks); |
| |
| File fakeSplitApexApks = File.createTempFile("ApexSplits", ""); |
| fakeSplitApexApks.delete(); |
| fakeSplitApexApks.mkdir(); |
| File splitApex = File.createTempFile("fakeSplitApex", ".apex", fakeSplitApexApks); |
| |
| File fakeSplitApkApks = File.createTempFile("ApkSplits", ""); |
| fakeSplitApkApks.delete(); |
| fakeSplitApkApks.mkdir(); |
| File splitApk1 = File.createTempFile("fakeSplitApk1", ".apk", fakeSplitApkApks); |
| mBundletoolJar = File.createTempFile("/fake/absolute/path/bundletool", ".jar"); |
| File splitApk2 = File.createTempFile("fakeSplitApk2", ".apk", fakeSplitApkApks); |
| try { |
| mockCleanInstalledApexPackages(); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| |
| assertTrue(fakeSplitApexApks != null); |
| assertTrue(fakeSplitApkApks != null); |
| assertTrue(mFakeApexApks != null); |
| assertTrue(mFakeApkApks != null); |
| assertEquals(1, fakeSplitApexApks.listFiles().length); |
| assertEquals(2, fakeSplitApkApks.listFiles().length); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApexApks); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApkApks); |
| |
| List<String> trainInstallCmd = new ArrayList<>(); |
| trainInstallCmd.add("install-multi-package"); |
| trainInstallCmd.add("--enable-rollback"); |
| trainInstallCmd.add(splitApex.getAbsolutePath()); |
| String cmd = ""; |
| for (File f : fakeSplitApkApks.listFiles()) { |
| if (!cmd.isEmpty()) { |
| cmd += ":" + f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } else { |
| cmd += f.getParentFile().getAbsolutePath() + "/" + f.getName(); |
| } |
| } |
| trainInstallCmd.add(cmd); |
| when(mMockDevice.executeAdbCommand(trainInstallCmd.toArray(new String[0]))) |
| .thenReturn("Success"); |
| |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| SPLIT_APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME)) |
| .thenReturn("Success"); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(SPLIT_APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| Mockito.verify(mMockBundletoolUtil, times(1)) |
| .generateDeviceSpecFile(Mockito.any(ITestDevice.class)); |
| // Extract splits 1 time to get the package name for the module, and again during |
| // installation. |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| Mockito.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| verify(mMockDevice, times(3)).reboot(); |
| verify(mMockDevice, times(1)).executeAdbCommand(trainInstallCmd.toArray(new String[0])); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)) |
| .executeShellCommand("pm rollback-app " + SPLIT_APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(2)).waitForDeviceAvailable(); |
| } finally { |
| FileUtil.deleteFile(mFakeApexApks); |
| FileUtil.deleteFile(mFakeApkApks); |
| FileUtil.recursiveDelete(fakeSplitApexApks); |
| FileUtil.deleteFile(fakeSplitApexApks); |
| FileUtil.recursiveDelete(fakeSplitApkApks); |
| FileUtil.deleteFile(fakeSplitApkApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| } |
| |
| @Test |
| public void testInstallUsingBundletool_skipModuleNotPreloaded() throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| mSetter.setOptionValue("ignore-if-module-not-preloaded", "true"); |
| // Will skip this apex module |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APEX_APKS_NAME); |
| // Will install this apk module |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APK__APKS_NAME); |
| mFakeApexApks = File.createTempFile("fakeApex", ".apks"); |
| mFakeApkApks = File.createTempFile("fakeApk", ".apks"); |
| InOrder order = inOrder(mMockDevice, mMockBundletoolUtil); |
| |
| File fakeSplitApexApks = File.createTempFile("ApexSplits", ""); |
| fakeSplitApexApks.delete(); |
| fakeSplitApexApks.mkdir(); |
| File splitApex = File.createTempFile("fakeSplitApex", ".apex", fakeSplitApexApks); |
| |
| File fakeSplitApkApks = File.createTempFile("ApkSplits", ""); |
| fakeSplitApkApks.delete(); |
| fakeSplitApkApks.mkdir(); |
| File splitApk1 = File.createTempFile("fakeSplitApk1", ".apk", fakeSplitApkApks); |
| mBundletoolJar = File.createTempFile("bundletool", ".jar"); |
| File splitApk2 = File.createTempFile("fakeSplitApk2", ".apk", fakeSplitApkApks); |
| try { |
| mockCleanInstalledApexPackages(); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| |
| assertNotNull(fakeSplitApexApks); |
| assertNotNull(fakeSplitApkApks); |
| assertNotNull(mFakeApexApks); |
| assertNotNull(mFakeApkApks); |
| assertEquals(1, fakeSplitApexApks.listFiles().length); |
| assertEquals(2, fakeSplitApkApks.listFiles().length); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| eq(mFakeApexApks), |
| anyString(), |
| any(ITestDevice.class), |
| any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApexApks); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| eq(mFakeApkApks), |
| anyString(), |
| any(ITestDevice.class), |
| any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApkApks); |
| // Split apex package is not preloaded in the device so should not be activated. |
| when(mMockDevice.getActiveApexes()).thenReturn(new HashSet<>()); |
| when(mMockDevice.uninstallPackage(SPLIT_APK_PACKAGE_NAME)).thenReturn(null); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(SPLIT_APK_PACKAGE_NAME); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| |
| order.verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| order.verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| order.verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| order.verify(mMockDevice, times(1)).reboot(); |
| order.verify(mMockDevice, times(2)).getActiveApexes(); |
| order.verify(mMockBundletoolUtil, times(1)) |
| .generateDeviceSpecFile(Mockito.any(ITestDevice.class)); |
| // Extract splits 1 time to get the package name for the module, does not attempt to |
| // install. |
| order.verify(mMockBundletoolUtil, times(1)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| // The 1st time to exact the package name, the 2nd time to check if it is apex before |
| // installing. |
| order.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class)); |
| order.verify(mMockBundletoolUtil, times(1)) |
| .installApks(eq(mFakeApkApks), eq(mMockDevice)); |
| order.verify(mMockDevice, times(1)).uninstallPackage(SPLIT_APK_PACKAGE_NAME); |
| } finally { |
| FileUtil.deleteFile(mFakeApexApks); |
| FileUtil.deleteFile(mFakeApkApks); |
| FileUtil.recursiveDelete(fakeSplitApexApks); |
| FileUtil.deleteFile(fakeSplitApexApks); |
| FileUtil.recursiveDelete(fakeSplitApkApks); |
| FileUtil.deleteFile(fakeSplitApkApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| } |
| |
| @Test |
| public void testInstallUsingBundletool_rebootAfterInstallSingleSplitApexApks() |
| throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| InOrder order = inOrder(mMockDevice, mMockBundletoolUtil); |
| mSetter.setOptionValue("ignore-if-module-not-preloaded", "true"); |
| mBundletoolJar = File.createTempFile("bundletool", ".jar"); |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APEX_APKS_NAME); |
| mFakeApexApks = File.createTempFile("fakeApex", ".apks"); |
| File fakeSplitApexApks = File.createTempFile("ApexSplits", ""); |
| fakeSplitApexApks.delete(); |
| fakeSplitApexApks.mkdir(); |
| File splitApex = File.createTempFile("fakeSplitApex", ".apex", fakeSplitApexApks); |
| |
| try { |
| mockCleanInstalledApexPackages(); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| assertNotNull(fakeSplitApexApks); |
| assertNotNull(mFakeApexApks); |
| assertEquals(1, fakeSplitApexApks.listFiles().length); |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(fakeSplitApexApks); |
| Set<ApexInfo> activatedApex = new HashSet<>(); |
| activatedApex.add( |
| new ApexInfo( |
| SPLIT_APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| |
| order.verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| order.verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| order.verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| order.verify(mMockDevice, times(1)).reboot(); |
| order.verify(mMockDevice, times(1)).getActiveApexes(); |
| order.verify(mMockDevice, times(1)).getActiveApexes(); |
| order.verify(mMockBundletoolUtil, times(1)) |
| .generateDeviceSpecFile(any(ITestDevice.class)); |
| // The 1st time to exact the package name, the 2nd time to extract apex for |
| // installation. |
| order.verify(mMockBundletoolUtil, times(2)) |
| .extractSplitsFromApks( |
| Mockito.eq(mFakeApexApks), |
| anyString(), |
| any(ITestDevice.class), |
| any(IBuildInfo.class)); |
| order.verify(mMockDevice, times(1)).installPackage(eq(splitApex), anyBoolean(), any()); |
| order.verify(mMockDevice, times(1)).reboot(); |
| order.verify(mMockDevice, times(1)).getActiveApexes(); |
| } finally { |
| FileUtil.deleteFile(mFakeApexApks); |
| FileUtil.deleteFile(splitApex); |
| FileUtil.recursiveDelete(fakeSplitApexApks); |
| FileUtil.deleteFile(fakeSplitApexApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| } |
| |
| @Test |
| public void testSetupAndTearDown_SingleInstall_NoEnableRollback() throws Exception { |
| mSetter.setOptionValue("enable-rollback", "false"); |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| doReturn(new HashSet<>()) |
| .doReturn(new HashSet<>()) |
| .doReturn(new HashSet<>(Arrays.asList(fakeApexData))) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex)); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| verifySuccessfulInstallPackageNoEnableRollback(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_MultiInstall_NoEnableRollback() throws Exception { |
| mSetter.setOptionValue("enable-rollback", "false"); |
| mSetter.setOptionValue("skip-apex-teardown", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX2_NAME); |
| |
| ApexInfo fakeApexData = |
| new ApexInfo( |
| APEX_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex"); |
| ApexInfo fakeApex2Data = |
| new ApexInfo( |
| APEX2_PACKAGE_NAME, |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX2_PACKAGE_NAME@1.apex"); |
| doReturn(new HashSet<>()) |
| .doReturn(new HashSet<>()) |
| .doReturn(new HashSet<>(Arrays.asList(fakeApexData, fakeApex2Data))) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| when(mMockDevice.getMainlineModuleInfo()).thenReturn(new HashSet<>()); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(APEX2_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| when(mMockDevice.executeAdbCommand((String[]) Mockito.any())).thenReturn("Success"); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApex, mFakeApex2)); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, atLeastOnce()).getActiveApexes(); |
| verify(mMockDevice, times(1)).getMainlineModuleInfo(); |
| verifySuccessfulInstallMultiPackagesNoEnableRollback(); |
| } |
| |
| /** |
| * Test that teardown without setup does not cause a NPE. |
| */ |
| @Test |
| public void testTearDown() throws Exception { |
| |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_noModulesPreloaded() throws Exception { |
| mSetter.setOptionValue("ignore-if-module-not-preloaded", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(new HashSet<String>()); |
| mockCleanInstalledApexPackages(); |
| doReturn(ImmutableSet.of()) |
| .doReturn(new HashSet<ApexInfo>()) |
| .when(mMockDevice) |
| .getActiveApexes(); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifyCleanInstalledApexPackages(); |
| verify(mMockDevice, times(1)).reboot(); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_skipModulesNotPreloaded() throws Exception { |
| mSetter.setOptionValue("ignore-if-module-not-preloaded", "true"); |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| // Module not preloaded. |
| mInstallApexModuleTargetPreparer.addTestFileName(APK2_NAME); |
| mockCleanInstalledApexPackages(); |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApk, mFakeApex)); |
| setActivatedApex(); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME)) |
| .thenReturn("Success"); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verifySuccessfulInstallMultiPackages(); |
| verify(mMockDevice, times(3)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)).executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice).waitForDeviceAvailable(); |
| } |
| |
| @Test(expected = TargetSetupError.class) |
| public void testSetupAndTearDown_throwExceptionModulesNotPreloaded() throws Exception { |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK2_NAME); |
| mockCleanInstalledApexPackages(); |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| "com.android.FAKE_APEX_PACKAGE_NAME", |
| 1, |
| "/system/apex/com.android.FAKE_APEX_PACKAGE_NAME.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| when(mMockDevice.uninstallPackage(APK_PACKAGE_NAME)).thenReturn(null); |
| |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verify(mMockDevice, times(1)).reboot(); |
| verify(mMockDevice, times(3)).getActiveApexes(); |
| verify(mMockDevice, times(1)).uninstallPackage(APK_PACKAGE_NAME); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| } |
| |
| @Test |
| public void testSetupAndTearDown_skipModulesThatFailToExtract() throws Exception { |
| mMockBundletoolUtil = mock(BundletoolUtil.class); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(SPLIT_APK__APKS_NAME); |
| mFakeApkApks = File.createTempFile("fakeApk", ".apks"); |
| mBundletoolJar = File.createTempFile("bundletool", ".jar"); |
| |
| mockCleanInstalledApexPackages(); |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| "com.android.FAKE_APEX_PACKAGE_NAME", |
| 1, |
| "/system/apex/com.android.FAKE_APEX_PACKAGE_NAME.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(SPLIT_APK_PACKAGE_NAME); |
| installableModules.add(APK_PACKAGE_NAME); |
| when(mMockDevice.getInstalledPackageNames()).thenReturn(installableModules); |
| when(mMockBundletoolUtil.generateDeviceSpecFile(Mockito.any(ITestDevice.class))) |
| .thenReturn("serial.json"); |
| |
| when(mMockBundletoolUtil.extractSplitsFromApks( |
| Mockito.eq(mFakeApkApks), |
| anyString(), |
| Mockito.any(ITestDevice.class), |
| Mockito.any(IBuildInfo.class))) |
| .thenReturn(null); |
| |
| // Only install apk, throw no error for apks. |
| mockSuccessfulInstallMultiPackages(Arrays.asList(mFakeApk)); |
| when(mMockDevice.uninstallPackage(APK_PACKAGE_NAME)).thenReturn(null); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| |
| mInstallApexModuleTargetPreparer.setUp(mTestInfo); |
| mInstallApexModuleTargetPreparer.tearDown(mTestInfo, null); |
| verify(mMockDevice, times(2)).getActiveApexes(); |
| verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).getInstalledPackageNames(); |
| verify(mMockDevice, times(1)).uninstallPackage(APK_PACKAGE_NAME); |
| verify(mMockDevice).reboot(); |
| |
| FileUtil.deleteFile(mFakeApkApks); |
| FileUtil.deleteFile(mBundletoolJar); |
| } |
| |
| private void verifySuccessfulInstallPackages(List<File> files) throws Exception { |
| int child_session_id = 1; |
| for (File f : files) { |
| verify(mMockDevice, times(1)).executeShellV2Command(String.format( |
| "pm install-write -S %d %s %s %s", |
| f.length(), |
| String.valueOf(child_session_id), |
| mInstallApexModuleTargetPreparer.parsePackageName(f, null), |
| MODULE_PUSH_REMOTE_PATH + f.getName())); |
| } |
| verify(mMockDevice, times(files.size())).executeShellV2Command(String.format( |
| "pm install-add-session " + "123" + " " + String.valueOf(child_session_id))); |
| verify(mMockDevice, times(1)).executeShellV2Command(PARENT_SESSION_CREATION_CMD); |
| verify(mMockDevice, times(1)).executeShellV2Command("pm install-commit " + "123"); |
| } |
| |
| private void mockSuccessfulInstallMultiPackages(List<File> files) throws Exception { |
| for (File f : files) { |
| when(mMockDevice.pushFile(f, MODULE_PUSH_REMOTE_PATH + f.getName())) |
| .thenReturn(Boolean.TRUE); |
| } |
| |
| CommandResult parent_session_creation_res = new CommandResult(); |
| parent_session_creation_res.setStdout("123"); |
| parent_session_creation_res.setStatus(CommandStatus.SUCCESS); |
| when(mMockDevice.executeShellV2Command(PARENT_SESSION_CREATION_CMD)).thenReturn(parent_session_creation_res); |
| when(mMockDevice.executeShellV2Command(PARENT_SESSION_CREATION_ROLLBACK_NO_ENABLE_CMD)).thenReturn(parent_session_creation_res); |
| |
| CommandResult successful_shell_cmd_res = new CommandResult(); |
| successful_shell_cmd_res.setStatus(CommandStatus.SUCCESS); |
| // Use same session id for child sessions in the test as the file iteration is non-deterministic |
| int child_session_id = 1; |
| for (File f : files) { |
| CommandResult child_session_creation_res = new CommandResult(); |
| child_session_creation_res.setStdout(String.valueOf(child_session_id)); |
| child_session_creation_res.setStatus(CommandStatus.SUCCESS); |
| if (f.getName().endsWith("apex")) { |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APEX)).thenReturn(child_session_creation_res); |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_ROLLBACK_NO_ENABLE_CMD_APEX)).thenReturn(child_session_creation_res); |
| } else { |
| when(mMockDevice.executeShellV2Command(CHILD_SESSION_CREATION_CMD_APK)).thenReturn(child_session_creation_res); |
| } |
| when(mMockDevice.executeShellV2Command( |
| String.format( |
| "pm install-write -S %d %s %s %s", |
| f.length(), |
| String.valueOf(child_session_id), |
| mInstallApexModuleTargetPreparer.parsePackageName(f, mMockDevice.getDeviceDescriptor()), |
| MODULE_PUSH_REMOTE_PATH + f.getName()))).thenReturn(successful_shell_cmd_res); |
| when(mMockDevice.executeShellV2Command( |
| String.format( |
| "pm install-add-session " + parent_session_creation_res.getStdout() + " " + String.valueOf(child_session_id)))).thenReturn(successful_shell_cmd_res); |
| } |
| when(mMockDevice.executeShellV2Command("pm install-commit " + parent_session_creation_res.getStdout())).thenReturn(successful_shell_cmd_res); |
| } |
| |
| private void verifySuccessfulInstallMultiPackages() throws Exception { |
| verify(mMockDevice, times(1)).executeShellV2Command("pm install-commit " + "123"); |
| } |
| |
| private void verifySuccessfulInstallPackageNoEnableRollback() throws Exception { |
| verify(mMockDevice, times(1)).executeShellV2Command(CHILD_SESSION_CREATION_ROLLBACK_NO_ENABLE_CMD_APEX); |
| verify(mMockDevice, times(1)).executeShellV2Command("pm install-commit " + "123"); |
| } |
| |
| private void verifySuccessfulInstallMultiPackagesNoEnableRollback() throws Exception { |
| verify(mMockDevice, times(2)).executeShellV2Command(CHILD_SESSION_CREATION_ROLLBACK_NO_ENABLE_CMD_APEX); |
| verify(mMockDevice, times(1)).executeShellV2Command("pm install-commit " + "123"); |
| } |
| |
| private void mockCleanInstalledApexPackages() throws DeviceNotAvailableException { |
| CommandResult res = new CommandResult(); |
| res.setStdout("test.apex"); |
| when(mMockDevice.executeShellV2Command("ls " + APEX_DATA_DIR)).thenReturn(res); |
| when(mMockDevice.executeShellV2Command("ls " + SESSION_DATA_DIR)).thenReturn(res); |
| when(mMockDevice.executeShellV2Command("ls " + STAGING_DATA_DIR)).thenReturn(res); |
| } |
| |
| private void verifyCleanInstalledApexPackages() throws DeviceNotAvailableException { |
| verify(mMockDevice, times(1)).deleteFile(APEX_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(SESSION_DATA_DIR + "*"); |
| verify(mMockDevice, times(1)).deleteFile(STAGING_DATA_DIR + "*"); |
| } |
| |
| private void setActivatedApex() throws DeviceNotAvailableException { |
| Set<ApexInfo> activatedApex = new HashSet<ApexInfo>(); |
| activatedApex.add( |
| new ApexInfo( |
| "com.android.FAKE_APEX_PACKAGE_NAME", |
| 1, |
| "/data/apex/active/com.android.FAKE_APEX_PACKAGE_NAME@1.apex")); |
| when(mMockDevice.getActiveApexes()).thenReturn(activatedApex); |
| } |
| |
| private Set<String> setupInstallableModulesSingleApexSingleApk() throws DeviceNotAvailableException{ |
| mInstallApexModuleTargetPreparer.addTestFileName(APEX_NAME); |
| mInstallApexModuleTargetPreparer.addTestFileName(APK_NAME); |
| mockCleanInstalledApexPackages(); |
| when(mMockDevice.executeShellCommand("pm rollback-app " + APEX_PACKAGE_NAME)) |
| .thenReturn("Success"); |
| Set<String> installableModules = new HashSet<>(); |
| installableModules.add(APEX_PACKAGE_NAME); |
| installableModules.add(APK_PACKAGE_NAME); |
| return installableModules; |
| } |
| } |