• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.dsu;
18 
19 import com.android.tradefed.build.IBuildInfo;
20 import com.android.tradefed.build.IDeviceBuildInfo;
21 import com.android.tradefed.config.Option;
22 import com.android.tradefed.config.Option.Importance;
23 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
24 import com.android.tradefed.util.FileUtil;
25 import com.android.tradefed.util.SparseImageUtil;
26 import com.android.tradefed.util.StreamUtil;
27 import com.android.tradefed.util.ZipUtil2;
28 
29 import org.apache.commons.compress.archivers.zip.ZipFile;
30 import org.junit.Before;
31 import org.junit.After;
32 import org.junit.Assert;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 
36 import java.io.File;
37 import java.io.IOException;
38 import java.util.concurrent.TimeUnit;
39 
40 /**
41  * Test Dynamic System Updates by booting in and out of a supplied system image
42  */
43 @RunWith(DeviceJUnit4ClassRunner.class)
44 public class DSUEndtoEndTest extends DsuTestBase {
45     private static final long kDefaultUserdataSize = 4L * 1024 * 1024 * 1024;
46     private static final String LPUNPACK_PATH = "bin/lpunpack";
47 
48     // Example: atest -v DSUEndtoEndTest -- --test-arg \
49     // com.android.tradefed.testtype.HostTest:set-option:system_image_path:/full/path/to/system.img
50     @Option(name="system_image_path",
51             shortName='s',
52             description="full path to the system image to use. If not specified, attempt " +
53                         "to download the image from the test infrastructure",
54             importance=Importance.ALWAYS)
55     private String mSystemImagePath;
56 
57     private File mTempDir;
58 
getTempPath(String relativePath)59     private File getTempPath(String relativePath) throws IOException {
60         if (mTempDir == null) {
61             mTempDir = FileUtil.createTempDir("DSUEndtoEndTest");
62         }
63         return new File(mTempDir, relativePath);
64     }
65 
66     /** Extract system.img from build info to a temproary file. */
extractSystemImageFromBuildInfo(IBuildInfo buildInfo)67     private File extractSystemImageFromBuildInfo(IBuildInfo buildInfo)
68             throws IOException, InterruptedException {
69         File imgZip = ((IDeviceBuildInfo) buildInfo).getDeviceImageFile();
70         Assert.assertNotNull(
71                 "Failed to fetch system image. See system_image_path parameter", imgZip);
72 
73         File superImg = getTempPath("super.img");
74         if (imgZip.isDirectory()) {
75             File systemImg = new File(imgZip, "system.img");
76             if (systemImg.exists()) {
77                 return systemImg;
78             }
79             superImg = new File(imgZip, "super.img");
80             Assert.assertTrue(
81                     "No system.img or super.img in img zip.",
82                     superImg.exists());
83         } else {
84             try (ZipFile zip = new ZipFile(imgZip)) {
85                 File systemImg = getTempPath("system.img");
86                 if (ZipUtil2.extractFileFromZip(zip, "system.img", systemImg)) {
87                     return systemImg;
88                 }
89                 Assert.assertTrue(
90                         "No system.img or super.img in img zip.",
91                         ZipUtil2.extractFileFromZip(zip, "super.img", superImg));
92             }
93         }
94 
95         if (SparseImageUtil.isSparse(superImg)) {
96             File unsparseSuperImage = getTempPath("super.raw");
97             SparseImageUtil.unsparse(superImg, unsparseSuperImage);
98             superImg = unsparseSuperImage;
99         }
100 
101         File otaTools = buildInfo.getFile("otatools.zip");
102         Assert.assertNotNull("No otatools.zip in BuildInfo.", otaTools);
103         File otaToolsDir = getTempPath("otatools");
104         ZipUtil2.extractZip(otaTools, otaToolsDir);
105 
106         String lpunpackPath = new File(otaToolsDir, LPUNPACK_PATH).getAbsolutePath();
107         File outputDir = getTempPath("lpunpack_output");
108         outputDir.mkdirs();
109         String[] cmd = {
110             lpunpackPath, "-p", "system_a", superImg.getAbsolutePath(), outputDir.getAbsolutePath()
111         };
112         Process p = Runtime.getRuntime().exec(cmd);
113         p.waitFor();
114         if (p.exitValue() != 0) {
115             String stderr = StreamUtil.getStringFromStream(p.getErrorStream());
116             Assert.fail(String.format("lpunpack returned %d. (%s)", p.exitValue(), stderr));
117         }
118         return new File(outputDir, "system_a.img");
119     }
120 
121     @Before
setUp()122     public void setUp() {
123         mTempDir = null;
124     }
125 
126     @After
tearDown()127     public void tearDown() {
128         FileUtil.recursiveDelete(mTempDir);
129     }
130 
131     @Test
testDSU()132     public void testDSU() throws Exception {
133         File systemImage;
134         if (mSystemImagePath != null) {
135             systemImage = new File(mSystemImagePath);
136         } else {
137             systemImage = extractSystemImageFromBuildInfo(getBuild());
138         }
139         Assert.assertTrue("not a valid file", systemImage.isFile());
140 
141         if (SparseImageUtil.isSparse(systemImage)) {
142             File unsparseSystemImage = getTempPath("system.raw");
143             SparseImageUtil.unsparse(systemImage, unsparseSystemImage);
144             systemImage = unsparseSystemImage;
145         }
146 
147         boolean wasRoot = getDevice().isAdbRoot();
148         if (!wasRoot)
149             Assert.assertTrue("Test requires root", getDevice().enableAdbRoot());
150 
151         assertDsuStatus("normal");
152 
153         // Sleep after installing to allow time for gsi_tool to reboot. This prevents a race between
154         // the device rebooting and waitForDeviceAvailable() returning.
155         getDevice()
156                 .executeShellV2Command(
157                         String.format(
158                                 "gsi_tool install --userdata-size %d"
159                                         + " --gsi-size %d"
160                                         + " && sleep 10000000",
161                                 getDsuUserdataSize(kDefaultUserdataSize), systemImage.length()),
162                         systemImage,
163                         null,
164                         10,
165                         TimeUnit.MINUTES,
166                         1);
167         getDevice().waitForDeviceAvailable();
168         getDevice().enableAdbRoot();
169 
170         assertDsuStatus("running");
171 
172         getDevice().rebootUntilOnline();
173 
174         assertDsuStatus("installed");
175 
176         assertShellCommand("gsi_tool enable");
177 
178         getDevice().reboot();
179 
180         assertDsuStatus("running");
181 
182         getDevice().reboot();
183 
184         assertDsuStatus("running");
185 
186         assertShellCommand("gsi_tool wipe");
187 
188         getDevice().rebootUntilOnline();
189 
190         assertDsuStatus("normal");
191 
192         if (wasRoot) {
193             getDevice().enableAdbRoot();
194         }
195     }
196 }
197 
198