1 /* 2 * Copyright (C) 2023 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.targetprep; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.ArgumentMatchers.anyList; 24 import static org.mockito.ArgumentMatchers.anyString; 25 import static org.mockito.ArgumentMatchers.eq; 26 import static org.mockito.Mockito.doThrow; 27 import static org.mockito.Mockito.never; 28 import static org.mockito.Mockito.verify; 29 import static org.mockito.Mockito.when; 30 31 import com.android.tradefed.config.OptionSetter; 32 import com.android.tradefed.device.ITestDevice; 33 import com.android.tradefed.invoker.IInvocationContext; 34 import com.android.tradefed.invoker.InvocationContext; 35 import com.android.tradefed.invoker.TestInformation; 36 import com.android.tradefed.log.ITestLogger; 37 import com.android.tradefed.result.error.DeviceErrorIdentifier; 38 import com.android.tradefed.result.error.InfraErrorIdentifier; 39 import com.android.tradefed.util.CommandResult; 40 import com.android.tradefed.util.CommandStatus; 41 import com.android.tradefed.util.DeviceActionUtil; 42 43 import com.google.common.collect.ImmutableList; 44 45 import org.junit.Before; 46 import org.junit.Rule; 47 import org.junit.Test; 48 import org.junit.rules.TemporaryFolder; 49 import org.junit.runner.RunWith; 50 import org.junit.runners.JUnit4; 51 import org.mockito.ArgumentCaptor; 52 import org.mockito.Mock; 53 import org.mockito.junit.MockitoJUnit; 54 import org.mockito.junit.MockitoRule; 55 56 import java.io.File; 57 import java.io.IOException; 58 import java.util.List; 59 60 @RunWith(JUnit4.class) 61 public final class DeviceActionTargetPreparerTest { 62 63 private static final String SERIAL = "serial"; 64 65 @Rule public final MockitoRule mockito = MockitoJUnit.rule(); 66 @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); 67 68 @Mock DeviceActionUtil mockDeviceActionUtil; 69 @Mock ITestLogger mockTestLogger; 70 @Mock ITestDevice mockDevice; 71 @Mock CommandResult mCommandResult; 72 73 private OptionSetter mSetter; 74 private TestInformation mTestInfo; 75 private DeviceActionTargetPreparer mDeviceActionTargetPreparer; 76 77 @Before setUp()78 public void setUp() throws Exception { 79 File deviceActionJar = tempFolder.newFile("DeviceActionMainline_deploy.jar"); 80 File bundletoolJar = tempFolder.newFile("bundletool.jar"); 81 IInvocationContext context = new InvocationContext(); 82 context.addAllocatedDevice(SERIAL, mockDevice); 83 mTestInfo = TestInformation.newBuilder().setInvocationContext(context).build(); 84 when(mockDevice.getSerialNumber()).thenReturn(SERIAL); 85 when(mockDeviceActionUtil.execute(any(), anyString(), anyList())) 86 .thenReturn(mCommandResult); 87 when(mCommandResult.getStderr()).thenReturn(""); 88 when(mCommandResult.getStdout()).thenReturn(""); 89 when(mCommandResult.getStatus()).thenReturn(CommandStatus.SUCCESS); 90 when(mCommandResult.getExitCode()).thenReturn(0); 91 mDeviceActionTargetPreparer = new DeviceActionTargetPreparer(); 92 mSetter = new OptionSetter(mDeviceActionTargetPreparer); 93 mSetter.setOptionValue("bundletool-jar", bundletoolJar.getAbsolutePath()); 94 mSetter.setOptionValue("device-action-jar", deviceActionJar.getAbsolutePath()); 95 mDeviceActionTargetPreparer.setDeviceActionUtil(mockDeviceActionUtil); 96 mDeviceActionTargetPreparer.setTestLogger(mockTestLogger); 97 } 98 99 @Test setUp_resetSuccess()100 public void setUp_resetSuccess() throws Exception { 101 mSetter.setOptionValue("da-command", "RESET"); 102 103 mDeviceActionTargetPreparer.setUp(mTestInfo); 104 105 verify(mockDeviceActionUtil) 106 .execute(DeviceActionUtil.Command.RESET, SERIAL, ImmutableList.of()); 107 } 108 109 @Test setUp_installMainlineModules()110 public void setUp_installMainlineModules() throws Exception { 111 File apk1 = new File("apk1"); 112 File apk2 = new File("apk2"); 113 mSetter.setOptionValue("da-command", "INSTALL_MAINLINE"); 114 mSetter.setOptionValue("enable-rollback", "false"); 115 mSetter.setOptionValue("mainline-modules", apk1.getAbsolutePath()); 116 mSetter.setOptionValue("mainline-modules", apk2.getAbsolutePath()); 117 118 mDeviceActionTargetPreparer.setUp(mTestInfo); 119 120 ArgumentCaptor<List> argCaptor = ArgumentCaptor.forClass(List.class); 121 verify(mockDeviceActionUtil) 122 .execute( 123 eq(DeviceActionUtil.Command.INSTALL_MAINLINE), 124 eq(SERIAL), 125 argCaptor.capture()); 126 List<String> args = argCaptor.getValue(); 127 assertThat(args).hasSize(1); 128 assertThat(args) 129 .containsAnyOf( 130 String.format( 131 "file_mainline_modules=%s, file_mainline_modules=%s", 132 apk1.getAbsolutePath(), apk2.getAbsolutePath()), 133 String.format( 134 "file_mainline_modules=%s, file_mainline_modules=%s", 135 apk2.getAbsolutePath(), apk1.getAbsolutePath())); 136 } 137 138 @Test setUp_installApksZips()139 public void setUp_installApksZips() throws Exception { 140 File zip1 = new File("zip1"); 141 File zip2 = new File("zip2"); 142 mSetter.setOptionValue("da-command", "INSTALL_MAINLINE"); 143 mSetter.setOptionValue("enable-rollback", "true"); 144 mSetter.setOptionValue("apks-zips", zip1.getAbsolutePath()); 145 mSetter.setOptionValue("apks-zips", zip2.getAbsolutePath()); 146 147 mDeviceActionTargetPreparer.setUp(mTestInfo); 148 149 ArgumentCaptor<List> argCaptor = ArgumentCaptor.forClass(List.class); 150 verify(mockDeviceActionUtil) 151 .execute( 152 eq(DeviceActionUtil.Command.INSTALL_MAINLINE), 153 eq(SERIAL), 154 argCaptor.capture()); 155 List<String> args = argCaptor.getValue(); 156 assertThat(args).hasSize(2); 157 assertThat(args).contains("enable_rollback"); 158 assertThat(args) 159 .containsAnyOf( 160 String.format( 161 "file_apks_zips=%s, file_apks_zips=%s", 162 zip1.getAbsolutePath(), zip2.getAbsolutePath()), 163 String.format( 164 "file_apks_zips=%s, file_apks_zips=%s", 165 zip2.getAbsolutePath(), zip1.getAbsolutePath())); 166 } 167 168 @Test setUp_installTrainFolder()169 public void setUp_installTrainFolder() throws Exception { 170 File trainFolder = tempFolder.newFolder("train"); 171 mSetter.setOptionValue("da-command", "INSTALL_MAINLINE"); 172 mSetter.setOptionValue("dev-key-signed", "true"); 173 mSetter.setOptionValue("train-folder", trainFolder.getAbsolutePath()); 174 175 mDeviceActionTargetPreparer.setUp(mTestInfo); 176 177 verify(mockDeviceActionUtil) 178 .execute( 179 DeviceActionUtil.Command.INSTALL_MAINLINE, 180 SERIAL, 181 ImmutableList.of( 182 String.format( 183 "file_train_folder=%s", trainFolder.getAbsolutePath()), 184 "enable_rollback", 185 "dev_key_signed")); 186 } 187 188 @Test setUp_doNothingIfNoModuleToInstall()189 public void setUp_doNothingIfNoModuleToInstall() throws Exception { 190 mSetter.setOptionValue("da-command", "INSTALL_MAINLINE"); 191 192 mDeviceActionTargetPreparer.setUp(mTestInfo); 193 194 verify(mockDeviceActionUtil, never()) 195 .execute(any(DeviceActionUtil.Command.class), anyString(), anyList()); 196 } 197 198 @Test setUp_executeFailureThrowExecutionException()199 public void setUp_executeFailureThrowExecutionException() throws Exception { 200 mSetter.setOptionValue("da-command", "RESET"); 201 when(mCommandResult.getExitCode()).thenReturn(1); 202 203 TargetSetupError t = 204 assertThrows( 205 TargetSetupError.class, () -> mDeviceActionTargetPreparer.setUp(mTestInfo)); 206 207 assertThat(t.getErrorId()).isEqualTo(DeviceErrorIdentifier.DEVICE_ACTION_EXECUTION_FAILURE); 208 verify(mockDeviceActionUtil).saveToLogs(DeviceActionUtil.Command.RESET, mockTestLogger); 209 } 210 211 @Test setUp_saveLogErrorThrowInfraException()212 public void setUp_saveLogErrorThrowInfraException() throws Exception { 213 mSetter.setOptionValue("da-command", "RESET"); 214 doThrow(new IOException()).when(mockDeviceActionUtil).generateLogFile(mCommandResult); 215 216 TargetSetupError t = 217 assertThrows( 218 TargetSetupError.class, () -> mDeviceActionTargetPreparer.setUp(mTestInfo)); 219 220 assertThat(t.getErrorId()).isEqualTo(InfraErrorIdentifier.FAIL_TO_CREATE_FILE); 221 } 222 223 @Test setUp_saveLogErrorAndExectionFailureThrowExecutionException()224 public void setUp_saveLogErrorAndExectionFailureThrowExecutionException() throws Exception { 225 mSetter.setOptionValue("da-command", "RESET"); 226 when(mCommandResult.getExitCode()).thenReturn(1); 227 doThrow(new IOException()).when(mockDeviceActionUtil).generateLogFile(mCommandResult); 228 229 TargetSetupError t = 230 assertThrows( 231 TargetSetupError.class, () -> mDeviceActionTargetPreparer.setUp(mTestInfo)); 232 233 assertThat(t.getErrorId()).isEqualTo(DeviceErrorIdentifier.DEVICE_ACTION_EXECUTION_FAILURE); 234 } 235 } 236