1 /* 2 * Copyright (C) 2016 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.util; 17 18 import com.android.tradefed.log.LogUtil.CLog; 19 import com.android.tradefed.result.LogDataType; 20 21 import org.json.JSONException; 22 import org.json.JSONObject; 23 24 import java.io.File; 25 import java.io.PrintWriter; 26 import java.io.StringWriter; 27 import java.util.HashMap; 28 import java.util.Iterator; 29 import java.util.Map; 30 31 /** 32 * Helper to serialize/deserialize the events to be passed to the log. 33 */ 34 public class SubprocessEventHelper { 35 private static final String CLASSNAME_KEY = "className"; 36 private static final String TESTNAME_KEY = "testName"; 37 private static final String TRACE_KEY = "trace"; 38 private static final String CAUSE_KEY = "cause"; 39 private static final String RUNNAME_KEY = "runName"; 40 private static final String TESTCOUNT_KEY = "testCount"; 41 private static final String TIME_KEY = "time"; 42 private static final String REASON_KEY = "reason"; 43 private static final String START_TIME = "start_time"; 44 private static final String END_TIME = "end_time"; 45 46 private static final String DATA_NAME_KEY = "dataName"; 47 private static final String DATA_TYPE_KEY = "dataType"; 48 private static final String DATA_FILE_KEY = "dataFile"; 49 50 private static final String TEST_TAG_KEY = "testTag"; 51 52 /** 53 * Helper for testRunStarted information 54 */ 55 public static class TestRunStartedEventInfo { 56 public String mRunName = null; 57 public Integer mTestCount = null; 58 59 public TestRunStartedEventInfo(String runName, int testCount) { 60 mRunName = runName; 61 mTestCount = testCount; 62 } 63 64 public TestRunStartedEventInfo(JSONObject jsonObject) throws JSONException { 65 mRunName = jsonObject.getString(RUNNAME_KEY); 66 mTestCount = jsonObject.getInt(TESTCOUNT_KEY); 67 } 68 69 @Override 70 public String toString() { 71 JSONObject tags = new JSONObject(); 72 try { 73 if (mRunName != null) { 74 tags.put(RUNNAME_KEY, mRunName); 75 } 76 if (mTestCount != null) { 77 tags.put(TESTCOUNT_KEY, mTestCount.intValue()); 78 } 79 } catch (JSONException e) { 80 CLog.e(e); 81 } 82 return tags.toString(); 83 } 84 } 85 86 /** 87 * Helper for testRunFailed information 88 */ 89 public static class TestRunFailedEventInfo { 90 public String mReason = null; 91 92 public TestRunFailedEventInfo(String reason) { 93 mReason = reason; 94 } 95 96 public TestRunFailedEventInfo(JSONObject jsonObject) throws JSONException { 97 mReason = jsonObject.getString(REASON_KEY); 98 } 99 100 @Override 101 public String toString() { 102 JSONObject tags = new JSONObject(); 103 try { 104 if (mReason != null) { 105 tags.put(REASON_KEY, mReason); 106 } 107 } catch (JSONException e) { 108 CLog.e(e); 109 } 110 return tags.toString(); 111 } 112 } 113 114 /** 115 * Helper for testRunEnded Information. 116 */ 117 public static class TestRunEndedEventInfo { 118 public Long mTime = null; 119 public Map<String, String> mRunMetrics = null; 120 121 public TestRunEndedEventInfo(Long time, Map<String, String> runMetrics) { 122 mTime = time; 123 mRunMetrics = runMetrics; 124 } 125 126 public TestRunEndedEventInfo(JSONObject jsonObject) throws JSONException { 127 mTime = jsonObject.getLong(TIME_KEY); 128 jsonObject.remove(TIME_KEY); 129 Iterator<?> i = jsonObject.keys(); 130 mRunMetrics = new HashMap<String, String>(); 131 while(i.hasNext()) { 132 String key = (String) i.next(); 133 mRunMetrics.put(key, jsonObject.get(key).toString()); 134 } 135 } 136 137 @Override 138 public String toString() { 139 JSONObject tags = null; 140 try { 141 if (mRunMetrics != null) { 142 tags = new JSONObject(mRunMetrics); 143 } else { 144 tags = new JSONObject(); 145 } 146 if (mTime != null) { 147 tags.put(TIME_KEY, mTime.longValue()); 148 } 149 } catch (JSONException e) { 150 CLog.e(e); 151 } 152 return tags.toString(); 153 } 154 } 155 156 /** 157 * Helper for InvocationFailed information. 158 */ 159 public static class InvocationFailedEventInfo { 160 public Throwable mCause = null; 161 162 public InvocationFailedEventInfo(Throwable cause) { 163 mCause = cause; 164 } 165 166 public InvocationFailedEventInfo(JSONObject jsonObject) throws JSONException { 167 String stack = jsonObject.getString("cause"); 168 mCause = new Throwable(stack); 169 } 170 171 @Override 172 public String toString() { 173 JSONObject tags = new JSONObject(); 174 try { 175 if (mCause != null) { 176 StringWriter sw = new StringWriter(); 177 PrintWriter pw = new PrintWriter(sw); 178 mCause.printStackTrace(pw); 179 tags.put(CAUSE_KEY, sw.toString()); 180 } 181 } catch (JSONException e) { 182 CLog.e(e); 183 } 184 return tags.toString(); 185 } 186 } 187 188 /** Base Helper for TestIgnored information. */ 189 public static class BaseTestEventInfo { 190 public String mClassName = null; 191 public String mTestName = null; 192 193 public BaseTestEventInfo(String className, String testName) { 194 mClassName = className; 195 mTestName = testName; 196 } 197 198 public BaseTestEventInfo(JSONObject jsonObject) throws JSONException { 199 mClassName = jsonObject.getString(CLASSNAME_KEY); 200 jsonObject.remove(CLASSNAME_KEY); 201 mTestName = jsonObject.getString(TESTNAME_KEY); 202 jsonObject.remove(TESTNAME_KEY); 203 } 204 205 protected JSONObject getNewJson() { 206 return new JSONObject(); 207 } 208 209 @Override 210 public String toString() { 211 JSONObject tags = null; 212 try { 213 tags = getNewJson(); 214 if (mClassName != null) { 215 tags.put(CLASSNAME_KEY, mClassName); 216 } 217 if (mTestName != null) { 218 tags.put(TESTNAME_KEY, mTestName); 219 } 220 } catch (JSONException e) { 221 CLog.e(e); 222 } 223 return tags.toString(); 224 } 225 } 226 227 /** Helper for testStarted information */ 228 public static class TestStartedEventInfo extends BaseTestEventInfo { 229 public Long mStartTime = null; 230 231 public TestStartedEventInfo(String className, String testName, Long startTime) { 232 super(className, testName); 233 mStartTime = startTime; 234 } 235 236 public TestStartedEventInfo(JSONObject jsonObject) throws JSONException { 237 super(jsonObject); 238 if (jsonObject.has(START_TIME)) { 239 mStartTime = jsonObject.getLong(START_TIME); 240 } 241 jsonObject.remove(START_TIME); 242 } 243 244 @Override 245 protected JSONObject getNewJson() { 246 JSONObject json = new JSONObject(); 247 try { 248 json.put(START_TIME, mStartTime); 249 } catch (JSONException e) { 250 CLog.e(e); 251 } 252 return json; 253 } 254 } 255 256 /** Helper for testFailed information. */ 257 public static class FailedTestEventInfo extends BaseTestEventInfo { 258 public String mTrace = null; 259 260 public FailedTestEventInfo(String className, String testName, String trace) { 261 super(className, testName); 262 mTrace = trace; 263 } 264 265 public FailedTestEventInfo(JSONObject jsonObject) throws JSONException { 266 super(jsonObject); 267 mTrace = jsonObject.getString(TRACE_KEY); 268 } 269 270 @Override 271 public String toString() { 272 JSONObject tags = null; 273 try { 274 tags = new JSONObject(super.toString()); 275 if (mTrace != null) { 276 tags.put(TRACE_KEY, mTrace); 277 } 278 } catch (JSONException e) { 279 CLog.e(e); 280 } 281 return tags.toString(); 282 } 283 } 284 285 /** 286 * Helper for testEnded information. 287 */ 288 public static class TestEndedEventInfo extends BaseTestEventInfo { 289 public Map<String, String> mRunMetrics = null; 290 public Long mEndTime = null; 291 292 public TestEndedEventInfo(String className, String testName, 293 Map<String, String> runMetrics) { 294 super(className, testName); 295 mRunMetrics = runMetrics; 296 mEndTime = System.currentTimeMillis(); 297 } 298 299 /** 300 * Create an event object to represent the testEnded callback. 301 * 302 * @param className the classname of the tests 303 * @param testName the name of the tests 304 * @param endTime the timestamp at which the test ended (from {@link 305 * System#currentTimeMillis()}) 306 * @param runMetrics the metrics reported by the test. 307 */ 308 public TestEndedEventInfo( 309 String className, String testName, Long endTime, Map<String, String> runMetrics) { 310 super(className, testName); 311 mEndTime = endTime; 312 mRunMetrics = runMetrics; 313 } 314 315 /** Create and populate and event object for testEnded from a JSON. */ 316 public TestEndedEventInfo(JSONObject jsonObject) throws JSONException { 317 super(jsonObject); 318 if (jsonObject.has(END_TIME)) { 319 mEndTime = jsonObject.getLong(END_TIME); 320 } 321 jsonObject.remove(END_TIME); 322 Iterator<?> i = jsonObject.keys(); 323 mRunMetrics = new HashMap<String, String>(); 324 while(i.hasNext()) { 325 String key = (String) i.next(); 326 mRunMetrics.put(key, jsonObject.get(key).toString()); 327 } 328 } 329 330 @Override 331 protected JSONObject getNewJson() { 332 JSONObject json; 333 if (mRunMetrics != null) { 334 json = new JSONObject(mRunMetrics); 335 } else { 336 json = new JSONObject(); 337 } 338 try { 339 json.put(END_TIME, mEndTime); 340 } catch (JSONException e) { 341 CLog.e(e); 342 } 343 return json; 344 } 345 } 346 347 /** Helper for testLog information. */ 348 public static class TestLogEventInfo { 349 public String mDataName = null; 350 public LogDataType mLogType = null; 351 public File mDataFile = null; 352 353 public TestLogEventInfo(String dataName, LogDataType dataType, File dataFile) { 354 mDataName = dataName; 355 mLogType = dataType; 356 mDataFile = dataFile; 357 } 358 359 public TestLogEventInfo(JSONObject jsonObject) throws JSONException { 360 mDataName = jsonObject.getString(DATA_NAME_KEY); 361 jsonObject.remove(DATA_NAME_KEY); 362 mLogType = LogDataType.valueOf(jsonObject.getString(DATA_TYPE_KEY)); 363 jsonObject.remove(DATA_TYPE_KEY); 364 mDataFile = new File(jsonObject.getString(DATA_FILE_KEY)); 365 } 366 367 @Override 368 public String toString() { 369 JSONObject tags = null; 370 try { 371 tags = new JSONObject(); 372 if (mDataName != null) { 373 tags.put(DATA_NAME_KEY, mDataName); 374 } 375 if (mLogType != null) { 376 tags.put(DATA_TYPE_KEY, mLogType.toString()); 377 } 378 if (mDataFile != null) { 379 tags.put(DATA_FILE_KEY, mDataFile.getAbsolutePath()); 380 } 381 } catch (JSONException e) { 382 CLog.e(e); 383 } 384 return tags.toString(); 385 } 386 } 387 388 /** Helper for invocation started information. */ 389 public static class InvocationStartedEventInfo { 390 public String mTestTag = null; 391 public Long mStartTime = null; 392 393 public InvocationStartedEventInfo(String testTag, Long startTime) { 394 mTestTag = testTag; 395 mStartTime = startTime; 396 } 397 398 public InvocationStartedEventInfo(JSONObject jsonObject) throws JSONException { 399 mTestTag = jsonObject.getString(TEST_TAG_KEY); 400 if (jsonObject.has(START_TIME)) { 401 mStartTime = jsonObject.getLong(START_TIME); 402 } 403 } 404 405 @Override 406 public String toString() { 407 JSONObject tags = null; 408 try { 409 tags = new JSONObject(); 410 if (mTestTag != null) { 411 tags.put(TEST_TAG_KEY, mTestTag); 412 } 413 if (mStartTime != null) { 414 tags.put(START_TIME, mStartTime); 415 } 416 } catch (JSONException e) { 417 CLog.e(e); 418 } 419 return tags.toString(); 420 } 421 } 422 } 423