Suppress all failures in setSecurityManager() with vogar.
diff --git a/tools/runner/expectations/brokentests.txt b/tools/runner/expectations/brokentests.txt
index 29fbf7d..2d98c23 100644
--- a/tools/runner/expectations/brokentests.txt
+++ b/tools/runner/expectations/brokentests.txt
@@ -1,5 +1,14 @@
 # This file contains expectations for tests that we don't ever intend to fix.
 
+# We're retiring the security manager. Unfortunately, tests all over the place
+# need to check that they're secure, so they all fail when we refuse to install
+# a security manager. This suppresses all of these failures.
+# http://b/issue?id=2585285
+failure disable securityManager
+result EXEC_FAILED
+pattern .*java.lang.UnsupportedOperationException\s+at java.lang.System.setSecurityManager.*
+
+
 # The RI avoids blocking calls when '\r' is the last character. We don't
 # bother since that adds complexity to every other read call, and '\r' as the
 # last character will be diminishingly rare anyway.
diff --git a/tools/runner/java/vogar/Driver.java b/tools/runner/java/vogar/Driver.java
index 7b3a833..aaf0cf6 100644
--- a/tools/runner/java/vogar/Driver.java
+++ b/tools/runner/java/vogar/Driver.java
@@ -32,7 +32,6 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.Logger;
 import vogar.commands.Command;
