| /* |
| * 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.IBuildInfo; |
| import com.android.tradefed.build.IDeviceBuildInfo; |
| import com.android.tradefed.config.Option; |
| import com.android.tradefed.config.Option.Importance; |
| import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; |
| import com.android.tradefed.util.FileUtil; |
| import com.android.tradefed.util.SparseImageUtil; |
| import com.android.tradefed.util.StreamUtil; |
| import com.android.tradefed.util.ZipUtil2; |
| |
| import org.apache.commons.compress.archivers.zip.ZipFile; |
| import org.junit.Before; |
| import org.junit.After; |
| import org.junit.Assert; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.io.File; |
| import java.io.IOException; |
| 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 DsuTestBase { |
| private static final long kDefaultUserdataSize = 4L * 1024 * 1024 * 1024; |
| private static final String LPUNPACK_PATH = "bin/lpunpack"; |
| |
| // 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; |
| |
| private File mTempDir; |
| |
| private File getTempPath(String relativePath) throws IOException { |
| if (mTempDir == null) { |
| mTempDir = FileUtil.createTempDir("DSUEndtoEndTest"); |
| } |
| return new File(mTempDir, relativePath); |
| } |
| |
| /** Extract system.img from build info to a temproary file. */ |
| private File extractSystemImageFromBuildInfo(IBuildInfo buildInfo) |
| throws IOException, InterruptedException { |
| File imgZip = ((IDeviceBuildInfo) buildInfo).getDeviceImageFile(); |
| Assert.assertNotNull( |
| "Failed to fetch system image. See system_image_path parameter", imgZip); |
| |
| File superImg = getTempPath("super.img"); |
| try (ZipFile zip = new ZipFile(imgZip)) { |
| File systemImg = getTempPath("system.img"); |
| if (ZipUtil2.extractFileFromZip(zip, "system.img", systemImg)) { |
| return systemImg; |
| } |
| Assert.assertTrue( |
| "No system.img or super.img in img zip.", |
| ZipUtil2.extractFileFromZip(zip, "super.img", superImg)); |
| } |
| |
| if (SparseImageUtil.isSparse(superImg)) { |
| File unsparseSuperImage = getTempPath("super.raw"); |
| SparseImageUtil.unsparse(superImg, unsparseSuperImage); |
| superImg = unsparseSuperImage; |
| } |
| |
| File otaTools = buildInfo.getFile("otatools.zip"); |
| Assert.assertNotNull("No otatools.zip in BuildInfo.", otaTools); |
| File otaToolsDir = getTempPath("otatools"); |
| ZipUtil2.extractZip(otaTools, otaToolsDir); |
| |
| String lpunpackPath = new File(otaToolsDir, LPUNPACK_PATH).getAbsolutePath(); |
| File outputDir = getTempPath("lpunpack_output"); |
| outputDir.mkdirs(); |
| String[] cmd = { |
| lpunpackPath, "-p", "system_a", superImg.getAbsolutePath(), outputDir.getAbsolutePath() |
| }; |
| Process p = Runtime.getRuntime().exec(cmd); |
| p.waitFor(); |
| if (p.exitValue() != 0) { |
| String stderr = StreamUtil.getStringFromStream(p.getErrorStream()); |
| Assert.fail(String.format("lpunpack returned %d. (%s)", p.exitValue(), stderr)); |
| } |
| return new File(outputDir, "system_a.img"); |
| } |
| |
| @Before |
| public void setUp() { |
| mTempDir = null; |
| } |
| |
| @After |
| public void tearDown() { |
| FileUtil.recursiveDelete(mTempDir); |
| } |
| |
| @Test |
| public void testDSU() throws Exception { |
| File systemImage; |
| if (mSystemImagePath != null) { |
| systemImage = new File(mSystemImagePath); |
| } else { |
| systemImage = extractSystemImageFromBuildInfo(getBuild()); |
| } |
| Assert.assertTrue("not a valid file", systemImage.isFile()); |
| |
| if (SparseImageUtil.isSparse(systemImage)) { |
| File unsparseSystemImage = getTempPath("system.raw"); |
| SparseImageUtil.unsparse(systemImage, unsparseSystemImage); |
| systemImage = unsparseSystemImage; |
| } |
| |
| boolean wasRoot = getDevice().isAdbRoot(); |
| if (!wasRoot) |
| Assert.assertTrue("Test requires root", getDevice().enableAdbRoot()); |
| |
| assertDsuStatus("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( |
| String.format( |
| "gsi_tool install --userdata-size %d" |
| + " --gsi-size %d" |
| + " && sleep 10000000", |
| getDsuUserdataSize(kDefaultUserdataSize), systemImage.length()), |
| systemImage, |
| null, |
| 10, |
| TimeUnit.MINUTES, |
| 1); |
| getDevice().waitForDeviceAvailable(); |
| getDevice().enableAdbRoot(); |
| |
| assertDsuStatus("running"); |
| |
| getDevice().rebootUntilOnline(); |
| |
| assertDsuStatus("installed"); |
| |
| assertShellCommand("gsi_tool enable"); |
| |
| getDevice().reboot(); |
| |
| assertDsuStatus("running"); |
| |
| getDevice().reboot(); |
| |
| assertDsuStatus("running"); |
| |
| assertShellCommand("gsi_tool wipe"); |
| |
| getDevice().rebootUntilOnline(); |
| |
| assertDsuStatus("normal"); |
| |
| if (wasRoot) { |
| getDevice().enableAdbRoot(); |
| } |
| } |
| } |
| |