aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Jones <bjones@galois.com>2013-07-03 09:46:29 -0700
committerGravatar Benjamin Jones <bjones@galois.com>2013-07-03 09:46:29 -0700
commita2e6f86c5b1d33d7d37afe7af807701d2ee74e9b (patch)
treeefd4dd6488f1e4f156ffbaccfeb10a40f86fc231
parent0f717faf40cd7ea6c28c407d0a517d730fc6591f (diff)
parent02b1aff60bad96af14ec73eab5a128c98f821f61 (diff)
Merge branch 'master' of github.com:GaloisInc/FiveUI
-rw-r--r--exampleData/headlessRuns/headingsRun.json13
-rw-r--r--exampleData/ruleSets/accessibility/titleNonEmpty.js4
-rw-r--r--src/batchtools/headless/pom.xml9
-rw-r--r--src/batchtools/headless/src/main/java/com/galois/fiveui/BatchRunner.java49
-rw-r--r--src/batchtools/headless/src/main/java/com/galois/fiveui/HeadlessRunDescription.java52
-rw-r--r--src/batchtools/headless/src/main/java/com/galois/fiveui/Reporter.java623
-rw-r--r--src/batchtools/rsTester/src/main/java/com/galois/fiveui/Result.java5
-rw-r--r--src/batchtools/webdrivers/src/main/java/com/galois/fiveui/drivers/Drivers.java14
8 files changed, 440 insertions, 329 deletions
diff --git a/exampleData/headlessRuns/headingsRun.json b/exampleData/headlessRuns/headingsRun.json
new file mode 100644
index 0000000..d6e5135
--- /dev/null
+++ b/exampleData/headlessRuns/headingsRun.json
@@ -0,0 +1,13 @@
+/*
+ * A very basic headless run example. This configuration runs two rule sets on
+ * the Whitehouse main webpage.
+ */
+{
+ "rulePath" : "../ruleSets/",
+ "crawlType" : "2 5 1000 *localhost*",
+ "firefoxProfile": "../../profiles/firefox/",
+ "runs": [
+ { "url": "http://localhost:8000/sites/headings.html", "ruleSet": "accessibility/accessibility.json" },
+ { "url": "http://localhost:8000/sites/headings.html", "ruleSet": "basic/basicUIRules.json" }
+ ]
+}
diff --git a/exampleData/ruleSets/accessibility/titleNonEmpty.js b/exampleData/ruleSets/accessibility/titleNonEmpty.js
index 27e281f..ff3388e 100644
--- a/exampleData/ruleSets/accessibility/titleNonEmpty.js
+++ b/exampleData/ruleSets/accessibility/titleNonEmpty.js
@@ -1,6 +1,6 @@
-exports.name = "titleNonEmpty";
+exports.name = "titleExists";
-exports.description = "Title of page is non-empty";
+exports.description = "Title of page should not be empty";
exports.rule = function(report) {
if (document.title == '') {
diff --git a/src/batchtools/headless/pom.xml b/src/batchtools/headless/pom.xml
index 1b84aaa..7e85a75 100644
--- a/src/batchtools/headless/pom.xml
+++ b/src/batchtools/headless/pom.xml
@@ -24,6 +24,15 @@
</pluginRepositories>
<build>
+ <resources>
+ <resource>
+ <directory>../../js</directory>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
diff --git a/src/batchtools/headless/src/main/java/com/galois/fiveui/BatchRunner.java b/src/batchtools/headless/src/main/java/com/galois/fiveui/BatchRunner.java
index 74bd109..934620a 100644
--- a/src/batchtools/headless/src/main/java/com/galois/fiveui/BatchRunner.java
+++ b/src/batchtools/headless/src/main/java/com/galois/fiveui/BatchRunner.java
@@ -23,21 +23,19 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
+import com.galois.fiveui.drivers.Drivers;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.Maps;
import com.google.common.io.Files;
-import com.galois.fiveui.Result;
-import com.galois.fiveui.RuleSet;
-import com.galois.fiveui.Utils;
-import com.galois.fiveui.drivers.Drivers;
import edu.uci.ics.crawler4j.util.IO;
-
-import org.apache.log4j.Logger; // System.out.* is old fashioned
+// System.out.* is old fashioned
/**
@@ -52,14 +50,8 @@ public class BatchRunner {
private JavascriptExecutor _exe;
private String _root; // FiveUI root directory
- private static final String JS_SRC_ROOT = "src/js/";
-
- // Hard coded JS files, relative to the FiveUI root directory.
- private static final String J_QUERY_JS = "lib/jquery/jquery.js";
- private static final String MD5_JS = "lib/md5.js";
-
private static Logger logger = Logger.getLogger("com.galois.fiveui.BatchRunner");
-
+
private void registerDriver(WebDriver driver) {
logger.debug("registering new webdriver...");
this._driver = driver;
@@ -144,7 +136,7 @@ public class BatchRunner {
* Drive the browser(s)
***********************/
- for (WebDriver driver: getDrivers()) {
+ for (WebDriver driver: getDrivers(run.getFirefoxProfile())) {
registerDriver(driver);
for (String url: urls) {
logger.info("loading " + url + " for ruleset run ...");
@@ -260,13 +252,20 @@ public class BatchRunner {
*/
private String wrapRule(RuleSet ruleSet) throws IOException {
String injected = "fiveui = {};";
- injected += Utils.readFile(_root + JS_SRC_ROOT + J_QUERY_JS);
- injected += Utils.readFile(_root + JS_SRC_ROOT + "lib/underscore.js");
- injected += Utils.readFile(_root + JS_SRC_ROOT + MD5_JS);
- injected += Utils.readFile(_root + JS_SRC_ROOT + "fiveui/injected/prelude.js");
- injected += Utils.readFile(_root + JS_SRC_ROOT + "fiveui/injected/jquery-plugins.js");
- injected += Utils.readFile(_root + JS_SRC_ROOT + "selenium/selenium-injected-compute.js");
- injected += Utils.readFile(_root + JS_SRC_ROOT + "fiveui/injected/compute.js");
+ Class<? extends BatchRunner> cl = this.getClass();
+
+ try {
+ injected += Utils.readStream(cl.getResourceAsStream("/lib/jquery/jquery.js"));
+ injected += Utils.readStream(cl.getResourceAsStream("/lib/underscore.js"));
+ injected += Utils.readStream(cl.getResourceAsStream("/lib/md5.js"));
+ injected += Utils.readStream(cl.getResourceAsStream("/fiveui/injected/prelude.js"));
+ injected += Utils.readStream(cl.getResourceAsStream("/fiveui/injected/jquery-plugins.js"));
+ injected += Utils.readStream(cl.getResourceAsStream("/selenium/selenium-injected-compute.js"));
+ injected += Utils.readStream(cl.getResourceAsStream("/fiveui/injected/compute.js"));
+ } catch (NullPointerException e) {
+ logger.error("Could not access javascript resources");
+ throw e;
+ }
if (null != ruleSet.getDependencies()) {
for (String dep : ruleSet.getDependencies()) {
@@ -285,11 +284,11 @@ public class BatchRunner {
*
* @return list of initialized WebDriver objects
*/
- private static ImmutableList<WebDriver> getDrivers() {
+ private static ImmutableList<WebDriver> getDrivers(String ffProfile) {
logger.debug("building webdrivers ...");
ImmutableList<WebDriver> r = ImmutableList.<WebDriver>of(
- Drivers.buildFFDriver()
- // , Drivers.buildChromeDriver()
+ Drivers.buildFFDriver(ffProfile)
+ //, Drivers.buildChromeDriver()
);
logger.debug("built: " + r.toString());
return r;
diff --git a/src/batchtools/headless/src/main/java/com/galois/fiveui/HeadlessRunDescription.java b/src/batchtools/headless/src/main/java/com/galois/fiveui/HeadlessRunDescription.java
index c9b70de..8b41fe4 100644
--- a/src/batchtools/headless/src/main/java/com/galois/fiveui/HeadlessRunDescription.java
+++ b/src/batchtools/headless/src/main/java/com/galois/fiveui/HeadlessRunDescription.java
@@ -24,8 +24,10 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
+import com.google.gson.JsonIOException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
+import com.google.gson.JsonSyntaxException;
/**
* @author bjones
@@ -36,6 +38,7 @@ public class HeadlessRunDescription {
private static Logger logger = Logger.getLogger("com.galois.fiveui.HeadlessRunDescription");
private static String _crawlType;
private List<HeadlessAtom> _atoms;
+ private static String _firefoxProfile;
public HeadlessRunDescription (List<HeadlessAtom> atoms) {
_atoms = atoms;
@@ -58,12 +61,28 @@ public class HeadlessRunDescription {
*/
public static HeadlessRunDescription parse(String runDescFileName)
throws FileNotFoundException {
- GsonBuilder gsonBuilder = new GsonBuilder();
- gsonBuilder.registerTypeAdapter(HeadlessRunDescription.class,
- new HeadlessRunDescription.Deserializer(runDescFileName));
- Gson gson = gsonBuilder.create();
- Reader in = new InputStreamReader(new FileInputStream(runDescFileName));
- return gson.fromJson(in, HeadlessRunDescription.class);
+ HeadlessRunDescription runDescr = null;
+ try {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ gsonBuilder.registerTypeAdapter(HeadlessRunDescription.class,
+ new HeadlessRunDescription.Deserializer(runDescFileName));
+ Gson gson = gsonBuilder.create();
+ Reader in = new InputStreamReader(new FileInputStream(runDescFileName));
+ runDescr = gson.fromJson(in, HeadlessRunDescription.class);
+ } catch (JsonSyntaxException e) {
+ System.err.println("We were unable to parse the run description at: "+runDescFileName);
+ System.err.println(e.getLocalizedMessage());
+
+ e.printStackTrace();
+ throw new IllegalStateException("Could not parse run description");
+ } catch (JsonIOException e) {
+ System.err.println("We were unable to load the run description at: "+runDescFileName);
+ System.err.println(e.getLocalizedMessage());
+
+ e.printStackTrace();
+ throw new IllegalStateException("Could not parse run description");
+ }
+ return runDescr;
}
public static class Deserializer implements JsonDeserializer<HeadlessRunDescription> {
@@ -80,7 +99,7 @@ public class HeadlessRunDescription {
}
public static void reportError(JsonElement json) {
- logger.error("HeadlessRunDescription.parse: ran into unexpected jsonElement type:");
+ logger.error("HeadlessRunDescription.parse: ran into unexpected jsonElement type: \""+json+"\"");
logger.error(" " + json.getAsString());
}
@@ -114,6 +133,13 @@ public class HeadlessRunDescription {
if (null != runDescDir) {
ruleSetDir = runDescDir + File.separator + ruleSetDir;
}
+
+ String ffProfile = objGetString(obj, "firefoxProfile");
+ if (null != ffProfile) {
+ ffProfile = runDescDir + File.separator + ffProfile;
+ }
+ _firefoxProfile = ffProfile;
+
_crawlType = objGetString(obj, "crawlType");
arr = obj.get("runs").getAsJsonArray();
} else if (json.isJsonArray()) {
@@ -127,13 +153,20 @@ public class HeadlessRunDescription {
Builder<HeadlessAtom> atoms = ImmutableList.builder();
for (JsonElement jsonElement : arr) {
+ // we only care about json objects, so if anything else is found,
+ // skip this loop:
+ if (!jsonElement.isJsonObject()) {
+ continue;
+ }
try {
+
JsonObject obj = jsonElement.getAsJsonObject();
atoms.add(HeadlessAtom.fromJsonObject(obj, ruleSetDir));
} catch (IOException e) {
logger.error("HeadlessAtom.parse: error parsing ruleSet file: " + e.getMessage());
System.exit(1);
} catch (IllegalStateException e) {
+ e.printStackTrace();
reportError(jsonElement);
}
}
@@ -151,6 +184,10 @@ public class HeadlessRunDescription {
return gson.toJson(this);
}
+ public String getFirefoxProfile() {
+ return _firefoxProfile;
+ }
+
@Override
public int hashCode() {
final int prime = 31;
@@ -178,4 +215,5 @@ public class HeadlessRunDescription {
return true;
}
+
}
diff --git a/src/batchtools/headless/src/main/java/com/galois/fiveui/Reporter.java b/src/batchtools/headless/src/main/java/com/galois/fiveui/Reporter.java
index cad8bee..f0461d4 100644
--- a/src/batchtools/headless/src/main/java/com/galois/fiveui/Reporter.java
+++ b/src/batchtools/headless/src/main/java/com/galois/fiveui/Reporter.java
@@ -32,6 +32,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import com.google.common.collect.Lists;
import com.googlecode.jatl.Html;
/**
@@ -40,292 +41,346 @@ import com.googlecode.jatl.Html;
* generated in HTML and returned as human readable strings by getSummaryPage(),
* getURLPage(), and getRulePage(). The client is responsible for writing them
* to .html files (or whatever).
- *
+ *
* @author bjones
- *
+ *
*/
public class Reporter {
- /** see sortBy* and computeSummaryStats methods for map semantics */
- private final Map<String, List<Result>> _byURLMap;
- private final Map<String, List<Result>> _byRuleMap;
- private final Map<String, int[]> _passFailMap;
- private Map<String, String> _ruleNameToDesc;
- private static String GLOBAL_CSS =
- "h1 { font-size: 150%; }" +
- "h2 { font-size: 110%; }" +
- "li { margin: 5 0 0 0; }" +
- "table { border: 1px solid grey; cellpadding: 5%; width: 200px; }\n" +
- "td.pass-number{ text-align: right;color: green; }\n" +
- "td.fail-number{ text-align: right;color: red; }\n" +
- "td.text{ text-align: left; }\n" +
- "th { font-weight: bold; }\n" +
- "td, th { border: 1px solid grey; }\n" +
- ".hlRow { background: #EEEEEE; }\n" +
- ".regRow { background: #FFFFFF; }\n";
+ /** see sortBy* and computeSummaryStats methods for map semantics */
+ private final Map<String, List<Result>> _byURLMap;
+ private final Map<String, List<Result>> _byRuleMap;
+ private final Map<String, int[]> _passFailMap;
+ private Map<String, String> _ruleNameToDesc;
+ private static String GLOBAL_CSS = "h1 { font-size: 150%; }"
+ + "h2 { font-size: 110%; }"
+ + "li { margin: 5 0 0 0; }"
+ + "table { border: 1px solid grey; cellpadding: 5%; width: 200px; }\n"
+ + "td.pass-number{ text-align: right;color: green; }\n"
+ + "td.fail-number{ text-align: right;color: red; }\n"
+ + "td.text{ text-align: left; }\n" + "th { font-weight: bold; }\n"
+ + "td, th { border: 1px solid grey; }\n"
+ + ".hlRow { background: #EEEEEE; }\n"
+ + ".regRow { background: #FFFFFF; }\n";
+
+ /**
+ * Construct a Reporter object. The constructor takes a list of results and
+ * uses them to populate various maps used in reporting.
+ *
+ * @param results
+ * a list of Result objects
+ */
+ public Reporter(List<Result> results) {
+ this._byURLMap = sortByURL(results);
+ this._byRuleMap = sortByRule(results);
+ this._passFailMap = computeSummaryStats(results);
+ this._ruleNameToDesc = extractRuleDesc(results);
+ }
+
+ /**
+ * Build the HTML markup for a summary page based on the precomputed map
+ * this._passFailMap.
+ *
+ * @return String containing human-readable HTML representing a summary page
+ */
+ public String getSummary() {
+ StringWriter summaryPage = new StringWriter();
+ final Map<String, int[]> scopedMap = this._passFailMap;
+ Html page = new Html(summaryPage);
+ page = makeHead(page, "Summary of Results");
+ page = new Html(page) {
+ {
+ h1().text("Headless Run Summary").end();
+ p();
+ ul();
+ li().a().href("byURL.html").text("Results organized by URL")
+ .end().end();
+ li().a().href("byRule.html").text("Results organized by Rule")
+ .end().end();
+ end();
+ end();
+ p();
+ div().id("stats");
+ makeSummaryStats(scopedMap);
+ end();
+ end();
+ endAll();
+ done();
+ }
- /**
- * Construct a Reporter object. The constructor takes a list of results
- * and uses them to populate various maps used in reporting.
- *
- * @param results a list of Result objects
- */
- public Reporter(List<Result> results) {
- this._byURLMap = sortByURL(results);
- this._byRuleMap = sortByRule(results);
- this._passFailMap = computeSummaryStats(results);
- this._ruleNameToDesc = extractRuleDesc(results);
- }
+ /**
+ * Report statistics on the headless run. Note, "pass" means the URL
+ * passed all tests in the ruleset, but "fail" can be reported for
+ * the same test on multiple offenders in the page.
+ */
+ Html makeSummaryStats(Map<String, int[]> passFailMap) {
+ int uniqueURLs = passFailMap.size();
+ int[] passFailList;
- /**
- * Build the HTML markup for a summary page based on the precomputed map
- * this._passFailMap.
- *
- * @return String containing human-readable HTML representing a summary page
- */
- public String getSummary() {
- StringWriter summaryPage = new StringWriter();
- final Map<String, int[]> scopedMap = this._passFailMap;
- Html page = new Html(summaryPage);
- page = makeHead(page, "Summary of Results");
- page = new Html(page) {{
- h1().text("Headless Run Summary").end();
- p();
- ul();
- li().a().href("byURL.html").text("Results organized by URL").end().end();
- li().a().href("byRule.html").text("Results organized by Rule").end().end();
- end();
- end();
- p();
- div().id ("stats");
- makeSummaryStats(scopedMap);
- end();
- end();
- endAll();
- done();
- }
- /**
- * Report statistics on the headless run. Note, "pass"
- * means the URL passed all tests in the ruleset, but "fail" can be
- * reported for the same test on multiple offenders in the page.
- */
- Html makeSummaryStats(Map<String, int[]> passFailMap) {
- int uniqueURLs = passFailMap.size();
- int[] passFailList;
+ p();
+ h3().text("Unique URLs: ");
+ span().classAttr("number").text(String.valueOf(uniqueURLs))
+ .end();
+ end().end();
- p();
- h3().text("Unique URLs: ");
- span().classAttr("number").text(String.valueOf(uniqueURLs)).end();
- end().end();
+ p();
+ table().id("stats-table");
+ tr();
+ th().text("URL").end();
+ th().text("Pass").end();
+ th().text("Fail").end();
+ end();
+ int i = 0; // index for **alternate row highlighting**
+ List<String> sortedKeys = Lists.newArrayList();
+ sortedKeys.addAll(passFailMap.keySet());
+ Collections.sort(sortedKeys);
+ for (String key : sortedKeys) {
+ passFailList = passFailMap.get(key);
+ tr().classAttr(i % 2 == 0 ? "hlRow" : "regRow");
+ td().classAttr("text").a().href(key).text(key).end().end();
+ td().classAttr("pass-number")
+ .text(String.valueOf(passFailList[0])).end();
+ td().classAttr("fail-number")
+ .text(String.valueOf(passFailList[1])).end();
+ end();
+ i++;
+ }
+ end(); // end <table>
+ return end(); // end <p>
+ }
+ };
+ return summaryPage.getBuffer().toString();
+ }
+
+ /**
+ * Build the HTML markup for a report page sorted by URL.
+ *
+ * @return String containing human-readable HTML representing a report page
+ */
+ public String getByURL() {
+ StringWriter byURLPage = new StringWriter();
+ final Map<String, List<Result>> scopedMap = this._byURLMap;
+ Html page = new Html(byURLPage);
+ page = makeHead(page, "Results sorted by URL");
+ page = new Html(page) {
+ {
+ body();
+ h1().text("Results by URL").end();
+ ol();
+ List<String> sortedKeys = Lists.newArrayList();
+ sortedKeys.addAll(scopedMap.keySet());
+ Collections.sort(sortedKeys);
+ for (String url : sortedKeys) {
+ li().h2().a().href(url).text(url).end().end();
+ ul();
+ int i = 0;
+ for (Result r : scopedMap.get(url)) {
+ String cAttr = i % 2 == 0 ? "hlRow" : "regRow";
+
+ // format an individual Result for this url:
+ li().classAttr(cAttr).b().text(r.getRuleName()).end();
+ resultToHtml(this, r, cAttr);
+ end();
+ i++;
+ }
+ end();
+ end();
+ }
+ endAll();
+ done();
+ }
+
+ };
+ return byURLPage.getBuffer().toString();
+ }
+
+
+
+ /**
+ * Build the HTML markup for a report page sorted by rule name.
+ *
+ * @return String containing human-readable HTML representing a report page
+ */
+ public String getByRule() {
+ StringWriter byRulePage = new StringWriter();
+ final Map<String, List<Result>> scopedMap = this._byRuleMap;
+ final Map<String, String> scopedRuleNameToDesc = this._ruleNameToDesc;
+ Html page = new Html(byRulePage);
+ page = makeHead(page, "Results sorted by rule");
+ page = new Html(page) {
+ {
+ h1().text("Results by Rule").end();
+ ul();
+ List<String> sortedKeys = new ArrayList<String>();
+ sortedKeys.addAll(scopedMap.keySet());
+ Collections.sort(sortedKeys);
+ for (String rule : sortedKeys) {
+ li();
+ b().text(rule).end()
+ .text(": " + scopedRuleNameToDesc.get(rule));
+ ul();
+ int i = 0;
+ for (Result r : scopedMap.get(rule)) {
+ String cAttr = i % 2 == 0 ? "hlRow" : "regRow";
+
+ li().classAttr(cAttr).b().text(r.getURL()).end();
+ resultToHtml(this, r, cAttr);
+ end();
+ i++;
+ }
+ end();
+ end();
+ }
+ endAll();
+ done();
+ }
+ };
+ return byRulePage.getBuffer().toString();
+ }
- p();
- table().id("stats-table");
- tr();
- th().text("URL").end();
- th().text("Pass").end();
- th().text("Fail").end();
- end();
- int i = 0; // index for **alternate row highlighting**
- List<String> sortedKeys = new ArrayList<String>();
- sortedKeys.addAll(passFailMap.keySet());
- Collections.sort(sortedKeys);
- for (String key: sortedKeys) {
- passFailList = passFailMap.get(key);
- tr().classAttr(i % 2 == 0 ? "hlRow" : "regRow");
- td().classAttr("text").a().href(key).text(key).end().end();
- td().classAttr("pass-number").text(String.valueOf(passFailList[0])).end();
- td().classAttr("fail-number").text(String.valueOf(passFailList[1])).end();
- end();
- i++;
- }
- end(); // end <table>
- return end(); // end <p>
- }
- };
- return summaryPage.getBuffer().toString();
- }
- /**
- * Build the HTML markup for a report page sorted by URL.
- *
- * @return String containing human-readable HTML representing a report page
- */
- public String getByURL() {
- StringWriter byURLPage = new StringWriter();
- final Map<String, List<Result>> scopedMap = this._byURLMap;
- Html page = new Html(byURLPage);
- page = makeHead(page, "Results sorted by URL");
- page = new Html(page) {{
- body();
- h1().text("Results by URL").end();
- ol();
- List<String> sortedKeys = new ArrayList<String>();
- sortedKeys.addAll(scopedMap.keySet());
- Collections.sort(sortedKeys);
- for (String url: sortedKeys) {
- li().h2().a().href(url).text(url).end().end();
- ul();
- int i = 0;
- for (Result r: scopedMap.get(url)) {
- li().classAttr(i % 2 == 0 ? "regRow" : "hlRow");
- text(r.getRuleName() + ": " + r.getRuleDesc()).br();
- text(r.getProblem()).end();
- i++;
- }
- end();
- end();
- }
- endAll();
- done();
- }};
- return byURLPage.getBuffer().toString();
- }
+ private void resultToHtml(Html html, Result r, String cAttr) {
+
+ html.ul();
+ html.li().b().text("Description:").end();
+ html.text(r.getRuleDesc()).end();
+
+ html.li().b().text("Message:").end();
+ html.text(r.getMsg()).end();
- /**
- * Build the HTML markup for a report page sorted by rule name.
- *
- * @return String containing human-readable HTML representing a report page
- */
- public String getByRule() {
- StringWriter byRulePage = new StringWriter();
- final Map<String, List<Result>> scopedMap = this._byRuleMap;
- final Map<String, String> scopedRuleNameToDesc = this._ruleNameToDesc;
- Html page = new Html(byRulePage);
- page = makeHead(page, "Results sorted by rule");
- page = new Html(page) {{
- h1().text("Results by Rule").end();
- ul();
- List<String> sortedKeys = new ArrayList<String>();
- sortedKeys.addAll(scopedMap.keySet());
- Collections.sort(sortedKeys);
- for (String rule: sortedKeys) {
- li();
- b().text(rule).end().text(": " + scopedRuleNameToDesc.get(rule));
- ul();
- int i = 0;
- for (Result r: scopedMap.get(rule)) {
- li().classAttr(i % 2 == 0 ? "regRow" : "hlRow");
- text("Problem: " + r.getProblem()).br();
- text("URL: ").a().href(r.getURL()).text(r.getURL()).end().end();
- i++;
- }
- end();
- end();
- }
- endAll();
- done();
- }};
- return byRulePage.getBuffer().toString();
- }
+ html.li().b().text("xpath:").end();
+ html.text(r.getXpath()).end();
+
+ html.li().b().text("Severity:").end();
+ html.text(r.getType().toString()).end();
+
+ html.li().b().text("Browser:").end();
+ html.text(r.getDriver().toString()).end();
+
+ html.li().b().text("Url:").end();
+ html.a().href(r.getURL()).text(r.getURL()).end().end();
- /**
- * Utility method to take all the reports and write them to standard file
- * names under a given directory.
- *
- * @param dirName name of the directory where the reports should be written
- * @throws IOException
- */
- public void writeReportsToDir(String dirName) throws IOException {
- PrintWriter summaryFile = new PrintWriter(new FileWriter(dirName + File.separator + "summary.html"));
- PrintWriter byURLFile = new PrintWriter(new FileWriter(dirName + File.separator + "byURL.html"));
- PrintWriter byRuleFile = new PrintWriter(new FileWriter(dirName + File.separator + "byRule.html"));
- summaryFile.write(this.getSummary());
- summaryFile.close();
- byURLFile.write(this.getByURL());
- byURLFile.close();
- byRuleFile.write(this.getByRule());
- byRuleFile.close();
- }
+ html.end();
+ }
+
+ /**
+ * Utility method to take all the reports and write them to standard file
+ * names under a given directory.
+ *
+ * @param dirName
+ * name of the directory where the reports should be written
+ * @throws IOException
+ */
+ public void writeReportsToDir(String dirName) throws IOException {
+ PrintWriter summaryFile = new PrintWriter(new FileWriter(dirName
+ + File.separator + "summary.html"));
+ PrintWriter byURLFile = new PrintWriter(new FileWriter(dirName
+ + File.separator + "byURL.html"));
+ PrintWriter byRuleFile = new PrintWriter(new FileWriter(dirName
+ + File.separator + "byRule.html"));
+ summaryFile.write(this.getSummary());
+ summaryFile.close();
+ byURLFile.write(this.getByURL());
+ byURLFile.close();
+ byRuleFile.write(this.getByRule());
+ byRuleFile.close();
+ }
- /** Private fields **/
+ /** Private fields **/
- private Html makeHead(Html page, final String title) {
- return new Html(page) {{
- html();
- head();
- title().text(title).end();
- style().type("text/css").text(GLOBAL_CSS).end();
- end();
- body();
- }};
- }
+ private Html makeHead(Html page, final String title) {
+ return new Html(page) {
+ {
+ html();
+ head();
+ title().text(title).end();
+ style().type("text/css").text(GLOBAL_CSS).end();
+ end();
+ body();
+ }
+ };
+ }
- /**
- * Populate a Map<String, List<Result>> representing the results sorted by
- * URL.
- *
- * @param results a list of results
- * @return a map representing the results sorted by URL.
- */
- private Map<String, List<Result>>sortByURL(List<Result> results) {
- /** map semantics: Map< url, [rule1, rule2, ...] > */
- Map<String, List<Result>> map = new HashMap<String, List<Result>>();
- String url;
- List<Result> list;
- for (Result r: results) {
- url = r.getURL();
- if (map.containsKey(url)) {
- list = map.get(url);
- list.add(r);
- } else {
- list = new ArrayList<Result>();
- list.add(r);
- map.put(url, list);
- }
- }
- return map;
- }
+ /**
+ * Populate a Map<String, List<Result>> representing the results sorted by
+ * URL.
+ *
+ * @param results
+ * a list of results
+ * @return a map representing the results sorted by URL.
+ */
+ private Map<String, List<Result>> sortByURL(List<Result> results) {
+ /** map semantics: Map< url, [rule1, rule2, ...] > */
+ Map<String, List<Result>> map = new HashMap<String, List<Result>>();
+ String url;
+ List<Result> list;
+ for (Result r : results) {
+ url = r.getURL();
+ if (map.containsKey(url)) {
+ list = map.get(url);
+ list.add(r);
+ } else {
+ list = new ArrayList<Result>();
+ list.add(r);
+ map.put(url, list);
+ }
+ }
+ return map;
+ }
- /**
- * Populate a Map<String, List<Result>> representing the results sorted by
- * rule name.
- *
- * @param results a list of results
- * @return a map representing the results sorted by rule name.
- */
- private Map<String, List<Result>>sortByRule(List<Result> results) {
- /** map semantics: Map< rule, [url1, url2, ...] > */
- Map<String, List<Result>> map = new HashMap<String, List<Result>>();
- String rule;
- List<Result> list;
- for (Result r: results) {
- rule = r.getRuleName();
- if (map.containsKey(rule)) {
- list = map.get(rule);
- list.add(r);
- } else {
- list = new ArrayList<Result>();
- list.add(r);
- map.put(rule, list);
- }
- }
- return map;
- }
+ /**
+ * Populate a Map<String, List<Result>> representing the results sorted by
+ * rule name.
+ *
+ * @param results
+ * a list of results
+ * @return a map representing the results sorted by rule name.
+ */
+ private Map<String, List<Result>> sortByRule(List<Result> results) {
+ /** map semantics: Map< rule, [url1, url2, ...] > */
+ Map<String, List<Result>> map = new HashMap<String, List<Result>>();
+ String rule;
+ List<Result> list;
+ for (Result r : results) {
+ rule = r.getRuleName();
+ if (map.containsKey(rule)) {
+ list = map.get(rule);
+ list.add(r);
+ } else {
+ list = new ArrayList<Result>();
+ list.add(r);
+ map.put(rule, list);
+ }
+ }
+ return map;
+ }
- /**
- * Build a map of ruleName -> ruleDesc entries occurring in the given list of
- * results.
- *
- * @param results a list of results
- * @return a map associating rule names to rule descriptions
- */
- private Map<String, String> extractRuleDesc(List<Result> results) {
- Map<String, String> assoc = new HashMap<String, String>();
- for (Result r: results)
- if (!assoc.containsKey(r.getRuleName()))
- assoc.put(r.getRuleName(), r.getRuleDesc());
- return assoc;
- }
+ /**
+ * Build a map of ruleName -> ruleDesc entries occurring in the given list
+ * of results.
+ *
+ * @param results
+ * a list of results
+ * @return a map associating rule names to rule descriptions
+ */
+ private Map<String, String> extractRuleDesc(List<Result> results) {
+ Map<String, String> assoc = new HashMap<String, String>();
+ for (Result r : results)
+ if (!assoc.containsKey(r.getRuleName()))
+ assoc.put(r.getRuleName(), r.getRuleDesc());
+ return assoc;
+ }
- /**
+ /**
* Compute summary statistics from the results list. This includes number of
* passes and fails for each URL checked.
- *
- * @param results a list of results
+ *
+ * @param results
+ * a list of results
* @return a map representing the results sorted by rule name.
*/
private Map<String, int[]> computeSummaryStats(List<Result> results) {
- /** passFailMap semantics: Map<url, {#pass, #fail}> */
+ /** passFailMap semantics: Map<url, {#pass, #fail}> */
Map<String, int[]> passFailMap = new HashMap<String, int[]>();
String url;
int pass, fail;
@@ -334,26 +389,28 @@ public class Reporter {
Matcher matcher;
for (Result result : results) {
- pass = fail = 0;
- url = result.getURL();
- if (result.getType() == ResType.Pass) {
- // now we have to parse out how many tests passed
- matcher = numberPassedPattern.matcher(result.getMsg());
- if (matcher.find())
- pass = Integer.parseInt(matcher.group(1)); // throws exception if parse fails
- } else if (result.getType() == ResType.Error) {
- // each error result corresponds to one test
- fail = 1;
- }
+ pass = fail = 0;
+ url = result.getURL();
+ if (result.getType() == ResType.Pass) {
+ // now we have to parse out how many tests passed
+ matcher = numberPassedPattern.matcher(result.getMsg());
+ if (matcher.find())
+ pass = Integer.parseInt(matcher.group(1)); // throws
+ // exception if
+ // parse fails
+ } else if (result.getType() == ResType.Error) {
+ // each error result corresponds to one test
+ fail = 1;
+ }
- if (passFailMap.containsKey(url)) {
- passFailList = passFailMap.get(url);
- } else {
- passFailList = new int[] { 0, 0};
- passFailMap.put(url, passFailList);
- }
- passFailList[0] += pass;
- passFailList[1] += fail;
+ if (passFailMap.containsKey(url)) {
+ passFailList = passFailMap.get(url);
+ } else {
+ passFailList = new int[] { 0, 0 };
+ passFailMap.put(url, passFailList);
+ }
+ passFailList[0] += pass;
+ passFailList[1] += fail;
}
return passFailMap;
}
diff --git a/src/batchtools/rsTester/src/main/java/com/galois/fiveui/Result.java b/src/batchtools/rsTester/src/main/java/com/galois/fiveui/Result.java
index a367d1d..6c83c7b 100644
--- a/src/batchtools/rsTester/src/main/java/com/galois/fiveui/Result.java
+++ b/src/batchtools/rsTester/src/main/java/com/galois/fiveui/Result.java
@@ -205,4 +205,9 @@ public class Result {
+ " |\\_ " + _ruleDesc + "\n"
+ " \\_ " + _prob;
}
+
+ public String getXpath() {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/src/batchtools/webdrivers/src/main/java/com/galois/fiveui/drivers/Drivers.java b/src/batchtools/webdrivers/src/main/java/com/galois/fiveui/drivers/Drivers.java
index 9dd0736..8ac41d1 100644
--- a/src/batchtools/webdrivers/src/main/java/com/galois/fiveui/drivers/Drivers.java
+++ b/src/batchtools/webdrivers/src/main/java/com/galois/fiveui/drivers/Drivers.java
@@ -42,8 +42,6 @@ public class Drivers {
private static final String defaultFiveuiRootPath = "../../../";
private static final String firefoxProfilePath = "profiles/firefox";
private static final String chromeProfilePath = "profiles/chrome";
- private static final String firefoxExtensionPath = "build/fiveui.xpi";
- private static final String chromeExtensionPath = "build/fiveui.crx";
/**
* Query the OS environment for the FiveUI root path, or return a default.
@@ -53,21 +51,14 @@ public class Drivers {
return (null != rootPath) ? rootPath + File.separator : defaultFiveuiRootPath;
}
- public static FirefoxDriver buildFFDriver() {
+ public static FirefoxDriver buildFFDriver(String ffProfile) {
// Extracted into a method so we can set up profiles
String rootPath = getRootPath();
- File profileDir = new File(rootPath+firefoxProfilePath);
+ File profileDir = new File(ffProfile);
FirefoxProfile profile = new FirefoxProfile(profileDir);
- File fiveuiXpi = new File(rootPath+firefoxExtensionPath);
- try {
- profile.addExtension(fiveuiXpi);
- } catch (IOException e) {
- System.err.println("could not load firefox with FiveUI");
- e.printStackTrace();
- }
String ffBinaryPath = System.getProperty(FIREFOX_BIN_PATH);
@@ -100,7 +91,6 @@ public class Drivers {
options.addArguments("--user-data-dir=" + rootPath + chromeProfilePath); // ,
// "--enable-logging",
// "--v=1");
- options.addExtensions(new File(rootPath + chromeExtensionPath));
String chromeBinaryPath = System.getProperty(CHROME_BIN_PATH);
if (null == chromeBinaryPath) {