You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
6.6 KiB
168 lines
6.6 KiB
/*
|
|
* Copyright (C) 2019 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.tests.dsu;
|
|
|
|
import com.android.tradefed.build.BuildRetrievalError;
|
|
import com.android.tradefed.build.IBuildInfo;
|
|
import com.android.tradefed.build.IDeviceBuildInfo;
|
|
import com.android.tradefed.config.Option;
|
|
import com.android.tradefed.config.Option.Importance;
|
|
import com.android.tradefed.device.DeviceNotAvailableException;
|
|
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
|
|
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
|
|
import com.android.tradefed.util.CommandResult;
|
|
import com.android.tradefed.util.ZipUtil2;
|
|
|
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
|
|
|
import org.junit.After;
|
|
import org.junit.Assert;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.lang.Process;
|
|
import java.lang.Runtime;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
/**
|
|
* Test Dynamic System Updates by booting in and out of a supplied system image
|
|
*/
|
|
@RunWith(DeviceJUnit4ClassRunner.class)
|
|
public class DSUEndtoEndTest extends BaseHostJUnit4Test {
|
|
private static final long kDefaultUserdataSize = 4L * 1024 * 1024 * 1024;
|
|
private static final String LPUNPACK_PATH = "bin/lpunpack";
|
|
private static final String SIMG2IMG_PATH = "bin/simg2img";
|
|
|
|
// Example: atest -v DSUEndtoEndTest -- --test-arg \
|
|
// com.android.tradefed.testtype.HostTest:set-option:system_image_path:/full/path/to/system.img
|
|
@Option(name="system_image_path",
|
|
shortName='s',
|
|
description="full path to the system image to use. If not specified, attempt " +
|
|
"to download the image from the test infrastructure",
|
|
importance=Importance.ALWAYS)
|
|
private String mSystemImagePath;
|
|
|
|
@Option(name="userdata_size",
|
|
shortName='u',
|
|
description="size in bytes of the new userdata partition",
|
|
importance=Importance.ALWAYS)
|
|
private long mUserdataSize = kDefaultUserdataSize;
|
|
|
|
private File mUnsparseSystemImage;
|
|
|
|
@After
|
|
public void teardown() throws Exception {
|
|
if (mUnsparseSystemImage != null) {
|
|
mUnsparseSystemImage.delete();
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testDSU() throws Exception {
|
|
String simg2imgPath = "simg2img";
|
|
if (mSystemImagePath == null) {
|
|
IBuildInfo buildInfo = getBuild();
|
|
File imgs = ((IDeviceBuildInfo) buildInfo).getDeviceImageFile();
|
|
Assert.assertNotEquals("Failed to fetch system image. See system_image_path parameter", null, imgs);
|
|
File otaTools = buildInfo.getFile("otatools.zip");
|
|
File tempdir = ZipUtil2.extractZipToTemp(otaTools, "otatools");
|
|
File system = ZipUtil2.extractFileFromZip(new ZipFile(imgs), "system.img");
|
|
if (system == null) {
|
|
File superImg = ZipUtil2.extractFileFromZip(new ZipFile(imgs), "super.img");
|
|
String lpunpackPath = new File(tempdir, LPUNPACK_PATH).getAbsolutePath();
|
|
String outputDir = superImg.getParentFile().getAbsolutePath();
|
|
String[] cmd = {lpunpackPath, "-p", "system_a", superImg.getAbsolutePath(), outputDir};
|
|
Process p = Runtime.getRuntime().exec(cmd);
|
|
p.waitFor();
|
|
if (p.exitValue() == 0) {
|
|
mSystemImagePath = new File(outputDir, "system_a.img").getAbsolutePath();
|
|
} else {
|
|
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
|
|
int len;
|
|
byte[] buf = new byte[1024];
|
|
while ((len = p.getErrorStream().read(buf)) != -1) {
|
|
stderr.write(buf, 0, len);
|
|
}
|
|
Assert.assertEquals("non-zero exit value (" + stderr.toString("UTF-8") + ")", 0, p.exitValue());
|
|
}
|
|
} else {
|
|
mSystemImagePath = system.getAbsolutePath();
|
|
}
|
|
simg2imgPath = new File(tempdir, SIMG2IMG_PATH).getAbsolutePath();
|
|
}
|
|
File gsi = new File(mSystemImagePath);
|
|
Assert.assertTrue("not a valid file", gsi.isFile());
|
|
String[] cmd = {simg2imgPath, mSystemImagePath, mSystemImagePath + ".raw"};
|
|
Process p = Runtime.getRuntime().exec(cmd);
|
|
p.waitFor();
|
|
if (p.exitValue() == 0) {
|
|
mUnsparseSystemImage = new File(mSystemImagePath + ".raw");
|
|
gsi = mUnsparseSystemImage;
|
|
}
|
|
|
|
boolean wasRoot = getDevice().isAdbRoot();
|
|
if (!wasRoot)
|
|
Assert.assertTrue("Test requires root", getDevice().enableAdbRoot());
|
|
|
|
expectGsiStatus("normal");
|
|
|
|
// Sleep after installing to allow time for gsi_tool to reboot. This prevents a race between
|
|
// the device rebooting and waitForDeviceAvailable() returning.
|
|
getDevice().executeShellV2Command("gsi_tool install --userdata-size " + mUserdataSize +
|
|
" --gsi-size " + gsi.length() + " && sleep 10000000", gsi, null, 10, TimeUnit.MINUTES, 1);
|
|
getDevice().waitForDeviceAvailable();
|
|
getDevice().enableAdbRoot();
|
|
|
|
expectGsiStatus("running");
|
|
|
|
getDevice().rebootUntilOnline();
|
|
|
|
expectGsiStatus("installed");
|
|
|
|
CommandResult result = getDevice().executeShellV2Command("gsi_tool enable");
|
|
Assert.assertEquals("gsi_tool enable failed", 0, result.getExitCode().longValue());
|
|
|
|
getDevice().reboot();
|
|
|
|
expectGsiStatus("running");
|
|
|
|
getDevice().reboot();
|
|
|
|
expectGsiStatus("running");
|
|
|
|
getDevice().executeShellV2Command("gsi_tool wipe");
|
|
|
|
getDevice().rebootUntilOnline();
|
|
|
|
expectGsiStatus("normal");
|
|
|
|
if (wasRoot) {
|
|
getDevice().enableAdbRoot();
|
|
}
|
|
}
|
|
|
|
private void expectGsiStatus(String expected) throws Exception {
|
|
CommandResult result = getDevice().executeShellV2Command("gsi_tool status");
|
|
String status = result.getStdout().split("\n", 2)[0].trim();
|
|
Assert.assertEquals("Device not in expected DSU state", expected, status);
|
|
}
|
|
}
|
|
|