1 /* 2 * Copyright (C) 2008 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.cts; 18 19 import com.android.cts.TestSession.ResultObserver; 20 21 import java.util.TimerTask; 22 23 /** 24 * Correspond to junit's test method, provide functions on storing 25 * and executing a test from CTS test harness. 26 */ 27 public class Test implements DeviceObserver { 28 public static final String METHOD_SEPARATOR = "#"; 29 30 private TestController mTestController; 31 private TestCase mParentCase; 32 private String mName; 33 private String mType; 34 private String mKnownFailure; 35 private long mStartTime; 36 private long mEndTime; 37 38 protected boolean mTestStop; 39 protected TestDevice mDevice; 40 protected HostTimer mTimeOutTimer; 41 protected ProgressObserver mProgressObserver; 42 protected CtsTestResult mResult; 43 44 public Test(final TestCase parentCase, final String name, 45 final String type, final String knownFailure, final int resCode) { 46 mParentCase = parentCase; 47 mName = name; 48 mType = type; 49 mKnownFailure = knownFailure; 50 mResult = new CtsTestResult(resCode); 51 52 mTestController = null; 53 mProgressObserver = null; 54 mTestStop = false; 55 } 56 57 /** 58 * Check if it's known failure test. 59 * 60 * @return If known failure test, return true; else, return false. 61 */ 62 public boolean isKnownFailure() { 63 return (mKnownFailure != null); 64 } 65 66 /** 67 * Get the known failure description. 68 * 69 * @return The known failure description. 70 */ 71 public String getKnownFailure() { 72 return mKnownFailure; 73 } 74 75 /** 76 * Set the test controller. 77 * 78 * @param testController The test controller. 79 */ 80 public void setTestController(final TestController testController) { 81 mTestController = testController; 82 } 83 84 /** 85 * Get the test controller. 86 * 87 * @return The test controller. 88 */ 89 public TestController getTestController() { 90 return mTestController; 91 } 92 93 /** 94 * Get the instrumentation runner. 95 * 96 * @return The instrumentation runner. 97 */ 98 public String getInstrumentationRunner() { 99 TestPackage pkg = mParentCase.getParent().getParent(); 100 return pkg.getInstrumentationRunner(); 101 } 102 103 /** 104 * Get the test name of this test. 105 * 106 * @return The test name of this test. 107 */ 108 public String getName() { 109 return mName; 110 } 111 112 /** 113 * Get the test type of this test. 114 * 115 * @return The test type of this test. 116 */ 117 public String getType() { 118 return mType; 119 } 120 121 /** 122 * Get the parent TestCase containing the test. 123 * 124 * @return The parent TestCase. 125 */ 126 public TestCase getTestCase() { 127 return mParentCase; 128 } 129 130 /** 131 * Get the parent TestSuite containing the test. 132 * 133 * @return The parent TestSuite. 134 */ 135 public TestSuite getTestSuite() { 136 return mParentCase.getParent(); 137 } 138 139 /** 140 * Get the parent TestPackage containing the test. 141 * 142 * @return The parent TestPackage. 143 */ 144 public TestPackage getTestPackage() { 145 return mParentCase.getParent().getParent(); 146 } 147 148 /** 149 * Get the app package name space of this test. 150 * 151 * @return The app package name space of this test. 152 */ 153 public String getAppNameSpace() { 154 TestPackage pkg = mParentCase.getParent().getParent(); 155 return pkg.getAppNameSpace(); 156 } 157 158 /** 159 * Get the full name of this test. 160 * 161 * @return The full name of this test. 162 */ 163 public String getFullName() { 164 TestSuite suite = mParentCase.getParent(); 165 return suite.getFullName() + "." + mParentCase.getName() 166 + METHOD_SEPARATOR + mName; 167 } 168 169 /** 170 * Set test result. 171 * 172 * @param result The result. 173 */ 174 public void setResult(CtsTestResult result) { 175 if (isKnownFailure()) { 176 result.reverse(); 177 } 178 mResult = result; 179 CUIOutputStream.println("(" + mResult.getResultString() + ")"); 180 if (!mResult.isPass()) { 181 String failedMessage = result.getFailedMessage(); 182 String stackTrace = result.getStackTrace(); 183 if (failedMessage != null) { 184 CUIOutputStream.println(failedMessage); 185 } 186 if (stackTrace != null) { 187 CUIOutputStream.println(stackTrace); 188 } 189 } 190 setEndTime(System.currentTimeMillis()); 191 192 ResultObserver.getInstance().notifyUpdate(); 193 } 194 195 /** 196 * Add test result. 197 * 198 * @param result The result. 199 */ 200 public void addResult(CtsTestResult result) { 201 if (isKnownFailure()) { 202 result.reverse(); 203 } 204 mResult = result; 205 } 206 207 /** 208 * Get the result. 209 * 210 * @return the result. 211 */ 212 public CtsTestResult getResult() { 213 return mResult; 214 } 215 216 /** 217 * Set start Test time. 218 * 219 * @param time The start time. 220 */ 221 public void setStartTime(final long time) { 222 mStartTime = time; 223 } 224 225 /** 226 * Set end Test time. 227 * 228 * @param time The end time. 229 */ 230 public void setEndTime(final long time) { 231 mEndTime = time; 232 } 233 234 /** 235 * Get Test start time. 236 * 237 * @return The start time. 238 */ 239 public long getStartTime() { 240 return mStartTime; 241 } 242 243 /** 244 * Get Test end time. 245 * 246 * @return The end time. 247 */ 248 public long getEndTime() { 249 return mEndTime; 250 } 251 252 /** 253 * Print the message without appending the new line mark. 254 * 255 * @param msg the message to be print. 256 */ 257 protected void print(final String msg) { 258 if (!mTestStop) { 259 CUIOutputStream.print(msg); 260 } 261 } 262 263 /** 264 * The timer task which aids in guarding the running test 265 * with the guarding timer. If the executing of the test 266 * is not finished, and the guarding timer is expired, 267 * this task will be executed to force the finish of the 268 * running test. 269 */ 270 class TimeOutTask extends TimerTask { 271 private Test mTest; 272 273 public TimeOutTask(final Test testResult) { 274 mTest = testResult; 275 } 276 277 /** {@inheritDoc} */ 278 @Override 279 public void run() { 280 mProgressObserver.stop(); 281 synchronized (mTimeOutTimer) { 282 mTimeOutTimer.cancel(true); 283 mTimeOutTimer.sendNotify(); 284 } 285 286 Log.d("mTimeOutTimer timed out"); 287 288 if (!mTestStop) { 289 mTest.setResult( 290 new CtsTestResult(CtsTestResult.CODE_TIMEOUT, null, null)); 291 } 292 293 killDeviceProcess(mTest.getAppNameSpace()); 294 } 295 } 296 297 /** 298 * Kill the device process. 299 * 300 * @param packageName The package name. 301 */ 302 private void killDeviceProcess(final String packageName) { 303 mDevice.killProcess(packageName); 304 } 305 306 /** 307 * Set test stopped. 308 * 309 * @param testStopped If true, it's stopped. Else, still running. 310 */ 311 public void setTestStopped(final boolean testStopped) { 312 mTestStop = testStopped; 313 } 314 315 /** 316 * Run the test over device given. 317 * 318 * @param device the device to run the test. 319 */ 320 public void run(final TestDevice device) throws DeviceDisconnectedException, 321 ADBServerNeedRestartException { 322 323 if ((getName() == null) || (getName().length() == 0)) { 324 return; 325 } 326 327 if (TestSession.exceedsMaxCount()) { 328 throw new ADBServerNeedRestartException("Test count reached overflow point"); 329 } else { 330 TestSession.incTestCount(); 331 } 332 333 mTestStop = false; 334 mDevice = device; 335 mTimeOutTimer = new HostTimer(new TimeOutTask(this), 336 HostConfig.Ints.individualStartTimeoutMs.value()); 337 mTimeOutTimer.start(); 338 mProgressObserver = new ProgressObserver(); 339 mProgressObserver.start(); 340 341 setStartTime(System.currentTimeMillis()); 342 String testFullName = getFullName(); 343 print(testFullName + "..."); 344 345 runImpl(); 346 347 synchronized (mTimeOutTimer) { 348 if (!mTestStop) { 349 try { 350 mTimeOutTimer.waitOn(); 351 } catch (InterruptedException e) { 352 Log.d("time out object interrupted"); 353 } 354 } 355 356 mProgressObserver.stop(); 357 if (mTimeOutTimer.isTimeOut()) { 358 return; 359 } else { 360 //not caused by timer timing out 361 //need to cancel timer 362 mTimeOutTimer.cancel(false); 363 } 364 } 365 366 setResult(mResult); 367 } 368 369 /** 370 * Implementation of running test. 371 */ 372 protected void runImpl() throws DeviceDisconnectedException { 373 mDevice.runTest(this); 374 } 375 376 /** 377 * Notify the result. 378 * 379 * @param result The result. 380 */ 381 public void notifyResult(CtsTestResult result) { 382 383 Log.d("Test.notifyResult() is called. (Test.getFullName()=" + getFullName()); 384 mResult = result; 385 if (mTimeOutTimer != null) { 386 synchronized (mTimeOutTimer) { 387 // set result again in case timeout just happened 388 mResult = result; 389 Log.d("notifyUpdateResult() detects that it needs to cancel mTimeOutTimer"); 390 if (mTimeOutTimer != null) { 391 mTimeOutTimer.sendNotify(); 392 } 393 } 394 } 395 } 396 397 /** {@inheritDoc} */ 398 public void notifyInstallingComplete(final int resultCode) { 399 } 400 401 /** {@inheritDoc} */ 402 public void notifyUninstallingComplete(final int resultCode) { 403 } 404 405 /** {@inheritDoc} */ 406 public void notifyInstallingTimeout(final TestDevice testDevice) { 407 } 408 409 /** {@inheritDoc} */ 410 public void notifyUninstallingTimeout(final TestDevice testDevice) { 411 } 412 413 /** {@inheritDoc} */ 414 public void notifyTestingDeviceDisconnected() { 415 Log.d("Test.notifyTestingDeviceDisconnected() is called"); 416 if (mProgressObserver != null) { 417 mProgressObserver.stop(); 418 } 419 420 if (mTimeOutTimer != null) { 421 synchronized (mTimeOutTimer) { 422 mTimeOutTimer.cancel(false); 423 mTimeOutTimer.sendNotify(); 424 } 425 } 426 } 427 } 428 429