diff options
Diffstat (limited to 'tests')
3 files changed, 578 insertions, 1 deletions
diff --git a/tests/auto/corelib/kernel/qjniobject/CMakeLists.txt b/tests/auto/corelib/kernel/qjniobject/CMakeLists.txt index 98509dc0e5f..1d320b49c86 100644 --- a/tests/auto/corelib/kernel/qjniobject/CMakeLists.txt +++ b/tests/auto/corelib/kernel/qjniobject/CMakeLists.txt @@ -14,8 +14,16 @@ endif() qt_internal_add_test(tst_qjniobject SOURCES tst_qjniobject.cpp + LIBRARIES + Qt::CorePrivate ) +# if we can, enable C++23 so that we can use std::expected in the test +# otherwise the test will use our own tl::expected copy from qexpected_p.h +if ("${CMAKE_CXX_COMPILE_FEATURES}" MATCHES "cxx_std_23") + set_property(TARGET tst_qjniobject PROPERTY CXX_STANDARD 23) +endif() + if(ANDROID) set_property(TARGET tst_qjniobject APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/testdata 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 e0765fcb7e0..bdec173ca97 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 @@ -137,6 +137,10 @@ public class QtJniObjectTestClass public Throwable throwableMethod() { return staticThrowableMethod(); } // -------------------------------------------------------------------------------------------- + public static void staticThrowingMethod() throws Throwable { throw new Throwable(A_STRING_OBJECT); } + public void throwingMethod() throws Throwable { throw new Throwable(A_STRING_OBJECT); } + + // -------------------------------------------------------------------------------------------- public static Object[] staticObjectArrayMethod() { Object[] array = { new Object(), new Object(), new Object() }; return array; } public Object[] objectArrayMethod() { return staticObjectArrayMethod(); } diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index c06b500778b..215b3bf3b78 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -8,12 +8,20 @@ #include <QtCore/QJniObject> #include <QTest> +#if defined(__cpp_lib_expected) +# include <expected> +#else +# include <QtCore/private/qexpected_p.h> +#endif + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; static constexpr const char testClassName[] = "org/qtproject/qt/android/testdatapackage/QtJniObjectTestClass"; Q_DECLARE_JNI_CLASS(QtJniObjectTestClass, testClassName) +Q_DECLARE_JNI_CLASS(NoSuchClass, "no/such/Class") + using TestClass = QtJniTypes::QtJniObjectTestClass; static const jbyte A_BYTE_VALUE = 127; @@ -125,6 +133,24 @@ private slots: void callback(); void callStaticOverloadResolution(); + void implicitExceptionHandling_construct(); + void implicitExceptionHandling_callMethod(); + void implicitExceptionHandling_callStaticMethod(); + void implicitExceptionHandling_getField(); + void implicitExceptionHandling_setField(); + void implicitExceptionHandling_getStaticField(); + void implicitExceptionHandling_setStaticField(); + + void constructWithException(); + void callMethodWithException(); + void callMethodWithMonadic(); + void callMethodWithTryCatch(); + void callStaticMethodWithException(); + void getFieldWithException(); + void setFieldWithException(); + void getStaticFieldWithException(); + void setStaticFieldWithException(); + void cleanupTestCase(); }; @@ -2303,8 +2329,547 @@ void tst_QJniObject::callStaticOverloadResolution() QCOMPARE(result, value); } -QT_END_NAMESPACE +void tst_QJniObject::implicitExceptionHandling_construct() +{ + QJniEnvironment env; + const QRegularExpression invalidClass("java.lang.ClassNotFoundException: .*"); + const QRegularExpression invalidMethod("java.lang.NoSuchMethodError: .*"); + + // Constructor, including named constructor + { + QTest::ignoreMessage(QtWarningMsg, invalidClass); + QJniObject testObject("NoSuchClass"); + QVERIFY(!env.checkAndClearExceptions()); + } + { + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + QJniObject testObject = QJniObject::construct<TestClass>(u"NoSuchConstructor"_s); + QVERIFY(!env.checkAndClearExceptions()); + } +} + +void tst_QJniObject::implicitExceptionHandling_callMethod() +{ + QJniEnvironment env; + const QRegularExpression invalidMethod("java.lang.NoSuchMethodError: .*"); + const QRegularExpression throwingMethod("java.lang.Throwable: .*"); + + QJniObject testObject = QJniObject::construct<TestClass>(); + + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + testObject.callMethod<void>("noSuchMethod1"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + testObject.callMethod<void>("noSuchMethod2", "()V"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, throwingMethod); + testObject.callMethod<void>("throwingMethod"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + (void)testObject.callObjectMethod<jstring>("noSuchMethod"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + testObject.callObjectMethod("noSuchMethod", "()V"); + QVERIFY(!env.checkAndClearExceptions()); +} + +void tst_QJniObject::implicitExceptionHandling_callStaticMethod() +{ + QJniEnvironment env; + const QRegularExpression invalidClass("java.lang.ClassNotFoundException: .*"); + const QRegularExpression invalidMethod("java.lang.NoSuchMethodError: .*"); + const QRegularExpression throwingMethod("java.lang.Throwable: .*"); + + const jclass classId = env.findClass<TestClass>(); + QVERIFY(classId != nullptr); + + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + TestClass::callStaticMethod<void>("noSuchStaticMethod"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + QJniObject::callStaticMethod<void>(QtJniTypes::Traits<TestClass>::className(), + "noSuchStaticMethod2", "()V"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidClass); + QJniObject::callStaticMethod<void>("noSuchClass", "noSuchStaticMethod2", "()V"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, throwingMethod); + jmethodID methodId = env.findStaticMethod<void>(classId, "staticThrowingMethod"); + QVERIFY(methodId != nullptr); + QJniObject::callStaticMethod<void>(classId, methodId); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidClass); + QJniObject::callStaticObjectMethod("noSuchClass", "noSuchStaticMethod", "()V"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + QJniObject::callStaticObjectMethod(classId, "noSuchStaticMethod", "()V"); + QVERIFY(!env.checkAndClearExceptions()); +} + +void tst_QJniObject::implicitExceptionHandling_getField() +{ + QJniEnvironment env; + const QRegularExpression invalidField("java.lang.NoSuchFieldError: .*"); + + QJniObject testObject = QJniObject::construct<TestClass>(); + QTest::ignoreMessage(QtWarningMsg, invalidField); + (void)testObject.getField<int>("noSuchField"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + (void)testObject.getObjectField<jobject>("noSuchObjectField"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + (void)testObject.getObjectField("noSuchObjectField2", "Ljava/lang/Object;"); + QVERIFY(!env.checkAndClearExceptions()); +} + +void tst_QJniObject::implicitExceptionHandling_setField() +{ + QJniEnvironment env; + const QRegularExpression invalidField("java.lang.NoSuchFieldError: .*"); + + QJniObject testObject = QJniObject::construct<TestClass>(); + QTest::ignoreMessage(QtWarningMsg, invalidField); + testObject.setField("noSuchField", 123); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + testObject.setField("BOOLEAN_VAR", "I", 123); + QVERIFY(!env.checkAndClearExceptions()); + + // make sure that code specifying deducible type explicitly still works + static_assert(std::is_same_v<decltype(testObject.setField<jboolean>("BOOLEAN_VAR", true)), + void>); +} + +void tst_QJniObject::implicitExceptionHandling_getStaticField() +{ + QJniEnvironment env; + const QRegularExpression invalidClass("java.lang.ClassNotFoundException: .*"); + const QRegularExpression invalidField("java.lang.NoSuchFieldError: .*"); + + const jclass classId = env.findClass<TestClass>(); + QVERIFY(classId != nullptr); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + (void)TestClass::getStaticField<int>("noSuchStaticField"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + (void)QJniObject::getStaticField<int>(classId, "noSuchStaticField"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidClass); + (void)QJniObject::getStaticObjectField("noSuchClass", "noSuchStaticField", "I"); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + (void)QJniObject::getStaticObjectField(classId, "S_BOOLEAN_VAR", "I"); + QVERIFY(!env.checkAndClearExceptions()); +} + +void tst_QJniObject::implicitExceptionHandling_setStaticField() +{ + QJniEnvironment env; + const QRegularExpression invalidClass("java.lang.ClassNotFoundException: .*"); + const QRegularExpression invalidField("java.lang.NoSuchFieldError: .*"); + + const jclass classId = env.findClass<TestClass>(); + QVERIFY(classId != nullptr); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + TestClass::setStaticField("noSuchStaticField", 123); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + QJniObject::setStaticField(classId, "noSuchStaticField", 123); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidClass); + QJniObject::setStaticField("noSuchClass", "noSuchStaticField", 123); + QVERIFY(!env.checkAndClearExceptions()); + + QTest::ignoreMessage(QtWarningMsg, invalidField); + QJniObject::setStaticField(QtJniTypes::Traits<TestClass>::className(), + "S_BOOLEAN_VAR", "I", 123); + QVERIFY(!env.checkAndClearExceptions()); + + // make sure that code specifying deducible type explicitly still works + static_assert(std::is_same_v<decltype(TestClass::setStaticField<jboolean>("S_BOOLEAN_VAR", true)), + void>); +} + +#if __cpp_lib_expected +template <typename T> +using QJniReturnValue = std::expected<T, jthrowable>; +using BadAccessException = std::bad_expected_access<jthrowable>; +// even with __cpp_lib_expected >= 202211L, monadic functions seem to be rather +// broken or not reliably available +#define EXPECTED_HAS_MONADIC false +#elif TL_EXPECTED_VERSION_MAJOR +#define EXPECTED_HAS_MONADIC true +template <typename T> +using QJniReturnValue = tl::expected<T, jthrowable>; +using BadAccessException = tl::bad_expected_access<jthrowable>; +#endif + +static_assert(QtJniTypes::Traits<QJniReturnValue<int>>::signature() == + QtJniTypes::Traits<int>::signature()); +static_assert(QtJniTypes::Traits<QJniReturnValue<QString>>::signature() == + QtJniTypes::Traits<QString>::signature()); + + +void tst_QJniObject::constructWithException() +{ +#if __cpp_lib_expected + qInfo() << "Testing explicit exception handling with std::expected" << __cpp_lib_expected; +#elif defined(TL_EXPECTED_VERSION_MAJOR) + qInfo() << "Testing explicit exception handling with tl::expected"; +#else + qInfo() << "Testing explicit exception handling with QJniReturnValue"; +#endif + + const QRegularExpression invalidClass("java.lang.ClassNotFoundException: .*"); + { + QTest::ignoreMessage(QtWarningMsg, invalidClass); + QJniObject invalid = QJniObject::construct<QtJniTypes::NoSuchClass>(); + } + + QVERIFY(!QJniEnvironment().checkAndClearExceptions()); + + { + // can only handle exceptions when using the named constructor + auto result = QJniObject::construct<QJniReturnValue<TestClass>>(); + QVERIFY(result); + result = QJniObject::construct<QJniReturnValue<TestClass>>(u"123"_s); + QVERIFY(!result); + QVERIFY(result.error()); + } + + QVERIFY(!QJniEnvironment().checkAndClearExceptions()); + + { + const auto result = QJniObject::construct<QJniReturnValue<QtJniTypes::NoSuchClass>>(); + QVERIFY(!result); + QVERIFY(result.error()); + } + + QVERIFY(!QJniEnvironment().checkAndClearExceptions()); + + { + // no way to prevent implicit exception here + QTest::ignoreMessage(QtWarningMsg, invalidClass); + QtJniTypes::NoSuchClass noSuchClass; + QVERIFY(!noSuchClass.isValid()); + } + + QVERIFY(!QJniEnvironment().checkAndClearExceptions()); +} + +void tst_QJniObject::callMethodWithException() +{ + TestClass testObject; + { + auto result = testObject.callMethod<QJniReturnValue<void>>("voidMethod"); + QVERIFY(result); + result = testObject.callMethod<QJniReturnValue<void>>("voidMethod", 123); + QVERIFY(!result); + QVERIFY(result.error()); + } + + { + auto result = testObject.callMethod<QJniReturnValue<jint>>("intMethod"); + QVERIFY(result); + QCOMPARE(result.value(), A_INT_VALUE); + result = testObject.callMethod<QJniReturnValue<jint>>("intMethod", 123); + QVERIFY(!result); + QVERIFY(result.error()); + QCOMPARE(result.value_or(456), 456); + } + + { + auto result = testObject.callMethod<QJniReturnValue<jstring>>("stringMethod"); + QVERIFY(result); + QVERIFY(result.value()); + result = testObject.callMethod<QJniReturnValue<jstring>>("stringMethod", 123); + QVERIFY(!result); + QVERIFY(result.error()); + } + + { + auto result = testObject.callMethod<QJniReturnValue<QString>>("stringMethod"); + QVERIFY(result); + QVERIFY(!result.value().isEmpty()); + result = testObject.callMethod<QJniReturnValue<QString>>("stringMethod", 123); + QVERIFY(!result); + QVERIFY(result.error()); + QCOMPARE(result.value_or(u"Default"_s), u"Default"_s); + } + + { + QJniArray<jboolean> newArray(QList<jboolean>{true, false, false}); + auto result = testObject.callMethod<QJniReturnValue<QJniArray<jboolean>>>("reverseBooleanArray", newArray); + // this shorthand cannot work with e.g. std::expected + // result = testObject.callMethod<QJniReturnValue<jboolean[]>>("reverseBooleanArray", newArray); + QVERIFY(result); + QCOMPARE(result.value().toContainer(), (QList<jboolean>{false, false, true})); + result = testObject.callMethod<QJniReturnValue<QJniArray<jboolean>>>("reverseBooleanArray", 123); + QVERIFY(!result); + QVERIFY(result.error()); + } + + // throwing method - QJniObject cleans the exception and prints qWarning + { + QTest::ignoreMessage(QtWarningMsg, QRegularExpression(u"java.lang.Throwable: "_s + A_STRING_OBJECT() + u".*"_s)); + testObject.callMethod<void>("throwingMethod"); + + auto result = testObject.callMethod<QJniReturnValue<void>>("throwingMethod"); + QVERIFY(!result); + const QStringList stackTrace = QJniEnvironment::stackTrace(result.error()); + QCOMPARE_GE(stackTrace.size(), 1); + QCOMPARE(stackTrace.at(0), u"java.lang.Throwable: "_s + A_STRING_OBJECT()); + } +} + +void tst_QJniObject::callMethodWithMonadic() +{ +#if !EXPECTED_HAS_MONADIC + QSKIP("Used version of std::expected does not have monadic functions"); +#else + enum Monadic { + AndThen, + OrElse, + Transform, + }; + + TestClass testObject; + { + QList<Monadic> flow; + const auto result = testObject.callMethod<QJniReturnValue<void>>("voidMethod") + .and_then([&flow]{ + flow << AndThen; + return QJniReturnValue<void>(); + }) + .or_else([&flow](jthrowable error){ + if (error) + flow << OrElse; + else + qWarning("Invalid call to or_else monadic"); + return QJniReturnValue<void>(); + }) + .transform([&flow](){ + flow << Transform; + return 42; + }); + QCOMPARE(flow, (QList<Monadic>{AndThen, Transform})); + QVERIFY(result); + QCOMPARE(*result, 42); + } + { + QList<Monadic> flow; + const auto result = testObject.callMethod<QJniReturnValue<void>>("voidMethod", 123) + .and_then([&flow]{ + flow << AndThen; + return QJniReturnValue<void>(); + }) + .or_else([&flow](jthrowable error){ + if (error) + flow << OrElse; + else + qWarning("Invalid call to or_else monadic"); + return QJniReturnValue<void>(typename QJniReturnValue<void>::unexpected_type(error)); + }) + .transform([&flow](){ + flow << Transform; + return 42; + }); + QCOMPARE(flow, (QList<Monadic>{OrElse})); + QVERIFY(!result); + } + + { + QList<Monadic> flow; + const auto result = testObject.callMethod<QJniReturnValue<jobject>>("objectMethod") + .and_then([&flow](auto &&obj){ + flow << AndThen; + return QJniReturnValue<jobject>(obj); + }) + .or_else([&flow](jthrowable error){ + if (error) + flow << OrElse; + else + qWarning("Invalid call to or_else monadic"); + return QJniReturnValue<jobject>(typename QJniReturnValue<void>::unexpected_type(error)); + }) + .transform([&flow](auto &&obj){ + flow << Transform; + return QJniObject(obj).template getField<int>("INT_FIELD"); + }) + .and_then([&flow](auto value){ + flow << AndThen; + return QJniReturnValue<int>(value * 2); + }); + QCOMPARE(flow, (QList<Monadic>{AndThen, Transform, AndThen})); + QVERIFY(result); + QCOMPARE(*result, 246); + } + { + QList<Monadic> flow; + const auto result = testObject.callMethod<QJniReturnValue<jobject>>("objectMethod", 123) + .and_then([&flow](const QJniObject &obj){ + flow << AndThen; + return QJniReturnValue<jobject>(obj.object()); + }) + .or_else([&flow](jthrowable error){ + if (error) + flow << OrElse; + else + qWarning("Invalid call to or_else monadic"); + return QJniReturnValue<jobject>(typename QJniReturnValue<jobject>::unexpected_type(error)); + }) + .transform([&flow](const QJniObject &obj){ + flow << Transform; + return obj.getField<int>("INT_FIELD"); + }); + QCOMPARE(flow, (QList<Monadic>{OrElse})); + QVERIFY(!result); + } +#endif +} + +void tst_QJniObject::callMethodWithTryCatch() +{ + TestClass testObject; + + const QRegularExpression invalidMethod("java.lang.NoSuchMethodError: .*"); + QTest::ignoreMessage(QtWarningMsg, invalidMethod); + + try { + const auto result = testObject.callMethod<QJniReturnValue<QJniObject>>("objectMethod", 123); + result.value().getField<int>("INT_FIELD"); + } + catch (BadAccessException &e) { + qWarning().noquote() << QJniEnvironment::stackTrace(e.error()).join('\n'); + } +} + +void tst_QJniObject::callStaticMethodWithException() +{ + { + auto result = TestClass::callStaticMethod<QJniReturnValue<int>>("staticIntMethod"); + QVERIFY(result); + QCOMPARE(*result, A_INT_VALUE); + result = TestClass::callStaticMethod<QJniReturnValue<int>>("staticIntMethod", 123); + QVERIFY(!result && result.error()); + } + + { + auto result = TestClass::callStaticMethod<QJniReturnValue<QString>>("staticStringMethod"); + QVERIFY(result); + QCOMPARE(*result, A_STRING_OBJECT()); + result = TestClass::callStaticMethod<QJniReturnValue<QString>>("staticStringMethod", 123); + QVERIFY(!result && result.error()); + } + + // throwing method + { + const auto result = TestClass::callStaticMethod<QJniReturnValue<void>>("staticThrowingMethod"); + QVERIFY(!result); + QStringList stackTrace = QJniEnvironment::stackTrace(result.error()); + QCOMPARE_GE(stackTrace.size(), 1); + QCOMPARE(stackTrace.at(0), u"java.lang.Throwable: "_s + A_STRING_OBJECT()); + } +} + +void tst_QJniObject::getFieldWithException() +{ + TestClass testObject; + { + auto result = testObject.getField<QJniReturnValue<jboolean>>("BOOL_FIELD"); + QVERIFY(result); + result = testObject.getField<QJniReturnValue<jboolean>>("INVALID_BOOL"); + QVERIFY(!result && result.error()); + } + + { + auto result = testObject.getField<QJniReturnValue<QString>>("STRING_OBJECT_VAR"); + QVERIFY(result); + result = testObject.getField<QJniReturnValue<QString>>("INVALID_STRING"); + QVERIFY(!result && result.error()); + } +} + +void tst_QJniObject::setFieldWithException() +{ + TestClass testObject; + { + auto result = testObject.setField<QJniReturnValue<jboolean>>("BOOL_FIELD", true); + QVERIFY(result); + result = testObject.setField<QJniReturnValue<jboolean>>("SET_INVALID_BOOL", true); + QVERIFY(!result); + QVERIFY(result.error()); + } + + { + auto result = testObject.setField<QJniReturnValue<QString>>("STRING_OBJECT_VAR", u"test"_s); + QVERIFY(result); + result = testObject.setField<QJniReturnValue<QString>>("SET_INVALID_STRING", u"test"_s); + QVERIFY(!result); + QVERIFY(result.error()); + } +} + +void tst_QJniObject::getStaticFieldWithException() +{ + { + auto result = TestClass::getStaticField<QJniReturnValue<jshort>>("S_SHORT_VAR"); + QVERIFY(result); + result = TestClass::getStaticField<QJniReturnValue<jshort>>("S_INVALID_SHORT"); + QVERIFY(!result); + QVERIFY(result.error()); + } + + { + auto result = TestClass::getStaticField<QJniReturnValue<QString>>("S_STRING_OBJECT_VAR"); + QVERIFY(result); + result = TestClass::getStaticField<QJniReturnValue<QString>>("S_INVALID_STRING"); + QVERIFY(!result); + QVERIFY(result.error()); + } +} + +void tst_QJniObject::setStaticFieldWithException() +{ + { + auto result = TestClass::setStaticField<QJniReturnValue<jboolean>>("S_BOOLEAN_VAR", true); + QVERIFY(result); + result = TestClass::setStaticField<QJniReturnValue<jboolean>>("SET_S_INVALID_BOOL", true); + QVERIFY(!result); + QVERIFY(result.error()); + } + + { + auto result = TestClass::setStaticField<QJniReturnValue<QString>>("S_STRING_OBJECT_VAR", u"test"_s); + QVERIFY(result); + result = TestClass::setStaticField<QJniReturnValue<QString>>("SET_S_INVALID_STRING", u"test"_s); + QVERIFY(!result); + QVERIFY(result.error()); + } +} QTEST_MAIN(tst_QJniObject) +QT_END_NAMESPACE + #include "tst_qjniobject.moc" |
