Multi-device support for vm-tests.

Change-Id: I303fa0a34e1a84cd00a8ef6b16ed841ad454265e
diff --git a/tools/vm-tests/Android.mk b/tools/vm-tests/Android.mk
index 9c8051e..f807774 100644
--- a/tools/vm-tests/Android.mk
+++ b/tools/vm-tests/Android.mk
@@ -30,7 +30,7 @@
 LOCAL_MODULE := cts-dalvik-buildutil
 LOCAL_MODULE_CLASS := JAVA_LIBRARIES
 
-LOCAL_JAVA_LIBRARIES := dx dasm cfassembler 
+LOCAL_JAVA_LIBRARIES := dx dasm cfassembler hosttestlib ddmlib
 LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
 
 include $(BUILD_HOST_JAVA_LIBRARY)
@@ -66,12 +66,13 @@
 $(GENERATED_FILES): PRIVATE_INTERMEDIATES := $(intermediates)/tests
 $(GENERATED_FILES): PRIVATE_INTERMEDIATES_MAIN_FILES := $(intermediates)/main_files
 $(GENERATED_FILES): PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES := $(intermediates)/hostjunit_files
-$(GENERATED_FILES): $(HOST_OUT_JAVA_LIBRARIES)/cts-dalvik-buildutil.jar $(HOST_OUT_JAVA_LIBRARIES)/dasm.jar $(HOST_OUT_JAVA_LIBRARIES)/dx.jar $(HOST_OUT_JAVA_LIBRARIES)/cfassembler.jar
+$(GENERATED_FILES): $(HOST_OUT_JAVA_LIBRARIES)/cts-dalvik-buildutil.jar $(HOST_OUT_JAVA_LIBRARIES)/dasm.jar $(HOST_OUT_JAVA_LIBRARIES)/dx.jar $(HOST_OUT_JAVA_LIBRARIES)/cfassembler.jar  $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar $(HOST_OUT_JAVA_LIBRARIES)/ddmlib.jar
+
 	$(hide) mkdir -p $@
 # copy Util class to compile later together with the generated host side junit tests	
 	$(hide) mkdir -p $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/dot/junit && cp $(PRIVATE_SRC_FOLDER)/util/build/DeviceUtil.java.template $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/dot/junit/DeviceUtil.java
 # generated and compile the host side junit tests
-	$(hide) java -cp $(subst $(space),$(colon),$^):$(HOST_JDK_TOOLS_JAR) util.build.BuildDalvikSuite $(PRIVATE_SRC_FOLDER) $(PRIVATE_INTERMEDIATES) $<:$(PRIVATE_LIB_FOLDER)/junit.jar $(PRIVATE_INTERMEDIATES_MAIN_FILES) $(BUILD_UTIL_INTERMEDIATES_CLASSES) $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES) $$RUN_VM_TESTS_RTO
+	$(hide) java -cp $(subst $(space),$(colon),$^):$(HOST_JDK_TOOLS_JAR) util.build.BuildDalvikSuite $(PRIVATE_SRC_FOLDER) $(PRIVATE_INTERMEDIATES) $<:$(PRIVATE_LIB_FOLDER)/junit.jar:$(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar:$(HOST_OUT_JAVA_LIBRARIES)/ddmlib.jar $(PRIVATE_INTERMEDIATES_MAIN_FILES) $(BUILD_UTIL_INTERMEDIATES_CLASSES) $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES) $$RUN_VM_TESTS_RTO
 	@echo "wrote generated Main_*.java files to $(PRIVATE_INTERMEDIATES_MAIN_FILES)"
 INSTALLED_TESTS := $(dir $(LOCAL_INSTALLED_MODULE))../cts_dalviktests/timestamp
 
