1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tests.apex; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import static org.junit.Assume.assumeTrue; 23 24 import android.cts.install.lib.host.InstallUtilsHost; 25 import android.platform.test.annotations.RequiresDevice; 26 27 import com.android.tests.rollback.host.AbandonSessionsRule; 28 import com.android.tradefed.config.Option; 29 import com.android.tradefed.config.Option.Importance; 30 import com.android.tradefed.device.ITestDevice.ApexInfo; 31 import com.android.tradefed.log.LogUtil.CLog; 32 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 33 34 import org.junit.After; 35 import org.junit.Assert; 36 import org.junit.Before; 37 import org.junit.Rule; 38 import org.junit.Test; 39 40 import java.io.File; 41 import java.time.Duration; 42 import java.util.List; 43 import java.util.Set; 44 45 /** 46 * Base test to check if Apex can be staged, activated and uninstalled successfully. 47 */ 48 public abstract class ApexE2EBaseHostTest extends BaseHostJUnit4Test { 49 50 private static final String OPTION_APEX_FILE_NAME = "apex_file_name"; 51 52 private static final Duration BOOT_COMPLETE_TIMEOUT = Duration.ofMinutes(2); 53 54 private static final String USERSPACE_REBOOT_SUPPORTED_PROP = 55 "init.userspace_reboot.is_supported"; 56 57 // Protected so that derived tests can have access to test utils automatically 58 protected final InstallUtilsHost mHostUtils = new InstallUtilsHost(this); 59 60 @Rule 61 public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this); 62 63 @Option(name = OPTION_APEX_FILE_NAME, 64 description = "The file name of the apex module.", 65 importance = Importance.IF_UNSET, 66 mandatory = true 67 ) 68 protected String mApexFileName = null; 69 70 @Before setUp()71 public void setUp() throws Exception { 72 assumeTrue("Updating APEX is not supported", mHostUtils.isApexUpdateSupported()); 73 uninstallAllApexes(); 74 } 75 76 @After tearDown()77 public void tearDown() throws Exception { 78 assumeTrue("Updating APEX is not supported", mHostUtils.isApexUpdateSupported()); 79 uninstallAllApexes(); 80 } 81 getAllApexFilenames()82 protected List<String> getAllApexFilenames() { 83 return List.of(mApexFileName); 84 } 85 86 @Test testStageActivateUninstallApexPackage()87 public final void testStageActivateUninstallApexPackage() throws Exception { 88 stageActivateUninstallApexPackage(false/*userspaceReboot*/); 89 } 90 91 @Test 92 @RequiresDevice // TODO(b/147726967): Remove when Userspace reboot works on cuttlefish testStageActivateUninstallApexPackageWithUserspaceReboot()93 public final void testStageActivateUninstallApexPackageWithUserspaceReboot() throws Exception { 94 assumeTrue("Userspace reboot not supported on the device", 95 getDevice().getBooleanProperty(USERSPACE_REBOOT_SUPPORTED_PROP, false)); 96 stageActivateUninstallApexPackage(true/*userspaceReboot*/); 97 } 98 stageActivateUninstallApexPackage(boolean userspaceReboot)99 private void stageActivateUninstallApexPackage(boolean userspaceReboot) throws Exception { 100 ApexInfo apex = installApex(mApexFileName); 101 102 reboot(userspaceReboot); // for install to take affect 103 Set<ApexInfo> activatedApexes = getDevice().getActiveApexes(); 104 assertWithMessage("Failed to activate %s", apex).that(activatedApexes).contains(apex); 105 106 additionalCheck(); 107 } 108 uninstallAllApexes()109 private void uninstallAllApexes() throws Exception { 110 for (String filename : getAllApexFilenames()) { 111 ApexInfo apex = mHostUtils.getApexInfo(mHostUtils.getTestFile(filename)); 112 uninstallApex(apex.name); 113 } 114 } 115 installApex(String filename)116 protected final ApexInfo installApex(String filename) throws Exception { 117 File testAppFile = mHostUtils.getTestFile(filename); 118 119 String installResult = mHostUtils.installStagedPackage(testAppFile); 120 assertWithMessage("failed to install test app %s. Reason: %s", filename, installResult) 121 .that(installResult).isNull(); 122 123 ApexInfo testApexInfo = mHostUtils.getApexInfo(testAppFile); 124 Assert.assertNotNull(testApexInfo); 125 return testApexInfo; 126 } 127 reboot(boolean userspaceReboot)128 protected final void reboot(boolean userspaceReboot) throws Exception { 129 if (userspaceReboot) { 130 assertThat(getDevice().setProperty("test.userspace_reboot.requested", "1")).isTrue(); 131 getDevice().rebootUserspace(); 132 } else { 133 getDevice().reboot(); 134 } 135 boolean success = getDevice().waitForBootComplete(BOOT_COMPLETE_TIMEOUT.toMillis()); 136 assertWithMessage("Device didn't boot in %s", BOOT_COMPLETE_TIMEOUT).that(success).isTrue(); 137 if (userspaceReboot) { 138 // If userspace reboot fails and fallback to hard reboot is triggered then 139 // test.userspace_reboot.requested won't be set. 140 boolean res = getDevice().getBooleanProperty("test.userspace_reboot.requested", false); 141 String message = "Userspace reboot failed, fallback to full reboot was triggered. "; 142 message += "Boot reason: " + getDevice().getProperty("sys.boot.reason.last"); 143 assertWithMessage(message).that(res).isTrue(); 144 } 145 } 146 147 /** 148 * Do some additional check, invoked by {@link #testStageActivateUninstallApexPackage()}. 149 */ additionalCheck()150 public void additionalCheck() throws Exception {}; 151 uninstallApex(String apexName)152 protected final void uninstallApex(String apexName) throws Exception { 153 String res = getDevice().uninstallPackage(apexName); 154 if (res != null) { 155 // Uninstall failed. Most likely this means that there were no apex installed. No need 156 // to reboot. 157 CLog.i("Uninstall of %s failed: %s, likely already on factory version", apexName, res); 158 } else { 159 // Uninstall succeeded. Need to reboot. 160 getDevice().reboot(); // for the uninstall to take affect 161 } 162 } 163 } 164