@@ -282,7 +281,7 @@
 
     public void outcome(Outcome outcome) {
         outcomes.put(outcome.getName(), outcome);
-        Expectation expectation = expectationStore.get(outcome.getName());
+        Expectation expectation = expectationStore.get(outcome);
         boolean ok = expectation.matches(outcome);
         if (ok) {
             successes++;
diff --git a/tools/runner/java/vogar/Expectation.java b/tools/runner/java/vogar/Expectation.java
index b52b5a3..d997709 100644
--- a/tools/runner/java/vogar/Expectation.java
+++ b/tools/runner/java/vogar/Expectation.java
@@ -69,32 +69,6 @@
         return result == outcome.getResult() && patternMatches(outcome);
     }
 
-    /**
-     * Returns the failure message for this failed run. This message is intended
-     * to help to diagnose why the run result didn't match what was expected.
-     */
-    public String getFailureMessage(Outcome outcome) {
-        StringBuilder builder = new StringBuilder();
-
-        if (result != Result.SUCCESS && result != outcome.getResult()) {
-            builder.append("Expected result: ")
-                    .append(result)
-                    .append("\n");
-        }
-
-        if (!patternMatches(outcome)) {
-            builder.append("Expected output to match \"")
-                    .append(pattern.pattern())
-                    .append("\"\n");
-        }
-
-        for (String output : outcome.getOutputLines()) {
-            builder.append(output).append("\n");
-        }
-
-        return builder.toString();
-    }
-
     private boolean patternMatches(Outcome outcome) {
         return pattern.matcher(Strings.join(outcome.getOutputLines(), "\n")).matches();
     }
diff --git a/tools/runner/java/vogar/ExpectationStore.java b/tools/runner/java/vogar/ExpectationStore.java
index f10ae22..7d5a758 100644
--- a/tools/runner/java/vogar/ExpectationStore.java
+++ b/tools/runner/java/vogar/ExpectationStore.java
@@ -28,7 +28,18 @@
 import java.util.regex.Pattern;
 
 /**
- * A database of expected outcomes.
+ * A database of expected outcomes. Entries in this database come in two forms.
+ * <ul>
+ *   <li>Outcome expectations name an outcome (or its prefix, such as
+ *       "java.util"), its expected result, and an optional pattern to match
+ *       the expected output.
+ *   <li>Failure expectations include a pattern that may match the output of any
+ *       outcome. These expectations are useful for hiding failures caused by
+ *       cross-cutting features that aren't supported.
+ * </ul>
+ *
+ * <p>If an outcome matches both an outcome expectation and a failure
+ * expectation, the outcome expectation will be returned.
  */
 final class ExpectationStore {
 
@@ -37,26 +48,50 @@
     /** Matches lines in the file containing a key and value pair. */
     private static final Pattern KEY_VALUE_PAIR_PATTERN = Pattern.compile("(\\w+)\\s+(.+)");
 
-    private final Map<String, Expectation> expectedResults;
+    private final Map<String, Expectation> outcomes = new HashMap<String, Expectation>();
+    private final Map<String, Expectation> failures = new HashMap<String, Expectation>();
 
-    private ExpectationStore(Map<String, Expectation> expectedResults) {
-        this.expectedResults = expectedResults;
-    }
+    private ExpectationStore() {}
 
     /**
-     * Finds the expected result for the specified action or outcome. This
+     * Finds the expected result for the specified action or outcome name. This
      * returns a value for all names, even if no explicit expectation was set.
      */
     public Expectation get(String name) {
+        Expectation byName = getByName(name);
+        return byName != null ? byName : Expectation.SUCCESS;
+    }
+
+    /**
+     * Finds the expected result for the specified outcome after it has
+     * completed. Unlike {@code get()}, this also takes into account the
+     * outcome's output.
+     */
+    public Expectation get(Outcome outcome) {
+        Expectation byName = getByName(outcome.getName());
+        if (byName != null) {
+            return byName;
+        }
+
+        for (Map.Entry<String, Expectation> entry : failures.entrySet()) {
+            if (entry.getValue().matches(outcome)) {
+                return entry.getValue();
+            }
+        }
+
+        return Expectation.SUCCESS;
+    }
+
+    private Expectation getByName(String name) {
         while (true) {
-            Expectation expectation = expectedResults.get(name);
+            Expectation expectation = outcomes.get(name);
             if (expectation != null) {
                 return expectation;
             }
 
             int dot = name.lastIndexOf('.');
             if (dot == -1) {
-                return Expectation.SUCCESS;
+                return null;
             }
 
             name = name.substring(0, dot);
@@ -64,26 +99,25 @@
     }
 
     public static ExpectationStore parse(Set<File> expectationFiles) throws IOException {
-        Map<String, Expectation> expectedResults = new HashMap<String, Expectation>();
+        ExpectationStore result = new ExpectationStore();
         for (File f : expectationFiles) {
             if (f.exists()) {
-                expectedResults.putAll(parse(f));
+                result.parse(f);
             }
         }
-        return new ExpectationStore(expectedResults);
+        return result;
     }
 
-
-    public static Map<String, Expectation> parse(File expectationsFile)
-            throws IOException {
+    public void parse(File expectationsFile) throws IOException {
         logger.fine("loading expectations file " + expectationsFile);
 
         BufferedReader reader = new BufferedReader(new FileReader(expectationsFile));
+        int count = 0;
         try {
-            Map<String, Expectation> results = new HashMap<String, Expectation>();
             Matcher keyValuePairMatcher = KEY_VALUE_PAIR_PATTERN.matcher("");
 
             // the fields of interest for the current element
+            String type = null;
             String qualifiedName = null;
             Result result = null;
             String pattern = null;
@@ -110,21 +144,16 @@
                 } else if (key.equals("pattern") && pattern == null) {
                     pattern = value;
 
-                } else if (key.equals("test")) {
+                } else if (key.equals("test") || key.equals("failure")) {
                     // when we encounter a new qualified name, the previous
                     // element is complete. Add it to the results.
                     if (qualifiedName != null) {
-                        Expectation expectation = new Expectation(result, pattern);
-                        Expectation previous = results.put(qualifiedName, expectation);
-                        if (previous != null) {
-                            throw new IllegalArgumentException(
-                                    "Duplicate expectations for " + qualifiedName);
-                        }
-
+                        count++;
+                        put(type, qualifiedName, result, pattern);
                         result = null;
                         pattern = null;
                     }
-
+                    type = key;
                     qualifiedName = value;
 
                 } else {
@@ -135,18 +164,22 @@
 
             // add the last element in the file
             if (qualifiedName != null) {
-                Expectation expectation = new Expectation(result, pattern);
-                Expectation previous = results.put(qualifiedName, expectation);
-                if (previous != null) {
-                    throw new IllegalArgumentException(
-                            "Duplicate expectations for " + qualifiedName);
-                }
+                count++;
+                put(type, qualifiedName, result, pattern);
             }
 
-            logger.fine("loaded " + results.size() + " expectations.");
-            return results;
+            logger.fine("loaded " + count + " expectations from " + expectationsFile);
         } finally {
             reader.close();
         }
     }
+
+    void put(String type, String qualifiedName, Result result, String pattern) {
+        Expectation expectation = new Expectation(result, pattern);
+        Map<String, Expectation> map = "test".equals(type) ? outcomes : failures;
+        if (map.put(qualifiedName, expectation) != null) {
+            throw new IllegalArgumentException(
+                    "Duplicate expectations for " + qualifiedName);
+        }
+    }
 }
diff --git a/tools/runner/java/vogar/XmlReportPrinter.java b/tools/runner/java/vogar/XmlReportPrinter.java
index f8c25fb..59db75d 100644
--- a/tools/runner/java/vogar/XmlReportPrinter.java
+++ b/tools/runner/java/vogar/XmlReportPrinter.java
@@ -122,7 +122,7 @@
 
             suite.outcomes.add(outcome);
 
-            Expectation expectation = expectationStore.get(outcome.getName());
+            Expectation expectation = expectationStore.get(outcome);
             if (!expectation.matches(outcome)) {
                 if (outcome.getResult() == Result.EXEC_FAILED) {
                     suite.failuresCount++;
@@ -169,7 +169,7 @@
             serializer.attribute(ns, ATTR_CLASSNAME, outcome.getSuiteName());
             serializer.attribute(ns, ATTR_TIME, "0");
 
-            Expectation expectation = expectationStore.get(outcome.getName());
+            Expectation expectation = expectationStore.get(outcome);
             if (!expectation.matches(outcome)) {
                 String result = outcome.getResult() == Result.EXEC_FAILED ? FAILURE : ERROR;
                 serializer.startTag(ns, result);