• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 public class ModuleDef implements IModuleDef {
61 
62     private final String mId;
63     private final String mName;
64     private final IAbi mAbi;
65     private final Set<String> mTokens = new HashSet<>();
66     private IRemoteTest mTest = null;
67     private List<ITargetPreparer> mDynamicConfigPreparers = new ArrayList<>();
68     private List<ITargetPreparer> mPreconditions = new ArrayList<>();
69     private List<ITargetPreparer> mPreparers = new ArrayList<>();
70     private List<ITargetCleaner> mCleaners = new ArrayList<>();
71     private IBuildInfo mBuild;
72     private ITestDevice mDevice;
73     private Set<String> mPreparerWhitelist = new HashSet<>();
74     private ConfigurationDescriptor mConfigurationDescriptor;
75     private IInvocationContext mContext;
76 
ModuleDef(String name, IAbi abi, IRemoteTest test, List<ITargetPreparer> preparers, ConfigurationDescriptor configurationDescriptor)77     public ModuleDef(String name, IAbi abi, IRemoteTest test,
78             List<ITargetPreparer> preparers, ConfigurationDescriptor configurationDescriptor) {
79         mId = AbiUtils.createId(abi.getName(), name);
80         mName = name;
81         mAbi = abi;
82         mTest = test;
83         mConfigurationDescriptor = configurationDescriptor;
84         initializePrepareLists(preparers);
85     }
86 
87     /**
88      * Sort preparers into different lists according to their types
89      *
90      * @param preparers target preparers
91      * @throws IllegalArgumentException
92      */
initializePrepareLists(List<ITargetPreparer> preparers)93     protected void initializePrepareLists(List<ITargetPreparer> preparers)
94             throws IllegalArgumentException {
95         boolean hasAbiReceiver = false;
96         for (ITargetPreparer preparer : preparers) {
97             if (preparer instanceof IAbiReceiver) {
98                 hasAbiReceiver = true;
99             }
100             // Separate preconditions and dynamicconfigpushers from other target preparers.
101             if (preparer instanceof PreconditionPreparer) {
102                 mPreconditions.add(preparer);
103             } else if (preparer instanceof DynamicConfigPusher) {
104                 mDynamicConfigPreparers.add(preparer);
105             } else if (preparer instanceof TokenRequirement) {
106                 mTokens.addAll(((TokenRequirement) preparer).getTokens());
107             } else {
108                 mPreparers.add(preparer);
109             }
110             if (preparer instanceof ITargetCleaner) {
111                 mCleaners.add((ITargetCleaner) preparer);
112             }
113         }
114         // Reverse cleaner order
115         Collections.reverse(mCleaners);
116 
117         checkRequiredInterfaces(hasAbiReceiver);
118     }
119 
120     /**
121      * Check whether required interfaces are implemented.
122      *
123      * @param hasAbiReceiver whether at lease one of the preparers is AbiReceiver
124      * @throws IllegalArgumentException
125      */
checkRequiredInterfaces(boolean hasAbiReceiver)126     protected void checkRequiredInterfaces(boolean hasAbiReceiver) throws IllegalArgumentException {
127         // Required interfaces:
128         if (!hasAbiReceiver && !(mTest instanceof IAbiReceiver)) {
129             throw new IllegalArgumentException(mTest + "does not implement IAbiReceiver"
130                     + " - for multi-abi testing (64bit)");
131         } else if (!(mTest instanceof IRuntimeHintProvider)) {
132             throw new IllegalArgumentException(mTest + " does not implement IRuntimeHintProvider"
133                     + " - to provide estimates of test invocation time");
134         } else if (!(mTest instanceof ITestCollector)) {
135             throw new IllegalArgumentException(mTest + " does not implement ITestCollector"
136                     + " - for test list collection");
137         } else if (!(mTest instanceof ITestFilterReceiver)) {
138             throw new IllegalArgumentException(mTest + " does not implement ITestFilterReceiver"
139                     + " - to allow tests to be filtered");
140         }
141     }
142 
143     /**
144      * {@inheritDoc}
145      */
146     @Override
toString()147     public String toString() {
148         return mId;
149     }
150 
151     /**
152      * {@inheritDoc}
153      */
154     @Override
getId()155     public String getId() {
156         return mId;
157     }
158 
159     /**
160      * {@inheritDoc}
161      */
162     @Override
getName()163     public String getName() {
164         return mName;
165     }
166 
167     /**
168      * @return the mPreparerWhitelist
169      */
getPreparerWhitelist()170     protected Set<String> getPreparerWhitelist() {
171         return mPreparerWhitelist;
172     }
173 
174     /**
175      * {@inheritDoc}
176      */
177     @Override
getAbi()178     public IAbi getAbi() {
179         return mAbi;
180     }
181 
182     /**
183      * {@inheritDoc}
184      */
185     @Override
getTokens()186     public Set<String> getTokens() {
187         return mTokens;
188     }
189 
190     /**
191      * {@inheritDoc}
192      */
193     @Override
getRuntimeHint()194     public long getRuntimeHint() {
195         if (mTest instanceof IRuntimeHintProvider) {
196             return ((IRuntimeHintProvider) mTest).getRuntimeHint();
197         }
198         return TimeUnit.MINUTES.toMillis(1); // Default 1 minute.
199     }
200 
201     /**
202      * {@inheritDoc}
203      */
204     @Override
getTest()205     public IRemoteTest getTest() {
206         return mTest;
207     }
208 
209     /**
210      * {@inheritDoc}
211      */
212     @Override
setPreparerWhitelist(Set<String> preparerWhitelist)213     public void setPreparerWhitelist(Set<String> preparerWhitelist) {
214         mPreparerWhitelist.addAll(preparerWhitelist);
215     }
216 
217     /**
218      * {@inheritDoc}
219      */
220     @Override
compareTo(IModuleDef moduleDef)221     public int compareTo(IModuleDef moduleDef) {
222         return getName().compareTo(moduleDef.getName());
223     }
224 
225     /**
226      * {@inheritDoc}
227      */
228     @Override
setBuild(IBuildInfo build)229     public void setBuild(IBuildInfo build) {
230         mBuild = build;
231     }
232 
233     /**
234      * {@inheritDoc}
235      */
236     @Override
getDevice()237     public ITestDevice getDevice() {
238         return mDevice;
239     }
240 
241     /**
242      * {@inheritDoc}
243      */
244     @Override
setDevice(ITestDevice device)245     public void setDevice(ITestDevice device) {
246         mDevice = device;
247     }
248 
249     /**
250      * {@inheritDoc}
251      */
252     @Override
run(ITestInvocationListener listener)253     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
254         CLog.d("Running module %s", toString());
255         runPreparerSetups();
256 
257         CLog.d("Test: %s", mTest.getClass().getSimpleName());
258         prepareTestClass();
259 
260         IModuleListener moduleListener = new ModuleListener(this, listener);
261         // Guarantee events testRunStarted and testRunEnded in case underlying test runner does not
262         ModuleFinisher moduleFinisher = new ModuleFinisher(moduleListener);
263         mTest.run(moduleFinisher);
264         moduleFinisher.finish();
265 
266         // Tear down
267         runPreparerTeardowns();
268     }
269 
270     /**
271      * Run preparers' teardown functions.
272      */
runPreparerTeardowns()273     protected void runPreparerTeardowns() throws DeviceNotAvailableException {
274         for (ITargetCleaner cleaner : mCleaners) {
275             CLog.d("Cleaner: %s", cleaner.getClass().getSimpleName());
276             cleaner.tearDown(mDevice, mBuild, null);
277         }
278     }
279 
280     /**
281      * Run preparers' setup functions.
282      *
283      * @throws DeviceNotAvailableException
284      */
runPreparerSetups()285     protected void runPreparerSetups() throws DeviceNotAvailableException {
286         // Run DynamicConfigPusher setup once more, in case cleaner has previously
287         // removed dynamic config file from the target (see b/32877809)
288         for (ITargetPreparer preparer : mDynamicConfigPreparers) {
289             runPreparerSetup(preparer);
290         }
291         // Setup
292         for (ITargetPreparer preparer : mPreparers) {
293             runPreparerSetup(preparer);
294         }
295     }
296 
297     /**
298      * Set test classes attributes according to their interfaces.
299      */
prepareTestClass()300     protected void prepareTestClass() {
301         if (mTest instanceof IAbiReceiver) {
302             ((IAbiReceiver) mTest).setAbi(mAbi);
303         }
304         if (mTest instanceof IBuildReceiver) {
305             ((IBuildReceiver) mTest).setBuild(mBuild);
306         }
307         if (mTest instanceof IDeviceTest) {
308             ((IDeviceTest) mTest).setDevice(mDevice);
309         }
310         if (mTest instanceof IInvocationContextReceiver) {
311             ((IInvocationContextReceiver) mTest).setInvocationContext(mContext);
312         }
313     }
314 
315     /**
316      * {@inheritDoc}
317      */
318     @Override
prepare(boolean skipPrep, List<String> preconditionArgs)319     public boolean prepare(boolean skipPrep, List<String> preconditionArgs)
320             throws DeviceNotAvailableException {
321         for (ITargetPreparer preparer : mDynamicConfigPreparers) {
322             runPreparerSetup(preparer);
323         }
324         for (ITargetPreparer preparer : mPreconditions) {
325             setOption(preparer, CompatibilityTest.SKIP_PRECONDITIONS_OPTION,
326                     Boolean.toString(skipPrep));
327             for (String preconditionArg : preconditionArgs) {
328                 setOption(preparer, CompatibilityTest.PRECONDITION_ARG_OPTION, preconditionArg);
329             }
330             try {
331                 runPreparerSetup(preparer);
332             } catch (RuntimeException e) {
333                 CLog.e("Precondition class %s failed", preparer.getClass().getCanonicalName());
334                 return false;
335             }
336         }
337         return true;
338     }
339 
runPreparerSetup(ITargetPreparer preparer)340     private void runPreparerSetup(ITargetPreparer preparer) throws DeviceNotAvailableException {
341         String preparerName = preparer.getClass().getCanonicalName();
342         if (!mPreparerWhitelist.isEmpty() && !mPreparerWhitelist.contains(preparerName)) {
343             CLog.d("Skipping Preparer: %s since it is not in the whitelist %s",
344                     preparerName, mPreparerWhitelist);
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