1 /*
2  * Copyright (C) 2017 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.testtype.suite;
17 
18 import com.android.tradefed.build.StubBuildProvider;
19 import com.android.tradefed.config.Configuration;
20 import com.android.tradefed.config.IConfiguration;
21 import com.android.tradefed.config.IDeviceConfiguration;
22 import com.android.tradefed.device.metric.FilePullerLogCollector;
23 import com.android.tradefed.device.metric.IMetricCollector;
24 import com.android.tradefed.result.TextResultReporter;
25 import com.android.tradefed.targetprep.ITargetPreparer;
26 import com.android.tradefed.targetprep.multi.IMultiTargetPreparer;
27 import com.android.tradefed.testtype.suite.module.BaseModuleController;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 /**
33  * This class will help validating that the {@link IConfiguration} loaded for the suite are meeting
34  * the expected requirements: - No Build providers - No Result reporters
35  */
36 public class ValidateSuiteConfigHelper {
37 
38     /**
39      * Special exemption list for some collectors. They would be overly cumbersome to be defined at
40      * the suite level.
41      */
42     private static final List<String> ALLOWED_COLLECTOR_IN_MODULE = new ArrayList<>();
43 
44     static {
45         // This collector simply pull and log file from the device. it is useful at the module level
46         // so they can specify which 'key' is going to be watched to be pulled.
FilePullerLogCollector.class.getCanonicalName()47         ALLOWED_COLLECTOR_IN_MODULE.add(FilePullerLogCollector.class.getCanonicalName());
48     }
49 
ValidateSuiteConfigHelper()50     private ValidateSuiteConfigHelper() {}
51 
52     /**
53      * Check that a configuration is properly built to run in a suite.
54      *
55      * @param config a {@link IConfiguration} to be checked if valide for suite.
56      */
validateConfig(IConfiguration config)57     public static void validateConfig(IConfiguration config) {
58         if (config.getDeviceConfig().size() < 2) {
59             // Special handling for single device objects.
60             if (!config.getBuildProvider().getClass().isAssignableFrom(StubBuildProvider.class)) {
61                 throwRuntime(
62                         config,
63                         String.format(
64                                 "%s objects are not allowed in module.",
65                                 Configuration.BUILD_PROVIDER_TYPE_NAME));
66             }
67             checkTargetPrep(config, config.getTargetPreparers());
68         }
69         // if a multi device config is presented, ensure none of the devices define a build_provider
70         for (IDeviceConfiguration deviceConfig : config.getDeviceConfig()) {
71             if (!deviceConfig
72                     .getBuildProvider()
73                     .getClass()
74                     .isAssignableFrom(StubBuildProvider.class)) {
75                 throwRuntime(
76                         config,
77                         String.format(
78                                 "%s objects are not allowed in module.",
79                                 Configuration.BUILD_PROVIDER_TYPE_NAME));
80             }
81             checkTargetPrep(config, deviceConfig.getTargetPreparers());
82         }
83         if (config.getTestInvocationListeners().size() != 1) {
84             throwRuntime(
85                     config,
86                     String.format(
87                             "%s objects are not allowed in module.",
88                             Configuration.RESULT_REPORTER_TYPE_NAME));
89         }
90         if (!config.getTestInvocationListeners()
91                 .get(0)
92                 .getClass()
93                 .isAssignableFrom(TextResultReporter.class)) {
94             throwRuntime(
95                     config,
96                     String.format(
97                             "%s objects are not allowed in module.",
98                             Configuration.RESULT_REPORTER_TYPE_NAME));
99         }
100         // For now we do not allow pre-multi target preparers in modules.
101         if (config.getMultiPreTargetPreparers().size() > 0) {
102             throwRuntime(
103                     config,
104                     String.format(
105                             "%s objects are not allowed in module.",
106                             Configuration.MULTI_PRE_TARGET_PREPARER_TYPE_NAME));
107         }
108 
109         // Check multi target preparers
110         checkTargetPrep(config, config.getMultiTargetPreparers());
111 
112         // Check metric collectors
113         for (IMetricCollector collector : config.getMetricCollectors()) {
114             // Only some collectors are allowed in the module
115             if (!ALLOWED_COLLECTOR_IN_MODULE.contains(collector.getClass().getCanonicalName())) {
116                 throwRuntime(
117                         config,
118                         String.format(
119                                 "%s objects are not allowed in module. Except for: %s",
120                                 Configuration.DEVICE_METRICS_COLLECTOR_TYPE_NAME,
121                                 ALLOWED_COLLECTOR_IN_MODULE));
122             }
123         }
124 
125         // Check that we validate the module_controller.
126         Object controller = config.getConfigurationObject(ModuleDefinition.MODULE_CONTROLLER);
127         if (controller != null) {
128             if (!(controller instanceof BaseModuleController)) {
129                 throwRuntime(
130                         config,
131                         String.format(
132                                 "%s object should be of type %s",
133                                 ModuleDefinition.MODULE_CONTROLLER, BaseModuleController.class));
134             }
135         }
136     }
137 
138     /**
139      * Check target_preparer and multi_target_preparer to ensure they do not extends each other as
140      * it could lead to some issues.
141      */
checkTargetPrep(IConfiguration config, List<?> targetPrepList)142     private static boolean checkTargetPrep(IConfiguration config, List<?> targetPrepList) {
143         for (Object o : targetPrepList) {
144             if (o instanceof ITargetPreparer && o instanceof IMultiTargetPreparer) {
145                 throwRuntime(
146                         config,
147                         String.format(
148                                 "%s is extending both %s and " + "%s",
149                                 o.getClass().getCanonicalName(),
150                                 Configuration.TARGET_PREPARER_TYPE_NAME,
151                                 Configuration.MULTI_PREPARER_TYPE_NAME));
152                 return false;
153             }
154         }
155         return true;
156     }
157 
throwRuntime(IConfiguration config, String msg)158     private static void throwRuntime(IConfiguration config, String msg) {
159         throw new RuntimeException(
160                 String.format(
161                         "Configuration %s cannot be run in a suite: %s", config.getName(), msg));
162     }
163 }
164