Add GkiDeviceFlashPreparer for GKI flash preparation.
Bug: 151989050
Test: unit tests, BootTest, CTS
Change-Id: Ia299e09664bae37e77802b8acaea4a0312bde219
Merged-in: Ia299e09664bae37e77802b8acaea4a0312bde219
diff --git a/res/config/template/preparers/gki-device-flash-preparer.xml b/res/config/template/preparers/gki-device-flash-preparer.xml
new file mode 100644
index 0000000..dfeffa9
--- /dev/null
+++ b/res/config/template/preparers/gki-device-flash-preparer.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 Google Inc. All Rights Reserved -->
+<configuration description="Common template for flashing the device with GKI image." >
+ <target_preparer class="com.android.tradefed.targetprep.GkiDeviceFlashPreparer" />
+</configuration>
diff --git a/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java b/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java
index b7457eb..98aaf56 100644
--- a/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java
+++ b/src/com/android/tradefed/targetprep/DeviceFlashPreparer.java
@@ -124,6 +124,11 @@
mDeviceBootTime = bootTime;
}
+ /** Gets the device boot wait time */
+ protected long getDeviceBootWaitTime() {
+ return mDeviceBootTime;
+ }
+
/**
* Gets the interval between device boot poll attempts.
* <p/>
diff --git a/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparer.java b/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparer.java
new file mode 100644
index 0000000..8ab27d6
--- /dev/null
+++ b/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparer.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2020 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 com.android.tradefed.build.IDeviceBuildInfo;
+import com.android.tradefed.config.GlobalConfiguration;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.DeviceUnresponsiveException;
+import com.android.tradefed.device.IDeviceManager;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.ITestDevice.RecoveryMode;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.IRunUtil;
+import com.android.tradefed.util.RunUtil;
+import com.android.tradefed.util.ZipUtil2;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A target preparer that flash the device with android common kernel generic image. Please see
+ * https://source.android.com/devices/architecture/kernel/android-common for details.
+ */
+@OptionClass(alias = "gki-device-flash-preparer")
+public class GkiDeviceFlashPreparer extends BaseTargetPreparer {
+
+ private static final String GKI_BOOT_IMG = "gki_boot.img";
+ private static final String MKBOOTIMG = "mkbootimg";
+ private static final String OTATOOLS_ZIP = "otatools.zip";
+ private static final String RAMDISK_RECOVERY_IMG = "ramdisk_recovery.img";
+ private static final String KERNEL_IMAGE = "kernel_image"; // The Image.gz file key
+ private static final String VENDOR_BOOT_IMG = "vendor_boot.img";
+ private static final String DTBO_IMG = "dtbo.img";
+ // Wait time for device state to stablize in millisecond
+ private static final int STATE_STABLIZATION_WAIT_TIME = 60000;
+
+ @Option(
+ name = "device-boot-time",
+ description = "max time to wait for device to boot. Set as 5 minutes by default",
+ isTimeVal = true)
+ private long mDeviceBootTime = 5 * 60 * 1000;
+
+ // The temp directory for files generated by target preparer
+ private File mPreparerTmpDir;
+
+ /** {@inheritDoc} */
+ @Override
+ public void setUp(TestInformation testInfo)
+ throws TargetSetupError, BuildError, DeviceNotAvailableException {
+ ITestDevice device = testInfo.getDevice();
+ IDeviceBuildInfo buildInfo = (IDeviceBuildInfo) testInfo.getBuildInfo();
+
+ try {
+ mPreparerTmpDir = FileUtil.createTempDir("gki_preparer_setup");
+ validateGkiBootImg(device, buildInfo);
+ flashGki(device, buildInfo);
+ } catch (IOException ioe) {
+ throw new TargetSetupError(ioe.getMessage(), ioe, device.getDeviceDescriptor());
+ } finally {
+ FileUtil.recursiveDelete(mPreparerTmpDir);
+ }
+ // Wait some time after flashing the image.
+ getRunUtil().sleep(STATE_STABLIZATION_WAIT_TIME);
+ device.rebootUntilOnline();
+ if (device.enableAdbRoot()) {
+ device.setDate(null);
+ }
+ try {
+ device.setRecoveryMode(RecoveryMode.AVAILABLE);
+ device.waitForDeviceAvailable(mDeviceBootTime);
+ } catch (DeviceUnresponsiveException e) {
+ // assume this is a build problem
+ throw new DeviceFailedToBootError(
+ String.format(
+ "Device %s did not become available after flashing GKI. Exception: %s",
+ device.getSerialNumber(), e),
+ device.getDeviceDescriptor());
+ }
+ device.postBootSetup();
+ CLog.i("Device update completed on %s", device.getDeviceDescriptor());
+ }
+
+ /**
+ * Get a reference to the {@link IDeviceManager}
+ *
+ * @return the {@link IDeviceManager} to use
+ */
+ @VisibleForTesting
+ IDeviceManager getDeviceManager() {
+ return GlobalConfiguration.getDeviceManagerInstance();
+ }
+
+ /**
+ * Get the {@link IRunUtil} instance to use.
+ *
+ * @return the {@link IRunUtil} to use
+ */
+ @VisibleForTesting
+ protected IRunUtil getRunUtil() {
+ return RunUtil.getDefault();
+ }
+
+ /**
+ * Flash GKI images.
+ *
+ * @param device the {@link ITestDevice}
+ * @param buildInfo the {@link IDeviceBuildInfo} the device build info
+ * @throws TargetSetupError, DeviceNotAvailableException, IOException
+ */
+ private void flashGki(ITestDevice device, IDeviceBuildInfo buildInfo)
+ throws TargetSetupError, DeviceNotAvailableException {
+ IDeviceManager deviceManager = getDeviceManager();
+ device.waitForDeviceOnline();
+ device.rebootIntoBootloader();
+ long start = System.currentTimeMillis();
+ deviceManager.takeFlashingPermit();
+ CLog.v(
+ "Flashing permit obtained after %ds",
+ TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
+ // Don't allow interruptions during flashing operations.
+ getRunUtil().allowInterrupt(false);
+ try {
+ if (buildInfo.getFile(VENDOR_BOOT_IMG) != null) {
+ executeFastbootCmd(
+ device,
+ "flash",
+ "vendor_boot",
+ buildInfo.getFile(VENDOR_BOOT_IMG).getAbsolutePath());
+ }
+ if (buildInfo.getFile(DTBO_IMG) != null) {
+ executeFastbootCmd(
+ device, "flash", "dtbo", buildInfo.getFile(DTBO_IMG).getAbsolutePath());
+ }
+ executeFastbootCmd(
+ device, "flash", "boot", buildInfo.getFile(GKI_BOOT_IMG).getAbsolutePath());
+ } finally {
+ deviceManager.returnFlashingPermit();
+ // Allow interruption at the end no matter what.
+ getRunUtil().allowInterrupt(true);
+ CLog.v(
+ "Flashing permit returned after %ds",
+ TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
+ }
+ }
+
+ /**
+ * Validate GKI boot image is expected. Throw exception if there is no valid boot.img.
+ *
+ * @param device the {@link ITestDevice}
+ * @param buildInfo the {@link IDeviceBuildInfo} the device build info
+ * @throws TargetSetupError, IOException if there is no valid gki boot.img
+ */
+ public void validateGkiBootImg(ITestDevice device, IDeviceBuildInfo buildInfo)
+ throws TargetSetupError {
+ if (buildInfo.getFile(GKI_BOOT_IMG) != null
+ && buildInfo.getFile(GKI_BOOT_IMG).length() > 0) {
+ return;
+ }
+ if (buildInfo.getFile(KERNEL_IMAGE) == null) {
+ throw new TargetSetupError(
+ KERNEL_IMAGE + " is not provided. Can not generate GKI boot.img.",
+ device.getDeviceDescriptor());
+ }
+ if (buildInfo.getFile(RAMDISK_RECOVERY_IMG) == null) {
+ throw new TargetSetupError(
+ RAMDISK_RECOVERY_IMG + " is not provided. Can not generate GKI boot.img.",
+ device.getDeviceDescriptor());
+ }
+ try {
+ File mkbootimg = getRequestedFile(device, MKBOOTIMG, buildInfo.getFile(OTATOOLS_ZIP));
+ File gkiBootImg = FileUtil.createTempFile("boot", ".img", mPreparerTmpDir);
+ String cmd =
+ String.format(
+ "%s --kernel %s --header_version 3 --base 0x00000000 "
+ + "--pagesize 4096 --ramdisk %s -o %s",
+ mkbootimg.getAbsolutePath(),
+ buildInfo.getFile(KERNEL_IMAGE),
+ buildInfo.getFile(RAMDISK_RECOVERY_IMG),
+ gkiBootImg.getAbsolutePath());
+ executeHostCommand(device, cmd);
+ CLog.i("The GKI boot.img is of size %d", gkiBootImg.length());
+ if (gkiBootImg.length() > 0) {
+ buildInfo.setFile(GKI_BOOT_IMG, gkiBootImg, "0");
+ } else {
+ throw new TargetSetupError(
+ "The mkbootimg tool didn't generate a valid boot.img.",
+ device.getDeviceDescriptor());
+ }
+ } catch (IOException e) {
+ throw new TargetSetupError("Fail to get mkbootimg.", e, device.getDeviceDescriptor());
+ }
+ }
+
+ /**
+ * Flash device images.
+ *
+ * @param device the {@link ITestDevice}
+ * @param buildInfo the {@link IDeviceBuildInfo} the device build info
+ * @throws TargetSetupError, DeviceNotAvailableException
+ */
+ private void flashDeviceImage(ITestDevice device, IDeviceBuildInfo buildInfo)
+ throws TargetSetupError, DeviceNotAvailableException {
+ IDeviceManager deviceManager = getDeviceManager();
+ long start = System.currentTimeMillis();
+ deviceManager.takeFlashingPermit();
+ CLog.v(
+ "Flashing permit obtained after %ds",
+ TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
+ // don't allow interruptions during flashing operations.
+ getRunUtil().allowInterrupt(false);
+ try {
+ executeFastbootCmd(
+ device,
+ "--skip-reboot",
+ "--disable-verity",
+ "update",
+ buildInfo.getDeviceImageFile().getAbsolutePath());
+ } finally {
+ // Allow interruption at the end no matter what.
+ getRunUtil().allowInterrupt(true);
+ deviceManager.returnFlashingPermit();
+ CLog.v(
+ "Flashing permit returned after %ds",
+ TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
+ }
+ }
+
+ /**
+ * Helper method to execute host command.
+ *
+ * @param device the {@link ITestDevice}
+ * @param command the command string
+ * @throws TargetSetupError, DeviceNotAvailableException
+ */
+ private void executeHostCommand(ITestDevice device, final String command)
+ throws TargetSetupError {
+ final CommandResult result = getRunUtil().runTimedCmd(300000L, command.split("\\s+"));
+ switch (result.getStatus()) {
+ case SUCCESS:
+ CLog.i(
+ "Command %s finished successfully, stdout = [%s].",
+ command, result.getStdout());
+ break;
+ case FAILED:
+ throw new TargetSetupError(
+ String.format(
+ "Command %s failed, stdout = [%s], stderr = [%s].",
+ command, result.getStdout(), result.getStderr()),
+ device.getDeviceDescriptor());
+ case TIMED_OUT:
+ throw new TargetSetupError(
+ String.format("Command %s timed out.", command),
+ device.getDeviceDescriptor());
+ case EXCEPTION:
+ throw new TargetSetupError(
+ String.format("Exception occurred when running command %s.", command),
+ device.getDeviceDescriptor());
+ }
+ }
+
+ /**
+ * Get the requested file from the source file (zip or folder) by requested file name.
+ *
+ * <p>The provided source file can be a zip file. The method will unzip it to tempary directory
+ * and find the requested file by the provided file name.
+ *
+ * <p>The provided source file can be a file folder. The method will find the requestd file by
+ * the provided file name.
+ *
+ * @param device the {@link ITestDevice}
+ * @param requestedFileName the requeste file name String
+ * @param sourceFile the source file
+ * @return the file that is specified by the requested file name
+ * @throws TargetSetupError, IOException
+ */
+ private File getRequestedFile(ITestDevice device, String requestedFileName, File sourceFile)
+ throws TargetSetupError, IOException {
+ File requestedFile = null;
+ if (sourceFile.getName().endsWith(".zip")) {
+ File destDir =
+ FileUtil.createTempDir(
+ FileUtil.getBaseName(sourceFile.getName()), mPreparerTmpDir);
+ ZipUtil2.extractZip(sourceFile, destDir);
+ requestedFile = FileUtil.findFile(destDir, requestedFileName);
+ } else if (sourceFile.isDirectory()) {
+ requestedFile = FileUtil.findFile(sourceFile, requestedFileName);
+ }
+ if (requestedFile == null || !requestedFile.exists()) {
+ throw new TargetSetupError(
+ String.format(
+ "Requested file with file_name %s does not exist in provided %s.",
+ requestedFileName, sourceFile),
+ device.getDeviceDescriptor());
+ }
+ return requestedFile;
+ }
+
+ /**
+ * Helper method to execute a fastboot command.
+ *
+ * @param device the {@link ITestDevice} to execute command on
+ * @param cmdArgs the arguments to provide to fastboot
+ * @return String the stderr output from command if non-empty. Otherwise returns the stdout Some
+ * fastboot commands are weird in that they dump output to stderr on success case
+ * @throws DeviceNotAvailableException if device is not available
+ * @throws TargetSetupError if fastboot command fails
+ */
+ private String executeFastbootCmd(ITestDevice device, String... cmdArgs)
+ throws DeviceNotAvailableException, TargetSetupError {
+ CLog.i("Execute fastboot command %s on %s", cmdArgs, device.getSerialNumber());
+ CommandResult result = device.executeLongFastbootCommand(cmdArgs);
+ CLog.v("fastboot stdout: " + result.getStdout());
+ CLog.v("fastboot stderr: " + result.getStderr());
+ CommandStatus cmdStatus = result.getStatus();
+ // fastboot command line output is in stderr even for successful run
+ if (result.getStderr().contains("FAILED")) {
+ // if output contains "FAILED", just override to failure
+ cmdStatus = CommandStatus.FAILED;
+ }
+ if (cmdStatus != CommandStatus.SUCCESS) {
+ throw new TargetSetupError(
+ String.format(
+ "fastboot command %s failed in device %s. stdout: %s, stderr: %s",
+ cmdArgs[0],
+ device.getSerialNumber(),
+ result.getStdout(),
+ result.getStderr()),
+ device.getDeviceDescriptor());
+ }
+ if (result.getStderr().length() > 0) {
+ return result.getStderr();
+ } else {
+ return result.getStdout();
+ }
+ }
+}
diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java
index fd4c1cd..ce2bdd6 100644
--- a/tests/src/com/android/tradefed/UnitTests.java
+++ b/tests/src/com/android/tradefed/UnitTests.java
@@ -225,6 +225,7 @@
import com.android.tradefed.targetprep.DynamicSystemPreparerTest;
import com.android.tradefed.targetprep.FastbootDeviceFlasherTest;
import com.android.tradefed.targetprep.FlashingResourcesParserTest;
+import com.android.tradefed.targetprep.GkiDeviceFlashPreparerTest;
import com.android.tradefed.targetprep.InstallAllTestZipAppsSetupTest;
import com.android.tradefed.targetprep.InstallApexModuleTargetPreparerTest;
import com.android.tradefed.targetprep.InstallApkSetupTest;
@@ -668,6 +669,7 @@
DynamicSystemPreparerTest.class,
FastbootDeviceFlasherTest.class,
FlashingResourcesParserTest.class,
+ GkiDeviceFlashPreparerTest.class,
InstallAllTestZipAppsSetupTest.class,
InstallApexModuleTargetPreparerTest.class,
InstallApkSetupTest.class,
diff --git a/tests/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparerTest.java b/tests/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparerTest.java
new file mode 100644
index 0000000..1fc81b6
--- /dev/null
+++ b/tests/src/com/android/tradefed/targetprep/GkiDeviceFlashPreparerTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2020 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.fail;
+
+import com.android.tradefed.build.DeviceBuildInfo;
+import com.android.tradefed.build.IDeviceBuildInfo;
+import com.android.tradefed.command.remote.DeviceDescriptor;
+import com.android.tradefed.device.DeviceAllocationState;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.IDeviceManager;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.ITestDevice.RecoveryMode;
+import com.android.tradefed.device.TestDeviceOptions;
+import com.android.tradefed.invoker.IInvocationContext;
+import com.android.tradefed.invoker.InvocationContext;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.IRunUtil;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+
+/** Unit tests for {@link GkiDevicePreparer}. */
+@RunWith(JUnit4.class)
+public class GkiDeviceFlashPreparerTest {
+
+ private IDeviceManager mMockDeviceManager;
+ private IDeviceFlasher mMockFlasher;
+ private GkiDeviceFlashPreparer mPreparer;
+ private ITestDevice mMockDevice;
+ private IDeviceBuildInfo mBuildInfo;
+ private File mTmpDir;
+ private TestInformation mTestInfo;
+ private OptionSetter mOptionSetter;
+ private CommandResult mSuccessResult;
+ private CommandResult mFailureResult;
+ private IRunUtil mMockRunUtil;
+ private DeviceDescriptor mDeviceDescriptor;
+
+ @Before
+ public void setUp() throws Exception {
+ mDeviceDescriptor =
+ new DeviceDescriptor(
+ "serial_1",
+ false,
+ DeviceAllocationState.Available,
+ "unknown",
+ "unknown",
+ "unknown",
+ "unknown",
+ "unknown");
+ mMockDeviceManager = EasyMock.createMock(IDeviceManager.class);
+ mMockDevice = EasyMock.createMock(ITestDevice.class);
+ EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn("serial_1");
+ EasyMock.expect(mMockDevice.getDeviceDescriptor()).andStubReturn(mDeviceDescriptor);
+ EasyMock.expect(mMockDevice.getOptions()).andReturn(new TestDeviceOptions()).anyTimes();
+ mMockRunUtil = EasyMock.createMock(IRunUtil.class);
+ mPreparer =
+ new GkiDeviceFlashPreparer() {
+ @Override
+ protected IRunUtil getRunUtil() {
+ return mMockRunUtil;
+ }
+
+ @Override
+ IDeviceManager getDeviceManager() {
+ return mMockDeviceManager;
+ }
+ };
+ // Reset default settings
+ mOptionSetter = new OptionSetter(mPreparer);
+ mTmpDir = FileUtil.createTempDir("tmp");
+ mBuildInfo = new DeviceBuildInfo("0", "");
+ mBuildInfo.setBuildFlavor("flavor");
+ IInvocationContext context = new InvocationContext();
+ context.addAllocatedDevice("device", mMockDevice);
+ context.addDeviceBuildInfo("device", mBuildInfo);
+ mTestInfo = TestInformation.newBuilder().setInvocationContext(context).build();
+ mSuccessResult = new CommandResult(CommandStatus.SUCCESS);
+ mSuccessResult.setStderr("OKAY [ 0.043s]");
+ mSuccessResult.setStdout("");
+ mFailureResult = new CommandResult(CommandStatus.FAILED);
+ mFailureResult.setStderr("FAILED (remote: 'Partition error')");
+ mFailureResult.setStdout("");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ FileUtil.recursiveDelete(mTmpDir);
+ }
+
+ /** Set EasyMock expectations for a normal setup call */
+ private void doSetupExpectations() throws Exception {
+ mMockRunUtil.sleep(EasyMock.anyLong());
+ mMockDevice.rebootUntilOnline();
+ EasyMock.expect(mMockDevice.enableAdbRoot()).andStubReturn(Boolean.TRUE);
+ mMockDevice.setDate(null);
+ mMockDevice.waitForDeviceAvailable(EasyMock.anyLong());
+ mMockDevice.setRecoveryMode(RecoveryMode.AVAILABLE);
+ mMockDevice.postBootSetup();
+ }
+
+ /* Verifies that preparer will throw exception when there is no valid GKI boot.img*/
+ @Test
+ public void testNoValidGkiImage() throws Exception {
+ try {
+ mPreparer.setUp(mTestInfo);
+ fail("TargetSetupError is expected");
+ } catch (TargetSetupError e) {
+ // expected
+ mPreparer.tearDown(mTestInfo, e);
+ }
+ }
+
+ /* Verifies that preparer can flash GKI boot image */
+ @Test
+ public void testSetup_Success() throws Exception {
+ File bootImg = FileUtil.createTempFile("boot", ".img", mTmpDir);
+ bootImg.renameTo(new File(mTmpDir, "boot.img"));
+ FileUtil.writeToFile("ddd", bootImg);
+ mBuildInfo.setFile("gki_boot.img", bootImg, "0");
+ mMockDevice.waitForDeviceOnline();
+ mMockDevice.rebootIntoBootloader();
+ mMockRunUtil.allowInterrupt(false);
+ EasyMock.expect(
+ mMockDevice.executeLongFastbootCommand(
+ "flash",
+ "boot",
+ mBuildInfo.getFile("gki_boot.img").getAbsolutePath()))
+ .andReturn(mSuccessResult);
+ mMockRunUtil.allowInterrupt(true);
+ doSetupExpectations();
+ EasyMock.replay(mMockDevice, mMockRunUtil);
+ mPreparer.setUp(mTestInfo);
+ mPreparer.tearDown(mTestInfo, null);
+ EasyMock.verify(mMockDevice, mMockRunUtil);
+ }
+
+ /* Verifies that preparer will throw TargetSetupError with GKI flash failure*/
+ @Test
+ public void testSetUp_GkiFlashFailure() throws Exception {
+ File bootImg = FileUtil.createTempFile("boot", ".img", mTmpDir);
+ bootImg.renameTo(new File(mTmpDir, "boot.img"));
+ FileUtil.writeToFile("ddd", bootImg);
+ mBuildInfo.setFile("gki_boot.img", bootImg, "0");
+ File deviceImg = FileUtil.createTempFile("device_image", ".zip", mTmpDir);
+ FileUtil.writeToFile("not an empty file", deviceImg);
+ mBuildInfo.setDeviceImageFile(deviceImg, "0");
+ mMockDevice.waitForDeviceOnline();
+ mMockDevice.rebootIntoBootloader();
+ mMockRunUtil.allowInterrupt(false);
+ EasyMock.expect(
+ mMockDevice.executeLongFastbootCommand(
+ "flash",
+ "boot",
+ mBuildInfo.getFile("gki_boot.img").getAbsolutePath()))
+ .andReturn(mFailureResult);
+ mMockRunUtil.allowInterrupt(true);
+ EasyMock.replay(mMockDevice, mMockRunUtil);
+ try {
+ mPreparer.setUp(mTestInfo);
+ fail("Expect to get TargetSetupError from setUp");
+ } catch (TargetSetupError e) {
+ // expected
+ }
+ EasyMock.verify(mMockDevice, mMockRunUtil);
+ }
+
+ /* Verifies that preparer will throw DeviceNotAvailableException if device fails to boot up */
+ @Test
+ public void testSetUp_BootFailure() throws Exception {
+ File bootImg = FileUtil.createTempFile("boot", ".img", mTmpDir);
+ bootImg.renameTo(new File(mTmpDir, "boot.img"));
+ FileUtil.writeToFile("ddd", bootImg);
+ mBuildInfo.setFile("gki_boot.img", bootImg, "0");
+ File deviceImg = FileUtil.createTempFile("device_image", ".zip", mTmpDir);
+ FileUtil.writeToFile("not an empty file", deviceImg);
+ mBuildInfo.setDeviceImageFile(deviceImg, "0");
+ mMockDevice.waitForDeviceOnline();
+ mMockDevice.rebootIntoBootloader();
+ mMockRunUtil.allowInterrupt(false);
+ EasyMock.expect(
+ mMockDevice.executeLongFastbootCommand(
+ "flash",
+ "boot",
+ mBuildInfo.getFile("gki_boot.img").getAbsolutePath()))
+ .andReturn(mSuccessResult);
+ mMockRunUtil.allowInterrupt(true);
+ mMockRunUtil.sleep(EasyMock.anyLong());
+ mMockDevice.rebootUntilOnline();
+ EasyMock.expectLastCall().andThrow(new DeviceNotAvailableException());
+ EasyMock.replay(mMockDevice, mMockRunUtil);
+ try {
+ mPreparer.setUp(mTestInfo);
+ fail("Expect to get DeviceNotAvailableException from setUp");
+ } catch (DeviceNotAvailableException e) {
+ // expected
+ }
+ EasyMock.verify(mMockDevice, mMockRunUtil);
+ }
+}