1 /* 2 * Copyright (C) 2015 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.compatibility.common.tradefed.testtype; 17 18 import com.android.compatibility.common.tradefed.result.IModuleListener; 19 import com.android.compatibility.common.tradefed.result.ModuleListener; 20 import com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher; 21 import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer; 22 import com.android.compatibility.common.tradefed.targetprep.TokenRequirement; 23 import com.android.tradefed.build.IBuildInfo; 24 import com.android.tradefed.config.ConfigurationDescriptor; 25 import com.android.tradefed.config.ConfigurationException; 26 import com.android.tradefed.config.OptionSetter; 27 import com.android.tradefed.device.DeviceNotAvailableException; 28 import com.android.tradefed.device.ITestDevice; 29 import com.android.tradefed.invoker.IInvocationContext; 30 import com.android.tradefed.log.LogUtil.CLog; 31 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; 32 import com.android.tradefed.result.ITestInvocationListener; 33 import com.android.tradefed.result.ResultForwarder; 34 import com.android.tradefed.targetprep.BuildError; 35 import com.android.tradefed.targetprep.ITargetCleaner; 36 import com.android.tradefed.targetprep.ITargetPreparer; 37 import com.android.tradefed.targetprep.TargetSetupError; 38 import com.android.tradefed.testtype.IAbi; 39 import com.android.tradefed.testtype.IAbiReceiver; 40 import com.android.tradefed.testtype.IBuildReceiver; 41 import com.android.tradefed.testtype.IDeviceTest; 42 import com.android.tradefed.testtype.IInvocationContextReceiver; 43 import com.android.tradefed.testtype.IRemoteTest; 44 import com.android.tradefed.testtype.IRuntimeHintProvider; 45 import com.android.tradefed.testtype.ITestCollector; 46 import com.android.tradefed.testtype.ITestFilterReceiver; 47 import com.android.tradefed.util.AbiUtils; 48 49 import java.util.ArrayList; 50 import java.util.Collections; 51 import java.util.HashMap; 52 import java.util.HashSet; 53 import java.util.List; 54 import java.util.Set; 55 import java.util.concurrent.TimeUnit; 56 57 /** 58 * Container for Compatibility test module info. 59 * 60 * @deprecated This class is associated with {@link CompatibilityTest} which is deprecate 61 */ 62 @Deprecated 63 public class ModuleDef implements IModuleDef { 64 65 private final String mId; 66 private final String mName; 67 private final IAbi mAbi; 68 private final Set<String> mTokens = new HashSet<>(); 69 private IRemoteTest mTest = null; 70 private List<ITargetPreparer> mDynamicConfigPreparers = new ArrayList<>(); 71 private List<ITargetPreparer> mPreconditions = new ArrayList<>(); 72 private List<ITargetPreparer> mPreparers = new ArrayList<>(); 73 private List<ITargetCleaner> mCleaners = new ArrayList<>(); 74 private IBuildInfo mBuild; 75 private ITestDevice mDevice; 76 private Set<String> mPreparerAllowlist = new HashSet<>(); 77 private ConfigurationDescriptor mConfigurationDescriptor; 78 private IInvocationContext mContext; 79 ModuleDef(String name, IAbi abi, IRemoteTest test, List<ITargetPreparer> preparers, ConfigurationDescriptor configurationDescriptor)80 public ModuleDef(String name, IAbi abi, IRemoteTest test, 81 List<ITargetPreparer> preparers, ConfigurationDescriptor configurationDescriptor) { 82 mId = AbiUtils.createId(abi.getName(), name); 83 mName = name; 84 mAbi = abi; 85 mTest = test; 86 mConfigurationDescriptor = configurationDescriptor; 87 initializePrepareLists(preparers); 88 } 89 90 /** 91 * Sort preparers into different lists according to their types 92 * 93 * @param preparers target preparers 94 * @throws IllegalArgumentException 95 */ initializePrepareLists(List<ITargetPreparer> preparers)96 protected void initializePrepareLists(List<ITargetPreparer> preparers) 97 throws IllegalArgumentException { 98 boolean hasAbiReceiver = false; 99 for (ITargetPreparer preparer : preparers) { 100 if (preparer instanceof IAbiReceiver) { 101 hasAbiReceiver = true; 102 } 103 // Separate preconditions and dynamicconfigpushers from other target preparers. 104 if (preparer instanceof PreconditionPreparer) { 105 mPreconditions.add(preparer); 106 } else if (preparer instanceof DynamicConfigPusher) { 107 mDynamicConfigPreparers.add(preparer); 108 } else if (preparer instanceof TokenRequirement) { 109 mTokens.addAll(((TokenRequirement) preparer).getTokens()); 110 } else { 111 mPreparers.add(preparer); 112 } 113 if (preparer instanceof ITargetCleaner) { 114 mCleaners.add((ITargetCleaner) preparer); 115 } 116 } 117 // Reverse cleaner order 118 Collections.reverse(mCleaners); 119 120 checkRequiredInterfaces(hasAbiReceiver); 121 } 122 123 /** 124 * Check whether required interfaces are implemented. 125 * 126 * @param hasAbiReceiver whether at lease one of the preparers is AbiReceiver 127 * @throws IllegalArgumentException 128 */ checkRequiredInterfaces(boolean hasAbiReceiver)129 protected void checkRequiredInterfaces(boolean hasAbiReceiver) throws IllegalArgumentException { 130 // Required interfaces: 131 if (!hasAbiReceiver && !(mTest instanceof IAbiReceiver)) { 132 throw new IllegalArgumentException(mTest + "does not implement IAbiReceiver" 133 + " - for multi-abi testing (64bit)"); 134 } else if (!(mTest instanceof IRuntimeHintProvider)) { 135 throw new IllegalArgumentException(mTest + " does not implement IRuntimeHintProvider" 136 + " - to provide estimates of test invocation time"); 137 } else if (!(mTest instanceof ITestCollector)) { 138 throw new IllegalArgumentException(mTest + " does not implement ITestCollector" 139 + " - for test list collection"); 140 } else if (!(mTest instanceof ITestFilterReceiver)) { 141 throw new IllegalArgumentException(mTest + " does not implement ITestFilterReceiver" 142 + " - to allow tests to be filtered"); 143 } 144 } 145 146 /** 147 * {@inheritDoc} 148 */ 149 @Override toString()150 public String toString() { 151 return mId; 152 } 153 154 /** 155 * {@inheritDoc} 156 */ 157 @Override getId()158 public String getId() { 159 return mId; 160 } 161 162 /** 163 * {@inheritDoc} 164 */ 165 @Override getName()166 public String getName() { 167 return mName; 168 } 169 170 /** @return the getPreparerAllowlist */ getPreparerAllowlist()171 protected Set<String> getPreparerAllowlist() { 172 return mPreparerAllowlist; 173 } 174 175 /** 176 * {@inheritDoc} 177 */ 178 @Override getAbi()179 public IAbi getAbi() { 180 return mAbi; 181 } 182 183 /** 184 * {@inheritDoc} 185 */ 186 @Override getTokens()187 public Set<String> getTokens() { 188 return mTokens; 189 } 190 191 /** 192 * {@inheritDoc} 193 */ 194 @Override getRuntimeHint()195 public long getRuntimeHint() { 196 if (mTest instanceof IRuntimeHintProvider) { 197 return ((IRuntimeHintProvider) mTest).getRuntimeHint(); 198 } 199 return TimeUnit.MINUTES.toMillis(1); // Default 1 minute. 200 } 201 202 /** 203 * {@inheritDoc} 204 */ 205 @Override getTest()206 public IRemoteTest getTest() { 207 return mTest; 208 } 209 210 /** {@inheritDoc} */ 211 @Override setPreparerAllowlist(Set<String> preparerAlowlist)212 public void setPreparerAllowlist(Set<String> preparerAlowlist) { 213 mPreparerAllowlist.addAll(preparerAlowlist); 214 } 215 216 /** 217 * {@inheritDoc} 218 */ 219 @Override compareTo(IModuleDef moduleDef)220 public int compareTo(IModuleDef moduleDef) { 221 return getName().compareTo(moduleDef.getName()); 222 } 223 224 /** 225 * {@inheritDoc} 226 */ 227 @Override setBuild(IBuildInfo build)228 public void setBuild(IBuildInfo build) { 229 mBuild = build; 230 } 231 232 /** 233 * {@inheritDoc} 234 */ 235 @Override getDevice()236 public ITestDevice getDevice() { 237 return mDevice; 238 } 239 240 /** 241 * {@inheritDoc} 242 */ 243 @Override setDevice(ITestDevice device)244 public void setDevice(ITestDevice device) { 245 mDevice = device; 246 } 247 248 /** 249 * {@inheritDoc} 250 */ 251 @Override run(ITestInvocationListener listener)252 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 253 CLog.d("Running module %s", toString()); 254 runPreparerSetups(); 255 256 CLog.d("Test: %s", mTest.getClass().getSimpleName()); 257 prepareTestClass(); 258 259 IModuleListener moduleListener = new ModuleListener(this, listener); 260 // Guarantee events testRunStarted and testRunEnded in case underlying test runner does not 261 ModuleFinisher moduleFinisher = new ModuleFinisher(moduleListener); 262 mTest.run(moduleFinisher); 263 moduleFinisher.finish(); 264 265 // Tear down 266 runPreparerTeardowns(); 267 } 268 269 /** 270 * Run preparers' teardown functions. 271 */ runPreparerTeardowns()272 protected void runPreparerTeardowns() throws DeviceNotAvailableException { 273 for (ITargetCleaner cleaner : mCleaners) { 274 CLog.d("Cleaner: %s", cleaner.getClass().getSimpleName()); 275 cleaner.tearDown(mDevice, mBuild, null); 276 } 277 } 278 279 /** 280 * Run preparers' setup functions. 281 * 282 * @throws DeviceNotAvailableException 283 */ runPreparerSetups()284 protected void runPreparerSetups() throws DeviceNotAvailableException { 285 // Run DynamicConfigPusher setup once more, in case cleaner has previously 286 // removed dynamic config file from the target (see b/32877809) 287 for (ITargetPreparer preparer : mDynamicConfigPreparers) { 288 runPreparerSetup(preparer); 289 } 290 // Setup 291 for (ITargetPreparer preparer : mPreparers) { 292 runPreparerSetup(preparer); 293 } 294 } 295 296 /** 297 * Set test classes attributes according to their interfaces. 298 */ prepareTestClass()299 protected void prepareTestClass() { 300 if (mTest instanceof IAbiReceiver) { 301 ((IAbiReceiver) mTest).setAbi(mAbi); 302 } 303 if (mTest instanceof IBuildReceiver) { 304 ((IBuildReceiver) mTest).setBuild(mBuild); 305 } 306 if (mTest instanceof IDeviceTest) { 307 ((IDeviceTest) mTest).setDevice(mDevice); 308 } 309 if (mTest instanceof IInvocationContextReceiver) { 310 ((IInvocationContextReceiver) mTest).setInvocationContext(mContext); 311 } 312 } 313 314 /** 315 * {@inheritDoc} 316 */ 317 @Override prepare(boolean skipPrep, List<String> preconditionArgs)318 public boolean prepare(boolean skipPrep, List<String> preconditionArgs) 319 throws DeviceNotAvailableException { 320 for (ITargetPreparer preparer : mDynamicConfigPreparers) { 321 runPreparerSetup(preparer); 322 } 323 for (ITargetPreparer preparer : mPreconditions) { 324 setOption(preparer, CompatibilityTest.SKIP_PRECONDITIONS_OPTION, 325 Boolean.toString(skipPrep)); 326 for (String preconditionArg : preconditionArgs) { 327 setOption(preparer, CompatibilityTest.PRECONDITION_ARG_OPTION, preconditionArg); 328 } 329 try { 330 runPreparerSetup(preparer); 331 } catch (RuntimeException e) { 332 CLog.e("Precondition class %s failed", preparer.getClass().getCanonicalName()); 333 return false; 334 } 335 } 336 return true; 337 } 338 runPreparerSetup(ITargetPreparer preparer)339 private void runPreparerSetup(ITargetPreparer preparer) throws DeviceNotAvailableException { 340 String preparerName = preparer.getClass().getCanonicalName(); 341 if (!mPreparerAllowlist.isEmpty() && !mPreparerAllowlist.contains(preparerName)) { 342 CLog.d( 343 "Skipping Preparer: %s since it is not in the allowList %s", 344 preparerName, mPreparerAllowlist); 345 return; 346 } 347 CLog.d("Preparer: %s", preparer.getClass().getSimpleName()); 348 if (preparer instanceof IAbiReceiver) { 349 ((IAbiReceiver) preparer).setAbi(mAbi); 350 } 351 try { 352 preparer.setUp(mDevice, mBuild); 353 } catch (BuildError e) { 354 // This should only happen for flashing new build 355 CLog.e("Unexpected BuildError from preparer: %s", 356 preparer.getClass().getCanonicalName()); 357 throw new RuntimeException(e); 358 } catch (TargetSetupError e) { 359 // log preparer class then rethrow & let caller handle 360 CLog.e("TargetSetupError in preparer: %s", 361 preparer.getClass().getCanonicalName()); 362 throw new RuntimeException(e); 363 } 364 } 365 setOption(Object target, String option, String value)366 private void setOption(Object target, String option, String value) { 367 try { 368 OptionSetter setter = new OptionSetter(target); 369 setter.setOptionValue(option, value); 370 } catch (ConfigurationException e) { 371 CLog.e(e); 372 } 373 } 374 375 /** 376 * {@inheritDoc} 377 */ 378 @Override setCollectTestsOnly(boolean collectTestsOnly)379 public void setCollectTestsOnly(boolean collectTestsOnly) { 380 ((ITestCollector) mTest).setCollectTestsOnly(collectTestsOnly); 381 } 382 383 /* 384 * ResultForwarder that tracks whether method testRunStarted() has been called for its 385 * listener. If not, invoking finish() will call testRunStarted with 0 tests for this module, 386 * as well as testRunEnded with 0 ms elapsed. 387 */ 388 private class ModuleFinisher extends ResultForwarder { 389 390 private boolean mFinished; 391 private ITestInvocationListener mListener; 392 ModuleFinisher(ITestInvocationListener listener)393 public ModuleFinisher(ITestInvocationListener listener) { 394 super(listener); 395 mListener = listener; 396 mFinished = false; 397 } 398 399 /** 400 * {@inheritDoc} 401 */ 402 @Override testRunStarted(String name, int numTests)403 public void testRunStarted(String name, int numTests) { 404 mListener.testRunStarted(name, numTests); 405 mFinished = true; 406 } 407 finish()408 public void finish() { 409 if (!mFinished) { 410 mListener.testRunStarted(mId, 0); 411 mListener.testRunEnded(0, new HashMap<String, Metric>()); 412 } 413 } 414 } 415 416 @Override getConfigurationDescriptor()417 public ConfigurationDescriptor getConfigurationDescriptor() { 418 return mConfigurationDescriptor; 419 } 420 421 /** 422 * @return the {@link IInvocationContext} for the module 423 */ getInvocationContext()424 protected IInvocationContext getInvocationContext() { 425 return mContext; 426 } 427 428 @Override setInvocationContext(IInvocationContext invocationContext)429 public void setInvocationContext(IInvocationContext invocationContext) { 430 mContext = invocationContext; 431 } 432 } 433