summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorAssam Boudjelthia <assam.boudjelthia@qt.io>2021-01-14 12:38:04 +0200
committerAssam Boudjelthia <assam.boudjelthia@qt.io>2021-01-27 17:23:04 +0200
commit4e60681c879a54cf5b34862a30e27c492ed36363 (patch)
tree01c7d46ae34a6596fa235eea915846b66e7e8670 /tests
parent407ce5c0afd905b38a7d82980a76ed834fc971eb (diff)
Make QJniObject and QJniEnvironment public API
As part of Qt 6 restructring for the extras modules, this change exposes the Jni APIs which are very important for Android platform. This patch adds the APIs QJniObject, QJniEnvironment, QJniExceptionCleaner based from private QtCore and QtAndroidExtras. The Jni interface is cross-platform which justifies the name, but currently, this API is used mainly for Android, and the naming comes generic without Android keyword to avoid any future limitation on supporting other platforms. [ChangeLog][QtCore] Add new QJniObject, QJniEnvironment and QJniExceptionCleaner APIs. Task-number: QTBUG-89482 Fixes: QTBUG-89633 Change-Id: I4382dd53a225375759b9d042f6035a4a9810572b Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/corelib/kernel/CMakeLists.txt4
-rw-r--r--tests/auto/corelib/kernel/qjnienvironment/CMakeLists.txt8
-rw-r--r--tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp106
-rw-r--r--tests/auto/corelib/kernel/qjniobject/CMakeLists.txt16
-rw-r--r--tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java177
-rw-r--r--tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp1054
6 files changed, 1365 insertions, 0 deletions
diff --git a/tests/auto/corelib/kernel/CMakeLists.txt b/tests/auto/corelib/kernel/CMakeLists.txt
index bb7a665c76..3326070727 100644
--- a/tests/auto/corelib/kernel/CMakeLists.txt
+++ b/tests/auto/corelib/kernel/CMakeLists.txt
@@ -45,3 +45,7 @@ endif()
if(QT_FEATURE_private_tests)
add_subdirectory(qproperty)
endif()
+if(ANDROID AND NOT ANDROID_EMBEDDED)
+ add_subdirectory(qjnienvironment)
+ add_subdirectory(qjniobject)
+endif()
diff --git a/tests/auto/corelib/kernel/qjnienvironment/CMakeLists.txt b/tests/auto/corelib/kernel/qjnienvironment/CMakeLists.txt
new file mode 100644
index 0000000000..b6c88ede33
--- /dev/null
+++ b/tests/auto/corelib/kernel/qjnienvironment/CMakeLists.txt
@@ -0,0 +1,8 @@
+#####################################################################
+## tst_qjnienvironment Test:
+#####################################################################
+
+qt_internal_add_test(tst_qjnienvironment
+ SOURCES
+ tst_qjnienvironment.cpp
+)
diff --git a/tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp b/tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp
new file mode 100644
index 0000000000..08cf0e4831
--- /dev/null
+++ b/tests/auto/corelib/kernel/qjnienvironment/tst_qjnienvironment.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QJniEnvironment>
+#include <QtTest/QtTest>
+
+class tst_QJniEnvironment : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void jniEnv();
+ void javaVM();
+};
+
+void tst_QJniEnvironment::jniEnv()
+{
+ QJniEnvironment env;
+ JavaVM *javaVM = env.javaVM();
+ QVERIFY(javaVM);
+
+ {
+ // JNI environment should now be attached to the current thread
+ JNIEnv *jni = 0;
+ QCOMPARE(javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_OK);
+
+ JNIEnv *e = env;
+ QVERIFY(e);
+
+ QCOMPARE(env->GetVersion(), JNI_VERSION_1_6);
+
+ // try to find an existing class
+ QVERIFY(env->FindClass("java/lang/Object"));
+ QVERIFY(!env->ExceptionCheck());
+
+ // try to find a nonexistent class
+ QVERIFY(!env->FindClass("this/doesnt/Exist"));
+ QVERIFY(env->ExceptionCheck());
+ env->ExceptionClear();
+
+ QVERIFY(env->FindClass("java/lang/Object"));
+ QVERIFY(!QJniEnvironment::exceptionCheckAndClear(env));
+
+ // try to find a nonexistent class
+ QVERIFY(!env->FindClass("this/doesnt/Exist"));
+ QVERIFY(QJniEnvironment::exceptionCheckAndClear(env));
+
+ // try to find an existing class with QJniEnvironment
+ QJniEnvironment env;
+ QVERIFY(env.findClass("java/lang/Object"));
+
+ // try to find a nonexistent class
+ QVERIFY(!env.findClass("this/doesnt/Exist"));
+
+ // clear exception with member function
+ QVERIFY(!env->FindClass("this/doesnt/Exist"));
+ QVERIFY(env.exceptionCheckAndClear());
+ }
+
+ // The env does not detach automatically, even if it goes out of scope. The only way it can
+ // be detached is if it's done explicitly, or if the thread we attached to gets killed (TLS clean-up).
+ JNIEnv *jni = nullptr;
+ QCOMPARE(javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_OK);
+}
+
+void tst_QJniEnvironment::javaVM()
+{
+ QJniEnvironment env;
+ JavaVM *javaVM = env.javaVM();
+ QVERIFY(javaVM);
+
+ QCOMPARE(env.javaVM(), javaVM);
+
+ JavaVM *vm = 0;
+ QCOMPARE(env->GetJavaVM(&vm), JNI_OK);
+ QCOMPARE(env.javaVM(), vm);
+}
+
+QTEST_MAIN(tst_QJniEnvironment)
+
+#include "tst_qjnienvironment.moc"
diff --git a/tests/auto/corelib/kernel/qjniobject/CMakeLists.txt b/tests/auto/corelib/kernel/qjniobject/CMakeLists.txt
new file mode 100644
index 0000000000..b0f5d0b640
--- /dev/null
+++ b/tests/auto/corelib/kernel/qjniobject/CMakeLists.txt
@@ -0,0 +1,16 @@
+#####################################################################
+## tst_qjniobject Test:
+#####################################################################
+
+qt_internal_add_test(tst_qjniobject
+ SOURCES
+ tst_qjniobject.cpp
+)
+
+if(ANDROID)
+ set_property(TARGET tst_qjniobject APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
+ ${CMAKE_CURRENT_SOURCE_DIR}/testdata
+ )
+ # QTBUG-88840 # special case
+ qt_android_generate_deployment_settings(tst_qjniobject) # special case
+endif()
diff --git a/tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java b/tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java
new file mode 100644
index 0000000000..4d6db749a5
--- /dev/null
+++ b/tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.qt.android.testdatapackage;
+
+public class QtJniObjectTestClass
+{
+ static final byte A_BYTE_VALUE = 127;
+ static final short A_SHORT_VALUE = 32767;
+ static final int A_INT_VALUE = 060701;
+ static final long A_LONG_VALUE = 060701;
+ static final float A_FLOAT_VALUE = 1.0f;
+ static final double A_DOUBLE_VALUE = 1.0;
+ static final boolean A_BOOLEAN_VALUE = true;
+ static final char A_CHAR_VALUE = 'Q';
+ static final String A_STRING_OBJECT = "TEST_DATA_STRING";
+ static final Class A_CLASS_OBJECT = QtJniObjectTestClass.class;
+ static final Object A_OBJECT_OBJECT = new QtJniObjectTestClass();
+ static final Throwable A_THROWABLE_OBJECT = new Throwable(A_STRING_OBJECT);
+
+ // --------------------------------------------------------------------------------------------
+ public static void staticVoidMethod() { return; }
+ public static void staticVoidMethodWithArgs(int a, boolean b, char c) { return; }
+
+ public void voidMethod() { return; }
+ public void voidMethodWithArgs(int a, boolean b, char c) { return; }
+
+ // --------------------------------------------------------------------------------------------
+ public static boolean staticBooleanMethod() { return A_BOOLEAN_VALUE; }
+ public static boolean staticBooleanMethodWithArgs(boolean a, boolean b, boolean c)
+ { return staticBooleanMethod(); }
+
+ public boolean booleanMethod() { return staticBooleanMethod(); }
+ public boolean booleanMethodWithArgs(boolean a, boolean b, boolean c)
+ { return staticBooleanMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static byte staticByteMethod() { return A_BYTE_VALUE; }
+ public static byte staticByteMethodWithArgs(byte a, byte b, byte c) { return staticByteMethod(); }
+
+ public byte byteMethod() { return staticByteMethod(); }
+ public byte byteMethodWithArgs(byte a, byte b, byte c)
+ { return staticByteMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static char staticCharMethod() { return A_CHAR_VALUE; }
+ public static char staticCharMethodWithArgs(char a, char b, char c) { return staticCharMethod(); }
+
+ public char charMethod() { return staticCharMethod(); }
+ public char charMethodWithArgs(char a, char b, char c)
+ { return staticCharMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static short staticShortMethod() { return A_SHORT_VALUE; }
+ public static short staticShortMethodWithArgs(short a, short b, short c) { return staticShortMethod(); }
+
+ public short shortMethod() { return staticShortMethod(); }
+ public short shortMethodWithArgs(short a, short b, short c)
+ { return staticShortMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static int staticIntMethod() { return A_INT_VALUE; }
+ public static int staticIntMethodWithArgs(int a, int b, int c) { return staticIntMethod(); }
+
+ public int intMethod() { return staticIntMethod(); }
+ public int intMethodWithArgs(int a, int b, int c) { return staticIntMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static long staticLongMethod() { return A_LONG_VALUE; }
+ public static long staticLongMethodWithArgs(long a, long b, long c) { return staticLongMethod(); }
+
+ public long longMethod() { return staticLongMethod(); }
+ public long longMethodWithArgs(long a, long b, long c)
+ { return staticLongMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static float staticFloatMethod() { return A_FLOAT_VALUE; }
+ public static float staticFloatMethodWithArgs(float a, float b, float c) { return staticFloatMethod(); }
+
+ public float floatMethod() { return staticFloatMethod(); }
+ public float floatMethodWithArgs(float a, float b, float c)
+ { return staticFloatMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static double staticDoubleMethod() { return A_DOUBLE_VALUE; }
+ public static double staticDoubleMethodWithArgs(double a, double b, double c)
+ { return staticDoubleMethod(); }
+
+ public double doubleMethod() { return staticDoubleMethod(); }
+ public double doubleMethodWithArgs(double a, double b, double c)
+ { return staticDoubleMethodWithArgs(a, b, c); }
+
+ // --------------------------------------------------------------------------------------------
+ public static Object staticObjectMethod() { return A_OBJECT_OBJECT; }
+ public Object objectMethod() { return staticObjectMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static Class staticClassMethod() { return A_CLASS_OBJECT; }
+ public Class classMethod() { return staticClassMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static String staticStringMethod() { return A_STRING_OBJECT; }
+ public String stringMethod() { return staticStringMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static Throwable staticThrowableMethod() { return A_THROWABLE_OBJECT; }
+ public Throwable throwableMethod() { return staticThrowableMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static Object[] staticObjectArrayMethod()
+ { Object[] array = { new Object(), new Object(), new Object() }; return array; }
+ public Object[] objectArrayMethod() { return staticObjectArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static boolean[] staticBooleanArrayMethod()
+ { boolean[] array = { true, true, true }; return array; }
+ public boolean[] booleanArrayMethod() { return staticBooleanArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static byte[] staticByteArrayMethod()
+ { byte[] array = { 'a', 'b', 'c' }; return array; }
+ public byte[] byteArrayMethod() { return staticByteArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static char[] staticCharArrayMethod()
+ { char[] array = { 'a', 'b', 'c' }; return array; }
+ public char[] charArrayMethod() { return staticCharArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static short[] staticShortArrayMethod() { short[] array = { 3, 2, 1 }; return array; }
+ public short[] shortArrayMethod() { return staticShortArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static int[] staticIntArrayMethod() { int[] array = { 3, 2, 1 }; return array; }
+ public int[] intArrayMethod() { return staticIntArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static long[] staticLongArrayMethod()
+ { long[] array = { 3, 2, 1 }; return array; }
+ public long[] longArrayMethod() { return staticLongArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static float[] staticFloatArrayMethod()
+ { float[] array = { 1.0f, 2.0f, 3.0f }; return array; }
+ public float[] floatArrayMethod() { return staticFloatArrayMethod(); }
+
+ // --------------------------------------------------------------------------------------------
+ public static double[] staticDoubleArrayMethod()
+ { double[] array = { 3.0, 2.0, 1.0 }; return array; }
+ public double[] doubleArrayMethod() { return staticDoubleArrayMethod(); }
+}
+
diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
new file mode 100644
index 0000000000..96637a72a6
--- /dev/null
+++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
@@ -0,0 +1,1054 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QString>
+#include <QtCore/QJniEnvironment>
+#include <QtCore/QJniObject>
+#include <QtTest>
+
+static const char testClassName[] = "org/qtproject/qt/android/testdatapackage/QtJniObjectTestClass";
+
+static const jbyte A_BYTE_VALUE = 127;
+static const jshort A_SHORT_VALUE = 32767;
+static const jint A_INT_VALUE = 060701;
+static const jlong A_LONG_VALUE = 060701;
+static const jfloat A_FLOAT_VALUE = 1.0;
+static const jdouble A_DOUBLE_VALUE = 1.0;
+static const jchar A_CHAR_VALUE = 'Q';
+
+static QString A_STRING_OBJECT()
+{
+ return QStringLiteral("TEST_DATA_STRING");
+}
+
+class tst_QJniObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QJniObject();
+
+private slots:
+ void initTestCase();
+
+ void ctor();
+ void callMethodTest();
+ void callObjectMethodTest();
+ void stringConvertionTest();
+ void compareOperatorTests();
+ void callStaticObjectMethodClassName();
+ void callStaticObjectMethod();
+ void callStaticBooleanMethodClassName();
+ void callStaticBooleanMethod();
+ void callStaticCharMethodClassName();
+ void callStaticCharMethod();
+ void callStaticIntMethodClassName();
+ void callStaticIntMethod();
+ void callStaticByteMethodClassName();
+ void callStaticByteMethod();
+ void callStaticDoubleMethodClassName();
+ void callStaticDoubleMethod();
+ void callStaticFloatMethodClassName();
+ void callStaticFloatMethod();
+ void callStaticLongMethodClassName();
+ void callStaticLongMethod();
+ void callStaticShortMethodClassName();
+ void callStaticShortMethod();
+ void getStaticObjectFieldClassName();
+ void getStaticObjectField();
+ void getStaticIntFieldClassName();
+ void getStaticIntField();
+ void getStaticByteFieldClassName();
+ void getStaticByteField();
+ void getStaticLongFieldClassName();
+ void getStaticLongField();
+ void getStaticDoubleFieldClassName();
+ void getStaticDoubleField();
+ void getStaticFloatFieldClassName();
+ void getStaticFloatField();
+ void getStaticShortFieldClassName();
+ void getStaticShortField();
+ void getStaticCharFieldClassName();
+ void getStaticCharField();
+ void getBooleanField();
+ void getIntField();
+ void templateApiCheck();
+ void isClassAvailable();
+ void fromLocalRef();
+
+ void cleanupTestCase();
+};
+
+tst_QJniObject::tst_QJniObject()
+{
+}
+
+void tst_QJniObject::initTestCase()
+{
+}
+
+void tst_QJniObject::cleanupTestCase()
+{
+}
+
+void tst_QJniObject::ctor()
+{
+ {
+ QJniObject object;
+ QVERIFY(!object.isValid());
+ }
+
+ {
+ QJniObject object("java/lang/String");
+ QVERIFY(object.isValid());
+ }
+
+ {
+ QJniObject string = QJniObject::fromString(QLatin1String("Hello, Java"));
+ QJniObject object("java/lang/String", "(Ljava/lang/String;)V", string.object<jstring>());
+ QVERIFY(object.isValid());
+ QCOMPARE(string.toString(), object.toString());
+ }
+
+ {
+ QJniEnvironment env;
+ jclass javaStringClass = env->FindClass("java/lang/String");
+ QJniObject string(javaStringClass);
+ QVERIFY(string.isValid());
+ }
+
+ {
+ QJniEnvironment env;
+ const QString qString = QLatin1String("Hello, Java");
+ jclass javaStringClass = env->FindClass("java/lang/String");
+ QJniObject string = QJniObject::fromString(qString);
+ QJniObject stringCpy(javaStringClass, "(Ljava/lang/String;)V", string.object<jstring>());
+ QVERIFY(stringCpy.isValid());
+ QCOMPARE(qString, stringCpy.toString());
+ }
+}
+
+void tst_QJniObject::callMethodTest()
+{
+ {
+ QJniObject jString1 = QJniObject::fromString(QLatin1String("Hello, Java"));
+ QJniObject jString2 = QJniObject::fromString(QLatin1String("hELLO, jAVA"));
+ QVERIFY(jString1 != jString2);
+
+ const jboolean isEmpty = jString1.callMethod<jboolean>("isEmpty");
+ QVERIFY(!isEmpty);
+
+ const jint ret = jString1.callMethod<jint>("compareToIgnoreCase",
+ "(Ljava/lang/String;)I",
+ jString2.object<jstring>());
+ QVERIFY(0 == ret);
+ }
+
+ {
+ jlong jLong = 100;
+ QJniObject longObject("java/lang/Long", "(J)V", jLong);
+ jlong ret = longObject.callMethod<jlong>("longValue");
+ QCOMPARE(ret, jLong);
+ }
+}
+
+void tst_QJniObject::callObjectMethodTest()
+{
+ const QString qString = QLatin1String("Hello, Java");
+ QJniObject jString = QJniObject::fromString(qString);
+ const QString qStringRet = jString.callObjectMethod<jstring>("toUpperCase").toString();
+ QCOMPARE(qString.toUpper(), qStringRet);
+
+ QJniObject subString = jString.callObjectMethod("substring",
+ "(II)Ljava/lang/String;",
+ 0, 4);
+ QCOMPARE(subString.toString(), qString.mid(0, 4));
+}
+
+void tst_QJniObject::stringConvertionTest()
+{
+ const QString qString(QLatin1String("Hello, Java"));
+ QJniObject jString = QJniObject::fromString(qString);
+ QVERIFY(jString.isValid());
+ QString qStringRet = jString.toString();
+ QCOMPARE(qString, qStringRet);
+}
+
+void tst_QJniObject::compareOperatorTests()
+{
+ QString str("hello!");
+ QJniObject stringObject = QJniObject::fromString(str);
+
+ jobject obj = stringObject.object();
+ jobject jobj = stringObject.object<jobject>();
+ jstring jsobj = stringObject.object<jstring>();
+
+ QVERIFY(obj == stringObject);
+ QVERIFY(jobj == stringObject);
+ QVERIFY(stringObject == jobj);
+ QVERIFY(jsobj == stringObject);
+ QVERIFY(stringObject == jsobj);
+
+ QJniObject stringObject3 = stringObject.object<jstring>();
+ QVERIFY(stringObject3 == stringObject);
+
+ QJniObject stringObject2 = QJniObject::fromString(str);
+ QVERIFY(stringObject != stringObject2);
+
+ jstring jstrobj = 0;
+ QJniObject invalidStringObject;
+ QVERIFY(invalidStringObject == jstrobj);
+
+ QVERIFY(jstrobj != stringObject);
+ QVERIFY(stringObject != jstrobj);
+ QVERIFY(!invalidStringObject.isValid());
+}
+
+void tst_QJniObject::callStaticObjectMethodClassName()
+{
+ QJniObject formatString = QJniObject::fromString(QLatin1String("test format"));
+ QVERIFY(formatString.isValid());
+
+ QVERIFY(QJniObject::isClassAvailable("java/lang/String"));
+ QJniObject returnValue = QJniObject::callStaticObjectMethod("java/lang/String",
+ "format",
+ "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;",
+ formatString.object<jstring>(),
+ jobjectArray(0));
+ QVERIFY(returnValue.isValid());
+
+ QString returnedString = returnValue.toString();
+
+ QCOMPARE(returnedString, QString::fromLatin1("test format"));
+}
+
+void tst_QJniObject::callStaticObjectMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/String");
+ QVERIFY(cls != 0);
+
+ QJniObject formatString = QJniObject::fromString(QLatin1String("test format"));
+ QVERIFY(formatString.isValid());
+
+ QJniObject returnValue = QJniObject::callStaticObjectMethod(cls,
+ "format",
+ "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;",
+ formatString.object<jstring>(),
+ jobjectArray(0));
+ QVERIFY(returnValue.isValid());
+
+ QString returnedString = returnValue.toString();
+
+ QCOMPARE(returnedString, QString::fromLatin1("test format"));
+}
+
+void tst_QJniObject::callStaticBooleanMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Boolean");
+ QVERIFY(cls != 0);
+
+ {
+ QJniObject parameter = QJniObject::fromString("true");
+ QVERIFY(parameter.isValid());
+
+ jboolean b = QJniObject::callStaticMethod<jboolean>(cls,
+ "parseBoolean",
+ "(Ljava/lang/String;)Z",
+ parameter.object<jstring>());
+ QVERIFY(b);
+ }
+
+ {
+ QJniObject parameter = QJniObject::fromString("false");
+ QVERIFY(parameter.isValid());
+
+ jboolean b = QJniObject::callStaticMethod<jboolean>(cls,
+ "parseBoolean",
+ "(Ljava/lang/String;)Z",
+ parameter.object<jstring>());
+ QVERIFY(!b);
+ }
+}
+
+void tst_QJniObject::callStaticBooleanMethodClassName()
+{
+ {
+ QJniObject parameter = QJniObject::fromString("true");
+ QVERIFY(parameter.isValid());
+
+ jboolean b = QJniObject::callStaticMethod<jboolean>("java/lang/Boolean",
+ "parseBoolean",
+ "(Ljava/lang/String;)Z",
+ parameter.object<jstring>());
+ QVERIFY(b);
+ }
+
+ {
+ QJniObject parameter = QJniObject::fromString("false");
+ QVERIFY(parameter.isValid());
+
+ jboolean b = QJniObject::callStaticMethod<jboolean>("java/lang/Boolean",
+ "parseBoolean",
+ "(Ljava/lang/String;)Z",
+ parameter.object<jstring>());
+ QVERIFY(!b);
+ }
+}
+
+void tst_QJniObject::callStaticByteMethodClassName()
+{
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jbyte returnValue = QJniObject::callStaticMethod<jbyte>("java/lang/Byte",
+ "parseByte",
+ "(Ljava/lang/String;)B",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, jbyte(number.toInt()));
+}
+
+void tst_QJniObject::callStaticByteMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Byte");
+ QVERIFY(cls != 0);
+
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jbyte returnValue = QJniObject::callStaticMethod<jbyte>(cls,
+ "parseByte",
+ "(Ljava/lang/String;)B",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, jbyte(number.toInt()));
+}
+
+void tst_QJniObject::callStaticIntMethodClassName()
+{
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jint returnValue = QJniObject::callStaticMethod<jint>("java/lang/Integer",
+ "parseInt",
+ "(Ljava/lang/String;)I",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toInt());
+}
+
+
+void tst_QJniObject::callStaticIntMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Integer");
+ QVERIFY(cls != 0);
+
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jint returnValue = QJniObject::callStaticMethod<jint>(cls,
+ "parseInt",
+ "(Ljava/lang/String;)I",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toInt());
+}
+
+void tst_QJniObject::callStaticCharMethodClassName()
+{
+ jchar returnValue = QJniObject::callStaticMethod<jchar>("java/lang/Character",
+ "toUpperCase",
+ "(C)C",
+ jchar('a'));
+ QCOMPARE(returnValue, jchar('A'));
+}
+
+
+void tst_QJniObject::callStaticCharMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Character");
+ QVERIFY(cls != 0);
+
+ jchar returnValue = QJniObject::callStaticMethod<jchar>(cls,
+ "toUpperCase",
+ "(C)C",
+ jchar('a'));
+ QCOMPARE(returnValue, jchar('A'));
+}
+
+void tst_QJniObject::callStaticDoubleMethodClassName ()
+{
+ QString number = QString::number(123.45);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jdouble returnValue = QJniObject::callStaticMethod<jdouble>("java/lang/Double",
+ "parseDouble",
+ "(Ljava/lang/String;)D",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toDouble());
+}
+
+
+void tst_QJniObject::callStaticDoubleMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Double");
+ QVERIFY(cls != 0);
+
+ QString number = QString::number(123.45);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jdouble returnValue = QJniObject::callStaticMethod<jdouble>(cls,
+ "parseDouble",
+ "(Ljava/lang/String;)D",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toDouble());
+}
+
+void tst_QJniObject::callStaticFloatMethodClassName()
+{
+ QString number = QString::number(123.45);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jfloat returnValue = QJniObject::callStaticMethod<jfloat>("java/lang/Float",
+ "parseFloat",
+ "(Ljava/lang/String;)F",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toFloat());
+}
+
+
+void tst_QJniObject::callStaticFloatMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Float");
+ QVERIFY(cls != 0);
+
+ QString number = QString::number(123.45);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jfloat returnValue = QJniObject::callStaticMethod<jfloat>(cls,
+ "parseFloat",
+ "(Ljava/lang/String;)F",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toFloat());
+}
+
+void tst_QJniObject::callStaticShortMethodClassName()
+{
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jshort returnValue = QJniObject::callStaticMethod<jshort>("java/lang/Short",
+ "parseShort",
+ "(Ljava/lang/String;)S",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toShort());
+}
+
+
+void tst_QJniObject::callStaticShortMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Short");
+ QVERIFY(cls != 0);
+
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jshort returnValue = QJniObject::callStaticMethod<jshort>(cls,
+ "parseShort",
+ "(Ljava/lang/String;)S",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, number.toShort());
+}
+
+void tst_QJniObject::callStaticLongMethodClassName()
+{
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jlong returnValue = QJniObject::callStaticMethod<jlong>("java/lang/Long",
+ "parseLong",
+ "(Ljava/lang/String;)J",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, jlong(number.toLong()));
+}
+
+void tst_QJniObject::callStaticLongMethod()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Long");
+ QVERIFY(cls != 0);
+
+ QString number = QString::number(123);
+ QJniObject parameter = QJniObject::fromString(number);
+
+ jlong returnValue = QJniObject::callStaticMethod<jlong>(cls,
+ "parseLong",
+ "(Ljava/lang/String;)J",
+ parameter.object<jstring>());
+ QCOMPARE(returnValue, jlong(number.toLong()));
+}
+
+void tst_QJniObject::getStaticObjectFieldClassName()
+{
+ {
+ QJniObject boolObject = QJniObject::getStaticObjectField<jobject>("java/lang/Boolean",
+ "FALSE",
+ "Ljava/lang/Boolean;");
+ QVERIFY(boolObject.isValid());
+
+ jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
+ QVERIFY(!booleanValue);
+ }
+
+ {
+ QJniObject boolObject = QJniObject::getStaticObjectField<jobject>("java/lang/Boolean",
+ "TRUE",
+ "Ljava/lang/Boolean;");
+ QVERIFY(boolObject.isValid());
+
+ jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
+ QVERIFY(booleanValue);
+ }
+
+ {
+ QJniObject boolObject = QJniObject::getStaticObjectField("java/lang/Boolean",
+ "FALSE",
+ "Ljava/lang/Boolean;");
+ QVERIFY(boolObject.isValid());
+ jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
+ QVERIFY(!booleanValue);
+ }
+}
+
+void tst_QJniObject::getStaticObjectField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Boolean");
+ QVERIFY(cls != 0);
+
+ {
+ QJniObject boolObject = QJniObject::getStaticObjectField<jobject>(cls,
+ "FALSE",
+ "Ljava/lang/Boolean;");
+ QVERIFY(boolObject.isValid());
+
+ jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
+ QVERIFY(!booleanValue);
+ }
+
+ {
+ QJniObject boolObject = QJniObject::getStaticObjectField<jobject>(cls,
+ "TRUE",
+ "Ljava/lang/Boolean;");
+ QVERIFY(boolObject.isValid());
+
+ jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
+ QVERIFY(booleanValue);
+ }
+
+ {
+ QJniObject boolObject = QJniObject::getStaticObjectField(cls,
+ "FALSE",
+ "Ljava/lang/Boolean;");
+ QVERIFY(boolObject.isValid());
+
+ jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
+ QVERIFY(!booleanValue);
+ }
+}
+
+void tst_QJniObject::getStaticIntFieldClassName()
+{
+ jint i = QJniObject::getStaticField<jint>("java/lang/Double", "SIZE");
+ QCOMPARE(i, 64);
+}
+
+void tst_QJniObject::getStaticIntField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Double");
+ QVERIFY(cls != 0);
+
+ jint i = QJniObject::getStaticField<jint>(cls, "SIZE");
+ QCOMPARE(i, 64);
+}
+
+void tst_QJniObject::getStaticByteFieldClassName()
+{
+ jbyte i = QJniObject::getStaticField<jbyte>("java/lang/Byte", "MAX_VALUE");
+ QCOMPARE(i, jbyte(127));
+}
+
+void tst_QJniObject::getStaticByteField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Byte");
+ QVERIFY(cls != 0);
+
+ jbyte i = QJniObject::getStaticField<jbyte>(cls, "MAX_VALUE");
+ QCOMPARE(i, jbyte(127));
+}
+
+void tst_QJniObject::getStaticLongFieldClassName()
+{
+ jlong i = QJniObject::getStaticField<jlong>("java/lang/Long", "MAX_VALUE");
+ QCOMPARE(i, jlong(9223372036854775807L));
+}
+
+void tst_QJniObject::getStaticLongField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Long");
+ QVERIFY(cls != 0);
+
+ jlong i = QJniObject::getStaticField<jlong>(cls, "MAX_VALUE");
+ QCOMPARE(i, jlong(9223372036854775807L));
+}
+
+void tst_QJniObject::getStaticDoubleFieldClassName()
+{
+ jdouble i = QJniObject::getStaticField<jdouble>("java/lang/Double", "NaN");
+ jlong *k = reinterpret_cast<jlong*>(&i);
+ QCOMPARE(*k, jlong(0x7ff8000000000000L));
+}
+
+void tst_QJniObject::getStaticDoubleField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Double");
+ QVERIFY(cls != 0);
+
+ jdouble i = QJniObject::getStaticField<jdouble>(cls, "NaN");
+ jlong *k = reinterpret_cast<jlong*>(&i);
+ QCOMPARE(*k, jlong(0x7ff8000000000000L));
+}
+
+void tst_QJniObject::getStaticFloatFieldClassName()
+{
+ jfloat i = QJniObject::getStaticField<jfloat>("java/lang/Float", "NaN");
+ unsigned *k = reinterpret_cast<unsigned*>(&i);
+ QCOMPARE(*k, unsigned(0x7fc00000));
+}
+
+void tst_QJniObject::getStaticFloatField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Float");
+ QVERIFY(cls != 0);
+
+ jfloat i = QJniObject::getStaticField<jfloat>(cls, "NaN");
+ unsigned *k = reinterpret_cast<unsigned*>(&i);
+ QCOMPARE(*k, unsigned(0x7fc00000));
+}
+
+void tst_QJniObject::getStaticShortFieldClassName()
+{
+ jshort i = QJniObject::getStaticField<jshort>("java/lang/Short", "MAX_VALUE");
+ QCOMPARE(i, jshort(32767));
+}
+
+void tst_QJniObject::getStaticShortField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Short");
+ QVERIFY(cls != 0);
+
+ jshort i = QJniObject::getStaticField<jshort>(cls, "MAX_VALUE");
+ QCOMPARE(i, jshort(32767));
+}
+
+void tst_QJniObject::getStaticCharFieldClassName()
+{
+ jchar i = QJniObject::getStaticField<jchar>("java/lang/Character", "MAX_VALUE");
+ QCOMPARE(i, jchar(0xffff));
+}
+
+void tst_QJniObject::getStaticCharField()
+{
+ QJniEnvironment env;
+ jclass cls = env->FindClass("java/lang/Character");
+ QVERIFY(cls != 0);
+
+ jchar i = QJniObject::getStaticField<jchar>(cls, "MAX_VALUE");
+ QCOMPARE(i, jchar(0xffff));
+}
+
+
+void tst_QJniObject::getBooleanField()
+{
+ QJniObject obj("org/qtproject/qt/android/QtActivityDelegate");
+
+ QVERIFY(obj.isValid());
+ QVERIFY(!obj.getField<jboolean>("m_fullScreen"));
+}
+
+void tst_QJniObject::getIntField()
+{
+ QJniObject obj("org/qtproject/qt/android/QtActivityDelegate");
+
+ QVERIFY(obj.isValid());
+ jint res = obj.getField<jint>("m_currentRotation");
+ QCOMPARE(res, -1);
+}
+
+void tst_QJniObject::templateApiCheck()
+{
+ QJniObject testClass(testClassName);
+ QVERIFY(testClass.isValid());
+
+ // void ---------------------------------------------------------------------------------------
+ QJniObject::callStaticMethod<void>(testClassName, "staticVoidMethod");
+ QJniObject::callStaticMethod<void>(testClassName,
+ "staticVoidMethodWithArgs",
+ "(IZC)V",
+ 1,
+ true,
+ 'c');
+
+ testClass.callMethod<void>("voidMethod");
+ testClass.callMethod<void>("voidMethodWithArgs", "(IZC)V", 1, true, 'c');
+
+ // jboolean -----------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jboolean>(testClassName, "staticBooleanMethod"));
+ QVERIFY(QJniObject::callStaticMethod<jboolean>(testClassName,
+ "staticBooleanMethodWithArgs",
+ "(ZZZ)Z",
+ true,
+ true,
+ true));
+
+ QVERIFY(testClass.callMethod<jboolean>("booleanMethod"));
+ QVERIFY(testClass.callMethod<jboolean>("booleanMethodWithArgs",
+ "(ZZZ)Z",
+ true,
+ true,
+ true));
+
+ // jbyte --------------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jbyte>(testClassName,
+ "staticByteMethod") == A_BYTE_VALUE);
+ QVERIFY(QJniObject::callStaticMethod<jbyte>(testClassName,
+ "staticByteMethodWithArgs",
+ "(BBB)B",
+ 1,
+ 1,
+ 1) == A_BYTE_VALUE);
+
+ QVERIFY(testClass.callMethod<jbyte>("byteMethod") == A_BYTE_VALUE);
+ QVERIFY(testClass.callMethod<jbyte>("byteMethodWithArgs", "(BBB)B", 1, 1, 1) == A_BYTE_VALUE);
+
+ // jchar --------------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jchar>(testClassName,
+ "staticCharMethod") == A_CHAR_VALUE);
+ QVERIFY(QJniObject::callStaticMethod<jchar>(testClassName,
+ "staticCharMethodWithArgs",
+ "(CCC)C",
+ jchar(1),
+ jchar(1),
+ jchar(1)) == A_CHAR_VALUE);
+
+ QVERIFY(testClass.callMethod<jchar>("charMethod") == A_CHAR_VALUE);
+ QVERIFY(testClass.callMethod<jchar>("charMethodWithArgs",
+ "(CCC)C",
+ jchar(1),
+ jchar(1),
+ jchar(1)) == A_CHAR_VALUE);
+
+ // jshort -------------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jshort>(testClassName,
+ "staticShortMethod") == A_SHORT_VALUE);
+ QVERIFY(QJniObject::callStaticMethod<jshort>(testClassName,
+ "staticShortMethodWithArgs",
+ "(SSS)S",
+ jshort(1),
+ jshort(1),
+ jshort(1)) == A_SHORT_VALUE);
+
+ QVERIFY(testClass.callMethod<jshort>("shortMethod") == A_SHORT_VALUE);
+ QVERIFY(testClass.callMethod<jshort>("shortMethodWithArgs",
+ "(SSS)S",
+ jshort(1),
+ jshort(1),
+ jshort(1)) == A_SHORT_VALUE);
+
+ // jint ---------------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jint>(testClassName,
+ "staticIntMethod") == A_INT_VALUE);
+ QVERIFY(QJniObject::callStaticMethod<jint>(testClassName,
+ "staticIntMethodWithArgs",
+ "(III)I",
+ jint(1),
+ jint(1),
+ jint(1)) == A_INT_VALUE);
+
+ QVERIFY(testClass.callMethod<jint>("intMethod") == A_INT_VALUE);
+ QVERIFY(testClass.callMethod<jint>("intMethodWithArgs",
+ "(III)I",
+ jint(1),
+ jint(1),
+ jint(1)) == A_INT_VALUE);
+
+ // jlong --------------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jlong>(testClassName,
+ "staticLongMethod") == A_LONG_VALUE);
+ QVERIFY(QJniObject::callStaticMethod<jlong>(testClassName,
+ "staticLongMethodWithArgs",
+ "(JJJ)J",
+ jlong(1),
+ jlong(1),
+ jlong(1)) == A_LONG_VALUE);
+
+ QVERIFY(testClass.callMethod<jlong>("longMethod") == A_LONG_VALUE);
+ QVERIFY(testClass.callMethod<jlong>("longMethodWithArgs",
+ "(JJJ)J",
+ jlong(1),
+ jlong(1),
+ jlong(1)) == A_LONG_VALUE);
+
+ // jfloat -------------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jfloat>(testClassName,
+ "staticFloatMethod") == A_FLOAT_VALUE);
+ QVERIFY(QJniObject::callStaticMethod<jfloat>(testClassName,
+ "staticFloatMethodWithArgs",
+ "(FFF)F",
+ jfloat(1.1),
+ jfloat(1.1),
+ jfloat(1.1)) == A_FLOAT_VALUE);
+
+ QVERIFY(testClass.callMethod<jfloat>("floatMethod") == A_FLOAT_VALUE);
+ QVERIFY(testClass.callMethod<jfloat>("floatMethodWithArgs",
+ "(FFF)F",
+ jfloat(1.1),
+ jfloat(1.1),
+ jfloat(1.1)) == A_FLOAT_VALUE);
+
+ // jdouble ------------------------------------------------------------------------------------
+ QVERIFY(QJniObject::callStaticMethod<jdouble>(testClassName,
+ "staticDoubleMethod") == A_DOUBLE_VALUE);
+ QVERIFY(QJniObject::callStaticMethod<jdouble>(testClassName,
+ "staticDoubleMethodWithArgs",
+ "(DDD)D",
+ jdouble(1.1),
+ jdouble(1.1),
+ jdouble(1.1)) == A_DOUBLE_VALUE);
+
+ QVERIFY(testClass.callMethod<jdouble>("doubleMethod") == A_DOUBLE_VALUE);
+ QVERIFY(testClass.callMethod<jdouble>("doubleMethodWithArgs",
+ "(DDD)D",
+ jdouble(1.1),
+ jdouble(1.1),
+ jdouble(1.1)) == A_DOUBLE_VALUE);
+
+ // jobject ------------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jobject>(testClassName,
+ "staticObjectMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jobject>("objectMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jclass -------------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jclass>(testClassName,
+ "staticClassMethod");
+ QVERIFY(res.isValid());
+ QJniEnvironment env;
+ QVERIFY(env->IsInstanceOf(testClass.object(), res.object<jclass>()));
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jclass>("classMethod");
+ QVERIFY(res.isValid());
+ QJniEnvironment env;
+ QVERIFY(env->IsInstanceOf(testClass.object(), res.object<jclass>()));
+ }
+ // jstring ------------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jstring>(testClassName,
+ "staticStringMethod");
+ QVERIFY(res.isValid());
+ QVERIFY(res.toString() == A_STRING_OBJECT());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jstring>("stringMethod");
+ QVERIFY(res.isValid());
+ QVERIFY(res.toString() == A_STRING_OBJECT());
+
+ }
+ // jthrowable ---------------------------------------------------------------------------------
+ {
+ // The Throwable object the same message (see: "getMessage()") as A_STRING_OBJECT
+ QJniObject res = QJniObject::callStaticObjectMethod<jthrowable>(testClassName,
+ "staticThrowableMethod");
+ QVERIFY(res.isValid());
+ QVERIFY(res.callObjectMethod<jstring>("getMessage").toString() == A_STRING_OBJECT());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jthrowable>("throwableMethod");
+ QVERIFY(res.isValid());
+ QVERIFY(res.callObjectMethod<jstring>("getMessage").toString() == A_STRING_OBJECT());
+ }
+
+ // jobjectArray -------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jobjectArray>(testClassName,
+ "staticObjectArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jobjectArray>("objectArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jbooleanArray ------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jbooleanArray>(testClassName,
+ "staticBooleanArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jbooleanArray>("booleanArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jbyteArray ---------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jbyteArray>(testClassName,
+ "staticByteArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jbyteArray>("byteArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jcharArray ---------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jcharArray>(testClassName,
+ "staticCharArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jcharArray>("charArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jshortArray --------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jshortArray>(testClassName,
+ "staticShortArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jshortArray>("shortArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jintArray ----------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jintArray>(testClassName,
+ "staticIntArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jintArray>("intArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jlongArray ---------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jlongArray>(testClassName,
+ "staticLongArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jlongArray>("longArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jfloatArray --------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jfloatArray>(testClassName,
+ "staticFloatArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jfloatArray>("floatArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ // jdoubleArray -------------------------------------------------------------------------------
+ {
+ QJniObject res = QJniObject::callStaticObjectMethod<jdoubleArray>(testClassName,
+ "staticDoubleArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+ {
+ QJniObject res = testClass.callObjectMethod<jdoubleArray>("doubleArrayMethod");
+ QVERIFY(res.isValid());
+ }
+
+}
+
+void tst_QJniObject::isClassAvailable()
+{
+ QVERIFY(QJniObject::isClassAvailable("java/lang/String"));
+ QVERIFY(!QJniObject::isClassAvailable("class/not/Available"));
+ QVERIFY(QJniObject::isClassAvailable("org/qtproject/qt/android/QtActivityDelegate"));
+}
+
+void tst_QJniObject::fromLocalRef()
+{
+ const int limit = 512 + 1;
+ QJniEnvironment env;
+ for (int i = 0; i != limit; ++i)
+ QJniObject o = QJniObject::fromLocalRef(env->FindClass("java/lang/String"));
+}
+
+QTEST_MAIN(tst_QJniObject)
+
+#include "tst_qjniobject.moc"