• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 
17 package com.android.cts;
18 
19 import com.android.cts.TestDevice.DeviceParameterCollector;
20 
21 import org.w3c.dom.Document;
22 import org.w3c.dom.Node;
23 import org.w3c.dom.ProcessingInstruction;
24 
25 import java.io.File;
26 import java.net.InetAddress;
27 import java.net.UnknownHostException;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Date;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 
34 import javax.xml.parsers.DocumentBuilderFactory;
35 
36 /**
37  * Store the information of a test plan.
38  */
39 public class TestSessionLog extends XMLResourceHandler {
40     private static final String EXPR_TEST_FAILED = ".+\\((\\S+):(\\d+)\\)";
41     private static Pattern mTestFailedPattern = Pattern.compile(EXPR_TEST_FAILED);
42     private static final String ATTRIBUTE_NAME = "name";
43     static final String ATTRIBUTE_RESULT = "result";
44     private static final String ATTRIBUTE_VERSION = "version";
45     private static final String ATTRIBUTE_DIGEST = "digest";
46     private static final String ATTRIBUTE_KNOWN_FAILURE = "KnownFailure";
47 
48     public static final String CTS_RESULT_FILE_NAME = "testResult.xml";
49     private static final String CTS_RESULT_FILE_VERSION = "1.2";
50 
51     static final String ATTRIBUTE_STARTTIME = "starttime";
52     static final String ATTRIBUTE_ENDTIME = "endtime";
53     static final String ATTRIBUTE_TESTPLAN = "testPlan";
54     static final String ATTRIBUTE_RESOLUTION = "resolution";
55     static final String ATTRIBUTE_SUBSCRIBER_ID = "subscriberId";
56     static final String ATTRIBUTE_DEVICE_ID = "deviceID";
57     static final String ATTRIBUTE_BUILD_ID = "buildID";
58     static final String ATTRIBUTE_BUILD_VERSION = "buildVersion";
59     static final String ATTRIBUTE_ANDROID_PLATFORM_VERSION = "androidPlatformVersion";
60     static final String ATTRIBUTE_LOCALES = "locales";
61     static final String ATTRIBUTE_XDPI = "Xdpi";
62     static final String ATTRIBUTE_YDPI = "Ydpi";
63     static final String ATTRIBUTE_TOUCH = "touch";
64     static final String ATTRIBUTE_NAVIGATION = "navigation";
65     static final String ATTRIBUTE_KEYPAD = "keypad";
66     static final String ATTRIBUTE_NETWORK = "network";
67     static final String ATTRIBUTE_IMEI = "imei";
68     static final String ATTRIBUTE_IMSI = "imsi";
69     static final String ATTRIBUTE_BUILD_NAME = "buildName";
70     static final String ATTRIBUTE_ARCH = "arch";
71     static final String ATTRIBUTE_VALUE = "value";
72 
73     static final String ATTRIBUTE_PASS = "pass";
74     static final String ATTRIBUTE_FAILED = "failed";
75     static final String ATTRIBUTE_TIMEOUT = "timeout";
76     static final String ATTRIBUTE_NOT_EXECUTED = "notExecuted";
77 
78     static final String TAG_DEVICEINFO = "DeviceInfo";
79     static final String TAG_HOSTINFO = "HostInfo";
80     static final String TAG_OSINFO = "Os";
81     static final String TAG_JAVA = "Java";
82     static final String TAG_CTS = "Cts";
83     static final String TAG_INTVALUE = "IntValue";
84     static final String TAG_SUMMARY = "Summary";
85     static final String TAG_SCREEN = "Screen";
86     static final String TAG_BUILD_INFO = "BuildInfo";
87     static final String TAG_PHONE_SUB_INFO = "PhoneSubInfo";
88     static final String TAG_TEST_RESULT = "TestResult";
89     static final String TAG_TESTPACKAGE = "TestPackage";
90     static final String TAG_TESTSUITE = "TestSuite";
91     static final String TAG_TESTCASE = "TestCase";
92     static final String TAG_FAILED_SCENE = "FailedScene";
93     static final String TAG_STACK_TRACE = "StackTrace";
94     static final String TAG_FAILED_MESSAGE = "message";
95 
96     private Collection<TestPackage> mTestPackages;
97     private Date mSessionStartTime;
98     private Date mSessionEndTime;
99     private String mResultPath;
100     private String mResultDir;
101     private String mTestPlanName;
102 
103     private ArrayList<DeviceParameterCollector> mDeviceParameterBase;
104 
TestSessionLog(final Collection<TestPackage> packages, final String testPlanName)105     public TestSessionLog(final Collection<TestPackage> packages, final String testPlanName) {
106         mTestPackages = packages;
107 
108         mDeviceParameterBase = new ArrayList<TestDevice.DeviceParameterCollector>();
109         mTestPlanName = testPlanName;
110 
111         mSessionStartTime = new Date();
112         mSessionEndTime = new Date();
113     }
114 
115     /**
116      * Get the test plan name.
117      *
118      * @return The test plan name.
119      */
getTestPlanName()120     public String getTestPlanName() {
121         return mTestPlanName;
122     }
123 
124     /**
125      * Get all result of this session.
126      *
127      * @return All the tests with a result code of this session.
128      */
getAllResults()129     public Collection<Test> getAllResults() {
130         if (mTestPackages == null || mTestPackages.size() == 0) {
131             return null;
132         }
133 
134         ArrayList<Test> results = new ArrayList<Test>();
135         for (TestPackage p : mTestPackages) {
136             results.addAll(p.getTests());
137         }
138 
139         return results;
140     }
141 
142     /**
143      * Get test list according to the result type code.
144      *
145      * @param resCode The result code.
146      * @return The list of {@link Test}.
147      */
getTestList(int resCode)148     public Collection<Test> getTestList(int resCode) {
149         if ((resCode < CtsTestResult.CODE_FIRST)
150                 || (resCode > CtsTestResult.CODE_LAST)) {
151             return null;
152         }
153 
154         ArrayList<Test> tests = new ArrayList<Test>();
155         for (Test test : getAllResults()) {
156             if (resCode == test.getResult().getResultCode()) {
157                 tests.add(test);
158             }
159         }
160 
161         return tests;
162     }
163 
164     /**
165      * Get TestSession start time
166      *
167      * @return The start time.
168      */
getStartTime()169     public Date getStartTime() {
170         return mSessionStartTime;
171     }
172 
173     /**
174      * Get TestSession end time
175      *
176      * @return The end time.
177      */
getEndTime()178     public Date getEndTime() {
179         return mSessionEndTime;
180     }
181 
182     /**
183      * Get test packages.
184      *
185      * @return The test packages.
186      */
getTestPackages()187     public Collection<TestPackage> getTestPackages() {
188         return mTestPackages;
189     }
190 
191     /**
192      * Get the path to the XML result file.
193      *
194      * @return The result path.
195      */
getResultPath()196     public String getResultPath() {
197         return mResultPath;
198     }
199 
200     /**
201      * Get the result directory.  This is the directory that all result files
202      * should go into.
203      */
getResultDir()204     public String getResultDir() {
205         return mResultDir;
206     }
207 
208     /**
209      * set TestSession start time
210      *
211      * @param time The start time.
212      */
setStartTime(final long time)213     public void setStartTime(final long time) {
214         mSessionStartTime.setTime(time);
215 
216         String startTimeStr = HostUtils.getFormattedTimeString(time, "_", ".", ".");
217         mResultDir = HostConfig.getInstance().getResultRepository().getRoot()
218             + File.separator + startTimeStr;
219         mResultPath =  mResultDir + File.separator + CTS_RESULT_FILE_NAME;
220         // Make sure the result directory exists
221         new File(mResultDir).mkdirs();
222     }
223 
224     /**
225      * set TestSession end time
226      *
227      * @param time The end time.
228      */
setEndTime(final long time)229     public void setEndTime(final long time) {
230         mSessionEndTime.setTime(time);
231     }
232 
233     /**
234      * Calling this functions indicates that the TestSession is complete.  This
235      * indicates to the TestSessionLog that it is time to store the results
236      * to the filesystem.
237      */
sessionComplete()238     public void sessionComplete() {
239         try {
240             writeToFile(new File(mResultPath), createResultDoc());
241             // Now zip up the results directory so we have something nice
242             // that people can upload.
243             HostUtils.zipUpDirectory(mResultDir,
244                     mResultDir + ".zip",
245                     new HostUtils.ZipFilenameTransformer() {
246                         public String transform(String filename) {
247                             if (filename.startsWith(mResultDir)) {
248                                 return filename.substring(mResultDir.length() + 1);
249                             }
250                             return filename;
251                         }
252             });
253         } catch (Exception e) {
254             Log.e("Got exception when trying to write to result file", e);
255         }
256         HostConfig.getInstance().extractResultResources(mResultDir);
257     }
258 
259     /**
260      * Create result Doc in XML format.
261      *
262      * @return Result document.
263      */
createResultDoc()264     protected Document createResultDoc() {
265         try {
266 
267             Document doc = DocumentBuilderFactory.newInstance()
268                     .newDocumentBuilder().newDocument();
269             ProcessingInstruction pr = doc.createProcessingInstruction(
270                     "xml-stylesheet", "type=\"text/xsl\"  href=\"cts_result.xsl\"");
271             doc.appendChild(pr);
272             Node root = doc.createElement(TAG_TEST_RESULT);
273             doc.appendChild(root);
274 
275             setAttribute(doc, root, ATTRIBUTE_VERSION, CTS_RESULT_FILE_VERSION);
276             setAttribute(doc, root, ATTRIBUTE_STARTTIME, HostUtils.dateToString(mSessionStartTime));
277             setAttribute(doc, root, ATTRIBUTE_ENDTIME, HostUtils.dateToString(mSessionEndTime));
278             setAttribute(doc, root, ATTRIBUTE_TESTPLAN, mTestPlanName);
279 
280             // set device information
281             for (int i = 0; i < mDeviceParameterBase.size(); i ++) {
282                 DeviceParameterCollector bldInfo = mDeviceParameterBase.get(i);
283                 // set device setting
284                 Node deviceSettingNode = doc.createElement(TAG_DEVICEINFO);
285 
286                 Node screenNode = doc.createElement(TAG_SCREEN);
287                 setAttribute(doc, screenNode, ATTRIBUTE_RESOLUTION, bldInfo.getScreenResolution());
288                 deviceSettingNode.appendChild(screenNode);
289                 Node simCardNode = doc.createElement(TAG_PHONE_SUB_INFO);
290                 setAttribute(doc, simCardNode, ATTRIBUTE_SUBSCRIBER_ID, bldInfo.getPhoneNumber());
291                 deviceSettingNode.appendChild(simCardNode);
292                 root.appendChild(deviceSettingNode);
293 
294                 Node devInfoNode = doc.createElement(TAG_BUILD_INFO);
295                 setAttribute(doc, devInfoNode, ATTRIBUTE_DEVICE_ID, bldInfo.getSerialNumber());
296                 setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_ID, bldInfo.getBuildId());
297                 setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_NAME, bldInfo.getProductName());
298                 setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_VERSION,
299                              bldInfo.getBuildVersion());
300                 setAttribute(doc, devInfoNode, ATTRIBUTE_ANDROID_PLATFORM_VERSION,
301                              bldInfo.getAndroidPlatformVersion());
302                 setAttribute(doc, devInfoNode, ATTRIBUTE_LOCALES, bldInfo.getLocales());
303                 setAttribute(doc, devInfoNode, ATTRIBUTE_XDPI, bldInfo.getXdpi());
304                 setAttribute(doc, devInfoNode, ATTRIBUTE_YDPI, bldInfo.getYdpi());
305                 setAttribute(doc, devInfoNode, ATTRIBUTE_TOUCH, bldInfo.getTouchInfo());
306                 setAttribute(doc, devInfoNode, ATTRIBUTE_NAVIGATION, bldInfo.getNavigation());
307                 setAttribute(doc, devInfoNode, ATTRIBUTE_KEYPAD, bldInfo.getKeypad());
308                 setAttribute(doc, devInfoNode, ATTRIBUTE_NETWORK, bldInfo.getNetwork());
309                 setAttribute(doc, devInfoNode, ATTRIBUTE_IMEI, bldInfo.getIMEI());
310                 setAttribute(doc, devInfoNode, ATTRIBUTE_IMSI, bldInfo.getIMSI());
311 
312                 setAttribute(doc, devInfoNode,
313                         DeviceParameterCollector.BUILD_FINGERPRINT, bldInfo.getBuildFingerPrint());
314                 setAttribute(doc, devInfoNode,
315                         DeviceParameterCollector.BUILD_TYPE, bldInfo.getBuildType());
316                 setAttribute(doc, devInfoNode,
317                         DeviceParameterCollector.BUILD_MODEL, bldInfo.getBuildModel());
318                 setAttribute(doc, devInfoNode,
319                         DeviceParameterCollector.BUILD_BRAND, bldInfo.getBuildBrand());
320                 setAttribute(doc, devInfoNode,
321                         DeviceParameterCollector.BUILD_BOARD, bldInfo.getBuildBoard());
322                 setAttribute(doc, devInfoNode,
323                         DeviceParameterCollector.BUILD_DEVICE, bldInfo.getBuildDevice());
324 
325                 deviceSettingNode.appendChild(devInfoNode);
326             }
327 
328             Node hostInfo = doc.createElement(TAG_HOSTINFO);
329             root.appendChild(hostInfo);
330             String hostName = "";
331             try {
332                 hostName = InetAddress.getLocalHost().getHostName();
333             } catch (UnknownHostException ignored) {}
334             setAttribute(doc, hostInfo, ATTRIBUTE_NAME, hostName);
335             Node osInfo = doc.createElement(TAG_OSINFO);
336             hostInfo.appendChild(osInfo);
337             setAttribute(doc, osInfo, ATTRIBUTE_NAME, System.getProperty("os.name"));
338             setAttribute(doc, osInfo, ATTRIBUTE_VERSION, System.getProperty("os.version"));
339             setAttribute(doc, osInfo, ATTRIBUTE_ARCH, System.getProperty("os.arch"));
340             Node javaInfo = doc.createElement(TAG_JAVA);
341             hostInfo.appendChild(javaInfo);
342             setAttribute(doc, javaInfo, ATTRIBUTE_NAME, System.getProperty("java.vendor"));
343             setAttribute(doc, javaInfo, ATTRIBUTE_VERSION, System.getProperty("java.version"));
344             Node ctsInfo = doc.createElement(TAG_CTS);
345             hostInfo.appendChild(ctsInfo);
346             setAttribute(doc, ctsInfo, ATTRIBUTE_VERSION, Version.asString());
347             for (HostConfig.Ints i : HostConfig.Ints.values()) {
348                 Node intValue = doc.createElement(TAG_INTVALUE);
349                 ctsInfo.appendChild(intValue);
350                 setAttribute(doc, intValue, ATTRIBUTE_NAME, i.name());
351                 setAttribute(doc, intValue, ATTRIBUTE_VALUE, i.value());
352             }
353 
354             int passNum = getTestList(CtsTestResult.CODE_PASS).size();
355             int failNum = getTestList(CtsTestResult.CODE_FAIL).size();
356             int notExecutedNum = getTestList(CtsTestResult.CODE_NOT_EXECUTED).size();
357             int timeOutNum = getTestList(CtsTestResult.CODE_TIMEOUT).size();
358             Node summaryNode = doc.createElement(TAG_SUMMARY);
359             root.appendChild(summaryNode);
360             setAttribute(doc, summaryNode, ATTRIBUTE_PASS, passNum);
361             setAttribute(doc, summaryNode, ATTRIBUTE_FAILED, failNum);
362             setAttribute(doc, summaryNode, ATTRIBUTE_NOT_EXECUTED, notExecutedNum);
363             setAttribute(doc, summaryNode, ATTRIBUTE_TIMEOUT, timeOutNum);
364 
365             for (TestPackage testPackage : mTestPackages) {
366                 Node testPackageNode = doc.createElement(TAG_TESTPACKAGE);
367                 setAttribute(doc, testPackageNode, ATTRIBUTE_NAME, testPackage.getAppBinaryName());
368                 setAttribute(doc, testPackageNode, TestSessionBuilder.ATTRIBUTE_APP_PACKAGE_NAME,
369                         testPackage.getAppPackageName());
370                 setAttribute(doc, testPackageNode, ATTRIBUTE_DIGEST,
371                              testPackage.getMessageDigest());
372 
373                 if (testPackage instanceof SignatureCheckPackage) {
374                     setAttribute(doc, testPackageNode,
375                               TestSessionBuilder.ATTRIBUTE_SIGNATURE_CHECK, "true");
376                 }
377 
378                 for (TestSuite testSuite : testPackage.getTestSuites()) {
379                     outputTestSuite(doc, testPackage, testPackageNode, testSuite);
380                 }
381                 root.appendChild(testPackageNode);
382             }
383 
384             return doc;
385         } catch (Exception e) {
386             Log.e("create result doc failed", e);
387         }
388         return null;
389     }
390 
391     /**
392      * Output TestSuite and result to XML DOM Document.
393      *
394      * @param doc The document.
395      * @param parentNode The parent node.
396      * @param testSuite The test suite.
397      */
outputTestSuite(final Document doc, final TestPackage testPackage, final Node parentNode, TestSuite testSuite)398     private void outputTestSuite(final Document doc,
399             final TestPackage testPackage, final Node parentNode,
400             TestSuite testSuite) {
401 
402         Collection<TestSuite> subSuites = testSuite.getSubSuites();
403         Collection<TestCase> testCases = testSuite.getTestCases();
404 
405         Node testSuiteNode = doc.createElement(TAG_TESTSUITE);
406         setAttribute(doc, testSuiteNode, ATTRIBUTE_NAME, testSuite.getName());
407 
408         for (TestCase testCase : testCases) {
409             Node testCaseNode = doc.createElement(TAG_TESTCASE);
410             testSuiteNode.appendChild(testCaseNode);
411             setAttribute(doc, testCaseNode, ATTRIBUTE_NAME, testCase.getName());
412             setAttribute(doc, testCaseNode, TestSessionBuilder.ATTRIBUTE_PRIORITY,
413                     testCase.getPriority());
414 
415             Collection<Test> tests = testCase.getTests();
416             for (Test test : tests) {
417                 Node testNode = doc.createElement(TestSessionBuilder.TAG_TEST);
418                 testCaseNode.appendChild(testNode);
419 
420                 if (test.isKnownFailure()) {
421                     setAttribute(doc, testNode, ATTRIBUTE_KNOWN_FAILURE, test.getKnownFailure());
422                 }
423 
424                 CtsTestResult result = test.getResult();
425                 setAttribute(doc, testNode, ATTRIBUTE_NAME, test.getName());
426                 setAttribute(doc, testNode, ATTRIBUTE_RESULT, result.getResultString());
427                 setAttribute(doc, testNode, ATTRIBUTE_STARTTIME,
428                              new Date(test.getStartTime()).toString());
429                 setAttribute(doc, testNode, ATTRIBUTE_ENDTIME,
430                              new Date(test.getEndTime()).toString());
431 
432                 String failedMessage = result.getFailedMessage();
433 
434                 if (failedMessage != null) {
435                     // failure message may contain control characters < 0x20 that get translated
436                     // into illegal XML character entities. Replace them first.
437                     failedMessage = HostUtils.replaceControlChars(failedMessage);
438                     Node failedMessageNode = doc.createElement(TAG_FAILED_SCENE);
439                     testNode.appendChild(failedMessageNode);
440                     setAttribute(doc, failedMessageNode,TAG_FAILED_MESSAGE, failedMessage);
441 
442                     String stackTrace = result.getStackTrace();
443                     if (stackTrace != null) {
444                         Node stackTraceNode = doc.createElement(TAG_STACK_TRACE);
445                         failedMessageNode.appendChild(stackTraceNode);
446                         Node stackTraceTextNode = doc.createTextNode(stackTrace);
447                         stackTraceNode.appendChild(stackTraceTextNode);
448                     }
449                 }
450             }
451         }
452 
453         for (TestSuite subSuite : subSuites) {
454             outputTestSuite(doc, testPackage, testSuiteNode, subSuite);
455             parentNode.appendChild(testSuiteNode);
456         }
457         parentNode.appendChild(testSuiteNode);
458     }
459 
460     /**
461      * Fetch failed file name and line number
462      *
463      * @param failedResult failed message
464      * @return failed file name and line number
465      */
getFailedLineNumber(final String failedResult)466     public final static String[] getFailedLineNumber(final String failedResult) {
467         Matcher m = mTestFailedPattern.matcher(failedResult);
468         if (m.matches()) {
469             return new String[]{m.group(1), m.group(2)};
470         }
471         return null;
472     }
473 
474     /**
475      * set the device information of a specific device
476      *
477      * @param dInfo The device information.
478      */
setDeviceInfo(final TestDevice.DeviceParameterCollector dInfo)479     public void setDeviceInfo(final TestDevice.DeviceParameterCollector dInfo) {
480         for (DeviceParameterCollector collector : mDeviceParameterBase) {
481             if (collector.getSerialNumber().equals(dInfo.getSerialNumber())) {
482                 //if there has information for the device with given serial number,
483                 //replace it with the new information.
484                 mDeviceParameterBase.remove(collector);
485                 break;
486             }
487         }
488         mDeviceParameterBase.add(dInfo);
489     }
490 }
491