Skip to content

Commit

Permalink
Add 2D object array tests.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 568281459
  • Loading branch information
jwhpryor authored and copybara-github committed Sep 25, 2023
1 parent 006e259 commit 39bed6b
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 11 deletions.
11 changes: 9 additions & 2 deletions implementation/class_ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef JNI_BIND_CLASS_REF_H_
#define JNI_BIND_CLASS_REF_H_

#include <type_traits>
#include <vector>

#include "class_defs/java_lang_classes.h"
Expand Down Expand Up @@ -70,11 +71,17 @@ class ClassRef {
LifecycleHelper<jobject, LifecycleType::GLOBAL>::Promote(
JniHelper::FindClass(JniT::kName.data())));
} else {
// Primitive types drop their rank by 1 because of how their
// signatures get derived in array_ref.h.
using JniTForLifecycle = std::conditional_t<
std::is_same_v<jobject, typename JniT::SpanType>, JniT,
typename JniT::RankLess1>;

return static_cast<jclass>(
LifecycleHelper<jobject, LifecycleType::GLOBAL>::Promote(
JniHelper::FindClass(
SelectorStaticInfo<JniTSelector<typename JniT::RankLess1,
-1>>::TypeName()
SelectorStaticInfo<
JniTSelector<JniTForLifecycle, -1>>::TypeName()
.data())));
}
};
Expand Down
4 changes: 2 additions & 2 deletions implementation/jni_helper/jni_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ namespace jni {
class JniHelper {
public:
// Finds a class with "name". Note, the classloader used is whatever is
// present on the statck when this is caled. No caching is performed,
// returned jclass is a local.
// present on the stack when this is called. No cacheing is performed,
// returned `jclass` is a local.
static jclass FindClass(const char* name);

// Returns a local ref jclass for the given jobject.
Expand Down
35 changes: 35 additions & 0 deletions implementation/local_array_multidimensional_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,39 @@ TEST_F(JniTest, Array_2D_Iterates_Raw_loops) {
EXPECT_EQ(sum, 35);
}

// Identical to above except with object loops.
TEST_F(JniTest, Array_2D_Iterates_Raw_loops_of_Objects) {
EXPECT_CALL(*env_, FindClass(StrEq("[LkClass;")));
EXPECT_CALL(*env_, NewObjectArray(5, _, Fake<jobjectArray>(100)));
EXPECT_CALL(*env_, GetArrayLength).WillOnce(Return(5)); // outer

EXPECT_CALL(*env_, GetObjectArrayElement)
.WillOnce(Return(Fake<jobjectArray>(1)))
.WillOnce(Return(Fake<jobjectArray>(2)))
.WillOnce(Return(Fake<jobjectArray>(3)))
.WillOnce(Return(Fake<jobjectArray>(4)))
.WillOnce(Return(Fake<jobjectArray>(5)));

// All the returned objectArrays are deleted.
EXPECT_CALL(*env_, DeleteLocalRef(Fake<jclass>()));
EXPECT_CALL(*env_, DeleteLocalRef(Fake<jobjectArray>(1)));
EXPECT_CALL(*env_, DeleteLocalRef(Fake<jobjectArray>(2)));
EXPECT_CALL(*env_, DeleteLocalRef(Fake<jobjectArray>(3)));
EXPECT_CALL(*env_, DeleteLocalRef(Fake<jobjectArray>(4)));
EXPECT_CALL(*env_, DeleteLocalRef(Fake<jobjectArray>(5)));

// Note: This is just 0 (default), not 100. 100 is the sample (i.e. template)
// object, no arg is the default that is created.
EXPECT_CALL(*env_, DeleteLocalRef(Fake<jobjectArray>()));

LocalArray<jobject, 2, kClass> new_array{5, Fake<jobjectArray>(100)};
EXPECT_EQ(jobject{new_array}, Fake<jobjectArray>());

int i = 1;
for (LocalArray<jobject, 1, kClass> arr : new_array.Pin()) {
EXPECT_EQ(jobject(arr), Fake<jobjectArray>(i));
++i;
}
}

} // namespace
26 changes: 19 additions & 7 deletions javatests/com/jnibind/test/ArrayTestMethodRank2.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,20 @@ void double2D(double baseOffset, double[][] arr) {
}
}

void object1D(ObjectTestHelper[] arr) {
for (ObjectTestHelper element : arr) {
System.out.println(element);
}
}

void object2D(int objectMemberOffset, ObjectTestHelper[][] arr) {
// TODO(b/143908983): Add object based test.
int curVal = objectMemberOffset;
for (ObjectTestHelper[] objectList : arr) {
for (ObjectTestHelper element : objectList) {
assertTrue(element.isEqualTo(new ObjectTestHelper(curVal, curVal, curVal)));
curVal++;
}
}
}

/** 2D Tests. * */
Expand Down Expand Up @@ -230,15 +242,15 @@ public void doubleTests2D() {
nativeDoubleTests2D(this, arr);
}

