Merge change Iacdc919f into eclair

* changes:
  Add a couple helper classes to be used as targets for calling from native code, add some utility functions to get stuff set up in native land, and implement one set of the several tests this all now makes easy(ish).
diff --git a/tests/tests/jni/libjnitest/helper.c b/tests/tests/jni/libjnitest/helper.c
index f61461b..0a8c69a 100644
--- a/tests/tests/jni/libjnitest/helper.c
+++ b/tests/tests/jni/libjnitest/helper.c
@@ -55,6 +55,7 @@
         }
 
         JniTestFunction *function = va_arg(args, JniTestFunction *);
+
         char *oneResult = function(env);
         if (oneResult != NULL) {
             char *newResult;
@@ -68,6 +69,12 @@
             }
             result = newResult;
         }
+
+        jthrowable oneException = (*env)->ExceptionOccurred(env);
+        if (oneException != NULL) {
+            (*env)->ExceptionDescribe(env);
+            (*env)->ExceptionClear(env);
+        }
     }
 
     va_end(args);
diff --git a/tests/tests/jni/libjnitest/macroized_tests.c b/tests/tests/jni/libjnitest/macroized_tests.c
index 3e98e8b..d45ce14 100644
--- a/tests/tests/jni/libjnitest/macroized_tests.c
+++ b/tests/tests/jni/libjnitest/macroized_tests.c
@@ -29,9 +29,22 @@
 #endif
 
 #include "helper.h"
+#include <stdbool.h>
 #include <stdlib.h>
 
 
