• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.dumprendertree2;
18 
19 import android.os.Bundle;
20 import android.os.Handler;
21 import android.os.Message;
22 import android.webkit.WebView;
23 
24 import name.fraser.neil.plaintext.diff_match_patch;
25 
26 import 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  */
34 public 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 
TextResult(String relativePath)58     public TextResult(String relativePath) {
59         mRelativePath = relativePath;
60     }
61 
setDumpChildFramesAsText(boolean dumpChildFramesAsText)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      */
TextResult(Bundle bundle)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
clearResults()82     public void clearResults() {
83         super.clearResults();
84         mExpectedResult = null;
85         mActualResult = null;
86     }
87 
88     @Override
getResultCode()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 
resultsMatch()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
didCrash()111     public boolean didCrash() {
112         return false;
113     }
114 
115     @Override
didTimeOut()116     public boolean didTimeOut() {
117         return mDidTimeOut;
118     }
119 
120     @Override
setDidTimeOut()121     public void setDidTimeOut() {
122         mDidTimeOut = true;
123     }
124 
125     @Override
getActualImageResult()126     public byte[] getActualImageResult() {
127         return null;
128     }
129 
130     @Override
getActualTextResult()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
setExpectedImageResult(byte[] expectedResult)141     public void setExpectedImageResult(byte[] expectedResult) {
142         /** This method is not applicable to this type of result */
143     }
144 
145     @Override
setExpectedImageResultPath(String relativePath)146     public void setExpectedImageResultPath(String relativePath) {
147         /** This method is not applicable to this type of result */
148     }
149 
150     @Override
getExpectedImageResultPath()151     public String getExpectedImageResultPath() {
152         /** This method is not applicable to this type of result */
153         return null;
154     }
155 
156     @Override
setExpectedTextResultPath(String relativePath)157     public void setExpectedTextResultPath(String relativePath) {
158         mExpectedResultPath = relativePath;
159     }
160 
161     @Override
getExpectedTextResultPath()162     public String getExpectedTextResultPath() {
163         return mExpectedResultPath;
164     }
165 
166     @Override
setExpectedTextResult(String expectedResult)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
getDiffAsHtml()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 
appendDiffHtml(StringBuilder html)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         // TODO: We should use a map for each line number and lines pair.
212         assert expectedLines.size() == expectedLineNums.size();
213         assert actualLines.size() == actualLineNums.size();
214         assert expectedLines.size() == actualLines.size();
215 
216         html.append(VisualDiffUtils.getHtml(expectedLineNums, expectedLines,
217                 actualLineNums, actualLines));
218     }
219 
220     @Override
getType()221     public TestType getType() {
222         return TestType.TEXT;
223     }
224 
225     @Override
obtainActualResults(WebView webview, Message resultObtainedMsg)226     public void obtainActualResults(WebView webview, Message resultObtainedMsg) {
227         mResultObtainedMsg = resultObtainedMsg;
228         Message msg = mHandler.obtainMessage(MSG_DOCUMENT_AS_TEXT);
229 
230         /**
231          * arg1 - should dump top frame as text
232          * arg2 - should dump child frames as text
233          */
234         msg.arg1 = 1;
235         msg.arg2 = mDumpChildFramesAsText ? 1 : 0;
236         webview.documentAsText(msg);
237     }
238 
239     @Override
getBundle()240     public Bundle getBundle() {
241         Bundle bundle = new Bundle();
242         bundle.putString("expectedTextualResult", mExpectedResult);
243         bundle.putString("expectedTextualResultPath", mExpectedResultPath);
244         bundle.putString("actualTextualResult", getActualTextResult());
245         bundle.putString("additionalTextOutputString", getAdditionalTextOutputString());
246         bundle.putString("relativePath", mRelativePath);
247         bundle.putBoolean("didTimeOut", mDidTimeOut);
248         bundle.putString("type", getType().name());
249         return bundle;
250     }
251 
252     @Override
getRelativePath()253     public String getRelativePath() {
254         return mRelativePath;
255     }
256 }
257