JNI: add test coverage to confirm assumptions about array validity

When the Java array that we hold a reference to is changed on the Java
side, then our reference continues to be valid, and references a
different object than the new array in Java.

Pick-to: 6.8
Change-Id: If8743cc1b2fabb254b9c0009f41377455719ec3e
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Volker Hilsheimer 2024-06-05 16:59:30 +02:00
parent 691f6b5b0c
commit 37bb00d850
2 changed files with 51 additions and 0 deletions

View File

@ -43,6 +43,8 @@ public class QtJniObjectTestClass
static char S_CHAR_VAR;
static String S_STRING_OBJECT_VAR;
static char[] S_CHAR_ARRAY = A_STRING_OBJECT.toCharArray();
// --------------------------------------------------------------------------------------------
public static void staticVoidMethod() { return; }
public static void staticVoidMethodWithArgs(int a, boolean b, char c) { return; }
@ -198,6 +200,18 @@ public class QtJniObjectTestClass
public char[] reverseCharArray(char[] array)
{ return staticReverseCharArray(array); }
// --------------------------------------------------------------------------------------------
public static char[] getStaticCharArray()
{ return S_CHAR_ARRAY; }
public static void mutateStaticCharArray(char [] values)
{
for (int i = 0; i < values.length; ++i) {
S_CHAR_ARRAY[i] = values[i];
}
}
public static void replaceStaticCharArray(char[] array)
{ S_CHAR_ARRAY = array; }
// --------------------------------------------------------------------------------------------
public static short[] staticShortArrayMethod() { short[] array = { 3, 2, 1 }; return array; }
public short[] shortArrayMethod() { return staticShortArrayMethod(); }

View File

@ -116,6 +116,7 @@ private slots:
void isClassAvailable();
void fromLocalRef();
void largeObjectArray();
void arrayLifetime();
void callback_data();
void callback();
@ -1884,6 +1885,42 @@ void tst_QJniObject::largeObjectArray()
}
}
void tst_QJniObject::arrayLifetime()
{
const auto stringData = A_STRING_OBJECT();
QJniArray oldChars = TestClass::callStaticMethod<jchar[]>("getStaticCharArray");
QVERIFY(oldChars.isValid());
QCOMPARE(oldChars.size(), stringData.size());
QCOMPARE(QChar(oldChars.toContainer().at(0)), stringData.at(0));
QJniArray<jchar> newChars{'a', 'b', 'c'};
// replace the first three characters in the array
TestClass::callStaticMethod<void>("mutateStaticCharArray", newChars);
// the old jcharArray is still valid and the size is unchanged
QVERIFY(oldChars.isValid());
QCOMPARE(oldChars.size(), A_STRING_OBJECT().size());
QCOMPARE(oldChars.toContainer().at(0), jchar('a'));
// get a second reference to the Java array
QJniArray updatedChars = TestClass::getStaticField<jchar[]>("S_CHAR_ARRAY");
// the two QJniArrays reference the same jobject
QCOMPARE(updatedChars.size(), oldChars.size());
QCOMPARE(updatedChars, oldChars);
// replace the Java array; the old jcharArray is still valid and unchanged
TestClass::callStaticMethod<void>("replaceStaticCharArray", newChars);
// the old jcharArray is still valid and unchanged
QVERIFY(oldChars.isValid());
QCOMPARE(oldChars.size(), stringData.size());
QCOMPARE(oldChars, updatedChars);
// we get the same object that we set
updatedChars = TestClass::getStaticField<jchar[]>("S_CHAR_ARRAY");
QCOMPARE(updatedChars, newChars);
QCOMPARE_NE(updatedChars, oldChars);
}
enum class CallbackParameterType
{
Object,