From d05438454f0e67ad5d8ce0c2b8533ac23dc3494a Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 29 Aug 2024 17:55:47 +0200 Subject: [PATCH] JNI: Add test coverage for a jobjectArray in a native function Make sure this works as it should. The bug report/support request wants to have a String[] parameter on the Java side, but then the C++ side can not use jobjectArray (as that has "[Ljava/lang/Object;" as signature), so use Object[] instead (which is one solution; the other is to use QList or (in 6.8) QStringList on the C++ side. What's easy to miss is that the jobjectArray that we get is a local ref, so we have to extend its lifetime by creating a QJniObject holding it as a global reference. We can then create a QJniArray from that QJniObject (without any type safety). Task-number: QTBUG-128456 Change-Id: I1e03b811165f9bc5106324d39fb58114ee8cf398 Reviewed-by: Assam Boudjelthia Reviewed-by: Petri Virkkunen (cherry picked from commit f9fd5870f7379103005839bc03543bb8f6da94c3) Reviewed-by: Qt Cherry-pick Bot --- .../testdata/QtJniObjectTestClass.java | 5 ++++ .../kernel/qjniobject/tst_qjniobject.cpp | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+) 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 index 21a8884198d..2d2b98c8358 100644 --- 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 @@ -304,6 +304,7 @@ public class QtJniObjectTestClass native public int callbackWithInt(int value); native public int callbackWithDouble(double value); native public int callbackWithJniArray(double[] value); + native public int callbackWithRawArray(Object[] value); native public int callbackWithQList(double[] value); native public int callbackWithStringList(String[] value); @@ -345,6 +346,10 @@ public class QtJniObjectTestClass { return callbackWithJniArray(value); } + public int callMeBackWithRawArray(Object[] value) + { + return callbackWithRawArray(value); + } public int callMeBackWithQList(double[] value) { return callbackWithQList(value); diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index 52418ef9aae..10b48dfa975 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -1956,6 +1956,7 @@ enum class CallbackParameterType Int, Double, JniArray, + RawArray, QList, QStringList, }; @@ -2022,6 +2023,14 @@ static int callbackWithJniArray(JNIEnv *, jobject, const QJniArray &val } Q_DECLARE_JNI_NATIVE_METHOD(callbackWithJniArray) +static std::optional calledWithRawArray; +static int callbackWithRawArray(JNIEnv *, jobject, jobjectArray value) +{ + calledWithRawArray.emplace(QJniObject(value)); + return int(CallbackParameterType::RawArray); +} +Q_DECLARE_JNI_NATIVE_METHOD(callbackWithRawArray) + static std::optional> calledWithQList; static int callbackWithQList(JNIEnv *, jobject, const QList &value) { @@ -2050,6 +2059,7 @@ void tst_QJniObject::callback_data() QTest::addRow("Int") << CallbackParameterType::Int; QTest::addRow("Double") << CallbackParameterType::Double; QTest::addRow("JniArray") << CallbackParameterType::JniArray; + QTest::addRow("RawArray") << CallbackParameterType::RawArray; QTest::addRow("QList") << CallbackParameterType::QList; QTest::addRow("QStringList") << CallbackParameterType::QStringList; } @@ -2128,6 +2138,19 @@ void tst_QJniObject::callback() QCOMPARE(calledWithJniArray, doubles); break; } + case CallbackParameterType::RawArray: { + QVERIFY(TestClass::registerNativeMethods({ + Q_JNI_NATIVE_METHOD(callbackWithRawArray) + })); + const QStringList strings{"a", "b", "c"}; + const QJniArray stringArray(strings); + result = testObject.callMethod("callMeBackWithRawArray", + stringArray.object()); + QVERIFY(calledWithRawArray); + const auto stringsReceived = QJniArray(*calledWithRawArray).toContainer(); + QCOMPARE(stringsReceived, strings); + break; + } case CallbackParameterType::QList: { QVERIFY(TestClass::registerNativeMethods({ Q_JNI_NATIVE_METHOD(callbackWithQList)