/*
// TODO(b/143908983): Add object based test.
@Test
public void objectTests2D() {
ObjectTestHelper[] objectTestHelper = {
new ObjectTestHelper(0, 0, 0), new ObjectTestHelper(1, 1, 1), new ObjectTestHelper(2, 2, 2)
ObjectTestHelper[][] arr = {
{new ObjectTestHelper(0, 0, 0), new ObjectTestHelper(1, 1, 1), new ObjectTestHelper(2, 2, 2)},
{new ObjectTestHelper(3, 3, 3), new ObjectTestHelper(4, 4, 4), new ObjectTestHelper(5, 5, 5)},
{new ObjectTestHelper(6, 6, 6), new ObjectTestHelper(7, 7, 7), new ObjectTestHelper(8, 8, 8)},
};

nativeObjectTests2D(this, objectTestHelper);
object2D(0, arr);
nativeObjectTests2D(this, arr);
}
*/
}
6 changes: 6 additions & 0 deletions javatests/com/jnibind/test/ObjectTestHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ public boolean isEqualTo(ObjectTestHelper rhs) {
&& this.intVal3 == rhs.intVal3;
}

public void increment(int val) {
intVal1 += val;
intVal2 += val;
intVal3 += val;
}

public int intVal1;
public int intVal2;
public int intVal3;
Expand Down
65 changes: 65 additions & 0 deletions javatests/com/jnibind/test/array_test_method_rank_2_jni.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <memory>

#include "modulo.h"
#include "javatests/com/jnibind/test/object_test_helper_jni.h"
#include "jni_bind.h"
#include "metaprogramming/lambda_string.h"

Expand Down Expand Up @@ -44,6 +45,9 @@ static constexpr Class kFixture {
Method {"long2D", Return<void>{}, Params{jlong{}, Array{jlong{}, Rank<2>{}}}},
Method {"float2D", Return<void>{}, Params{float{}, Array{jfloat{}, Rank<2>{}}}},
Method {"double2D", Return<void>{}, Params{jdouble{}, Array{jdouble{}, Rank<2>{}}}},
Method {"string2D", Return<void>{}, Params{Array{jstring{}, Rank<2>{}}}},
Method {"object1D", Return<void>{}, Params{Array{kObjectTestHelperClass, Rank<1>{}}}},
Method {"object2D", Return<void>{}, Params{int{}, Array{kObjectTestHelperClass, Rank<2>{}}}},
};
// clang-format on

Expand Down Expand Up @@ -189,4 +193,65 @@ Java_com_jnibind_test_ArrayTestMethodRank2_nativeDoubleTests2D(
LocalArray<jdouble, 2>{arr});
}

JNIEXPORT void JNICALL
Java_com_jnibind_test_ArrayTestMethodRank2_nativeObjectTests2D(
JNIEnv* env, jclass, jobject fixture_jobject,
jobjectArray arr_jobjectArray) {
LocalObject<kFixture> fixture{fixture_jobject};

// Simple lvalue pass through works as expected.
LocalArray<jobject, 2, kObjectTestHelperClass> arr{arr_jobjectArray};
fixture("object2D", 0, arr);

// Simple rvalue pass through works as expected.
fixture("object2D", 0, std::move(arr));

// Building a new array, and setting all the values by hand works.
LocalArray<jobject, 2, kObjectTestHelperClass> new_array{3, nullptr};

LocalArray<jobject, 1, kObjectTestHelperClass> row1{3};
row1.Set(0, LocalObject<kObjectTestHelperClass>{0, 0, 0});
row1.Set(1, LocalObject<kObjectTestHelperClass>{1, 1, 1});
row1.Set(2, LocalObject<kObjectTestHelperClass>{2, 2, 2});

LocalArray<jobject, 1, kObjectTestHelperClass> row2{3};
row2.Set(0, LocalObject<kObjectTestHelperClass>{3, 3, 3});
row2.Set(1, LocalObject<kObjectTestHelperClass>{4, 4, 4});
row2.Set(2, LocalObject<kObjectTestHelperClass>{5, 5, 5});

LocalArray<jobject, 1, kObjectTestHelperClass> row3{3};
row3.Set(0, LocalObject<kObjectTestHelperClass>{6, 6, 6});
row3.Set(1, LocalObject<kObjectTestHelperClass>{7, 7, 7});
row3.Set(2, LocalObject<kObjectTestHelperClass>{8, 8, 8});

new_array.Set(0, row1);
new_array.Set(1, row2);
new_array.Set(2, row3);

fixture("object2D", 0, new_array);

// You can pull the view multiple times with iterators (each value ticked 1).
{
for (LocalArray<jobject, 1> inner_array : new_array.Pin()) {
for (LocalObject<kObjectTestHelperClass> obj : inner_array.Pin()) {
obj("increment", 1);
}
}
fixture("object2D", 1, new_array);
}

// You can pull the view multiple times with raw loops.
{
for (int i = 0; i < new_array.Length(); ++i) {
LocalArray<jobject, 1, kObjectTestHelperClass> inn_arr{new_array.Get(i)};
for (int j = 0; j < inn_arr.Length(); ++j) {
inn_arr.Get(j)("increment", 1);
}
}
}

// Each variant increments base by 1, so 2 is used here.
fixture("object2D", 2, new_array);
}

} // extern "C"
1 change: 1 addition & 0 deletions javatests/com/jnibind/test/object_test_helper_jni.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ constexpr jni::Class kObjectTestHelperClass {
},

::jni::Method{"foo", ::jni::Return{}, ::jni::Params{}},
::jni::Method{"increment", ::jni::Return{}, ::jni::Params<int>{}},

::jni::Field{"intVal1", int{}},
::jni::Field{"intVal2", int{}},
Expand Down

0 comments on commit 39bed6b

Please sign in to comment.