+/** reference to test class {@code InstanceFromNative} */
+static jclass InstanceFromNative;
+
+/** reference to test class {@code StaticFromNative} */
+static jclass StaticFromNative;
+
+/** reference to field {@code InstanceFromNative.theOne} */
+static jfieldID InstanceFromNative_theOne;
+
+/** how to call a method: standard, array of args, or with a va_list */
+typedef enum { CALL_PLAIN, CALL_ARRAY, CALL_VA } callType;
+
 /*
  * CALL() calls the JNI function with the given name, using a JNIEnv
  * pointer named "env", and passing along any other arguments given.
@@ -47,6 +60,89 @@
 #endif
 
 
+/**
+ * Simple assert-like macro which returns NULL if the two values are
+ * equal, or an error message if they aren't.
+ */
+#define FAIL_IF_UNEQUAL(printfType, expected, actual)          \
+    ((expected) == (actual)) ? NULL :                          \
+        failure("expected " printfType " but got " printfType, \
+                expected, actual);
+
+
+/**
+ * Initializes the static variables. Returns NULL on success or an
+ * error string on failure.
+ */
+static char *initializeVariables(JNIEnv *env) {
+    jclass clazz;
+    jfieldID field;
+
+    clazz = CALL(FindClass, "android/jni/cts/StaticFromNative");
+    if (clazz == NULL) {
+        return failure("could not find StaticFromNative");
+    }
+
+    StaticFromNative = (jclass) CALL(NewGlobalRef, clazz);
+
+    clazz = CALL(FindClass, "android/jni/cts/InstanceFromNative");
+    if (clazz == NULL) {
+        return failure("could not find InstanceFromNative");
+    }
+
+    InstanceFromNative = (jclass) CALL(NewGlobalRef, clazz);
+
+    field = CALL(GetStaticFieldID, InstanceFromNative, "theOne",
+            "Landroid/jni/cts/InstanceFromNative;");
+    if (field == NULL) {
+        return failure("could not find InstanceFromNative.theOne");
+    }
+
+    InstanceFromNative_theOne = field;
+
+    return NULL;
+}
+
+/**
+ * Gets the standard instance of InstanceFromNative.
+ */
+static jobject getStandardInstance(JNIEnv *env) {
+    return CALL(GetStaticObjectField, InstanceFromNative,
+            InstanceFromNative_theOne);
+}
+
+/**
+ * Looks up a static method on StaticFromNative.
+ */
+static jmethodID findStaticMethod(JNIEnv *env, char **errorMsg,
+        const char *name, const char *sig) {
+    jmethodID result = CALL(GetStaticMethodID, StaticFromNative,
+            name, sig);
+
+    if (result == NULL) {
+        *errorMsg = failure("could not find static test method %s:%s",
+                name, sig);
+    }
+
+    return result;
+}
+
+/**
+ * Looks up an instance method on InstanceFromNative.
+ */
+static jmethodID findInstanceMethod(JNIEnv *env, char **errorMsg,
+        const char *name, const char *sig) {
+    jmethodID result = CALL(GetMethodID, InstanceFromNative, name, sig);
+
+    if (result == NULL) {
+        *errorMsg = failure("could not find instance test method %s:%s",
+                name, sig);
+    }
+
+    return result;
+}
+
+
 
 /*
  * The tests.
@@ -54,9 +150,55 @@
 
 // TODO: Missing functions:
 //   AllocObject
-//   CallBooleanMethod
-//   CallBooleanMethodA
-//   CallBooleanMethodV
+
+static char *help_CallBooleanMethod(JNIEnv *env, callType ct, ...) {
+    char *msg;
+    jobject o = getStandardInstance(env);
+    jmethodID method = findInstanceMethod(env, &msg, "returnBoolean", "()Z");
+
+    if (method == NULL) {
+        return msg;
+    }
+
+    jboolean result;
+
+    switch (ct) {
+        case CALL_PLAIN: {
+            result = CALL(CallBooleanMethod, o, method);
+            break;
+        }
+        case CALL_ARRAY: {
+            result = CALL(CallBooleanMethodA, o, method, NULL);
+            break;
+        }
+        case CALL_VA: {
+            va_list args;
+            va_start(args, ct);
+            result = CALL(CallBooleanMethodV, o, method, args);
+            va_end(args);
+            break;
+        }
+        default: {
+            return failure("shouldn't happen");
+        }
+    }
+    
+    return FAIL_IF_UNEQUAL("%d", true, result);
+}
+
+TEST_DECLARATION(CallBooleanMethod) {
+    return help_CallBooleanMethod(env, CALL_PLAIN);
+}
+
+TEST_DECLARATION(CallBooleanMethodA) {
+    return help_CallBooleanMethod(env, CALL_ARRAY);
+}
+
+TEST_DECLARATION(CallBooleanMethodV) {
+    return help_CallBooleanMethod(env, CALL_VA);
+}
+
+// TODO: Missing functions:
 //   CallByteMethod
 //   CallByteMethodA
 //   CallByteMethodV
@@ -111,9 +253,12 @@
 //   CallShortMethod
 //   CallShortMethodA
 //   CallShortMethodV
-//   CallStaticBooleanMethod
-//   CallStaticBooleanMethodA
-//   CallStaticBooleanMethodV
+//   CallStaticBooleanMethod (no args)
+//   CallStaticBooleanMethodA (no args)
+//   CallStaticBooleanMethodV (no args)
+//   CallStaticBooleanMethod (interesting args)
+//   CallStaticBooleanMethodA (interesting args)
+//   CallStaticBooleanMethodV (interesting args)
 //   CallStaticByteMethod
 //   CallStaticByteMethodA
 //   CallStaticByteMethodV
@@ -164,7 +309,7 @@
 //   ExceptionClear
 //   ExceptionDescribe
 //   ExceptionOccurred
-//   FatalError
+//   FatalError (Note: impossible to test in this framework)
 //   FindClass
 //   FromReflectedField
 //   FromReflectedMethod
@@ -313,12 +458,24 @@
  * a string listing information about all the failures.
  */
 static jstring runAllTests(JNIEnv *env) {
-    char *result = runJniTests(env,
-            RUN_TEST(DefineClass),
-            RUN_TEST(GetVersion),
-            NULL);
+    char *result = initializeVariables(env);
 
-    // TODO: Add more tests, above.
+    if (CALL(ExceptionOccurred)) {
+        CALL(ExceptionDescribe);
+        CALL(ExceptionClear);
+    }
+
+    if (result == NULL) {
+        result = runJniTests(env,
+                RUN_TEST(CallBooleanMethod),
+                RUN_TEST(CallBooleanMethodA),
+                RUN_TEST(CallBooleanMethodV),
+                RUN_TEST(DefineClass),
+                RUN_TEST(GetVersion),
+                NULL);
+
+        // TODO: Add more tests, above.
+    }
 
     if (result != NULL) {
         jstring s = CALL(NewStringUTF, result);
diff --git a/tests/tests/jni/src/android/jni/cts/InstanceFromNative.java b/tests/tests/jni/src/android/jni/cts/InstanceFromNative.java
new file mode 100644
index 0000000..5c153d3
--- /dev/null
+++ b/tests/tests/jni/src/android/jni/cts/InstanceFromNative.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.jni.cts;
+
+/**
+ * Class with a bunch of static methods that get called from native
+ * code. See {@code macroized_tests.c} in {@code libjnitest} for more
+ * details.
+ */
+public class InstanceFromNative {
+    /** convenient instance */
+    public static final InstanceFromNative theOne = new InstanceFromNative();
+    
+    /**
+     * Constructs an instance.
+     */
+    public InstanceFromNative() {
+        // This space intentionally left blank.
+    }
+
+    public void nop() {
+        // This space intentionally left blank.
+    }
+
+    public boolean returnBoolean() {
+        return true;
+    }
+    
+    public byte returnByte() {
+        return (byte) 14;
+    }
+    
+    public short returnShort() {
+        return (short) -608;
+    }
+    
+    public char returnChar() {
+        return (char) 9000;
+    }
+    
+    public int returnInt() {
+        return 4004004;
+    }
+    
+    public long returnLong() {
+        return -80080080087L;
+    }
+    
+    public float returnFloat() {
+        return 2.5e22f;
+    }
+    
+    public double returnDouble() {
+        return 7.503e100;
+    }
+    
+    public String returnString() {
+        return "muffins";
+    }
+}
diff --git a/tests/tests/jni/src/android/jni/cts/StaticFromNative.java b/tests/tests/jni/src/android/jni/cts/StaticFromNative.java
new file mode 100644
index 0000000..d1d339c
--- /dev/null
+++ b/tests/tests/jni/src/android/jni/cts/StaticFromNative.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.jni.cts;
+
+/**
+ * Class with a bunch of static methods that get called from native
+ * code. See {@code macroized_tests.c} in {@code libjnitest} for more
+ * details.
+ */
+public class StaticFromNative {
+    /**
+     * This class is uninstantiable.
+     */
+    private StaticFromNative() {
+        // This space intentionally left blank.
+    }
+
+    public static void nop() {
+        // This space intentionally left blank.
+    }
+
+    public static boolean returnBoolean() {
+        return true;
+    }
+    
+    public static byte returnByte() {
+        return (byte) 14;
+    }
+    
+    public static short returnShort() {
+        return (short) -608;
+    }
+    
+    public static char returnChar() {
+        return (char) 9000;
+    }
+    
+    public static int returnInt() {
+        return 4004004;
+    }
+    
+    public static long returnLong() {
+        return -80080080087L;
+    }
+    
+    public static float returnFloat() {
+        return 2.5e22f;
+    }
+    
+    public static double returnDouble() {
+        return 7.503e100;
+    }
+    
+    public static String returnString() {
+        return "muffins";
+    }
+}