summaryrefslogtreecommitdiffstats
path: root/tests/DumpRenderTree2/src
diff options
context:
space:
mode:
authorMaksymilian Osowski <maxosowski@google.com>2010-07-27 16:08:39 +0100
committerMaksymilian Osowski <maxosowski@google.com>2010-07-29 17:17:36 +0100
commit6d0dae6a6534a01ee4c58d4f4ee1bf115c82319c (patch)
tree3c2cc1b11b4efcf631297fe98d3e88c49b1bc996 /tests/DumpRenderTree2/src
parentd8aad91d8cdc64e00eec94a87b8dd3cc4d05c032 (diff)
downloadframeworks_base-6d0dae6a6534a01ee4c58d4f4ee1bf115c82319c.zip
frameworks_base-6d0dae6a6534a01ee4c58d4f4ee1bf115c82319c.tar.gz
frameworks_base-6d0dae6a6534a01ee4c58d4f4ee1bf115c82319c.tar.bz2
Upgraded DRT2 to generate nice HTML summaries of the tests.
Change-Id: Ibe4ee3af30fe20aeab2f3fed9c4c5693c9a0f268
Diffstat (limited to 'tests/DumpRenderTree2/src')
-rw-r--r--tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java14
-rw-r--r--tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java279
-rw-r--r--tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java89
-rw-r--r--tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java207
4 files changed, 446 insertions, 143 deletions
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
index 0a80ed4..a8c1f4c 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
@@ -24,7 +24,7 @@ import android.webkit.WebView;
* A class that represent a result of the test. It is responsible for returning the result's
* raw data and generating its own diff in HTML format.
*/
-public abstract class AbstractResult {
+public abstract class AbstractResult implements Comparable<AbstractResult> {
public enum TestType {
TEXT {
@@ -46,10 +46,10 @@ public abstract class AbstractResult {
public enum ResultCode {
PASS("Passed"),
- FAIL_RESULT_DIFFERS("Failed: different results"),
- FAIL_NO_EXPECTED_RESULT("Failed: no expected result"),
- FAIL_TIMED_OUT("Failed: timed out"),
- FAIL_CRASHED("Failed: crashed");
+ FAIL_RESULT_DIFFERS("Result differs"),
+ FAIL_NO_EXPECTED_RESULT("No expected result"),
+ FAIL_TIMED_OUT("Timed out"),
+ FAIL_CRASHED("Crashed");
private String mTitle;
@@ -63,6 +63,10 @@ public abstract class AbstractResult {
}
}
+ public int compareTo(AbstractResult another) {
+ return getRelativePath().compareTo(another.getRelativePath());
+ }
+
/**
* Makes the result object obtain the results of the test from the webview
* and store them in the format that suits itself bests. This method is asynchronous.
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
index 36cde86..fa01c74 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
@@ -17,11 +17,11 @@
package com.android.dumprendertree2;
import java.io.File;
-import java.util.EnumMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Set;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
/**
* A class that collects information about tests that ran and can create HTML
@@ -32,6 +32,7 @@ public class Summarizer {
private static final String LOG_TAG = "Summarizer";
private static final String CSS =
+ "<style type=\"text/css\">" +
"* {" +
" font-family: Verdana;" +
" border: 0;" +
@@ -39,23 +40,35 @@ public class Summarizer {
" padding: 0;}" +
"body {" +
" margin: 10px;}" +
- "a {" +
- " font-size: 12px;" +
- " color: black;}" +
"h1 {" +
- " font-size: 33px;" +
+ " font-size: 24px;" +
" margin: 4px 0 4px 0;}" +
"h2 {" +
- " font-size:22px;" +
+ " font-size:18px;" +
+ " text-transform: uppercase;" +
" margin: 20px 0 3px 0;}" +
- "h3 {" +
- " font-size: 20px;" +
- " margin-bottom: 6px;}" +
+ "h3, h3 a {" +
+ " font-size: 14px;" +
+ " color: black;" +
+ " text-decoration: none;" +
+ " margin-bottom: 4px;}" +
+ "h3 a span.path {" +
+ " text-decoration: underline;}" +
+ "h3 span.tri {" +
+ " text-decoration: none;}" +
+ "h3 img {" +
+ " width: 8px;" +
+ " margin-right: 4px;}" +
+ "div.diff {" +
+ " margin-bottom: 25px;}" +
+ "div.diff a {" +
+ " font-size: 12px;" +
+ " color: #888;}" +
"table.visual_diff {" +
" border-bottom: 0px solid;" +
" border-collapse: collapse;" +
" width: 100%;" +
- " margin-bottom: 3px;}" +
+ " margin-bottom: 2px;}" +
"table.visual_diff tr.headers td {" +
" border-bottom: 1px solid;" +
" border-top: 0;" +
@@ -83,7 +96,7 @@ public class Summarizer {
" border: 0;" +
" width: 0.4%}" +
"div.space {" +
- " margin-top:30px;}" +
+ " margin-top:4px;}" +
"span.eql {" +
" background-color: #f3f3f3;}" +
"span.del {" +
@@ -95,28 +108,57 @@ public class Summarizer {
"span.pass {" +
" color: green;}" +
"span.time_out {" +
- " color: orange;}";
- private static final String HTML_DIFF_BEGINNING = "<html><head><style type=\"text/css\">" +
- CSS + "</style></head><body>";
- private static final String HTML_DIFF_ENDING = "</body></html>";
-
- /** TODO: Make it a setting */
- private static final String HTML_DIFF_RELATIVE_PATH = "_diff.html";
- private static final String HTML_DIFF_INDEX_RELATIVE_PATH = "_diff-index.html";
+ " color: orange;}" +
+ "table.summary {" +
+ " border: 1px solid black;" +
+ " margin-top: 20px;}" +
+ "table.summary td {" +
+ " padding: 3px;}" +
+ "span.listItem {" +
+ " font-size: 11px;" +
+ " font-weight: normal;" +
+ " text-transform: uppercase;" +
+ " padding: 3px;" +
+ " -webkit-border-radius: 4px;}" +
+ "span." + AbstractResult.ResultCode.PASS.name() + "{" +
+ " background-color: #8ee100;" +
+ " color: black;}" +
+ "span." + AbstractResult.ResultCode.FAIL_RESULT_DIFFERS.name() + "{" +
+ " background-color: #ccc;" +
+ " color: black;}" +
+ "span." + AbstractResult.ResultCode.FAIL_NO_EXPECTED_RESULT.name() + "{" +
+ " background-color: #a700e4;" +
+ " color: #fff;}" +
+ "span." + AbstractResult.ResultCode.FAIL_TIMED_OUT.name() + "{" +
+ " background-color: #f3cb00;" +
+ " color: black;}" +
+ "span." + AbstractResult.ResultCode.FAIL_CRASHED.name() + "{" +
+ " background-color: #c30000;" +
+ " color: #fff;}" +
+ "</style>";
- /** A list containing relatives paths of tests that were skipped */
- private LinkedList<String> mSkippedTestsList = new LinkedList<String>();
+ private static final String SCRIPT =
+ "<script type=\"text/javascript\">" +
+ " function toggleDisplay(id) {" +
+ " element = document.getElementById(id);" +
+ " triangle = document.getElementById('tri.' + id);" +
+ " if (element.style.display == 'none') {" +
+ " element.style.display = 'inline';" +
+ " triangle.innerHTML = '&#x25bc; ';" +
+ " } else {" +
+ " element.style.display = 'none';" +
+ " triangle.innerHTML = '&#x25b6; ';" +
+ " }" +
+ " }" +
+ "</script>";
- /** Collection of tests grouped according to result. Sets are initialized lazily. */
- private Map<AbstractResult.ResultCode, Set<String>> mResults =
- new EnumMap<AbstractResult.ResultCode, Set<String>>(AbstractResult.ResultCode.class);
+ /** TODO: Make it a setting */
+ private static final String HTML_SUMMARY_RELATIVE_PATH = "summary.html";
- /**
- * Collection of tests for which results are ignored grouped according to result. Sets are
- * initialized lazily.
- */
- private Map<AbstractResult.ResultCode, Set<String>> mResultsIgnored =
- new EnumMap<AbstractResult.ResultCode, Set<String>>(AbstractResult.ResultCode.class);
+ private int mCrashedTestsCount = 0;
+ private List<AbstractResult> mFailedNotIgnoredTests = new ArrayList<AbstractResult>();
+ private List<AbstractResult> mIgnoredTests = new ArrayList<AbstractResult>();
+ private List<String> mPassedNotIgnoredTests = new ArrayList<String>();
private FileFilter mFileFilter;
private String mResultsRootDirPath;
@@ -124,99 +166,124 @@ public class Summarizer {
public Summarizer(FileFilter fileFilter, String resultsRootDirPath) {
mFileFilter = fileFilter;
mResultsRootDirPath = resultsRootDirPath;
- createHtmlDiff();
}
- private void createHtmlDiff() {
- FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_RELATIVE_PATH),
- HTML_DIFF_BEGINNING.getBytes(), false);
+ public void appendTest(AbstractResult result) {
+ String relativePath = result.getRelativePath();
+
+ if (result.getResultCode() == AbstractResult.ResultCode.FAIL_CRASHED) {
+ mCrashedTestsCount++;
+ }
+
+ if (mFileFilter.isIgnoreRes(relativePath)) {
+ mIgnoredTests.add(result);
+ } else if (result.getResultCode() == AbstractResult.ResultCode.PASS) {
+ mPassedNotIgnoredTests.add(relativePath);
+ } else {
+ mFailedNotIgnoredTests.add(result);
+ }
}
- private void appendHtmlDiff(String relativePath, String diff) {
+ public void summarize() {
StringBuilder html = new StringBuilder();
- html.append("<label id=\"" + relativePath + "\" />");
- html.append(diff);
- html.append("<a href=\"" + HTML_DIFF_INDEX_RELATIVE_PATH + "\">Back to index</a>");
- html.append("<div class=\"space\"></div>");
- FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_RELATIVE_PATH),
- html.toString().getBytes(), true);
- }
- private void finalizeHtmlDiff() {
- FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_RELATIVE_PATH),
- HTML_DIFF_ENDING.getBytes(), true);
+ html.append("<html><head>");
+ html.append(CSS);
+ html.append(SCRIPT);
+ html.append("</head><body>");
+
+ createTopSummaryTable(html);
+
+ createResultsListWithDiff(html, "Failed", mFailedNotIgnoredTests);
+
+ createResultsListWithDiff(html, "Ignored", mIgnoredTests);
+
+ createResultsListNoDiff(html, "Passed", mPassedNotIgnoredTests);
+
+ html.append("</body></html>");
+
+ FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_SUMMARY_RELATIVE_PATH),
+ html.toString().getBytes(), false);
}
- /** TODO: Add settings method, like setIndexSkippedTests(), setIndexTimedOutTests(), etc */
+ private void createTopSummaryTable(StringBuilder html) {
+ int total = mFailedNotIgnoredTests.size() +
+ mPassedNotIgnoredTests.size() +
+ mIgnoredTests.size();
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+ html.append("<h1> - total of " + total + " tests - ");
+ html.append(dateFormat.format(new Date()) + "</h1>");
- public void addSkippedTest(String relativePath) {
- mSkippedTestsList.addLast(relativePath);
+ html.append("<table class=\"summary\">");
+ createSummaryTableRow(html, "CRASHED", mCrashedTestsCount);
+ createSummaryTableRow(html, "FAILED", mFailedNotIgnoredTests.size());
+ createSummaryTableRow(html, "IGNORED", mIgnoredTests.size());
+ createSummaryTableRow(html, "PASSED", mPassedNotIgnoredTests.size());
+ html.append("</table>");
}
- public void appendTest(AbstractResult result) {
- String testPath = result.getRelativePath();
+ private void createSummaryTableRow(StringBuilder html, String caption, int size) {
+ html.append("<tr>");
+ html.append(" <td>" + caption + "</td>");
+ html.append(" <td>" + size + "</td>");
+ html.append("</tr>");
+ }
- AbstractResult.ResultCode resultCode = result.getResultCode();
+ private void createResultsListWithDiff(StringBuilder html, String title,
+ List<AbstractResult> resultsList) {
+ String relativePath;
+ String id = "";
+ AbstractResult.ResultCode resultCode;
- /** Add the test to correct collection according to its result code */
- if (mFileFilter.isIgnoreRes(testPath)) {
- /** Lazy initialization */
- if (mResultsIgnored.get(resultCode) == null) {
- mResultsIgnored.put(resultCode, new HashSet<String>());
- }
+ Collections.sort(resultsList);
+ html.append("<h2>" + title + " [" + resultsList.size() + "]</h2>");
+ for (AbstractResult result : resultsList) {
+ relativePath = result.getRelativePath();
+ resultCode = result.getResultCode();
- mResultsIgnored.get(resultCode).add(testPath);
- } else {
- /** Lazy initialization */
- if (mResults.get(resultCode) == null) {
- mResults.put(resultCode, new HashSet<String>());
+ html.append("<h3>");
+
+ if (resultCode == AbstractResult.ResultCode.PASS) {
+ html.append(relativePath);
+ } else {
+ /**
+ * Technically, two different paths could end up being the same, because
+ * ':' is a valid character in a path. However, it is probably not going
+ * to cause any problems in this case
+ */
+ id = relativePath.replace(File.separator, ":");
+ html.append("<a href=\"#\" onClick=\"toggleDisplay('" + id + "');");
+ html.append("return false;\">");
+ html.append("<span class=\"tri\" id=\"tri." + id + "\">&#x25b6; </span>");
+ html.append("<span class=\"path\">" + relativePath + "</span>");
+ html.append("</a>");
}
- mResults.get(resultCode).add(testPath);
- }
+ html.append(" <span class=\"listItem " + resultCode.name() + "\">");
+ html.append(resultCode.toString());
+ html.append("</span>");
- if (resultCode != AbstractResult.ResultCode.PASS) {
- appendHtmlDiff(testPath, result.getDiffAsHtml());
- }
- }
+ html.append("</h3>");
- public void summarize() {
- finalizeHtmlDiff();
- createHtmlDiffIndex();
- }
+ if (resultCode != AbstractResult.ResultCode.PASS) {
+ html.append("<div class=\"diff\" style=\"display: none;\" id=\"" + id + "\">");
+ html.append(result.getDiffAsHtml());
+ html.append("<a href=\"#\" onClick=\"toggleDisplay('" + id + "');");
+ html.append("return false;\">Hide</a>");
+ html.append("</div>");
+ }
- private void createHtmlDiffIndex() {
- StringBuilder html = new StringBuilder();
- html.append(HTML_DIFF_BEGINNING);
- Set<String> results;
- html.append("<h1>NOT ignored</h1>");
- appendResultsMap(mResults, html);
- html.append("<h1>Ignored</h1>");
- appendResultsMap(mResultsIgnored, html);
- html.append(HTML_DIFF_ENDING);
- FsUtils.writeDataToStorage(new File(mResultsRootDirPath, HTML_DIFF_INDEX_RELATIVE_PATH),
- html.toString().getBytes(), false);
+ html.append("<div class=\"space\"></div>");
+ }
}
- private void appendResultsMap(Map<AbstractResult.ResultCode, Set<String>> resultsMap,
- StringBuilder html) {
- Set<String> results;
- for (AbstractResult.ResultCode resultCode : AbstractResult.ResultCode.values()) {
- results = resultsMap.get(resultCode);
- if (results != null) {
- html.append("<h2>");
- html.append(resultCode.toString());
- html.append("</h2");
- for (String relativePath : results) {
- html.append("<a href=\"");
- html.append(HTML_DIFF_RELATIVE_PATH);
- html.append("#");
- html.append(relativePath);
- html.append("\">");
- html.append(relativePath);
- html.append("</a><br />");
- }
- }
+ private void createResultsListNoDiff(StringBuilder html, String title,
+ List<String> resultsList) {
+ Collections.sort(resultsList);
+ html.append("<h2>Passed [" + resultsList.size() + "]</h2>");
+ for (String result : resultsList) {
+ html.append("<h3>" + result + "</h3>");
+ html.append("<div class=\"space\"></div>");
}
}
} \ No newline at end of file
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
index 33ee4c7..4278d54 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
@@ -21,6 +21,10 @@ import android.os.Handler;
import android.os.Message;
import android.webkit.WebView;
+import name.fraser.neil.plaintext.diff_match_patch;
+
+import java.util.LinkedList;
+
/**
* A result object for which the expected output is text. It does not have an image
* expected result.
@@ -106,50 +110,71 @@ public class TextResult extends AbstractResult {
@Override
public String getDiffAsHtml() {
- /** TODO: just a stub
- * Probably needs rethinking anyway - just one table would be much better
- * This will require some changes in Summarizer in CSS as well */
StringBuilder html = new StringBuilder();
- html.append("<h3>");
- html.append(mRelativePath);
- html.append("</h3>");
html.append("<table class=\"visual_diff\">");
+ html.append(" <tr class=\"headers\">");
+ html.append(" <td colspan=\"2\">Expected result:</td>");
+ html.append(" <td class=\"space\"></td>");
+ html.append(" <td colspan=\"2\">Actual result:</td>");
+ html.append(" </tr>");
+
+ if (mExpectedResult == null || mActualResult == null) {
+ appendNullsHtml(html);
+ } else {
+ appendDiffHtml(html);
+ }
+
+ html.append(" <tr class=\"footers\">");
+ html.append(" <td colspan=\"2\"></td>");
+ html.append(" <td class=\"space\"></td>");
+ html.append(" <td colspan=\"2\"></td>");
+ html.append(" </tr>");
+ html.append("</table>");
+
+ return html.toString();
+ }
+
+ private void appendDiffHtml(StringBuilder html) {
+ LinkedList<diff_match_patch.Diff> diffs =
+ new diff_match_patch().diff_main(mExpectedResult, mActualResult);
- html.append("<tr class=\"headers\">");
- html.append("<td colspan=\"2\">Expected result:</td>");
- html.append("<td class=\"space\"></td>");
- html.append("<td colspan=\"2\">Actual result:</td>");
- html.append("</tr>");
+ diffs = VisualDiffUtils.splitDiffsOnNewline(diffs);
- html.append("<tr class=\"results\">");
- html.append("<td class=\"line_count\">1:</td>");
- html.append("<td class=\"line\">");
+ LinkedList<String> expectedLines = new LinkedList<String>();
+ LinkedList<Integer> expectedLineNums = new LinkedList<Integer>();
+ LinkedList<String> actualLines = new LinkedList<String>();
+ LinkedList<Integer> actualLineNums = new LinkedList<Integer>();
+
+ VisualDiffUtils.generateExpectedResultLines(diffs, expectedLineNums, expectedLines);
+ VisualDiffUtils.generateActualResultLines(diffs, actualLineNums, actualLines);
+
+ html.append(VisualDiffUtils.getHtml(expectedLineNums, expectedLines,
+ actualLineNums, actualLines));
+ }
+
+ private void appendNullsHtml(StringBuilder html) {
+ /** TODO: Create a separate row for each line of not null result */
+ html.append(" <tr class=\"results\">");
+ html.append(" <td class=\"line_count\">");
+ html.append(" </td>");
+ html.append(" <td class=\"line\">");
if (mExpectedResult == null) {
- html.append("NULL");
+ html.append("Expected result was NULL");
} else {
html.append(mExpectedResult.replace("\n", "<br />"));
}
- html.append("</td>");
- html.append("<td class=\"space\"></td>");
- html.append("<td class=\"line_count\">1:</td>");
- html.append("<td class=\"line\">");
+ html.append(" </td>");
+ html.append(" <td class=\"space\"></td>");
+ html.append(" <td class=\"line_count\">");
+ html.append(" </td>");
+ html.append(" <td class=\"line\">");
if (mActualResult == null) {
- html.append("NULL");
+ html.append("Actual result was NULL");
} else {
html.append(mActualResult.replace("\n", "<br />"));
}
- html.append("</td>");
- html.append("</tr>");
-
- html.append("<tr class=\"footers\">");
- html.append("<td colspan=\"2\"></td>");
- html.append("<td class=\"space\"></td>");
- html.append("<td colspan=\"2\"></td>");
- html.append("</tr>");
-
- html.append("</table>");
-
- return html.toString();
+ html.append(" </td>");
+ html.append(" </tr>");
}
@Override
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
new file mode 100644
index 0000000..250b6bc
--- /dev/null
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dumprendertree2;
+
+import name.fraser.neil.plaintext.diff_match_patch;
+
+import java.util.LinkedList;
+
+/**
+ * Helper methods fo TextResult.getDiffAsHtml()
+ */
+public class VisualDiffUtils {
+
+ private static final int DONT_PRINT_LINE_NUMBER = -1;
+
+ /**
+ * Preprocesses the list of diffs so that new line characters appear only at the end of
+ * diff.text
+ *
+ * @param diffs
+ * @return
+ * LinkedList of diffs where new line character appears only on the end of
+ * diff.text
+ */
+ public static LinkedList<diff_match_patch.Diff> splitDiffsOnNewline(
+ LinkedList<diff_match_patch.Diff> diffs) {
+ LinkedList<diff_match_patch.Diff> newDiffs = new LinkedList<diff_match_patch.Diff>();
+
+ String[] parts;
+ int lengthMinusOne;
+ for (diff_match_patch.Diff diff : diffs) {
+ parts = diff.text.split("\n", -1);
+ if (parts.length == 1) {
+ newDiffs.add(diff);
+ continue;
+ }
+
+ lengthMinusOne = parts.length - 1;
+ for (int i = 0; i < lengthMinusOne; i++) {
+ newDiffs.add(new diff_match_patch.Diff(diff.operation, parts[i] + "\n"));
+ }
+ if (!parts[lengthMinusOne].isEmpty()) {
+ newDiffs.add(new diff_match_patch.Diff(diff.operation, parts[lengthMinusOne]));
+ }
+ }
+
+ return newDiffs;
+ }
+
+ public static void generateExpectedResultLines(LinkedList<diff_match_patch.Diff> diffs,
+ LinkedList<Integer> lineNums, LinkedList<String> lines) {
+ String delSpan = "<span class=\"del\">";
+ String eqlSpan = "<span class=\"eql\">";
+
+ String line = "";
+ int i = 1;
+ for (diff_match_patch.Diff diff : diffs) {
+ switch (diff.operation) {
+ case DELETE:
+ line = processDiff(diff, lineNums, lines, line, i, delSpan);
+ if (line.equals("")) {
+ i++;
+ }
+ break;
+
+ case INSERT:
+ if (diff.text.endsWith("\n")) {
+ lineNums.add(DONT_PRINT_LINE_NUMBER);
+ lines.add("");
+ }
+ break;
+
+ case EQUAL:
+ line = processDiff(diff, lineNums, lines, line, i, eqlSpan);
+ if (line.equals("")) {
+ i++;
+ }
+ break;
+ }
+ }
+
+ if (!line.isEmpty()) {
+ lines.add(line);
+ lineNums.add(i);
+ }
+ }
+
+ public static void generateActualResultLines(LinkedList<diff_match_patch.Diff> diffs,
+ LinkedList<Integer> lineNums, LinkedList<String> lines) {
+ String insSpan = "<span class=\"ins\">";
+ String eqlSpan = "<span class=\"eql\">";
+
+ String line = "";
+ int i = 1;
+ for (diff_match_patch.Diff diff : diffs) {
+ switch (diff.operation) {
+ case INSERT:
+ line = processDiff(diff, lineNums, lines, line, i, insSpan);
+ if (line.equals("")) {
+ i++;
+ }
+ break;
+
+ case DELETE:
+ if (diff.text.endsWith("\n")) {
+ lineNums.add(DONT_PRINT_LINE_NUMBER);
+ lines.add("");
+ }
+ break;
+
+ case EQUAL:
+ line = processDiff(diff, lineNums, lines, line, i, eqlSpan);
+ if (line.equals("")) {
+ i++;
+ }
+ break;
+ }
+ }
+
+ if (!line.isEmpty()) {
+ lines.add(line);
+ lineNums.add(i);
+ }
+ }
+
+ /**
+ * Generate or append a line for a given diff and add it to given collections if necessary.
+ * It puts diffs in HTML spans.
+ *
+ * @param diff
+ * @param lineNums
+ * @param lines
+ * @param line
+ * @param i
+ * @param begSpan
+ * @return
+ */
+ public static String processDiff(diff_match_patch.Diff diff, LinkedList<Integer> lineNums,
+ LinkedList<String> lines, String line, int i, String begSpan) {
+ String endSpan = "</span>";
+ String br = "&nbsp;";
+
+ if (diff.text.endsWith("\n")) {
+ lineNums.add(i++);
+ /** TODO: Think of better way to replace stuff */
+ line += begSpan + diff.text.replace(" ", "&nbsp;&nbsp;")
+ + endSpan + br;
+ lines.add(line);
+ line = "";
+ } else {
+ line += begSpan + diff.text.replace(" ", "&nbsp;&nbsp;") + endSpan;
+ }
+
+ return line;
+ }
+
+ public static String getHtml(LinkedList<Integer> lineNums1, LinkedList<String> lines1,
+ LinkedList<Integer> lineNums2, LinkedList<String> lines2) {
+ StringBuilder html = new StringBuilder();
+ int lineNum;
+ int size = lines1.size();
+ for (int i = 0; i < size; i++) {
+ html.append("<tr class=\"results\">");
+
+ html.append(" <td class=\"line_count\">");
+ lineNum = lineNums1.removeFirst();
+ if (lineNum > 0) {
+ html.append(lineNum);
+ }
+ html.append(" </td>");
+
+ html.append(" <td class=\"line\">");
+ html.append(lines1.removeFirst());
+ html.append(" </td>");
+
+ html.append(" <td class=\"space\"></td>");
+
+ html.append(" <td class=\"line_count\">");
+ lineNum = lineNums2.removeFirst();
+ if (lineNum > 0) {
+ html.append(lineNum);
+ }
+ html.append(" </td>");
+
+ html.append(" <td class=\"line\">");
+ html.append(lines2.removeFirst());
+ html.append(" </td>");
+
+ html.append("</tr>");
+ }
+ return html.toString();
+ }
+}