1 /*
2  * Copyright (C) 2019 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.cluster;
17 
18 import com.android.annotations.VisibleForTesting;
19 import com.android.tradefed.log.LogUtil.CLog;
20 
21 import org.json.JSONArray;
22 import org.json.JSONException;
23 import org.json.JSONObject;
24 
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 
31 /** A class to model a TestEnvironment message returned by TFC API. */
32 public class TestEnvironment {
33 
34     final Map<String, String> mEnvVars = new HashMap<>();
35     final List<String> mSetupScripts = new ArrayList<>();
36     final List<String> mOutputFilePatterns = new ArrayList<>();
37     String mOutputFileUploadUrl = null;
38     boolean mUseSubprocessReporting = false;
39     long mInvocationTimeout = 0L;
40     long mOutputIdleTimeout = 0L;
41     final List<String> mJvmOptions = new ArrayList<>();
42     final Map<String, String> mJavaProperties = new HashMap<>();
43     String mContextFilePattern = null;
44     private final List<String> mExtraContextFiles = new ArrayList<>();
45     String mRetryCommandLine = null;
46     String mLogLevel = null;
47     final List<TradefedConfigObject> mTradefedConfigObjects = new ArrayList<>();
48     boolean mUseParallelSetup = false;
49     private final List<String> mExcludedFilesInJavaClasspath = new ArrayList<>();
50 
51     /**
52      * Adds an environment variable.
53      *
54      * @param name a variable name.
55      * @param value a variable value.
56      */
addEnvVar(final String name, final String value)57     public void addEnvVar(final String name, final String value) {
58         mEnvVars.put(name, value);
59     }
60 
61     /**
62      * Returns a {@link Map} object containing all env vars.
63      *
64      * @return unmodifiable map of all env vars.
65      */
getEnvVars()66     public Map<String, String> getEnvVars() {
67         return Collections.unmodifiableMap(mEnvVars);
68     }
69 
70     /**
71      * Adds a setup script command.
72      *
73      * @param s a setup script command.
74      */
addSetupScripts(final String s)75     public void addSetupScripts(final String s) {
76         mSetupScripts.add(s);
77     }
78 
79     /**
80      * Returns a list of setup script commands.
81      *
82      * @return unmodifiable list of commands
83      */
getSetupScripts()84     public List<String> getSetupScripts() {
85         return Collections.unmodifiableList(mSetupScripts);
86     }
87 
88     /**
89      * Adds an output file pattern.
90      *
91      * @param s a file pattern.
92      */
addOutputFilePattern(final String s)93     public void addOutputFilePattern(final String s) {
94         mOutputFilePatterns.add(s);
95     }
96 
97     /**
98      * Returns a list of output file patterns.
99      *
100      * @return unmodifiable list of file patterns.
101      */
getOutputFilePatterns()102     public List<String> getOutputFilePatterns() {
103         return Collections.unmodifiableList(mOutputFilePatterns);
104     }
105 
106     /**
107      * Sets an output file upload URL.
108      *
109      * @param s a URL.
110      */
setOutputFileUploadUrl(final String s)111     public void setOutputFileUploadUrl(final String s) {
112         mOutputFileUploadUrl = s;
113     }
114 
115     /**
116      * Returns an output file upload URL.
117      *
118      * @return a URL.
119      */
getOutputFileUploadUrl()120     public String getOutputFileUploadUrl() {
121         return mOutputFileUploadUrl;
122     }
123 
124     /**
125      * Returns whether to use subprocess reporting.
126      *
127      * @return a boolean.
128      */
useSubprocessReporting()129     public boolean useSubprocessReporting() {
130         return mUseSubprocessReporting;
131     }
132 
setUseSubprocessReporting(boolean f)133     public void setUseSubprocessReporting(boolean f) {
134         mUseSubprocessReporting = f;
135     }
136 
137     /**
138      * @return maximum millis to wait for an invocation
139      */
getInvocationTimeout()140     public long getInvocationTimeout() {
141         return mInvocationTimeout;
142     }
143 
setInvocationTimeout(long value)144     public void setInvocationTimeout(long value) {
145         mInvocationTimeout = value;
146     }
147 
148     /**
149      * @return maximum millis to wait for an idle subprocess
150      */
getOutputIdleTimeout()151     public long getOutputIdleTimeout() {
152         return mOutputIdleTimeout;
153     }
154 
setOutputIdleTimeout(long outputIdleTimeout)155     public void setOutputIdleTimeout(long outputIdleTimeout) {
156         mOutputIdleTimeout = outputIdleTimeout;
157     }
158 
159     /**
160      * Adds a JVM option.
161      *
162      * @param s a JVM option.
163      */
addJvmOption(final String s)164     public void addJvmOption(final String s) {
165         mJvmOptions.add(s);
166     }
167 
168     /**
169      * Returns a list of JVM options.
170      *
171      * @return unmodifiable list of options
172      */
getJvmOptions()173     public List<String> getJvmOptions() {
174         return Collections.unmodifiableList(mJvmOptions);
175     }
176 
177     /**
178      * Adds a java property.
179      *
180      * @param name a property name.
181      * @param value a property value.
182      */
addJavaProperty(final String name, final String value)183     public void addJavaProperty(final String name, final String value) {
184         mJavaProperties.put(name, value);
185     }
186 
187     /**
188      * Returns a {@link Map} object containing all Java properties.
189      *
190      * @return unmodifiable map of all runner properties.
191      */
getJavaProperties()192     public Map<String, String> getJavaProperties() {
193         return Collections.unmodifiableMap(mJavaProperties);
194     }
195 
getContextFilePattern()196     public String getContextFilePattern() {
197         return mContextFilePattern;
198     }
199 
200     /** Adds a file path to append to the context file. */
addExtraContextFile(String path)201     public void addExtraContextFile(String path) {
202         mExtraContextFiles.add(path);
203     }
204 
205     /**
206      * @return list of additional file paths to append to context file
207      */
getExtraContextFiles()208     public List<String> getExtraContextFiles() {
209         return Collections.unmodifiableList(mExtraContextFiles);
210     }
211 
getRetryCommandLine()212     public String getRetryCommandLine() {
213         return mRetryCommandLine;
214     }
215 
getLogLevel()216     public String getLogLevel() {
217         return mLogLevel;
218     }
219 
getTradefedConfigObjects()220     public List<TradefedConfigObject> getTradefedConfigObjects() {
221         return Collections.unmodifiableList(mTradefedConfigObjects);
222     }
223 
224     /**
225      * Adds a {@link TradefedConfigObject}.
226      *
227      * @param obj a {@link TradefedConfigObject}.
228      */
229     @VisibleForTesting
addTradefedConfigObject(TradefedConfigObject obj)230     void addTradefedConfigObject(TradefedConfigObject obj) {
231         mTradefedConfigObjects.add(obj);
232     }
233 
234     /**
235      * Returns whether to use parallel setup.
236      *
237      * @return a boolean.
238      */
useParallelSetup()239     public boolean useParallelSetup() {
240         return mUseParallelSetup;
241     }
242 
setUseParallelSetup(boolean f)243     public void setUseParallelSetup(boolean f) {
244         mUseParallelSetup = f;
245     }
246 
addExcludedFileInJavaClasspath(final String s)247     public void addExcludedFileInJavaClasspath(final String s) {
248         mExcludedFilesInJavaClasspath.add(s);
249     }
250 
251     /**
252      * Returns a list of excluded files in java classpath
253      *
254      * @return unmodifiable list of files
255      */
getExcludedFilesInJavaClasspath()256     public List<String> getExcludedFilesInJavaClasspath() {
257         return Collections.unmodifiableList(mExcludedFilesInJavaClasspath);
258     }
259 
fromJson(JSONObject json)260     public static TestEnvironment fromJson(JSONObject json) throws JSONException {
261         TestEnvironment obj = new TestEnvironment();
262         final JSONArray envVars = json.optJSONArray("env_vars");
263         if (envVars != null) {
264             for (int i = 0; i < envVars.length(); i++) {
265                 final JSONObject envVar = envVars.getJSONObject(i);
266                 obj.addEnvVar(envVar.getString("key"), envVar.getString("value"));
267             }
268         } else {
269             CLog.w("env_vars is null");
270         }
271         JSONArray jvmOptions = json.optJSONArray("jvm_options");
272         if (jvmOptions != null) {
273             for (int i = 0; i < jvmOptions.length(); i++) {
274                 obj.addJvmOption(jvmOptions.getString(i));
275             }
276         } else {
277             CLog.w("jvm_options is null");
278         }
279         final JSONArray javaProperties = json.optJSONArray("java_properties");
280         if (javaProperties != null) {
281             for (int i = 0; i < javaProperties.length(); i++) {
282                 final JSONObject javaProperty = javaProperties.getJSONObject(i);
283                 obj.addJavaProperty(javaProperty.getString("key"), javaProperty.getString("value"));
284             }
285         } else {
286             CLog.w("java_properties is null");
287         }
288         final JSONArray scripts = json.optJSONArray("setup_scripts");
289         if (scripts != null) {
290             for (int i = 0; i < scripts.length(); i++) {
291                 obj.addSetupScripts(scripts.getString(i));
292             }
293         } else {
294             CLog.w("setup_scripts is null");
295         }
296         final JSONArray patterns = json.optJSONArray("output_file_patterns");
297         if (patterns != null) {
298             for (int i = 0; i < patterns.length(); i++) {
299                 obj.addOutputFilePattern(patterns.getString(i));
300             }
301         } else {
302             CLog.w("output_file_patterns is null");
303         }
304         final String url = json.optString("output_file_upload_url");
305         if (url != null) {
306             obj.setOutputFileUploadUrl(url);
307         } else {
308             CLog.w("output_file_upload_url is null");
309         }
310         obj.mUseSubprocessReporting = json.optBoolean("use_subprocess_reporting", true);
311         obj.mInvocationTimeout = json.optLong("invocation_timeout_millis", 0L);
312         obj.mOutputIdleTimeout = json.optLong("output_idle_timeout_millis", 0L);
313         obj.mContextFilePattern = json.optString("context_file_pattern");
314         JSONArray extraContextFiles = json.optJSONArray("extra_context_files");
315         if (extraContextFiles != null) {
316             for (int i = 0; i < extraContextFiles.length(); i++) {
317                 obj.addExtraContextFile(extraContextFiles.getString(i));
318             }
319         } else {
320             CLog.w("extra_context_files is null");
321         }
322         obj.mRetryCommandLine = json.optString("retry_command_line");
323         obj.mLogLevel = json.optString("log_level");
324         final JSONArray arr = json.optJSONArray("tradefed_config_objects");
325         if (arr != null) {
326             obj.mTradefedConfigObjects.addAll(TradefedConfigObject.fromJsonArray(arr));
327         }
328         obj.mUseParallelSetup = json.optBoolean("use_parallel_setup", true);
329         JSONArray excludedFiles = json.optJSONArray("excluded_files_in_java_classpath");
330         if (excludedFiles != null) {
331             for (int i = 0; i < excludedFiles.length(); i++) {
332                 obj.addExcludedFileInJavaClasspath(excludedFiles.getString(i));
333             }
334         } else {
335             CLog.w("exclude_files_in_java_classpath is null");
336         }
337         return obj;
338     }
339 }
340