Runtest support for tests that need 'make' not 'mmm' to build.

Change-Id: I0508db2578826249f9bf4756d5adc6f95e841231
diff --git a/testrunner/runtest.py b/testrunner/runtest.py
index d53312f..8975303 100755
--- a/testrunner/runtest.py
+++ b/testrunner/runtest.py
@@ -222,9 +222,12 @@
 
   def _DoBuild(self):
     logger.SilentLog("Building tests...")
+
+    tests = self._GetTestsToRun()
+    self._DoFullBuild(tests)
+
     target_set = Set()
     extra_args_set = Set()
-    tests = self._GetTestsToRun()
     for test_suite in tests:
       self._AddBuildTarget(test_suite, target_set, extra_args_set)
 
@@ -232,21 +235,8 @@
       if self._options.coverage:
         coverage.EnableCoverageBuild()
 
-      # hack to build cts dependencies
-      # TODO: remove this when build dependency support added to runtest or
-      # cts dependencies are removed
-      if self._IsCtsTests(tests):
-        # need to use make since these fail building with ONE_SHOT_MAKEFILE
-        cmd = ('make -j%s CtsTestStubs android.core.tests.runner' %
-               self._options.make_jobs)
-        logger.Log(cmd)
-        if not self._options.preview:
-          old_dir = os.getcwd()
-          os.chdir(self._root_path)
-          run_command.RunCommand(cmd, return_output=False)
-          os.chdir(old_dir)
-      target_build_string = " ".join(list(target_set))
-      extra_args_string = " ".join(list(extra_args_set))
+      target_build_string = ' '.join(list(target_set))
+      extra_args_string = ' '.join(list(extra_args_set))
       # mmm cannot be used from python, so perform a similar operation using
       # ONE_SHOT_MAKEFILE
       cmd = 'ONE_SHOT_MAKEFILE="%s" make -j%s -C "%s" files %s' % (
@@ -263,12 +253,43 @@
         logger.Log("Syncing to device...")
         self._adb.Sync()
 
+  def _DoFullBuild(self, tests):
+    """If necessary, run a full 'make' command for the tests that need it."""
+    extra_args_set = Set()
+
+    # hack to build cts dependencies
+    # TODO: remove this when cts dependencies are removed
+    if self._IsCtsTests(tests):
+      # need to use make since these fail building with ONE_SHOT_MAKEFILE
+      extra_args_set.add('CtsTestStubs')
+      extra_args_set.add('android.core.tests.runner')
+    for test in tests:
+      if test.IsFullMake():
+        if test.GetExtraBuildArgs():
+          # extra args contains the args to pass to 'make'
+          extra_args_set.add(test.GetExtraBuildArgs())
+        else:
+          logger.Log("Warning: test %s needs a full build but does not specify"
+                     " extra_build_args" % test.GetName())
+
+    # check if there is actually any tests that required a full build
+    if extra_args_set:
+      cmd = ('make -j%s %s' % (self._options.make_jobs,
+                               ' '.join(list(extra_args_set))))
+      logger.Log(cmd)
+      if not self._options.preview:
+        old_dir = os.getcwd()
+        os.chdir(self._root_path)
+        run_command.RunCommand(cmd, return_output=False)
+        os.chdir(old_dir)
+
   def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
-    build_dir = test_suite.GetBuildPath()
-    if self._AddBuildTargetPath(build_dir, target_set):
-      extra_args_set.add(test_suite.GetExtraBuildArgs())
-    for path in test_suite.GetBuildDependencies(self._options):
-      self._AddBuildTargetPath(path, target_set)
+    if not test_suite.IsFullMake():
+      build_dir = test_suite.GetBuildPath()
+      if self._AddBuildTargetPath(build_dir, target_set):
+        extra_args_set.add(test_suite.GetExtraBuildArgs())
+      for path in test_suite.GetBuildDependencies(self._options):
+        self._AddBuildTargetPath(path, target_set)
 
   def _AddBuildTargetPath(self, build_dir, target_set):
     if build_dir is not None:
diff --git a/testrunner/test_defs.xml b/testrunner/test_defs.xml
index 47aa426..9263b63 100644
--- a/testrunner/test_defs.xml
+++ b/testrunner/test_defs.xml
@@ -484,9 +484,9 @@
 <test-native name="libjingle"
     build_path="vendor/google/libraries/libjingle"
     description="Libjingle."
+    full_make="true"
     extra_build_args="LIBJINGLE_TESTS=1" />
 
-
 <!-- host java tests -->
 <test-host name="cts-appsecurity"
     build_path="cts/tests/appsecurity-tests"
diff --git a/testrunner/test_defs.xsd b/testrunner/test_defs.xsd
index 7134459..6781941 100644
--- a/testrunner/test_defs.xsd
+++ b/testrunner/test_defs.xsd
@@ -41,7 +41,7 @@
         <xs:attribute name="name" type="xs:string" use="required" />
 
         <!-- File system path, relative to Android build root, to this
-        package's Android.mk file. -->
+        package's Android.mk file.-->
         <xs:attribute name="build_path" type="xs:string" use="required" />
 
         <!-- Include test in continuous test system. -->
@@ -55,10 +55,17 @@
         test. -->
         <xs:attribute name="description" type="xs:string" use="optional" />
 
+        <!-- Specifies that a full 'make', as opposed to 'mmm' command, is
+        needed to build this test. The build command used will be
+        'make extra_build_args' -->
+        <xs:attribute name="full_make" type="xs:boolean"
+                    use="optional" />
+
         <!--  Extra arguments to append to build command when building this
         test. -->
         <xs:attribute name="extra_build_args" type="xs:string"
                     use="optional" />
+
     </xs:complexType>
 
     <!-- Java on device instrumentation test.
diff --git a/testrunner/test_defs/test_suite.py b/testrunner/test_defs/test_suite.py
index 90d5792..102a738 100644
--- a/testrunner/test_defs/test_suite.py
+++ b/testrunner/test_defs/test_suite.py
@@ -32,6 +32,7 @@
     self._suite = None
     self._description = ''
     self._extra_build_args = ''
+    self._is_full_make = False
 
   def GetName(self):
     return self._name
@@ -88,6 +89,13 @@
     self._extra_build_args = build_args
     return self
 
+  def IsFullMake(self):
+    return self._is_full_make
+
+  def SetIsFullMake(self, full_make):
+    self._is_full_make = full_make
+    return self
+
   def Run(self, options, adb):
     """Runs the test.
 
diff --git a/testrunner/test_defs/xml_suite_helper.py b/testrunner/test_defs/xml_suite_helper.py
index b7ed83b..6cf2e6c 100644
--- a/testrunner/test_defs/xml_suite_helper.py
+++ b/testrunner/test_defs/xml_suite_helper.py
@@ -39,6 +39,7 @@
   _SUITE_ATTR = 'suite'
   _DESCRIPTION_ATTR = 'description'
   _EXTRA_BUILD_ARGS_ATTR = 'extra_build_args'
+  _FULL_MAKE_ATTR = 'full_make'
 
   def Parse(self, element):
     """Populates common suite attributes from given suite xml element.
@@ -79,6 +80,9 @@
                                                    default_value=''))
     test_suite.SetExtraBuildArgs(self._ParseAttribute(
         suite_element, self._EXTRA_BUILD_ARGS_ATTR, False, default_value=''))
+    test_suite.SetIsFullMake(self._ParseAttribute(
+        suite_element, self._FULL_MAKE_ATTR, False, default_value=False))
+
 
   def _ParseAttribute(self, suite_element, attribute_name, mandatory,
                       default_value=None):