Merge "Port the native scanner to cts_v2 bug:14792033" into jb-dev
diff --git a/common/host-side/native-scanner/Android.mk b/common/host-side/native-scanner/Android.mk
index 8d3242f..184cdc0 100644
--- a/common/host-side/native-scanner/Android.mk
+++ b/common/host-side/native-scanner/Android.mk
@@ -22,7 +22,7 @@
 
 LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
 
-LOCAL_JAVA_LIBRARIES := junit
+LOCAL_JAVA_LIBRARIES := compatibility-common-util-hostsidelib_v2
 
 LOCAL_MODULE := compatibility-native-scanner_v2
 
diff --git a/common/host-side/native-scanner/MANIFEST.mf b/common/host-side/native-scanner/MANIFEST.mf
index 86a7212..c5641ca 100644
--- a/common/host-side/native-scanner/MANIFEST.mf
+++ b/common/host-side/native-scanner/MANIFEST.mf
@@ -1,2 +1,3 @@
 Manifest-Version: 1.0
 Main-Class: com.android.compatibility.common.scanner.NativeScanner
+Class-Path: compatibility-common-util-hostsidelib_v2.jar
diff --git a/common/host-side/native-scanner/src/com/android/compatibility/common/scanner/NativeScanner.java b/common/host-side/native-scanner/src/com/android/compatibility/common/scanner/NativeScanner.java
index 581ee0b..7b9e447 100644
--- a/common/host-side/native-scanner/src/com/android/compatibility/common/scanner/NativeScanner.java
+++ b/common/host-side/native-scanner/src/com/android/compatibility/common/scanner/NativeScanner.java
@@ -16,15 +16,69 @@
 
 package com.android.compatibility.common.scanner;
 
+import com.android.compatibility.common.util.KeyValueArgsParser;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+
 /**
  * Passes the gtest output and outputs a list of test classes and methods.
  */
-public class NativeScanner {
+public final class NativeScanner {
 
-    public static void main(String[] args) throws Exception {
-        // TODO(stuartscott): Parse the gtest output comming from System.in and output in the format
-        // suite:com.android.sample.cts
-        // case:SampleDeviceTest
-        // test:testSharedPreferences
+    private static final String TEST_SUITE_ARG = "t";
+    private static final String USAGE = "Usage: compatibility-native-scanner -t TEST_SUITE"
+        + "  This code reads from stdin the list of tests."
+        + "  The format expected:"
+        + "    TEST_CASE_NAME."
+        + "      TEST_NAME";
+
+    /**
+     * @return An {@link ArrayList} of suites, classes and method names.
+     */
+    static ArrayList<String> getTestNames(BufferedReader reader, String testSuite)
+            throws IOException {
+        ArrayList<String> testNames = new ArrayList<String>();
+        testNames.add("suite:" + testSuite);
+
+        String testCaseName = null;
+        String line;
+        while ((line = reader.readLine()) != null) {
+            if (line.length() == 0) {
+                continue;
+            }
+            if (line.charAt(0) == ' ') {
+                if (testCaseName == null) {
+                    throw new RuntimeException("TEST_CASE_NAME not defined before first test.");
+                }
+                testNames.add("test:" + line.trim());
+            } else {
+                testCaseName = line.trim();
+                if (testCaseName.endsWith(".")) {
+                    testCaseName = testCaseName.substring(0, testCaseName.length()-1);
+                }
+                testNames.add("case:" + testCaseName);
+            }
+        }
+        return testNames;
+    }
+
+    /** Lookup test suite argument and scan {@code System.in} for test cases */
+    public static void main(String[] args) throws IOException {
+        HashMap<String, String> argMap = KeyValueArgsParser.parse(args);
+        if (!argMap.containsKey(TEST_SUITE_ARG)) {
+            System.err.println(USAGE);
+            System.exit(1);
+        }
+
+        String testSuite = argMap.get(TEST_SUITE_ARG);
+
+        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+        for (String name : getTestNames(reader, testSuite)) {
+            System.out.println(name);
+        }
     }
 }
diff --git a/common/host-side/native-scanner/tests/src/com/android/compatibility/common/scanner/NativeScannerTest.java b/common/host-side/native-scanner/tests/src/com/android/compatibility/common/scanner/NativeScannerTest.java
index 3e9ba17..c5d3157 100644
--- a/common/host-side/native-scanner/tests/src/com/android/compatibility/common/scanner/NativeScannerTest.java
+++ b/common/host-side/native-scanner/tests/src/com/android/compatibility/common/scanner/NativeScannerTest.java
@@ -16,10 +16,55 @@
 
 package com.android.compatibility.common.scanner;
 
+import com.android.compatibility.common.scanner.NativeScanner;
+
 import junit.framework.TestCase;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.List;
+import java.util.Iterator;
+
 public class NativeScannerTest extends TestCase {
 
-    // TODO(stuartscott): Add tests when there is something to test.
+    public void testSingleTestNamesCase() throws Exception {
+        StringReader singleTestString = new StringReader("FakeTestCase.\n  FakeTestName\n");
+        BufferedReader reader = new BufferedReader(singleTestString);
 
+        List<String> names = NativeScanner.getTestNames(reader, "TestSuite");
+        Iterator<String> it = names.iterator();
+        assertEquals("suite:TestSuite", it.next());
+        assertEquals("case:FakeTestCase", it.next());
+        assertEquals("test:FakeTestName", it.next());
+        assertFalse(it.hasNext());
+    }
+
+    public void testMultipleTestNamesCase() throws Exception {
+        StringReader singleTestString = new StringReader(
+          "Case1.\n  Test1\n  Test2\nCase2.\n  Test3\n Test4\n");
+        BufferedReader reader = new BufferedReader(singleTestString);
+
+        List<String> names = NativeScanner.getTestNames(reader, "TestSuite");
+
+        Iterator<String> it = names.iterator();
+        assertEquals("suite:TestSuite", it.next());
+        assertEquals("case:Case1", it.next());
+        assertEquals("test:Test1", it.next());
+        assertEquals("test:Test2", it.next());
+        assertEquals("case:Case2", it.next());
+        assertEquals("test:Test3", it.next());
+        assertEquals("test:Test4", it.next());
+        assertFalse(it.hasNext());
+    }
+
+    public void testMissingTestCaseNameCase() throws IOException {
+        StringReader singleTestString = new StringReader("  Test1\n");
+        BufferedReader reader = new BufferedReader(singleTestString);
+
+        try {
+            NativeScanner.getTestNames(reader, "TestSuite");
+            fail("Expected RuntimeException");
+        } catch (RuntimeException expected) {}
+    }
 }