Summarizer.java revision 5f0ccd76a88586ce85c17cb4db058934e693a4fc
1/*
2 * Copyright (C) 2010 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
17package com.android.dumprendertree2;
18
19import java.io.File;
20import java.util.EnumMap;
21import java.util.HashSet;
22import java.util.LinkedList;
23import java.util.Map;
24import java.util.Set;
25
26/**
27 * A class that collects information about tests that ran and can create HTML
28 * files with summaries and easy navigation.
29 */
30public class Summarizer {
31
32    private static final String LOG_TAG = "Summarizer";
33
34    private static final String CSS =
35            "* {" +
36            "       font-family: Verdana;" +
37            "       border: 0;" +
38            "       margin: 0;" +
39            "       padding: 0;}" +
40            "body {" +
41            "       margin: 10px;}" +
42            "a {" +
43            "       font-size: 12px;" +
44            "       color: black;}" +
45            "h1 {" +
46            "       font-size: 33px;" +
47            "       margin: 4px 0 4px 0;}" +
48            "h2 {" +
49            "       font-size:22px;" +
50            "       margin: 20px 0 3px 0;}" +
51            "h3 {" +
52            "       font-size: 20px;" +
53            "       margin-bottom: 6px;}" +
54            "table.visual_diff {" +
55            "       border-bottom: 0px solid;" +
56            "       border-collapse: collapse;" +
57            "       width: 100%;" +
58            "       margin-bottom: 3px;}" +
59            "table.visual_diff tr.headers td {" +
60            "       border-bottom: 1px solid;" +
61            "       border-top: 0;" +
62            "       padding-bottom: 3px;}" +
63            "table.visual_diff tr.results td {" +
64            "       border-top: 1px dashed;" +
65            "       border-right: 1px solid;" +
66            "       font-size: 15px;" +
67            "       vertical-align: top;}" +
68            "table.visual_diff tr.results td.line_count {" +
69            "       background-color:#aaa;" +
70            "       min-width:20px;" +
71            "       text-align: right;" +
72            "       border-right: 1px solid;" +
73            "       border-left: 1px solid;" +
74            "       padding: 2px 1px 2px 0px;}" +
75            "table.visual_diff tr.results td.line {" +
76            "       padding: 2px 0px 2px 4px;" +
77            "       border-right: 1px solid;" +
78            "       width: 49.8%;}" +
79            "table.visual_diff tr.footers td {" +
80            "       border-top: 1px solid;" +
81            "       border-bottom: 0;}" +
82            "table.visual_diff tr td.space {" +
83            "       border: 0;" +
84            "       width: 0.4%}" +
85            "div.space {" +
86            "       margin-top:30px;}" +
87            "span.eql {" +
88            "       background-color: #f3f3f3;}" +
89            "span.del {" +
90            "       background-color: #ff8888; }" +
91            "span.ins {" +
92            "       background-color: #88ff88; }" +
93            "span.fail {" +
94            "       color: red;}" +
95            "span.pass {" +
96            "       color: green;}" +
97            "span.time_out {" +
98            "       color: orange;}";
99    private static final String HTML_DIFF_BEGINNING = "<html><head><style type=\"text/css\">" +
100            CSS + "</style></head><body>";
101    private static final String HTML_DIFF_ENDING = "</body></html>";
102
103    /** TODO: Make it a setting */
104    private static final String HTML_DIFF_RELATIVE_PATH = "_diff.html";
105    private static final String HTML_DIFF_INDEX_RELATIVE_PATH = "_diff-index.html";
106
107    /** A list containing relatives paths of tests that were skipped */
108    private LinkedList<String> mSkippedTestsList = new LinkedList<String>();
109
110    /** Collection of tests grouped according to result. Sets are initialized lazily. */
111    private Map<AbstractResult.ResultCode, Set<String>> mResults =
112            new EnumMap<AbstractResult.ResultCode, Set<String>>(AbstractResult.ResultCode.class);
113
114    /**
115     * Collection of tests for which results are ignored grouped according to result. Sets are
116     * initialized lazily.
117     */
118    private Map<AbstractResult.ResultCode, Set<String>> mResultsIgnored =
119            new EnumMap<AbstractResult.ResultCode, Set<String>>(AbstractResult.ResultCode.class);
120
121    private FileFilter mFileFilter;
122    private String mResultsRootDirPath;
123
124    public Summarizer(FileFilter fileFilter, String resultsRootDirPath) {
125        mFileFilter = fileFilter;
126        mResultsRootDirPath = resultsRootDirPath;
127        createHtmlDiff();
128    }
129
130    private void createHtmlDiff() {
131        FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_RELATIVE_PATH),
132                HTML_DIFF_BEGINNING.getBytes(), false);
133    }
134
135    private void appendHtmlDiff(String relativePath, String diff) {
136        StringBuilder html = new StringBuilder();
137        html.append("<label id=\"" + relativePath + "\" />");
138        html.append(diff);
139        html.append("<a href=\"" + HTML_DIFF_INDEX_RELATIVE_PATH + "\">Back to index</a>");
140        html.append("<div class=\"space\"></div>");
141        FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_RELATIVE_PATH),
142                html.toString().getBytes(), true);
143    }
144
145    private void finalizeHtmlDiff() {
146        FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_RELATIVE_PATH),
147                HTML_DIFF_ENDING.getBytes(), true);
148    }
149
150    /** TODO: Add settings method, like setIndexSkippedTests(), setIndexTimedOutTests(), etc */
151
152    public void addSkippedTest(String relativePath) {
153        mSkippedTestsList.addLast(relativePath);
154    }
155
156    public void appendTest(AbstractResult result) {
157        String testPath = result.getRelativePath();
158
159        AbstractResult.ResultCode resultCode = result.getResultCode();
160
161        /** Add the test to correct collection according to its result code */
162        if (mFileFilter.isIgnoreRes(testPath)) {
163            /** Lazy initialization */
164            if (mResultsIgnored.get(resultCode) == null) {
165                mResultsIgnored.put(resultCode, new HashSet<String>());
166            }
167
168            mResultsIgnored.get(resultCode).add(testPath);
169        } else {
170            /** Lazy initialization */
171            if (mResults.get(resultCode) == null) {
172                mResults.put(resultCode, new HashSet<String>());
173            }
174
175            mResults.get(resultCode).add(testPath);
176        }
177
178        if (resultCode != AbstractResult.ResultCode.PASS) {
179            appendHtmlDiff(testPath, result.getDiffAsHtml());
180        }
181    }
182
183    public void summarize() {
184        finalizeHtmlDiff();
185        createHtmlDiffIndex();
186    }
187
188    private void createHtmlDiffIndex() {
189        StringBuilder html = new StringBuilder();
190        html.append(HTML_DIFF_BEGINNING);
191        Set<String> results;
192        html.append("<h1>NOT ignored</h1>");
193        appendResultsMap(mResults, html);
194        html.append("<h1>Ignored</h1>");
195        appendResultsMap(mResultsIgnored, html);
196        html.append(HTML_DIFF_ENDING);
197        FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_INDEX_RELATIVE_PATH),
198                html.toString().getBytes(), false);
199    }
200
201    private void appendResultsMap(Map<AbstractResult.ResultCode, Set<String>> resultsMap,
202            StringBuilder html) {
203        Set<String> results;
204        for (AbstractResult.ResultCode resultCode : AbstractResult.ResultCode.values()) {
205            results = resultsMap.get(resultCode);
206            if (results != null) {
207                html.append("<h2>");
208                html.append(resultCode.toString());
209                html.append("</h2");
210                for (String relativePath : results) {
211                    html.append("<a href=\"");
212                    html.append(HTML_DIFF_RELATIVE_PATH);
213                    html.append("#");
214                    html.append(relativePath);
215                    html.append("\">");
216                    html.append(relativePath);
217                    html.append("</a><br />");
218                }
219            }
220        }
221    }
222}