Add support for "large" tagged tests to have non-default timeout

Bug: 19657861
Change-Id: Ieba63fa36a139629572eb8b288771b48980d2ef6
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
index 833bf69..328b855 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
@@ -20,6 +20,7 @@
 
 import vogar.Expectation;
 import vogar.ExpectationStore;
+import vogar.Result;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -228,7 +229,8 @@
     }
 
     public static boolean isKnownFailure(ExpectationStore expectationStore, String testName) {
-        return expectationStore != null && expectationStore.get(testName) != Expectation.SUCCESS;
+        return expectationStore != null
+            && expectationStore.get(testName).getResult() != Result.SUCCESS;
     }
 
     // Returns the list of ABIs supported by this TestCase on this architecture.
diff --git a/tools/utils/CollectAllTests.java b/tools/utils/CollectAllTests.java
index 95b77f2..83c451e 100644
--- a/tools/utils/CollectAllTests.java
+++ b/tools/utils/CollectAllTests.java
@@ -447,6 +447,9 @@
                                                                     expectations,
                                                                     testClassName,
                                                                     testName);
+        int timeoutInMinutes = VogarUtils.timeoutInMinutes(expectations,
+                                                           testClassName,
+                                                           testName);
         TestClass testClass;
         if (testCases.containsKey(testClassName)) {
             testClass = testCases.get(testClassName);
@@ -456,7 +459,7 @@
         }
 
         testClass.mCases.add(new TestMethod(testName, "", "", supportedAbis,
-              knownFailure, false, false));
+              knownFailure, false, false, timeoutInMinutes));
     }
 
     private static boolean isJunit3Test(Class<?> klass) {
diff --git a/tools/utils/DescriptionGenerator.java b/tools/utils/DescriptionGenerator.java
index 09e1118..1e2542f 100644
--- a/tools/utils/DescriptionGenerator.java
+++ b/tools/utils/DescriptionGenerator.java
@@ -86,6 +86,7 @@
     static final String ATTRIBUTE_NAME = "name";
     static final String ATTRIBUTE_ABIS = "abis";
     static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
+    static final String ATTRIBUTE_TIMEOUT = "timeout";
 
     static final String XML_OUTPUT_PATH = "./description.xml";
 
@@ -438,6 +439,10 @@
                     if ((caze.mController != null) && (caze.mController.length() != 0)) {
                         setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
                     }
+                    if (caze.mTimeoutInMinutes != 0) {
+                        setAttribute(caseNode, ATTRIBUTE_TIMEOUT,
+                                     Integer.toString(caze.mTimeoutInMinutes));
+                    }
 
                     if (caze.mDescription != null && !caze.mDescription.equals("")) {
                         caseNode.appendChild(mDoc.createElement(TAG_DESCRIPTION))
@@ -573,9 +578,10 @@
                             VogarUtils.buildFullTestName(clazz.toString(), name));
                     Set<String> supportedAbis =
                             VogarUtils.extractSupportedAbis(architecture, expectation);
+                    int timeoutInMinutes = VogarUtils.timeoutInMinutes(expectation);
                     cases.add(new TestMethod(
                             name, method.commentText(), controller, supportedAbis,
-                                    knownFailure, isBroken, isSuppressed));
+                                    knownFailure, isBroken, isSuppressed, timeoutInMinutes));
                 }
             }
 
@@ -635,6 +641,7 @@
         String mKnownFailure;
         boolean mIsBroken;
         boolean mIsSuppressed;
+        int mTimeoutInMinutes;  // zero to use default timeout.
 
         /**
          * Construct an test case object.
@@ -644,7 +651,10 @@
          * @param knownFailure The reason of known failure.
          */
         TestMethod(String name, String description, String controller, Set<String> abis,
-                String knownFailure, boolean isBroken, boolean isSuppressed) {
+                String knownFailure, boolean isBroken, boolean isSuppressed, int timeoutInMinutes) {
+            if (timeoutInMinutes < 0) {
+                throw new IllegalArgumentException("timeoutInMinutes < 0: " + timeoutInMinutes);
+            }
             mName = name;
             mDescription = description;
             mController = controller;
@@ -652,6 +662,7 @@
             mKnownFailure = knownFailure;
             mIsBroken = isBroken;
             mIsSuppressed = isSuppressed;
+            mTimeoutInMinutes = timeoutInMinutes;
         }
     }
 }
diff --git a/tools/utils/VogarUtils.java b/tools/utils/VogarUtils.java
index 5e8b944..8e77e7c 100644
--- a/tools/utils/VogarUtils.java
+++ b/tools/utils/VogarUtils.java
@@ -19,6 +19,7 @@
 import vogar.Expectation;
 import vogar.ExpectationStore;
 import vogar.ModeId;
+import vogar.Result;
 
 import java.io.File;
 import java.io.FilenameFilter;
@@ -52,14 +53,14 @@
         }
         String fullTestName = buildFullTestName(testClassName, testMethodName);
         Expectation expectation = expectationStore.get(fullTestName);
-        if (expectation == Expectation.SUCCESS) {
+        if (expectation.getResult() == Result.SUCCESS) {
             return false;
         }
 
         String description = expectation.getDescription();
         boolean foundAbi = AbiUtils.parseAbiList(description).size() > 0;
 
-        return expectation != Expectation.SUCCESS && !foundAbi;
+        return expectation.getResult() != Result.SUCCESS && !foundAbi;
     }
 
     public static ExpectationStore provideExpectationStore(String dir) throws IOException {
@@ -119,7 +120,7 @@
                                                    String className,
                                                    String testName) {
 
-        String fullTestName = VogarUtils.buildFullTestName(className, testName);
+        String fullTestName = buildFullTestName(className, testName);
         Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
         for (ExpectationStore expectationStore : expectationStores) {
             Expectation expectation = expectationStore.get(fullTestName);
@@ -128,4 +129,44 @@
 
         return supportedAbiSet;
     }
+
+    /**
+     * Returns the greatest timeout in minutes for the test in all
+     * expectation stores, or 0 if no timeout was found.
+     */
+    public static int timeoutInMinutes(ExpectationStore[] expectationStores,
+            final String testClassName,
+            final String testMethodName) {
+        int timeoutInMinutes = 0;
+        for (ExpectationStore expectationStore : expectationStores) {
+            timeoutInMinutes = Math.max(timeoutInMinutes,
+                                        timeoutInMinutes(expectationStore,
+                                                         testClassName,
+                                                         testMethodName));
+        }
+        return timeoutInMinutes;
+    }
+
+    /**
+     * Returns the timeout in minutes for the test in the expectation
+     * stores, or 0 if no timeout was found.
+     */
+    public static int timeoutInMinutes(ExpectationStore expectationStore,
+            final String testClassName,
+            final String testMethodName) {
+        if (expectationStore == null) {
+            return 0;
+        }
+        String fullTestName = buildFullTestName(testClassName, testMethodName);
+        return timeoutInMinutes(expectationStore.get(fullTestName));
+    }
+
+    /**
+     * Returns the timeout in minutes for the expectation. Currently a
+     * tag of large results in a 60 minute timeout, otherwise 0 is
+     * returned to indicate a default timeout should be used.
+     */
+    public static int timeoutInMinutes(Expectation expectation) {
+        return expectation.getTags().contains("large") ? 60 : 0;
+    }
 }