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 17 package com.android.tradefed.targetprep; 18 19 import static org.easymock.EasyMock.anyLong; 20 import static org.easymock.EasyMock.expect; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 24 import com.android.tradefed.build.BuildInfo; 25 import com.android.tradefed.build.IBuildInfo; 26 import com.android.tradefed.log.LogUtil.CLog; 27 import com.android.tradefed.util.CommandResult; 28 import com.android.tradefed.util.CommandStatus; 29 import com.android.tradefed.util.FileUtil; 30 import com.android.tradefed.util.IRunUtil; 31 import org.easymock.EasyMock; 32 import org.junit.Before; 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 import org.junit.runners.JUnit4; 36 import org.mockito.Mock; 37 import java.io.File; 38 import java.io.IOException; 39 40 /** 41 * Unit tests for {@link VtsPythonVirtualenvPreparer}.</p> 42 * TODO: add tests to cover a full end-to-end scenario. 43 */ 44 @RunWith(JUnit4.class) 45 public class VtsPythonVirtualenvPreparerTest { 46 private MockPythonVirtualenvPreparer mPreparer; 47 private IRunUtil mMockRunUtil; 48 private MockFile mFile; 49 @Mock private IBuildInfo mBuildInfo; 50 51 class MockFile extends File { 52 public boolean createNewFileSuccess = true; 53 54 /** 55 * @param name 56 */ MockFile(String name)57 public MockFile(String name) { 58 super(name); 59 } 60 61 @Override createNewFile()62 public boolean createNewFile() throws IOException { 63 if (!createNewFileSuccess) { 64 throw new IOException(); 65 }; 66 67 return true; 68 } 69 } 70 71 class MockPythonVirtualenvPreparer extends VtsPythonVirtualenvPreparer { 72 public int mock_createVirtualenv = -1; 73 public int mock_checkHostReuseVirtualenv = -1; 74 public int mock_checkTestPlanLevelVirtualenv = -1; 75 public int mock_createVirtualenv_waitForOtherProcessToCreateVirtualEnv = -1; 76 77 @Override getRunUtil()78 protected IRunUtil getRunUtil() { 79 return mMockRunUtil; 80 } 81 82 @Override getVirtualenvCreationMarkFile()83 protected File getVirtualenvCreationMarkFile() { 84 return mFile; 85 } 86 87 @Override createVirtualenv()88 protected boolean createVirtualenv() throws IOException { 89 switch (mock_createVirtualenv) { 90 case 0: 91 return false; 92 case 1: 93 return true; 94 case 2: 95 throw new IOException(""); 96 default: 97 return super.createVirtualenv(); 98 } 99 } 100 101 @Override checkHostReuseVirtualenv(IBuildInfo buildInfo)102 protected boolean checkHostReuseVirtualenv(IBuildInfo buildInfo) throws IOException { 103 switch (mock_checkHostReuseVirtualenv) { 104 case 0: 105 return false; 106 case 1: 107 return true; 108 case 2: 109 throw new IOException(""); 110 default: 111 return super.checkHostReuseVirtualenv(buildInfo); 112 } 113 } 114 115 @SuppressWarnings("deprecation") 116 @Override checkTestPlanLevelVirtualenv(IBuildInfo buildInfo)117 protected boolean checkTestPlanLevelVirtualenv(IBuildInfo buildInfo) 118 throws TargetSetupError { 119 switch (mock_checkTestPlanLevelVirtualenv) { 120 case 0: 121 return false; 122 case 1: 123 return true; 124 case 2: 125 throw new TargetSetupError(""); 126 default: 127 return super.checkTestPlanLevelVirtualenv(buildInfo); 128 } 129 } 130 131 @SuppressWarnings("deprecation") 132 @Override createVirtualenv_waitForOtherProcessToCreateVirtualEnv()133 protected boolean createVirtualenv_waitForOtherProcessToCreateVirtualEnv() { 134 switch (mock_createVirtualenv_waitForOtherProcessToCreateVirtualEnv) { 135 case 0: 136 return false; 137 case 1: 138 return true; 139 default: 140 return super.createVirtualenv_waitForOtherProcessToCreateVirtualEnv(); 141 } 142 } 143 } 144 145 @Before setUp()146 public void setUp() throws Exception { 147 mMockRunUtil = EasyMock.createMock(IRunUtil.class); 148 mFile = new MockFile(""); 149 150 mPreparer = new MockPythonVirtualenvPreparer(); 151 VtsPythonVirtualenvPreparer.PIP_RETRY = 0; 152 mPreparer.mVenvDir = new File(""); 153 mPreparer.mDepModules.add("enum"); 154 } 155 156 /** 157 * Test that the installation of dependencies and requirements file is as expected. 158 */ 159 @Test testInstallDeps_reqFile_success()160 public void testInstallDeps_reqFile_success() throws Exception { 161 File requirementFile = FileUtil.createTempFile("reqfile", ".txt"); 162 try { 163 mPreparer.setRequirementsFile(requirementFile); 164 CommandResult result = new CommandResult(CommandStatus.SUCCESS); 165 result.setStdout("output"); 166 result.setStderr("std err"); 167 // First check that the install requirements was attempted. 168 expect(mMockRunUtil.runTimedCmd(anyLong(), EasyMock.eq(mPreparer.getPipPath()), 169 EasyMock.eq("install"), EasyMock.eq("-r"), 170 EasyMock.eq(requirementFile.getAbsolutePath()))) 171 .andReturn(result); 172 // Check that all default modules are installed 173 addDefaultModuleExpectations(mMockRunUtil, result); 174 EasyMock.replay(mMockRunUtil); 175 mPreparer.installDeps(); 176 EasyMock.verify(mMockRunUtil); 177 } finally { 178 FileUtil.deleteFile(requirementFile); 179 } 180 } 181 182 /** 183 * Test that if an extra dependency module is required, we install it too. 184 */ 185 @Test testInstallDeps_depModule_success()186 public void testInstallDeps_depModule_success() throws Exception { 187 mPreparer.addDepModule("blahblah"); 188 CommandResult result = new CommandResult(CommandStatus.SUCCESS); 189 result.setStdout("output"); 190 result.setStderr("std err"); 191 addDefaultModuleExpectations(mMockRunUtil, result); 192 // The non default module provided is also attempted to be installed. 193 expect(mMockRunUtil.runTimedCmd(anyLong(), EasyMock.eq(mPreparer.getPipPath()), 194 EasyMock.eq("install"), EasyMock.eq("blahblah"))) 195 .andReturn(result); 196 mMockRunUtil.sleep(VtsPythonVirtualenvPreparer.PIP_INSTALL_DELAY); 197 EasyMock.replay(mMockRunUtil); 198 mPreparer.installDeps(); 199 EasyMock.verify(mMockRunUtil); 200 } 201 202 /** 203 * Tests the value of PIP_INSTALL_DELAY is at least 1 second. 204 */ 205 @Test test_PIP_INSTALL_DELAY_minimum_value()206 public void test_PIP_INSTALL_DELAY_minimum_value() { 207 assertTrue(VtsPythonVirtualenvPreparer.PIP_INSTALL_DELAY >= 1000); 208 } 209 210 /** 211 * Test that an installation failure of the requirements file throws a {@link TargetSetupError}. 212 */ 213 @Test testInstallDeps_reqFile_failure()214 public void testInstallDeps_reqFile_failure() throws Exception { 215 File requirementFile = FileUtil.createTempFile("reqfile", ".txt"); 216 try { 217 mPreparer.setRequirementsFile(requirementFile); 218 CommandResult result = new CommandResult(CommandStatus.TIMED_OUT); 219 result.setStdout("output"); 220 result.setStderr("std err"); 221 expect(mMockRunUtil.runTimedCmd(anyLong(), EasyMock.eq(mPreparer.getPipPath()), 222 EasyMock.eq("install"), EasyMock.eq("-r"), 223 EasyMock.eq(requirementFile.getAbsolutePath()))) 224 .andReturn(result); 225 EasyMock.replay(mMockRunUtil); 226 IBuildInfo buildInfo = new BuildInfo(); 227 try { 228 mPreparer.installDeps(); 229 fail("installDeps succeeded despite a failed command"); 230 } catch (TargetSetupError e) { 231 assertTrue(buildInfo.getFile("PYTHONPATH") == null); 232 } 233 EasyMock.verify(mMockRunUtil); 234 } finally { 235 FileUtil.deleteFile(requirementFile); 236 } 237 } 238 239 /** 240 * Test that an installation failure of the dep module throws a {@link TargetSetupError}. 241 */ 242 @Test testInstallDeps_depModule_failure()243 public void testInstallDeps_depModule_failure() throws Exception { 244 CommandResult result = new CommandResult(CommandStatus.TIMED_OUT); 245 result.setStdout("output"); 246 result.setStderr("std err"); 247 expect(mMockRunUtil.runTimedCmd( 248 anyLong(), EasyMock.eq(mPreparer.getPipPath()), EasyMock.eq("list"))) 249 .andReturn(result); 250 expect(mMockRunUtil.runTimedCmd(anyLong(), EasyMock.eq(mPreparer.getPipPath()), 251 EasyMock.eq("install"), EasyMock.eq("enum"))) 252 .andReturn(result); 253 // If installing the dependency failed, an upgrade is attempted: 254 expect(mMockRunUtil.runTimedCmd(anyLong(), EasyMock.eq(mPreparer.getPipPath()), 255 EasyMock.eq("install"), EasyMock.eq("--upgrade"), EasyMock.eq("enum"))) 256 .andReturn(result); 257 EasyMock.replay(mMockRunUtil); 258 IBuildInfo buildInfo = new BuildInfo(); 259 try { 260 mPreparer.installDeps(); 261 mPreparer.addPathToBuild(buildInfo); 262 fail("installDeps succeeded despite a failed command"); 263 } catch (TargetSetupError e) { 264 assertTrue(buildInfo.getFile("PYTHONPATH") == null); 265 } 266 EasyMock.verify(mMockRunUtil); 267 } 268 addDefaultModuleExpectations(IRunUtil mockRunUtil, CommandResult result)269 private void addDefaultModuleExpectations(IRunUtil mockRunUtil, CommandResult result) { 270 expect(mockRunUtil.runTimedCmd( 271 anyLong(), EasyMock.eq(mPreparer.getPipPath()), EasyMock.eq("list"))) 272 .andReturn(result); 273 expect(mockRunUtil.runTimedCmd(anyLong(), EasyMock.eq(mPreparer.getPipPath()), 274 EasyMock.eq("install"), EasyMock.eq("enum"))) 275 .andReturn(result); 276 mMockRunUtil.sleep(VtsPythonVirtualenvPreparer.PIP_INSTALL_DELAY); 277 } 278 279 /** 280 * Tests the functionality of createVirtualenv. 281 * @throws IOException 282 */ 283 @Test test_initVirtualenv_creationSuccess()284 public void test_initVirtualenv_creationSuccess() throws IOException { 285 // Create virutalenv dir command success 286 CommandResult result = new CommandResult(); 287 result.setStatus(CommandStatus.SUCCESS); 288 expect(mMockRunUtil.runTimedCmd(EasyMock.anyInt(), EasyMock.eq("virtualenv"), 289 EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject())) 290 .andReturn(result); 291 EasyMock.replay(mMockRunUtil); 292 293 // Create completion mark file success 294 mFile.createNewFileSuccess = true; 295 296 assertTrue(mPreparer.createVirtualenv()); 297 } 298 299 /** 300 * Tests the functionality of createVirtualenv. 301 * @throws IOException 302 */ 303 @Test test_initVirtualenv_creationSuccess_completionFail()304 public void test_initVirtualenv_creationSuccess_completionFail() { 305 // Create virutalenv dir command success 306 CommandResult result = new CommandResult(); 307 result.setStatus(CommandStatus.SUCCESS); 308 expect(mMockRunUtil.runTimedCmd(EasyMock.anyInt(), EasyMock.eq("virtualenv"), 309 EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject())) 310 .andReturn(result); 311 EasyMock.replay(mMockRunUtil); 312 313 // Create completion mark file success 314 mFile.createNewFileSuccess = false; 315 316 try { 317 mPreparer.createVirtualenv(); 318 assertTrue("IOException is expected", false); 319 } catch (IOException e) { 320 // Expected. test pass 321 } 322 } 323 324 /** 325 * Tests the functionality of createVirtualenv. 326 * @throws IOException 327 */ 328 @Test test_initVirtualenv_creationFail_Errno26_waitSucceed()329 public void test_initVirtualenv_creationFail_Errno26_waitSucceed() throws IOException { 330 // Create virutalenv dir command success 331 CommandResult result = new CommandResult(); 332 result.setStatus(CommandStatus.FAILED); 333 result.setStderr("...Errno 26..."); 334 expect(mMockRunUtil.runTimedCmd(EasyMock.anyInt(), EasyMock.eq("virtualenv"), 335 EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject())) 336 .andReturn(result); 337 EasyMock.replay(mMockRunUtil); 338 339 // Wait succeed 340 mPreparer.mock_createVirtualenv_waitForOtherProcessToCreateVirtualEnv = 1; 341 342 assertTrue(mPreparer.createVirtualenv()); 343 } 344 345 /** 346 * Tests the functionality of createVirtualenv. 347 * @throws IOException 348 */ 349 @Test test_initVirtualenv_creationFail_Errno26_waitFailed()350 public void test_initVirtualenv_creationFail_Errno26_waitFailed() throws IOException { 351 // Create virutalenv dir command success 352 CommandResult result = new CommandResult(); 353 result.setStatus(CommandStatus.FAILED); 354 result.setStderr("...Errno 26..."); 355 expect(mMockRunUtil.runTimedCmd(EasyMock.anyInt(), EasyMock.eq("virtualenv"), 356 EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject())) 357 .andReturn(result); 358 EasyMock.replay(mMockRunUtil); 359 360 // Wait failed 361 mPreparer.mock_createVirtualenv_waitForOtherProcessToCreateVirtualEnv = 0; 362 363 assertTrue(!mPreparer.createVirtualenv()); 364 } 365 366 /** 367 * Tests the functionality of createVirtualenv. 368 * @throws IOException 369 */ 370 @Test test_initVirtualenv_creationFail_noErrno26()371 public void test_initVirtualenv_creationFail_noErrno26() throws IOException { 372 // Create virutalenv dir command success 373 CommandResult result = new CommandResult(); 374 result.setStatus(CommandStatus.FAILED); 375 result.setStderr("..."); 376 expect(mMockRunUtil.runTimedCmd(EasyMock.anyInt(), EasyMock.eq("virtualenv"), 377 EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject())) 378 .andReturn(result); 379 EasyMock.replay(mMockRunUtil); 380 381 assertTrue(!mPreparer.createVirtualenv()); 382 } 383 }