1 /* 2 * Copyright (C) 2016 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 package com.android.tradefed.targetprep; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.fail; 20 import static org.mockito.Mockito.doReturn; 21 import static org.mockito.Mockito.times; 22 23 import com.android.tradefed.build.BuildInfo; 24 import com.android.tradefed.build.IAppBuildInfo; 25 import com.android.tradefed.build.IBuildInfo; 26 import com.android.tradefed.build.VersionedFile; 27 import com.android.tradefed.config.OptionSetter; 28 import com.android.tradefed.device.DeviceNotAvailableException; 29 import com.android.tradefed.device.ITestDevice; 30 import com.android.tradefed.util.AaptParser; 31 import com.android.tradefed.util.FileUtil; 32 33 import java.io.File; 34 import java.util.ArrayList; 35 import java.util.HashSet; 36 import java.util.List; 37 import java.util.Set; 38 import java.util.concurrent.TimeUnit; 39 40 import org.easymock.EasyMock; 41 import org.junit.Before; 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 import org.junit.runners.JUnit4; 45 import org.mockito.Mockito; 46 47 /** 48 * Unit Tests for {@link AppSetup}. 49 */ 50 @RunWith(JUnit4.class) 51 public class AppSetupTest { 52 53 private static final String SERIAL = "serial"; 54 private AppSetup mAppSetup; 55 private ITestDevice mMockDevice; 56 private IAppBuildInfo mMockBuildInfo; 57 private AaptParser mMockAaptParser; 58 59 @Before 60 public void setUp() { 61 mAppSetup = new AppSetup(); 62 mMockDevice = EasyMock.createMock(ITestDevice.class); 63 EasyMock.expect(mMockDevice.getSerialNumber()).andStubReturn(SERIAL); 64 EasyMock.expect(mMockDevice.getDeviceDescriptor()).andStubReturn(null); 65 mMockBuildInfo = EasyMock.createMock(IAppBuildInfo.class); 66 mMockAaptParser = Mockito.mock(AaptParser.class); 67 } 68 69 private void replayMocks() { 70 EasyMock.replay(mMockDevice, mMockBuildInfo); 71 } 72 73 private void verifyMocks() { 74 EasyMock.verify(mMockDevice, mMockBuildInfo); 75 } 76 77 /** 78 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when the IBuildInfo is not an 79 * instance of {@link IAppBuildInfo}. 80 */ 81 @Test 82 public void testSetup_notIAppBuildInfo() throws Exception { 83 replayMocks(); 84 try { 85 mAppSetup.setUp(mMockDevice, new BuildInfo()); 86 fail("Should have thrown an exception."); 87 } catch (IllegalArgumentException expected) { 88 assertEquals("Provided buildInfo is not a AppBuildInfo", expected.getMessage()); 89 } 90 verifyMocks(); 91 } 92 93 /** 94 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when the apk installation fails 95 * with some error. 96 */ 97 @Test 98 public void testSetup_failToInstall() throws Exception { 99 List<VersionedFile> files = new ArrayList<>(); 100 File tmpFile = FileUtil.createTempFile("versioned", ".test"); 101 try { 102 files.add(new VersionedFile(tmpFile, "1")); 103 EasyMock.expect(mMockBuildInfo.getAppPackageFiles()).andReturn(files); 104 EasyMock.expect(mMockDevice.installPackage(EasyMock.eq(tmpFile), EasyMock.eq(true))) 105 .andReturn("Error"); 106 replayMocks(); 107 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 108 fail("Should have thrown an exception."); 109 } catch (BuildError expected) { 110 assertEquals(String.format("Failed to install %s on %s. Reason: Error null", 111 tmpFile.getName(), SERIAL), expected.getMessage()); 112 } finally { 113 FileUtil.deleteFile(tmpFile); 114 verifyMocks(); 115 } 116 } 117 118 /** 119 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when installation succeed but we 120 * cannot get any aapt info from the apk. 121 */ 122 @Test 123 public void testSetup_aaptCannotParse() throws Exception { 124 List<VersionedFile> files = new ArrayList<>(); 125 File tmpFile = FileUtil.createTempFile("versioned", ".test"); 126 try { 127 files.add(new VersionedFile(tmpFile, "1")); 128 EasyMock.expect(mMockBuildInfo.getAppPackageFiles()).andReturn(files); 129 EasyMock.expect(mMockDevice.installPackage(EasyMock.eq(tmpFile), EasyMock.eq(true))) 130 .andReturn(null); 131 replayMocks(); 132 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 133 fail("Should have thrown an exception."); 134 } catch (TargetSetupError expected) { 135 assertEquals(String.format("Failed to extract info from '%s' using aapt null", 136 tmpFile.getAbsolutePath()), expected.getMessage()); 137 } finally { 138 FileUtil.deleteFile(tmpFile); 139 verifyMocks(); 140 } 141 } 142 143 /** 144 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when the install succeed but we 145 * cannot find any package name on the apk. 146 */ 147 @Test 148 public void testSetup_noPackageName() throws Exception { 149 mAppSetup = new AppSetup() { 150 @Override 151 AaptParser doAaptParse(File apkFile) { 152 return mMockAaptParser; 153 } 154 }; 155 List<VersionedFile> files = new ArrayList<>(); 156 File tmpFile = FileUtil.createTempFile("versioned", ".test"); 157 try { 158 files.add(new VersionedFile(tmpFile, "1")); 159 EasyMock.expect(mMockBuildInfo.getAppPackageFiles()).andReturn(files); 160 EasyMock.expect(mMockDevice.installPackage(EasyMock.eq(tmpFile), EasyMock.eq(true))) 161 .andReturn(null); 162 doReturn(null).when(mMockAaptParser).getPackageName(); 163 replayMocks(); 164 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 165 fail("Should have thrown an exception."); 166 } catch (TargetSetupError expected) { 167 assertEquals(String.format("Failed to find package name for '%s' using aapt null", 168 tmpFile.getAbsolutePath()), expected.getMessage()); 169 } finally { 170 FileUtil.deleteFile(tmpFile); 171 verifyMocks(); 172 Mockito.verify(mMockAaptParser, times(1)).getPackageName(); 173 } 174 } 175 176 /** 177 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when checking min sdk is enabled 178 * and we fail to parse the file. 179 */ 180 @Test 181 public void testSetup_checkMinSdk_failParsing() throws Exception { 182 mAppSetup = new AppSetup() { 183 @Override 184 AaptParser doAaptParse(File apkFile) { 185 return null; 186 } 187 }; 188 OptionSetter setter = new OptionSetter(mAppSetup); 189 setter.setOptionValue("check-min-sdk", "true"); 190 List<VersionedFile> files = new ArrayList<>(); 191 File tmpFile = FileUtil.createTempFile("versioned", ".test"); 192 try { 193 files.add(new VersionedFile(tmpFile, "1")); 194 EasyMock.expect(mMockBuildInfo.getAppPackageFiles()).andReturn(files); 195 replayMocks(); 196 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 197 fail("Should have thrown an exception."); 198 } catch (TargetSetupError expected) { 199 assertEquals(String.format("Failed to extract info from '%s' using aapt null", 200 tmpFile.getName()), expected.getMessage()); 201 } finally { 202 FileUtil.deleteFile(tmpFile); 203 verifyMocks(); 204 } 205 } 206 207 /** 208 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when we check the min sdk level 209 * and the device API level is too low. Install should be skipped. 210 */ 211 @Test 212 public void testSetup_checkMinSdk_apiLow() throws Exception { 213 mAppSetup = new AppSetup() { 214 @Override 215 AaptParser doAaptParse(File apkFile) { 216 return mMockAaptParser; 217 } 218 }; 219 OptionSetter setter = new OptionSetter(mAppSetup); 220 setter.setOptionValue("check-min-sdk", "true"); 221 List<VersionedFile> files = new ArrayList<>(); 222 File tmpFile = FileUtil.createTempFile("versioned", ".test"); 223 try { 224 files.add(new VersionedFile(tmpFile, "1")); 225 EasyMock.expect(mMockBuildInfo.getAppPackageFiles()).andReturn(files); 226 EasyMock.expect(mMockDevice.getApiLevel()).andReturn(21).times(2); 227 doReturn(22).when(mMockAaptParser).getSdkVersion(); 228 replayMocks(); 229 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 230 } finally { 231 FileUtil.deleteFile(tmpFile); 232 verifyMocks(); 233 Mockito.verify(mMockAaptParser, times(2)).getSdkVersion(); 234 } 235 } 236 237 /** 238 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when api level of device is high 239 * enough to install the apk. 240 */ 241 @Test 242 public void testSetup_checkMinSdk_apiOk() throws Exception { 243 mAppSetup = new AppSetup() { 244 @Override 245 AaptParser doAaptParse(File apkFile) { 246 return mMockAaptParser; 247 } 248 }; 249 OptionSetter setter = new OptionSetter(mAppSetup); 250 setter.setOptionValue("check-min-sdk", "true"); 251 List<VersionedFile> files = new ArrayList<>(); 252 File tmpFile = FileUtil.createTempFile("versioned", ".test"); 253 try { 254 files.add(new VersionedFile(tmpFile, "1")); 255 EasyMock.expect(mMockBuildInfo.getAppPackageFiles()).andReturn(files); 256 EasyMock.expect(mMockDevice.getApiLevel()).andReturn(23); 257 doReturn(22).when(mMockAaptParser).getSdkVersion(); 258 EasyMock.expect(mMockDevice.installPackage(EasyMock.eq(tmpFile), EasyMock.eq(true))) 259 .andReturn(null); 260 doReturn("com.fake.package").when(mMockAaptParser).getPackageName(); 261 replayMocks(); 262 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 263 } finally { 264 FileUtil.deleteFile(tmpFile); 265 verifyMocks(); 266 Mockito.verify(mMockAaptParser, times(2)).getPackageName(); 267 Mockito.verify(mMockAaptParser, times(1)).getSdkVersion(); 268 } 269 } 270 271 /** 272 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when running a post install 273 * command. 274 */ 275 @Test 276 public void testSetup_executePostInstall() throws Exception { 277 final String fakeCmd = "fake command"; 278 OptionSetter setter = new OptionSetter(mAppSetup); 279 setter.setOptionValue("install", "false"); 280 setter.setOptionValue("post-install-cmd", fakeCmd); 281 mMockDevice.executeShellCommand(EasyMock.eq(fakeCmd), EasyMock.anyObject(), 282 EasyMock.anyLong(), EasyMock.eq(TimeUnit.MILLISECONDS), EasyMock.eq(1)); 283 EasyMock.expectLastCall(); 284 replayMocks(); 285 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 286 verifyMocks(); 287 } 288 289 /** 290 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when uninstall all package is 291 * requested but there is no package to uninstall. 292 */ 293 @Test 294 public void testSetup_uninstallAll_noPackage() throws Exception { 295 OptionSetter setter = new OptionSetter(mAppSetup); 296 setter.setOptionValue("install", "false"); 297 setter.setOptionValue("uninstall-all", "true"); 298 Set<String> res = new HashSet<>(); 299 EasyMock.expect(mMockDevice.getUninstallablePackageNames()).andReturn(res); 300 replayMocks(); 301 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 302 verifyMocks(); 303 } 304 305 /** 306 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when uninstall is working and all 307 * package to be uninstalled are uninstalled. 308 */ 309 @Test 310 public void testSetup_uninstallAll() throws Exception { 311 OptionSetter setter = new OptionSetter(mAppSetup); 312 setter.setOptionValue("install", "false"); 313 setter.setOptionValue("uninstall-all", "true"); 314 Set<String> res = new HashSet<>(); 315 res.add("com.fake1"); 316 EasyMock.expect(mMockDevice.getUninstallablePackageNames()).andReturn(res).times(2); 317 EasyMock.expect(mMockDevice.uninstallPackage("com.fake1")).andReturn(null).times(2); 318 EasyMock.expect(mMockDevice.getUninstallablePackageNames()).andReturn(new HashSet<>()); 319 replayMocks(); 320 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 321 verifyMocks(); 322 } 323 324 /** 325 * Test for {@link AppSetup#setUp(ITestDevice, IBuildInfo)} when uninstall is failing. 326 */ 327 @Test 328 public void testSetup_uninstallAll_fails() throws Exception { 329 OptionSetter setter = new OptionSetter(mAppSetup); 330 setter.setOptionValue("install", "false"); 331 setter.setOptionValue("uninstall-all", "true"); 332 Set<String> res = new HashSet<>(); 333 res.add("com.fake1"); 334 EasyMock.expect(mMockDevice.getUninstallablePackageNames()).andReturn(res).times(4); 335 EasyMock.expect(mMockDevice.uninstallPackage("com.fake1")).andReturn("error").times(3); 336 replayMocks(); 337 try { 338 mAppSetup.setUp(mMockDevice, mMockBuildInfo); 339 fail("Should have thrown an exception."); 340 } catch (DeviceNotAvailableException expected) { 341 assertEquals("Failed to uninstall apps on " + SERIAL, expected.getMessage()); 342 } 343 verifyMocks(); 344 } 345 346 /** 347 * Test for {@link AppSetup#tearDown(ITestDevice, IBuildInfo, Throwable)} when throwable is 348 * a DNAE instance, it should just return. 349 */ 350 @Test 351 public void testTearDown_DNAE() throws Exception { 352 replayMocks(); 353 mAppSetup.tearDown(mMockDevice, mMockBuildInfo, new DeviceNotAvailableException()); 354 verifyMocks(); 355 } 356 357 /** 358 * Test for {@link AppSetup#tearDown(ITestDevice, IBuildInfo, Throwable)}. 359 */ 360 @Test 361 public void testTearDown() throws Exception { 362 mMockDevice.reboot(); 363 EasyMock.expectLastCall(); 364 replayMocks(); 365 mAppSetup.tearDown(mMockDevice, mMockBuildInfo, null); 366 verifyMocks(); 367 } 368 } 369