diff --git a/tools/vm-tests/src/util/build/BuildDalvikSuite.java b/tools/vm-tests/src/util/build/BuildDalvikSuite.java
index a3ff7e3..af130b6 100644
--- a/tools/vm-tests/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests/src/util/build/BuildDalvikSuite.java
@@ -64,7 +64,7 @@
 
     // the folder for the generated junit-files for the cts host (which in turn
     // execute the real vm tests using adb push/shell etc)
-    private static String HOSTJUNIT_SRC_OUTPUT_FOLDER = ""; 
+    private static String HOSTJUNIT_SRC_OUTPUT_FOLDER = "";
     private static String OUTPUT_FOLDER = "";
     private static String COMPILED_CLASSES_FOLDER = "";
 
@@ -77,11 +77,11 @@
     // "opcodes.add_double"
 
     private static final String TARGET_JAR_ROOT_PATH = "/data/local/tmp";
-    
+
     private int testClassCnt = 0;
     private int testMethodsCnt = 0;
-    
-    
+
+
     /*
      * using a linked hashmap to keep the insertion order for iterators.
      * the junit suite/tests adding order is used to generate the order of the
@@ -113,9 +113,9 @@
             CLASSES_OUTPUT_FOLDER = MAIN_SRC_OUTPUT_FOLDER + "/classes";
 
             COMPILED_CLASSES_FOLDER = args[4];
-            
+
             HOSTJUNIT_SRC_OUTPUT_FOLDER = args[5];
-            HOSTJUNIT_CLASSES_OUTPUT_FOLDER = HOSTJUNIT_SRC_OUTPUT_FOLDER 
+            HOSTJUNIT_CLASSES_OUTPUT_FOLDER = HOSTJUNIT_SRC_OUTPUT_FOLDER
                     + "/classes";
 
             if (args.length > 6) {
@@ -193,12 +193,14 @@
         }
         li.add(method);
     }
-    
+
     private static final String ctsAllTestsB =
         "package dot.junit;\n" +
         "import junit.framework.Test;\n" +
         "import junit.framework.TestSuite;\n" +
-        "public class AllJunitHostTests {\n" +
+        "import com.android.hosttest.DeviceTestSuite;\n" +
+        "\n" +
+        "public class AllJunitHostTests extends DeviceTestSuite {\n" +
         "    public static final Test suite() {\n" +
         "        TestSuite suite = new TestSuite(\"CTS Host tests for all " +
         " dalvik vm opcodes\");\n";
@@ -213,7 +215,7 @@
     private String curAllTestsData = ctsAllTestsB;
     private String curJunitFileName = null;
     private String curJunitFileData = "";
-    
+
     private JavacBuildStep javacHostJunitBuildStep;
 
     private void flushHostJunitFile() {
@@ -229,7 +231,7 @@
             curJunitFileData = "";
         }
     }
-    
+
     private void ctsFinish() {
     	flushHostJunitFile();
     	curAllTestsData+="return suite;\n}\n}\n";
@@ -242,35 +244,36 @@
     	javacHostJunitBuildStep.addSourceFile(new File(
     	        HOSTJUNIT_SRC_OUTPUT_FOLDER + "/dot/junit/DeviceUtil.java").
     	        getAbsolutePath());
-    	
     }
-    
+
     private void openCTSHostFileFor(String pName, String classOnlyName) {
         String sourceName = "JUnit_"+classOnlyName;
         // Add to AllTests.java
-        String suiteline = "suite.addTestSuite("+pName+"." + sourceName + 
+        String suiteline = "suite.addTestSuite("+pName+"." + sourceName +
                 ".class);\n";
         curAllTestsData += suiteline;
         // flush previous JunitFile
         flushHostJunitFile();
 
         // prepare current testcase-file
-        curJunitFileName = HOSTJUNIT_SRC_OUTPUT_FOLDER+"/" 
+        curJunitFileName = HOSTJUNIT_SRC_OUTPUT_FOLDER+"/"
                 + pName.replaceAll("\\.","/")+"/"+sourceName+".java";
         curJunitFileData =
             "package "+pName+";\n"+
             "import java.io.IOException;\n"+
             "import junit.framework.TestCase;\n"+
-            "import dot.junit.DeviceUtil;\n"+
-            "public class "+sourceName+" extends TestCase {\n";
+            "import com.android.hosttest.DeviceTestCase;\n"+
+            "import dot.junit.DeviceUtil;\n" +
+            "\n" +
+            "public class "+sourceName+" extends DeviceTestCase {\n";
     }
 
     private String getADBPushJavaLine(String source, String target) {
-        return "DeviceUtil.adbPush(\"" + source + "\", \"" + target + "\");";
+        return "DeviceUtil.adbPush(getDevice(), \"" + source + "\", \"" + target + "\");";
     }
 
     private String getADBExecJavaLine(String classpath, String mainclass) {
-        return "DeviceUtil.adbExec(\"" + classpath + "\", \"" + 
+        return "DeviceUtil.adbExec(getDevice(), \"" + classpath + "\", \"" +
                 mainclass + "\");";
     }
 
@@ -300,18 +303,18 @@
             //System.out.println("adb push "+sourceName+" "+targetName);
             curJunitFileData+= "    "+getADBPushJavaLine(sourceName, targetName);
             cp+= ":"+targetName;
-            // dot.junit.opcodes.invoke_interface_range.ITest 
+            // dot.junit.opcodes.invoke_interface_range.ITest
             // -> dot/junit/opcodes/invoke_interface_range/ITest.jar
         }
 
         //"dot.junit.opcodes.add_double_2addr.Main_testN2";
         String mainclass = pName + ".Main_" + method;
         curJunitFileData+= "    "+getADBExecJavaLine(cp, mainclass);
-        curJunitFileData+= "}\n\n"; 
-    }    
-    
+        curJunitFileData+= "}\n\n";
+    }
+
     private void handleTests() throws IOException {
-        System.out.println("collected "+testMethodsCnt+" test methods in " + 
+        System.out.println("collected "+testMethodsCnt+" test methods in " +
                 testClassCnt+" junit test classes");
         String datafileContent = "";
         Set<BuildStep> targets = new TreeSet<BuildStep>();
@@ -360,9 +363,9 @@
 
                 Set<String> dependentTestClassNames = parseTestClassName(pName,
                         classOnlyName, methodContent);
-                
+
                 addCTSHostMethod(pName, method, md, dependentTestClassNames);
-                
+
 
                 if (dependentTestClassNames.isEmpty()) {
                     continue;
@@ -409,7 +412,7 @@
 
                 char ca = method.charAt("test".length()); // either N,B,E,
                 // or V (VFE)
-                String comment;                
+                String comment;
                 switch (ca) {
                 case 'N':
                     comment = "Normal #" + method.substring(5);
@@ -432,8 +435,8 @@
                 for (String className : dependentTestClassNames) {
                     line += className + " ";
                 }
-                
-                
+
+
                 // test description
                 String[] pparts = pName.split("\\.");
                 // detail e.g. add_double
@@ -460,25 +463,25 @@
 
                     // Unescape reserved words
                     detail = detail.replace("opc-", "");
-                    
+
                     description = detail;
                 } else if ("verify".equals(type)) {
                     description = "verifier";
                 } else {
                     description = type + " " + detail;
-                }                
+                }
 
                 String details = (md.title != null ? md.title : "");
                 if (md.constraint != null) {
                     details = " Constraint " + md.constraint + ", " + details;
                 }
                 if (details.length() != 0) {
-                    details = details.substring(0, 1).toUpperCase() 
+                    details = details.substring(0, 1).toUpperCase()
                             + details.substring(1);
                 }
-                
+
                 line += ";" + description + ";" + comment + ";" + details;
-                
+
                 datafileContent += line + "\n";
                 generateBuildStepFor(pName, method, dependentTestClassNames,
                         targets);
@@ -486,10 +489,10 @@
 
 
         }
-        
+
         // write latest HOSTJUNIT generated file and AllTests.java
         ctsFinish();
-        
+
         File scriptDataDir = new File(OUTPUT_FOLDER + "/data/");
         scriptDataDir.mkdirs();
         writeToFile(new File(scriptDataDir, "scriptdata"), datafileContent);
@@ -497,13 +500,13 @@
         if (!javacHostJunitBuildStep.build()) {
             System.out.println("main javac cts-host-hostjunit-classes build " +
                     "step failed");
-            System.exit(1);        	
+            System.exit(1);
         }
-        
+
         if (javacBuildStep.build()) {
             for (BuildStep buildStep : targets) {
                 if (!buildStep.build()) {
-                    System.out.println("building failed. buildStep: " + 
+                    System.out.println("building failed. buildStep: " +
                             buildStep.getClass().getName()+", "+buildStep);
                     System.exit(1);
                 }
@@ -791,12 +794,12 @@
     private void writeToFileMkdir(File file, String content) {
 	    File parent = file.getParentFile();
 	    if (!parent.exists() && !parent.mkdirs()) {
-	        throw new RuntimeException("failed to create directory: " + 
+	        throw new RuntimeException("failed to create directory: " +
 	                parent.getAbsolutePath());
 	    }
 	    writeToFile(file, content);
-    }    
-    
+    }
+
     private void writeToFile(File file, String content) {
         try {
             if (file.length() == content.length()) {
diff --git a/tools/vm-tests/src/util/build/DeviceUtil.java.template b/tools/vm-tests/src/util/build/DeviceUtil.java.template
index ffb5b8b..4d634d1 100644
--- a/tools/vm-tests/src/util/build/DeviceUtil.java.template
+++ b/tools/vm-tests/src/util/build/DeviceUtil.java.template
@@ -1,10 +1,14 @@
 
 package dot.junit;
 
+
+import com.android.ddmlib.IDevice;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
 import java.util.Scanner;
 
 public class DeviceUtil {
@@ -86,22 +90,19 @@
         }
         return f.getAbsolutePath();
     }
-    
-    public static void adbPush(String source, String target) 
+
+    public static void adbPush(IDevice device, String source, String target)
             throws IOException {
-        DeviceUtil.digestCommand(new String[] {"adb", "push",
+        DeviceUtil.digestCommand(new String[] {"adb", "-s", device.getSerialNumber(), "push",
             DeviceUtil.createFilePath(source), target}, null);
     }
 
-    public static void adbExec(String classpath, String mainclass) {
-        DeviceUtil.digestCommand(new String[] {"adb", "shell", "mkdir", 
-               "/data/local/tmp/dalvik-cache"}, null);
-        DeviceUtil.digestCommand(new String[] {"adb", "shell", "ANDROID_DATA=/data/local/tmp", 
-               "dalvikvm", "-Xint:portable", "-Xmx512M",
-               "-Xss32K", "-Djava.io.tmpdir=/data/local/tmp",
-               "-classpath", classpath, mainclass,
-               "&&", "echo", "mk_dalvikvmok" }, "mk_dalvikvmok");
+    public static void adbExec(IDevice device, String classpath, String mainclass) {
+        DeviceUtil.digestCommand(new String[] {"adb", "-s", device.getSerialNumber(), "shell",
+               "mkdir", "/data/local/tmp/dalvik-cache"}, null);
+        DeviceUtil.digestCommand(new String[] {"adb", "-s", device.getSerialNumber(), "shell",
+               "ANDROID_DATA=/data/local/tmp", "dalvikvm", "-Xint:portable", "-Xmx512M", "-Xss32K",
+               "-Djava.io.tmpdir=/data/local/tmp", "-classpath", classpath, mainclass, "&&",
+               "echo", "mk_dalvikvmok" }, "mk_dalvikvmok");
     }
-    
- 
-}
+ }