Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.base.test; | |
| 6 | |
| 7 import android.support.test.internal.runner.listener.InstrumentationRunListener; | |
| 8 | |
| 9 import org.json.JSONArray; | |
| 10 import org.json.JSONObject; | |
| 11 import org.junit.runner.Description; | |
| 12 import org.junit.runner.Result; | |
| 13 | |
| 14 import org.chromium.base.Log; | |
| 15 | |
| 16 import java.io.File; | |
| 17 import java.io.FileOutputStream; | |
| 18 import java.io.IOException; | |
| 19 import java.io.OutputStreamWriter; | |
| 20 import java.io.Writer; | |
| 21 import java.lang.annotation.Annotation; | |
| 22 import java.lang.reflect.Method; | |
| 23 import java.util.Arrays; | |
| 24 import java.util.Collection; | |
| 25 import java.util.HashMap; | |
| 26 import java.util.HashSet; | |
| 27 import java.util.LinkedList; | |
| 28 import java.util.List; | |
| 29 import java.util.Map; | |
| 30 import java.util.Set; | |
| 31 | |
| 32 /** | |
| 33 * A RunListener that list out all the test information into a json file. | |
| 34 */ | |
| 35 public class TestListInstrumentationRunListener extends InstrumentationRunListen er { | |
| 36 private static final String TAG = "TestListRunListener"; | |
| 37 private static final Set<String> SKIP_METHODS = new HashSet<>( | |
| 38 Arrays.asList(new String[] {"toString", "hashCode", "annotationType" , "equals"})); | |
| 39 | |
| 40 private final Map<Class<?>, List<JSONObject>> mTestClassJSONObjects = new Ha shMap<>(); | |
|
mikecase (-- gone --)
2017/07/19 17:11:01
why not JSONArray instead of List<JSONObject>?
the real yoland
2017/07/20 02:04:32
I think this was done for perf reasons, but I don'
| |
| 41 private final String mOutputPath; | |
| 42 | |
| 43 public TestListInstrumentationRunListener(String outputPath) { | |
| 44 super(); | |
| 45 mOutputPath = outputPath; | |
| 46 } | |
| 47 | |
| 48 /** | |
| 49 * Store the test method description to a Map at the beginning of a test run . | |
| 50 */ | |
| 51 @Override | |
| 52 public void testStarted(Description desc) throws Exception { | |
| 53 if (!mTestClassJSONObjects.containsKey(desc.getTestClass())) { | |
| 54 mTestClassJSONObjects.put(desc.getTestClass(), new LinkedList<JSONOb ject>()); | |
| 55 } | |
| 56 mTestClassJSONObjects.get(desc.getTestClass()).add(getTestMethodJSON(des c)); | |
|
mikecase (-- gone --)
2017/07/19 17:11:01
I thought this was kinda confusing the way the cod
the real yoland
2017/07/20 02:04:33
Done
| |
| 57 } | |
| 58 | |
| 59 /** | |
| 60 * Create a JSONArray with all the test class JSONObjects and save it to lis ted output path. | |
| 61 */ | |
| 62 @Override | |
| 63 public void testRunFinished(Result result) throws Exception { | |
| 64 List<JSONObject> allTestClasses = new LinkedList<>(); | |
|
mikecase (-- gone --)
2017/07/19 17:11:01
Could this just be a JSONArray instead of creating
the real yoland
2017/07/20 02:04:33
Done
| |
| 65 for (Map.Entry<Class<?>, List<JSONObject>> entry : mTestClassJSONObjects .entrySet()) { | |
| 66 Class<?> testClass = entry.getKey(); | |
| 67 JSONObject classObject = | |
| 68 new JSONObject() | |
| 69 .put("class", testClass.getName()) | |
| 70 .put("superclass", testClass.getSuperclass().getName ()) | |
| 71 .put("annotations", | |
| 72 getAnnotationJSON(Arrays.asList(testClass.ge tAnnotations()))) | |
| 73 .put("methods", new JSONArray(entry.getValue())); | |
| 74 allTestClasses.add(classObject); | |
|
mikecase (-- gone --)
2017/07/19 17:11:01
As mentioned, I think the code would be more nicel
jbudorick
2017/07/19 20:43:34
w/ this suggestion, testRunFinished would just be
the real yoland
2017/07/20 02:04:32
Done
the real yoland
2017/07/20 02:04:33
Done
| |
| 75 } | |
| 76 Writer writer = null; | |
| 77 File file = new File(mOutputPath); | |
| 78 try { | |
| 79 writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8") ; | |
| 80 JSONArray allTestClassesJSON = new JSONArray(allTestClasses); | |
| 81 writer.write(allTestClassesJSON.toString()); | |
| 82 } catch (Exception e) { | |
| 83 Log.e(TAG, "failed to write json to file", e); | |
| 84 } finally { | |
| 85 if (writer != null) { | |
| 86 try { | |
| 87 writer.close(); | |
| 88 } catch (IOException e) { | |
| 89 } | |
| 90 } | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 /** | |
| 95 * Return a JSONOject that represent a Description of a method". | |
| 96 */ | |
| 97 static JSONObject getTestMethodJSON(Description desc) throws Exception { | |
| 98 return new JSONObject() | |
| 99 .put("method", desc.getMethodName()) | |
| 100 .put("annotations", getAnnotationJSON(desc.getAnnotations())); | |
| 101 } | |
| 102 | |
| 103 /** | |
| 104 * Create a JSONObject that represent a collection of anntations. | |
| 105 * | |
| 106 * For example, for the following group of annotations for ExampleClass | |
| 107 * <code> | |
| 108 * @A | |
| 109 * @B(message = "hello", level = 3) | |
| 110 * public class ExampleClass() {} | |
| 111 * </code> | |
| 112 * | |
| 113 * This method would return a JSONObject as such: | |
| 114 * <code> | |
| 115 * { | |
| 116 * "A": {}, | |
| 117 * "B": { | |
| 118 * "message": "hello", | |
| 119 * "level": "3" | |
| 120 * } | |
| 121 * } | |
| 122 * </code> | |
| 123 * | |
| 124 * The method accomplish this by though through each annotation and reflecti vely call the | |
| 125 * annotation's method to get the element value, with exceptions to methods like "equals()" | |
| 126 * or "hashCode". | |
| 127 */ | |
| 128 static JSONObject getAnnotationJSON(Collection<Annotation> annotations) | |
| 129 throws Exception { | |
| 130 JSONObject annotationsJsons = new JSONObject(); | |
| 131 for (Annotation a : annotations) { | |
| 132 JSONObject elementJsonObject = new JSONObject(); | |
| 133 for (Method method : a.annotationType().getMethods()) { | |
| 134 if (SKIP_METHODS.contains(method.getName())) { | |
| 135 continue; | |
| 136 } | |
| 137 try { | |
| 138 Object value = method.invoke(a); | |
| 139 if (value == null) { | |
| 140 elementJsonObject.put(method.getName(), null); | |
| 141 } else { | |
| 142 elementJsonObject.put(method.getName(), | |
| 143 value.getClass().isArray() | |
| 144 ? new JSONArray(Arrays.asList((Object[]) value)) | |
| 145 : value.toString()); | |
| 146 } | |
| 147 } catch (IllegalArgumentException e) { | |
| 148 } | |
| 149 } | |
| 150 annotationsJsons.put(a.annotationType().getSimpleName(), elementJson Object); | |
| 151 } | |
| 152 return annotationsJsons; | |
| 153 } | |
| 154 } | |
| OLD | NEW |