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