From 9b37762c5502bab72970932cd59bb38b2ed33720 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 28 Sep 2023 11:47:07 +0200 Subject: [PATCH] JNI: Add promotion for signed char and extend test case The jbyte type is a signed char, which also promotes to int in variadic argument functions. Extend the test case to make sure that we don't get any warnings for the most relevant parameter types. Change-Id: I7811e1eebdbc989ab5989eb1a2c502acd0540bc7 Reviewed-by: Juha Vuolle Reviewed-by: Zoltan Gera --- src/corelib/kernel/qjnitypes.h | 1 + .../testdata/QtJniObjectTestClass.java | 24 ++++ .../kernel/qjniobject/tst_qjniobject.cpp | 119 ++++++++++++++++-- 3 files changed, 133 insertions(+), 11 deletions(-) diff --git a/src/corelib/kernel/qjnitypes.h b/src/corelib/kernel/qjnitypes.h index cfba9d0ac00..6b64e5daea6 100644 --- a/src/corelib/kernel/qjnitypes.h +++ b/src/corelib/kernel/qjnitypes.h @@ -231,6 +231,7 @@ namespace QtJniMethods { template struct PromotedType { using Type = Arg; }; template <> struct PromotedType { using Type = int; }; template <> struct PromotedType { using Type = int; }; +template <> struct PromotedType { using Type = int; }; template <> struct PromotedType { using Type = unsigned int; }; template <> struct PromotedType { using Type = int; }; template <> struct PromotedType { using Type = unsigned int; }; 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 813aaf2bbfa..0775f2fde67 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 @@ -173,9 +173,33 @@ public class QtJniObjectTestClass // -------------------------------------------------------------------------------------------- native public int callbackWithObject(QtJniObjectTestClass that); + native public int callbackWithByte(byte value); + native public int callbackWithBoolean(boolean value); + native public int callbackWithInt(int value); + native public int callbackWithDouble(double value); public int callMeBackWithObject(QtJniObjectTestClass that) { return callbackWithObject(that); } + + public int callMeBackWithByte(byte value) + { + return callbackWithByte(value); + } + + public int callMeBackWithBoolean(boolean value) + { + return callbackWithBoolean(value); + } + + public int callMeBackWithInt(int value) + { + return callbackWithInt(value); + } + + public int callMeBackWithDouble(double value) + { + return callbackWithDouble(value); + } } diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index 65c9680d4e2..6e09bfd5133 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -113,6 +113,7 @@ private slots: void isClassAvailable(); void fromLocalRef(); + void callback_data(); void callback(); void cleanupTestCase(); @@ -1668,27 +1669,123 @@ void tst_QJniObject::fromLocalRef() static std::optional calledWithObject; -static int callbackWithObject(JNIEnv *env, jobject thiz, TestClass that) +static int callbackWithObject(JNIEnv *, jobject, TestClass that) { - Q_UNUSED(env); - Q_UNUSED(thiz); calledWithObject.emplace(that); return 42; } - Q_DECLARE_JNI_NATIVE_METHOD(callbackWithObject) +static std::optional calledWithByte; +static int callbackWithByte(JNIEnv *, jobject, jbyte value) +{ + calledWithByte.emplace(value); + return 43; +} +Q_DECLARE_JNI_NATIVE_METHOD(callbackWithByte) + +static std::optional calledWithBoolean; +static int callbackWithBoolean(JNIEnv *, jobject, bool value) +{ + calledWithBoolean.emplace(value); + return 44; +} +Q_DECLARE_JNI_NATIVE_METHOD(callbackWithBoolean) + +static std::optional calledWithInt; +static int callbackWithInt(JNIEnv *, jobject, int value) +{ + calledWithInt.emplace(value); + return 45; +} +Q_DECLARE_JNI_NATIVE_METHOD(callbackWithInt) + +static std::optional calledWithDouble; +static int callbackWithDouble(JNIEnv *, jobject, double value) +{ + calledWithDouble.emplace(value); + return 46; +} +Q_DECLARE_JNI_NATIVE_METHOD(callbackWithDouble) + +enum class CallbackParameterType +{ + Object, + Byte, + Boolean, + Int, + Double, +}; + +void tst_QJniObject::callback_data() +{ + QTest::addColumn("parameterType"); + QTest::addColumn("expectedResult"); + + QTest::addRow("Object") << CallbackParameterType::Object + << callbackWithObject(nullptr, nullptr, {}); + QTest::addRow("Byte") << CallbackParameterType::Byte + << callbackWithByte(nullptr, nullptr, {}); + QTest::addRow("Boolean") << CallbackParameterType::Boolean + << callbackWithBoolean(nullptr, nullptr, {}); + QTest::addRow("Int") << CallbackParameterType::Int + << callbackWithInt(nullptr, nullptr, {}); + QTest::addRow("Double") << CallbackParameterType::Double + << callbackWithDouble(nullptr, nullptr, {}); +} + void tst_QJniObject::callback() { + QFETCH(const CallbackParameterType, parameterType); + QFETCH(const int, expectedResult); + TestClass testObject; QJniEnvironment env; - QVERIFY(env.registerNativeMethods(testObject.objectClass(), { - Q_JNI_NATIVE_METHOD(callbackWithObject) - })); - int result = testObject.callMethod("callMeBackWithObject", testObject); - QVERIFY(calledWithObject); - QVERIFY(calledWithObject.value() == testObject); - QCOMPARE(result, 42); + int result = -1; + + switch (parameterType) { + case CallbackParameterType::Object: + QVERIFY(env.registerNativeMethods(testObject.objectClass(), { + Q_JNI_NATIVE_METHOD(callbackWithObject) + })); + result = testObject.callMethod("callMeBackWithObject", testObject); + QVERIFY(calledWithObject); + QCOMPARE(calledWithObject.value(), testObject); + break; + case CallbackParameterType::Byte: + QVERIFY(env.registerNativeMethods(testObject.objectClass(), { + Q_JNI_NATIVE_METHOD(callbackWithByte) + })); + result = testObject.callMethod("callbackWithByte", jbyte(123)); + QVERIFY(calledWithByte); + QCOMPARE(calledWithByte.value(), 123); + break; + case CallbackParameterType::Boolean: + QVERIFY(env.registerNativeMethods(testObject.objectClass(), { + Q_JNI_NATIVE_METHOD(callbackWithBoolean) + })); + result = testObject.callMethod("callbackWithBoolean", true); + QVERIFY(calledWithBoolean); + QCOMPARE(calledWithBoolean.value(), true); + break; + case CallbackParameterType::Int: + QVERIFY(env.registerNativeMethods(testObject.objectClass(), { + Q_JNI_NATIVE_METHOD(callbackWithInt) + })); + result = testObject.callMethod("callbackWithInt", 12345); + QVERIFY(calledWithInt); + QCOMPARE(calledWithInt.value(), 12345); + break; + case CallbackParameterType::Double: + QVERIFY(env.registerNativeMethods(testObject.objectClass(), { + Q_JNI_NATIVE_METHOD(callbackWithDouble) + })); + result = testObject.callMethod("callbackWithDouble", 1.2345); + QVERIFY(calledWithDouble); + QCOMPARE(calledWithDouble.value(), 1.2345); + break; + } + QCOMPARE(result, expectedResult); } QTEST_MAIN(tst_QJniObject)