1 /* 2 * Copyright (C) 2022 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.tradefed.device; 18 19 import static org.hamcrest.CoreMatchers.is; 20 import static org.hamcrest.MatcherAssert.assertThat; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 import static org.junit.Assume.assumeTrue; 26 27 import com.android.tradefed.invoker.TestInformation; 28 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 29 import com.android.tradefed.testtype.IDeviceTest; 30 import com.android.tradefed.testtype.ITestInformationReceiver; 31 import com.android.tradefed.util.CommandResult; 32 import com.android.tradefed.util.CommandStatus; 33 34 import org.junit.Before; 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 38 import java.io.File; 39 import java.io.FileNotFoundException; 40 import java.util.Arrays; 41 42 /** 43 * Functional tests for creating Microdroid {@link TestDevice}. 44 * 45 * <p>Requires a physical device to be connected. 46 */ 47 @RunWith(DeviceJUnit4ClassRunner.class) 48 public class MicrodroidFuncTest implements IDeviceTest, ITestInformationReceiver { 49 private static final String APK_NAME = "MicrodroidTestApp.apk"; 50 private static final String CONFIG_PATH = "assets/vm_config.json"; // path inside the APK 51 52 private TestDevice mTestDevice; 53 private TestInformation mTestInformation; 54 55 @Override setDevice(ITestDevice device)56 public void setDevice(ITestDevice device) { 57 mTestDevice = (TestDevice) device; 58 } 59 60 @Override getDevice()61 public ITestDevice getDevice() { 62 return mTestDevice; 63 } 64 65 @Override setTestInformation(TestInformation testInformation)66 public void setTestInformation(TestInformation testInformation) { 67 mTestInformation = testInformation; 68 } 69 70 @Override getTestInformation()71 public TestInformation getTestInformation() { 72 return mTestInformation; 73 } 74 75 @Before setup()76 public void setup() throws Exception { 77 mTestDevice.waitForDeviceAvailable(); 78 assumeTrue(mTestDevice.supportsMicrodroid()); 79 mTestDevice.executeShellV2Command("logcat -c"); 80 } 81 82 // tests if a microdroid TestDevice is created and stopped properly 83 @Test testStartAndShutdownMicrodroid()84 public void testStartAndShutdownMicrodroid() 85 throws DeviceNotAvailableException, FileNotFoundException { 86 final ITestDevice microdroid = 87 TestDevice.MicrodroidBuilder.fromFile( 88 findTestFile(mTestInformation, APK_NAME), CONFIG_PATH) 89 .debugLevel("full") 90 .memoryMib(0) 91 .numCpus(1) 92 .build(mTestDevice); 93 assertNotNull(microdroid); 94 95 MicrodroidHelper microdroidHelper = new MicrodroidHelper(); 96 97 // Test writing to /data partition 98 runOnDevice(microdroid, "echo MicrodroidTest > /data/local/tmp/test.txt"); 99 assertThat(runOnDevice(microdroid, "cat /data/local/tmp/test.txt"), is("MicrodroidTest")); 100 101 // Check if the APK & its idsig partitions exist 102 final String apkPartition = "/dev/block/by-name/microdroid-apk"; 103 assertTrue(microdroid.doesFileExist(apkPartition)); 104 final String apkIdsigPartition = "/dev/block/by-name/microdroid-apk-idsig"; 105 assertTrue(microdroid.doesFileExist(apkIdsigPartition)); 106 // Check the vm-instance partition as well 107 final String vmInstancePartition = "/dev/block/by-name/vm-instance"; 108 assertTrue(microdroid.doesFileExist(vmInstancePartition)); 109 110 // Check if the native library in the APK is has correct filesystem info 111 final String[] abis = 112 runOnDevice(microdroid, "getprop", "ro.product.cpu.abilist").split(","); 113 assertThat(abis.length, is(1)); 114 final String testLib = "/mnt/apk/lib/" + abis[0] + "/MicrodroidTestNativeLib.so"; 115 final String label = "u:object_r:system_file:s0"; 116 assertThat(runOnDevice(microdroid, "ls", "-Z", testLib), is(label + " " + testLib)); 117 118 // Check if the command in vm_config.json was executed by examining the side effect of the 119 // command 120 assertThat(runOnDevice(microdroid, "getprop", "debug.microdroid.app.run"), is("true")); 121 assertThat( 122 runOnDevice(microdroid, "getprop", "debug.microdroid.app.sublib.run"), is("true")); 123 124 // Check that no denials have happened so far 125 assertThat(runOnDevice(microdroid, "logcat -d -e 'avc:[[:space:]]{1,2}denied'"), is("")); 126 assertThat( 127 runOnDevice(microdroid, "cat /proc/cpuinfo | grep processor | wc -l"), 128 is(Integer.toString(1))); 129 130 assertThat( 131 microdroidHelper.runOnMicrodroid(microdroid.getSerialNumber(), "echo true"), 132 is("true")); 133 mTestDevice.shutdownMicrodroid(microdroid); 134 assertNull(microdroidHelper.tryRunOnMicrodroid(microdroid.getSerialNumber(), "echo true")); 135 } 136 runOnDevice(ITestDevice device, String... cmd)137 private String runOnDevice(ITestDevice device, String... cmd) 138 throws DeviceNotAvailableException { 139 CommandResult result = device.executeShellV2Command(join(cmd)); 140 if (result.getStatus() != CommandStatus.SUCCESS) { 141 fail(join(cmd) + " has failed: " + result); 142 } 143 return result.getStdout().trim(); 144 } 145 join(String... strs)146 private static String join(String... strs) { 147 return String.join(" ", Arrays.asList(strs)); 148 } 149 findTestFile(TestInformation testInformation, String name)150 private static File findTestFile(TestInformation testInformation, String name) 151 throws FileNotFoundException { 152 return testInformation.getDependencyFile(name, false); 153 } 154 } 155