TextResult.java revision fd487ad1b8d11dbc3df29b3073a0ec89f998c819
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 android.os.Bundle;
20import android.os.Handler;
21import android.os.Message;
22import android.webkit.WebView;
23
24import name.fraser.neil.plaintext.diff_match_patch;
25
26import java.util.LinkedList;
27
28/**
29 * A result object for which the expected output is text. It does not have an image
30 * expected result.
31 *
32 * <p>Created if layoutTestController.dumpAsText() was called.
33 */
34public class TextResult extends AbstractResult {
35
36    private static final int MSG_DOCUMENT_AS_TEXT = 0;
37
38    private String mExpectedResult;
39    private String mExpectedResultPath;
40    private String mActualResult;
41    private String mRelativePath;
42    private boolean mDidTimeOut;
43    private ResultCode mResultCode;
44    transient private Message mResultObtainedMsg;
45
46    private boolean mDumpChildFramesAsText;
47
48    transient private Handler mHandler = new Handler() {
49        @Override
50        public void handleMessage(Message msg) {
51            if (msg.what == MSG_DOCUMENT_AS_TEXT) {
52                mActualResult = (String)msg.obj;
53                mResultObtainedMsg.sendToTarget();
54            }
55        }
56    };
57
58    public TextResult(String relativePath) {
59        mRelativePath = relativePath;
60    }
61
62    public void setDumpChildFramesAsText(boolean dumpChildFramesAsText) {
63        mDumpChildFramesAsText = dumpChildFramesAsText;
64    }
65
66    /**
67     * Used to recreate the Result when received by the service.
68     *
69     * @param bundle
70     *      bundle with data used to recreate the result
71     */
72    public TextResult(Bundle bundle) {
73        mExpectedResult = bundle.getString("expectedTextualResult");
74        mExpectedResultPath = bundle.getString("expectedTextualResultPath");
75        mActualResult = bundle.getString("actualTextualResult");
76        setAdditionalTextOutputString(bundle.getString("additionalTextOutputString"));
77        mRelativePath = bundle.getString("relativePath");
78        mDidTimeOut = bundle.getBoolean("didTimeOut");
79    }
80
81    @Override
82    public void clearResults() {
83        super.clearResults();
84        mExpectedResult = null;
85        mActualResult = null;
86    }
87
88    @Override
89    public ResultCode getResultCode() {
90        if (mResultCode == null) {
91            mResultCode = resultsMatch() ? AbstractResult.ResultCode.RESULTS_MATCH
92                    : AbstractResult.ResultCode.RESULTS_DIFFER;
93        }
94        return mResultCode;
95    }
96
97    private boolean resultsMatch() {
98        assert mExpectedResult != null;
99        assert mActualResult != null;
100        // Trim leading and trailing empty lines, as other WebKit platforms do.
101        String leadingEmptyLines = "^\\n+";
102        String trailingEmptyLines = "\\n+$";
103        String trimmedExpectedResult = mExpectedResult.replaceFirst(leadingEmptyLines, "")
104                .replaceFirst(trailingEmptyLines, "");
105        String trimmedActualResult = mActualResult.replaceFirst(leadingEmptyLines, "")
106                .replaceFirst(trailingEmptyLines, "");
107        return trimmedExpectedResult.equals(trimmedActualResult);
108    }
109
110    @Override
111    public boolean didCrash() {
112        return false;
113    }
114
115    @Override
116    public boolean didTimeOut() {
117        return mDidTimeOut;
118    }
119
120    @Override
121    public void setDidTimeOut() {
122        mDidTimeOut = true;
123    }
124
125    @Override
126    public byte[] getActualImageResult() {
127        return null;
128    }
129
130    @Override
131    public String getActualTextResult() {
132        String additionalTextResultString = getAdditionalTextOutputString();
133        if (additionalTextResultString != null) {
134            return additionalTextResultString + mActualResult;
135        }
136
137        return mActualResult;
138    }
139
140    @Override
141    public void setExpectedImageResult(byte[] expectedResult) {
142        /** This method is not applicable to this type of result */
143    }
144
145    @Override
146    public void setExpectedImageResultPath(String relativePath) {
147        /** This method is not applicable to this type of result */
148    }
149
150    @Override
151    public String getExpectedImageResultPath() {
152        /** This method is not applicable to this type of result */
153        return null;
154    }
155
156    @Override
157    public void setExpectedTextResultPath(String relativePath) {
158        mExpectedResultPath = relativePath;
159    }
160
161    @Override
162    public String getExpectedTextResultPath() {
163        return mExpectedResultPath;
164    }
165
166    @Override
167    public void setExpectedTextResult(String expectedResult) {
168        // For text results, we use an empty string for the expected result when none is
169        // present, as other WebKit platforms do.
170        mExpectedResult = expectedResult == null ? "" : expectedResult;
171    }
172
173    @Override
174    public String getDiffAsHtml() {
175        assert mExpectedResult != null;
176        assert mActualResult != null;
177
178        StringBuilder html = new StringBuilder();
179        html.append("<table class=\"visual_diff\">");
180        html.append("    <tr class=\"headers\">");
181        html.append("        <td colspan=\"2\">Expected result:</td>");
182        html.append("        <td class=\"space\"></td>");
183        html.append("        <td colspan=\"2\">Actual result:</td>");
184        html.append("    </tr>");
185
186        appendDiffHtml(html);
187
188        html.append("    <tr class=\"footers\">");
189        html.append("        <td colspan=\"2\"></td>");
190        html.append("        <td class=\"space\"></td>");
191        html.append("        <td colspan=\"2\"></td>");
192        html.append("    </tr>");
193        html.append("</table>");
194
195        return html.toString();
196    }
197
198    private void appendDiffHtml(StringBuilder html) {
199        LinkedList<diff_match_patch.Diff> diffs =
200                new diff_match_patch().diff_main(mExpectedResult, mActualResult);
201
202        diffs = VisualDiffUtils.splitDiffsOnNewline(diffs);
203
204        LinkedList<String> expectedLines = new LinkedList<String>();
205        LinkedList<Integer> expectedLineNums = new LinkedList<Integer>();
206        LinkedList<String> actualLines = new LinkedList<String>();
207        LinkedList<Integer> actualLineNums = new LinkedList<Integer>();
208
209        VisualDiffUtils.generateExpectedResultLines(diffs, expectedLineNums, expectedLines);
210        VisualDiffUtils.generateActualResultLines(diffs, actualLineNums, actualLines);
211
212        html.append(VisualDiffUtils.getHtml(expectedLineNums, expectedLines,
213                actualLineNums, actualLines));
214    }
215
216    @Override
217    public TestType getType() {
218        return TestType.TEXT;
219    }
220
221    @Override
222    public void obtainActualResults(WebView webview, Message resultObtainedMsg) {
223        mResultObtainedMsg = resultObtainedMsg;
224        Message msg = mHandler.obtainMessage(MSG_DOCUMENT_AS_TEXT);
225
226        /**
227         * arg1 - should dump top frame as text
228         * arg2 - should dump child frames as text
229         */
230        msg.arg1 = 1;
231        msg.arg2 = mDumpChildFramesAsText ? 1 : 0;
232        webview.documentAsText(msg);
233    }
234
235    @Override
236    public Bundle getBundle() {
237        Bundle bundle = new Bundle();
238        bundle.putString("expectedTextualResult", mExpectedResult);
239        bundle.putString("expectedTextualResultPath", mExpectedResultPath);
240        bundle.putString("actualTextualResult", getActualTextResult());
241        bundle.putString("additionalTextOutputString", getAdditionalTextOutputString());
242        bundle.putString("relativePath", mRelativePath);
243        bundle.putBoolean("didTimeOut", mDidTimeOut);
244        bundle.putString("type", getType().name());
245        return bundle;
246    }
247
248    @Override
249    public String getRelativePath() {
250        return mRelativePath;
251    }
252}
253