1*65c59e02SInna Palant /*
2*65c59e02SInna Palant * Copyright (c) Facebook, Inc. and its affiliates.
3*65c59e02SInna Palant *
4*65c59e02SInna Palant * Licensed under the Apache License, Version 2.0 (the "License");
5*65c59e02SInna Palant * you may not use this file except in compliance with the License.
6*65c59e02SInna Palant * You may obtain a copy of the License at
7*65c59e02SInna Palant *
8*65c59e02SInna Palant * http://www.apache.org/licenses/LICENSE-2.0
9*65c59e02SInna Palant *
10*65c59e02SInna Palant * Unless required by applicable law or agreed to in writing, software
11*65c59e02SInna Palant * distributed under the License is distributed on an "AS IS" BASIS,
12*65c59e02SInna Palant * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*65c59e02SInna Palant * See the License for the specific language governing permissions and
14*65c59e02SInna Palant * limitations under the License.
15*65c59e02SInna Palant */
16*65c59e02SInna Palant
17*65c59e02SInna Palant #include <chrono>
18*65c59e02SInna Palant #include <ios>
19*65c59e02SInna Palant #include <stdexcept>
20*65c59e02SInna Palant #include <system_error>
21*65c59e02SInna Palant #include <thread>
22*65c59e02SInna Palant
23*65c59e02SInna Palant #include <fbjni/JThread.h>
24*65c59e02SInna Palant #include <fbjni/fbjni.h>
25*65c59e02SInna Palant
26*65c59e02SInna Palant #include "expect.h"
27*65c59e02SInna Palant #include "no_rtti.h"
28*65c59e02SInna Palant
29*65c59e02SInna Palant #include "inter_dso_exception_test_2/Test.h"
30*65c59e02SInna Palant
31*65c59e02SInna Palant #define EXPECT_SAME(A, B, C) EXPECT((A) == (B) && (B) == (C) && (C) == (A))
32*65c59e02SInna Palant
33*65c59e02SInna Palant // A lot of the functions here are just confirming that compilation works.
34*65c59e02SInna Palant #pragma GCC diagnostic ignored "-Wunused-function"
35*65c59e02SInna Palant
36*65c59e02SInna Palant using namespace facebook::jni;
37*65c59e02SInna Palant
38*65c59e02SInna Palant namespace {
39*65c59e02SInna Palant
40*65c59e02SInna Palant struct Callbacks : public facebook::jni::JavaClass<Callbacks> {
41*65c59e02SInna Palant constexpr static auto kJavaDescriptor =
42*65c59e02SInna Palant "Lcom/facebook/jni/FBJniTests$Callbacks;";
43*65c59e02SInna Palant };
44*65c59e02SInna Palant
45*65c59e02SInna Palant struct TestThing : public JavaClass<TestThing> {
46*65c59e02SInna Palant constexpr static auto kJavaDescriptor =
47*65c59e02SInna Palant "Lcom/facebook/jni/FBJniTests$TestThing;";
48*65c59e02SInna Palant };
49*65c59e02SInna Palant
50*65c59e02SInna Palant // Yes, sloppy and does not handle conversions correctly but does it's job here
ToString(JNIEnv * env,jstring java_string)51*65c59e02SInna Palant static std::string ToString(JNIEnv* env, jstring java_string) {
52*65c59e02SInna Palant auto chars = env->GetStringUTFChars(java_string, nullptr);
53*65c59e02SInna Palant if (chars == nullptr) {
54*65c59e02SInna Palant throw std::runtime_error{"Couldn't get UTF chars"};
55*65c59e02SInna Palant }
56*65c59e02SInna Palant
57*65c59e02SInna Palant std::string string{chars};
58*65c59e02SInna Palant env->ReleaseStringUTFChars(java_string, chars);
59*65c59e02SInna Palant
60*65c59e02SInna Palant return string;
61*65c59e02SInna Palant }
62*65c59e02SInna Palant
TestClassResolution(JNIEnv * env,jobject self,jstring class_name)63*65c59e02SInna Palant jboolean TestClassResolution(JNIEnv* env, jobject self, jstring class_name) {
64*65c59e02SInna Palant auto resolved_class = findClassLocal(ToString(env, class_name).c_str());
65*65c59e02SInna Palant return resolved_class.get() != nullptr ? JNI_TRUE : JNI_FALSE;
66*65c59e02SInna Palant }
67*65c59e02SInna Palant
68*65c59e02SInna Palant jboolean
TestLazyClassResolution(JNIEnv * env,jobject self,jstring class_name)69*65c59e02SInna Palant TestLazyClassResolution(JNIEnv* env, jobject self, jstring class_name) {
70*65c59e02SInna Palant auto resolved_class = alias_ref<jclass>{};
71*65c59e02SInna Palant resolved_class = findClassLocal(ToString(env, class_name).c_str());
72*65c59e02SInna Palant return resolved_class.get() != nullptr ? JNI_TRUE : JNI_FALSE;
73*65c59e02SInna Palant }
74*65c59e02SInna Palant
TestCreateInstanceOf(JNIEnv * env,jobject self,jstring class_name)75*65c59e02SInna Palant jobject TestCreateInstanceOf(JNIEnv* env, jobject self, jstring class_name) {
76*65c59e02SInna Palant auto clazz = findClassLocal(ToString(env, class_name).c_str());
77*65c59e02SInna Palant auto constructor = clazz->getConstructor<jobject(jstring)>();
78*65c59e02SInna Palant return clazz->newObject(constructor, class_name).release();
79*65c59e02SInna Palant }
80*65c59e02SInna Palant
TestTypeDescriptors(JNIEnv * env,jobject self)81*65c59e02SInna Palant jboolean TestTypeDescriptors(JNIEnv* env, jobject self) {
82*65c59e02SInna Palant #define FIXED_STRING_EXPECT_EQ(actual, expected) \
83*65c59e02SInna Palant static_assert((actual) == (expected), "descriptor mismatch")
84*65c59e02SInna Palant
85*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jboolean>::kDescriptor, "Z");
86*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jbyte>::kDescriptor, "B");
87*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jchar>::kDescriptor, "C");
88*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jdouble>::kDescriptor, "D");
89*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jfloat>::kDescriptor, "F");
90*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jint>::kDescriptor, "I");
91*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jlong>::kDescriptor, "J");
92*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jshort>::kDescriptor, "S");
93*65c59e02SInna Palant
94*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(
95*65c59e02SInna Palant jtype_traits<jstring>::kDescriptor, "Ljava/lang/String;");
96*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(
97*65c59e02SInna Palant jtype_traits<jobject>::kDescriptor, "Ljava/lang/Object;");
98*65c59e02SInna Palant
99*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jintArray>::kDescriptor, "[I");
100*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(
101*65c59e02SInna Palant jtype_traits<jtypeArray<jstring>>::kDescriptor, "[Ljava/lang/String;");
102*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(
103*65c59e02SInna Palant jtype_traits<jtypeArray<jtypeArray<jstring>>>::kDescriptor,
104*65c59e02SInna Palant "[[Ljava/lang/String;");
105*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(
106*65c59e02SInna Palant jtype_traits<jtypeArray<jintArray>>::kDescriptor, "[[I");
107*65c59e02SInna Palant
108*65c59e02SInna Palant // base_name() is meaningless for primitive types.
109*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jstring>::kBaseName, "java/lang/String");
110*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jobject>::kBaseName, "java/lang/Object");
111*65c59e02SInna Palant
112*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jintArray>::kBaseName, "[I");
113*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(
114*65c59e02SInna Palant jtype_traits<jtypeArray<jstring>>::kBaseName, "[Ljava/lang/String;");
115*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(
116*65c59e02SInna Palant jtype_traits<jtypeArray<jtypeArray<jstring>>>::kBaseName,
117*65c59e02SInna Palant "[[Ljava/lang/String;");
118*65c59e02SInna Palant FIXED_STRING_EXPECT_EQ(jtype_traits<jtypeArray<jintArray>>::kBaseName, "[[I");
119*65c59e02SInna Palant
120*65c59e02SInna Palant return JNI_TRUE;
121*65c59e02SInna Palant }
122*65c59e02SInna Palant
TestVirtualMethodResolution_I(JNIEnv * env,jobject self,jstring class_name,jstring method_name)123*65c59e02SInna Palant jboolean TestVirtualMethodResolution_I(
124*65c59e02SInna Palant JNIEnv* env,
125*65c59e02SInna Palant jobject self,
126*65c59e02SInna Palant jstring class_name,
127*65c59e02SInna Palant jstring method_name) {
128*65c59e02SInna Palant auto resolved_class = findClassLocal(ToString(env, class_name).c_str());
129*65c59e02SInna Palant auto resolved_method =
130*65c59e02SInna Palant resolved_class->getMethod<jint()>(ToString(env, method_name).c_str());
131*65c59e02SInna Palant return static_cast<bool>(resolved_method);
132*65c59e02SInna Palant }
133*65c59e02SInna Palant
TestVirtualMethodResolution_arrB(JNIEnv * env,jobject self,jstring class_name,jstring method_name)134*65c59e02SInna Palant jboolean TestVirtualMethodResolution_arrB(
135*65c59e02SInna Palant JNIEnv* env,
136*65c59e02SInna Palant jobject self,
137*65c59e02SInna Palant jstring class_name,
138*65c59e02SInna Palant jstring method_name) {
139*65c59e02SInna Palant auto resolved_class = findClassLocal(ToString(env, class_name).c_str());
140*65c59e02SInna Palant auto resolved_method = resolved_class->getMethod<jbyteArray()>(
141*65c59e02SInna Palant ToString(env, method_name).c_str());
142*65c59e02SInna Palant return static_cast<bool>(resolved_method);
143*65c59e02SInna Palant }
144*65c59e02SInna Palant
TestVirtualMethodResolution_S_arrS(JNIEnv * env,jobject self,jstring class_name,jstring method_name)145*65c59e02SInna Palant jboolean TestVirtualMethodResolution_S_arrS(
146*65c59e02SInna Palant JNIEnv* env,
147*65c59e02SInna Palant jobject self,
148*65c59e02SInna Palant jstring class_name,
149*65c59e02SInna Palant jstring method_name) {
150*65c59e02SInna Palant auto resolved_class = findClassLocal(ToString(env, class_name).c_str());
151*65c59e02SInna Palant auto resolved_method =
152*65c59e02SInna Palant resolved_class->getMethod<jtypeArray<jstring>(jstring)>(
153*65c59e02SInna Palant ToString(env, method_name).c_str());
154*65c59e02SInna Palant return static_cast<bool>(resolved_method);
155*65c59e02SInna Palant }
156*65c59e02SInna Palant
TestVirtualMethodResolution_arrarrS(JNIEnv * env,jobject self,jstring class_name,jstring method_name)157*65c59e02SInna Palant jboolean TestVirtualMethodResolution_arrarrS(
158*65c59e02SInna Palant JNIEnv* env,
159*65c59e02SInna Palant jobject self,
160*65c59e02SInna Palant jstring class_name,
161*65c59e02SInna Palant jstring method_name) {
162*65c59e02SInna Palant auto resolved_class = findClassLocal(ToString(env, class_name).c_str());
163*65c59e02SInna Palant auto resolved_method =
164*65c59e02SInna Palant resolved_class->getStaticMethod<jtypeArray<jtypeArray<jstring>>()>(
165*65c59e02SInna Palant ToString(env, method_name).c_str());
166*65c59e02SInna Palant return static_cast<bool>(resolved_method);
167*65c59e02SInna Palant }
168*65c59e02SInna Palant
TestVirtualMethodResolution_arrarrI(JNIEnv * env,jobject self,jstring class_name,jstring method_name)169*65c59e02SInna Palant jboolean TestVirtualMethodResolution_arrarrI(
170*65c59e02SInna Palant JNIEnv* env,
171*65c59e02SInna Palant jobject self,
172*65c59e02SInna Palant jstring class_name,
173*65c59e02SInna Palant jstring method_name) {
174*65c59e02SInna Palant auto resolved_class = findClassLocal(ToString(env, class_name).c_str());
175*65c59e02SInna Palant auto resolved_method =
176*65c59e02SInna Palant resolved_class->getStaticMethod<jtypeArray<jintArray>()>(
177*65c59e02SInna Palant ToString(env, method_name).c_str());
178*65c59e02SInna Palant return static_cast<bool>(resolved_method);
179*65c59e02SInna Palant }
180*65c59e02SInna Palant
TestLazyVirtualMethodResolution_I(JNIEnv * env,jobject self,jstring class_name,jstring method_name)181*65c59e02SInna Palant jboolean TestLazyVirtualMethodResolution_I(
182*65c59e02SInna Palant JNIEnv* env,
183*65c59e02SInna Palant jobject self,
184*65c59e02SInna Palant jstring class_name,
185*65c59e02SInna Palant jstring method_name) {
186*65c59e02SInna Palant auto resolved_class = findClassLocal(ToString(env, class_name).c_str());
187*65c59e02SInna Palant auto resolved_method = JMethod<jint()>{};
188*65c59e02SInna Palant resolved_method =
189*65c59e02SInna Palant resolved_class->getMethod<jint()>(ToString(env, method_name).c_str());
190*65c59e02SInna Palant return static_cast<bool>(resolved_method);
191*65c59e02SInna Palant }
192*65c59e02SInna Palant
TestJMethodCallbacks(JNIEnv * env,jobject self,Callbacks::javaobject callbacks)193*65c59e02SInna Palant void TestJMethodCallbacks(
194*65c59e02SInna Palant JNIEnv* env,
195*65c59e02SInna Palant jobject self,
196*65c59e02SInna Palant Callbacks::javaobject callbacks) {
197*65c59e02SInna Palant static const auto callbacks_class = Callbacks::javaClassStatic();
198*65c59e02SInna Palant
199*65c59e02SInna Palant static const auto void_foo = callbacks_class->getMethod<void()>("voidFoo");
200*65c59e02SInna Palant void_foo(callbacks);
201*65c59e02SInna Palant
202*65c59e02SInna Palant static const auto boolean_foo =
203*65c59e02SInna Palant callbacks_class->getMethod<jboolean()>("booleanFoo");
204*65c59e02SInna Palant boolean_foo(callbacks);
205*65c59e02SInna Palant
206*65c59e02SInna Palant static const auto byte_foo = callbacks_class->getMethod<jbyte()>("byteFoo");
207*65c59e02SInna Palant byte_foo(callbacks);
208*65c59e02SInna Palant
209*65c59e02SInna Palant static const auto char_foo = callbacks_class->getMethod<jchar()>("charFoo");
210*65c59e02SInna Palant char_foo(callbacks);
211*65c59e02SInna Palant
212*65c59e02SInna Palant static const auto short_foo =
213*65c59e02SInna Palant callbacks_class->getMethod<jshort()>("shortFoo");
214*65c59e02SInna Palant short_foo(callbacks);
215*65c59e02SInna Palant
216*65c59e02SInna Palant static const auto int_foo = callbacks_class->getMethod<jint()>("intFoo");
217*65c59e02SInna Palant int_foo(callbacks);
218*65c59e02SInna Palant
219*65c59e02SInna Palant static const auto long_foo = callbacks_class->getMethod<jlong()>("longFoo");
220*65c59e02SInna Palant long_foo(callbacks);
221*65c59e02SInna Palant
222*65c59e02SInna Palant static const auto float_foo =
223*65c59e02SInna Palant callbacks_class->getMethod<jfloat()>("floatFoo");
224*65c59e02SInna Palant float_foo(callbacks);
225*65c59e02SInna Palant
226*65c59e02SInna Palant static const auto double_foo =
227*65c59e02SInna Palant callbacks_class->getMethod<jdouble()>("doubleFoo");
228*65c59e02SInna Palant double_foo(callbacks);
229*65c59e02SInna Palant
230*65c59e02SInna Palant static const auto object_foo =
231*65c59e02SInna Palant callbacks_class->getMethod<jobject()>("objectFoo");
232*65c59e02SInna Palant object_foo(callbacks);
233*65c59e02SInna Palant
234*65c59e02SInna Palant static const auto string_foo =
235*65c59e02SInna Palant callbacks_class->getMethod<jstring()>("stringFoo");
236*65c59e02SInna Palant string_foo(callbacks);
237*65c59e02SInna Palant }
238*65c59e02SInna Palant
239*65c59e02SInna Palant // Try to test the static functions
TestJStaticMethodCallbacks(JNIEnv * env,jobject self)240*65c59e02SInna Palant void TestJStaticMethodCallbacks(JNIEnv* env, jobject self) {
241*65c59e02SInna Palant // static auto callbacks_class = findClassStatic(callbacks_class_name);
242*65c59e02SInna Palant auto cls = findClassLocal("com/facebook/jni/FBJniTests");
243*65c59e02SInna Palant jclass jcls = env->FindClass("com/facebook/jni/FBJniTests");
244*65c59e02SInna Palant
245*65c59e02SInna Palant static const auto void_foo_static =
246*65c59e02SInna Palant cls->getStaticMethod<void()>("voidFooStatic");
247*65c59e02SInna Palant void_foo_static(jcls);
248*65c59e02SInna Palant
249*65c59e02SInna Palant static const auto boolean_foo_static =
250*65c59e02SInna Palant cls->getStaticMethod<jboolean()>("booleanFooStatic");
251*65c59e02SInna Palant boolean_foo_static(jcls);
252*65c59e02SInna Palant
253*65c59e02SInna Palant static const auto byte_foo_static =
254*65c59e02SInna Palant cls->getStaticMethod<jbyte()>("byteFooStatic");
255*65c59e02SInna Palant byte_foo_static(jcls);
256*65c59e02SInna Palant
257*65c59e02SInna Palant static const auto char_foo_static =
258*65c59e02SInna Palant cls->getStaticMethod<jchar(jchar, jint)>("charFooStatic");
259*65c59e02SInna Palant char_foo_static(jcls, 'c', 5);
260*65c59e02SInna Palant
261*65c59e02SInna Palant static const auto short_foo_static =
262*65c59e02SInna Palant cls->getStaticMethod<jshort(jshort, jshort)>("shortFooStatic");
263*65c59e02SInna Palant short_foo_static(jcls, 17, 42);
264*65c59e02SInna Palant
265*65c59e02SInna Palant static const auto int_foo_static =
266*65c59e02SInna Palant cls->getStaticMethod<jint(jint)>("intFooStatic");
267*65c59e02SInna Palant int_foo_static(jcls, 5);
268*65c59e02SInna Palant
269*65c59e02SInna Palant static const auto long_foo_static =
270*65c59e02SInna Palant cls->getStaticMethod<jlong()>("longFooStatic");
271*65c59e02SInna Palant long_foo_static(jcls);
272*65c59e02SInna Palant
273*65c59e02SInna Palant static const auto float_foo_static =
274*65c59e02SInna Palant cls->getStaticMethod<jfloat()>("floatFooStatic");
275*65c59e02SInna Palant float_foo_static(jcls);
276*65c59e02SInna Palant
277*65c59e02SInna Palant static const auto double_foo_static =
278*65c59e02SInna Palant cls->getStaticMethod<jdouble()>("doubleFooStatic");
279*65c59e02SInna Palant double_foo_static(jcls);
280*65c59e02SInna Palant
281*65c59e02SInna Palant static const auto object_foo_static =
282*65c59e02SInna Palant cls->getStaticMethod<jobject()>("objectFooStatic");
283*65c59e02SInna Palant object_foo_static(jcls);
284*65c59e02SInna Palant
285*65c59e02SInna Palant static const auto string_foo_static =
286*65c59e02SInna Palant cls->getStaticMethod<jstring()>("stringFooStatic");
287*65c59e02SInna Palant string_foo_static(jcls);
288*65c59e02SInna Palant }
289*65c59e02SInna Palant
290*65c59e02SInna Palant jboolean
TestIsAssignableFrom(JNIEnv * env,jobject self,jclass cls1,jclass cls2)291*65c59e02SInna Palant TestIsAssignableFrom(JNIEnv* env, jobject self, jclass cls1, jclass cls2) {
292*65c59e02SInna Palant return adopt_local(cls1)->isAssignableFrom(cls2);
293*65c59e02SInna Palant }
294*65c59e02SInna Palant
295*65c59e02SInna Palant jboolean
TestIsInstanceOf(JNIEnv * env,jobject self,jobject test_object,jclass cls)296*65c59e02SInna Palant TestIsInstanceOf(JNIEnv* env, jobject self, jobject test_object, jclass cls) {
297*65c59e02SInna Palant auto clsref = adopt_local(test_object);
298*65c59e02SInna Palant return clsref->isInstanceOf(cls);
299*65c59e02SInna Palant }
300*65c59e02SInna Palant
TestIsSameObject(JNIEnv * env,jobject self,jobject a,jobject b)301*65c59e02SInna Palant jboolean TestIsSameObject(JNIEnv* env, jobject self, jobject a, jobject b) {
302*65c59e02SInna Palant return isSameObject(a, b);
303*65c59e02SInna Palant }
304*65c59e02SInna Palant
TestGetSuperclass(JNIEnv * env,jobject self,jclass test_class,jclass super_class)305*65c59e02SInna Palant jboolean TestGetSuperclass(
306*65c59e02SInna Palant JNIEnv* env,
307*65c59e02SInna Palant jobject self,
308*65c59e02SInna Palant jclass test_class,
309*65c59e02SInna Palant jclass super_class) {
310*65c59e02SInna Palant return isSameObject(
311*65c59e02SInna Palant adopt_local(test_class)->getSuperclass().get(), super_class);
312*65c59e02SInna Palant }
313*65c59e02SInna Palant
314*65c59e02SInna Palant jboolean
StaticCastAliasRefToString(JNIEnv *,jobject,jobject string_as_object)315*65c59e02SInna Palant StaticCastAliasRefToString(JNIEnv*, jobject, jobject string_as_object) {
316*65c59e02SInna Palant alias_ref<jobject> string_as_object_alias_ref{string_as_object};
317*65c59e02SInna Palant alias_ref<jstring> string_alias_ref =
318*65c59e02SInna Palant static_ref_cast<jstring>(string_as_object_alias_ref);
319*65c59e02SInna Palant return isSameObject(string_alias_ref.get(), string_as_object_alias_ref.get());
320*65c59e02SInna Palant }
321*65c59e02SInna Palant
DynamicCastAliasRefToThrowable(JNIEnv *,jobject,jobject might_actually_be_throwable)322*65c59e02SInna Palant jboolean DynamicCastAliasRefToThrowable(
323*65c59e02SInna Palant JNIEnv*,
324*65c59e02SInna Palant jobject,
325*65c59e02SInna Palant jobject might_actually_be_throwable) {
326*65c59e02SInna Palant alias_ref<jobject> might_actually_be_throwable_alias_ref{
327*65c59e02SInna Palant might_actually_be_throwable};
328*65c59e02SInna Palant // If the next line fails, it will throw an exception.
329*65c59e02SInna Palant alias_ref<jthrowable> throwable_alias_ref =
330*65c59e02SInna Palant dynamic_ref_cast<jthrowable>(might_actually_be_throwable_alias_ref);
331*65c59e02SInna Palant return isSameObject(
332*65c59e02SInna Palant throwable_alias_ref.get(), might_actually_be_throwable_alias_ref.get());
333*65c59e02SInna Palant }
334*65c59e02SInna Palant
335*65c59e02SInna Palant jboolean
StaticCastLocalRefToString(JNIEnv *,jobject,jobject string_as_object)336*65c59e02SInna Palant StaticCastLocalRefToString(JNIEnv*, jobject, jobject string_as_object) {
337*65c59e02SInna Palant local_ref<jobject> string_as_object_local_ref = adopt_local(string_as_object);
338*65c59e02SInna Palant local_ref<jstring> string_local_ref =
339*65c59e02SInna Palant static_ref_cast<jstring>(string_as_object_local_ref);
340*65c59e02SInna Palant return isSameObject(string_local_ref.get(), string_as_object_local_ref.get());
341*65c59e02SInna Palant }
342*65c59e02SInna Palant
DynamicCastLocalRefToString(JNIEnv *,jobject,jobject might_actually_be_string)343*65c59e02SInna Palant jboolean DynamicCastLocalRefToString(
344*65c59e02SInna Palant JNIEnv*,
345*65c59e02SInna Palant jobject,
346*65c59e02SInna Palant jobject might_actually_be_string) {
347*65c59e02SInna Palant local_ref<jobject> might_actually_be_string_local_ref =
348*65c59e02SInna Palant adopt_local(might_actually_be_string);
349*65c59e02SInna Palant // If the next line fails, it will throw an exception.
350*65c59e02SInna Palant local_ref<jstring> string_local_ref =
351*65c59e02SInna Palant dynamic_ref_cast<jstring>(might_actually_be_string_local_ref);
352*65c59e02SInna Palant return isSameObject(
353*65c59e02SInna Palant string_local_ref.get(), might_actually_be_string_local_ref.get());
354*65c59e02SInna Palant }
355*65c59e02SInna Palant
356*65c59e02SInna Palant jboolean
StaticCastGlobalRefToString(JNIEnv *,jobject,jobject string_as_object)357*65c59e02SInna Palant StaticCastGlobalRefToString(JNIEnv*, jobject, jobject string_as_object) {
358*65c59e02SInna Palant global_ref<jobject> string_as_object_global_ref =
359*65c59e02SInna Palant make_global(string_as_object);
360*65c59e02SInna Palant global_ref<jstring> string_global_ref =
361*65c59e02SInna Palant static_ref_cast<jstring>(string_as_object_global_ref);
362*65c59e02SInna Palant return isSameObject(
363*65c59e02SInna Palant string_global_ref.get(), string_as_object_global_ref.get());
364*65c59e02SInna Palant }
365*65c59e02SInna Palant
DynamicCastGlobalRefToString(JNIEnv *,jobject,jobject might_actually_be_string)366*65c59e02SInna Palant jboolean DynamicCastGlobalRefToString(
367*65c59e02SInna Palant JNIEnv*,
368*65c59e02SInna Palant jobject,
369*65c59e02SInna Palant jobject might_actually_be_string) {
370*65c59e02SInna Palant global_ref<jobject> might_actually_be_string_global_ref =
371*65c59e02SInna Palant make_global(might_actually_be_string);
372*65c59e02SInna Palant // If the next line fails, it will throw an exception.
373*65c59e02SInna Palant global_ref<jstring> string_global_ref =
374*65c59e02SInna Palant dynamic_ref_cast<jstring>(might_actually_be_string_global_ref);
375*65c59e02SInna Palant return isSameObject(
376*65c59e02SInna Palant string_global_ref.get(), might_actually_be_string_global_ref.get());
377*65c59e02SInna Palant }
378*65c59e02SInna Palant
379*65c59e02SInna Palant template <typename... Args>
Use(Args &&...args)380*65c59e02SInna Palant static void Use(Args&&... args) {}
381*65c59e02SInna Palant
TestWeakRefs(JNIEnv *,jobject self)382*65c59e02SInna Palant jboolean TestWeakRefs(JNIEnv*, jobject self) {
383*65c59e02SInna Palant using facebook::jni::internal::g_reference_stats;
384*65c59e02SInna Palant
385*65c59e02SInna Palant g_reference_stats.reset();
386*65c59e02SInna Palant {
387*65c59e02SInna Palant // Wrapping existing local that should be deleted (locals = 1)
388*65c59e02SInna Palant auto local = adopt_local(self);
389*65c59e02SInna Palant // Make new local (locals = 2)
390*65c59e02SInna Palant auto local2 = make_local(local);
391*65c59e02SInna Palant // Make weak (weaks = 1)
392*65c59e02SInna Palant auto weak = make_weak(local);
393*65c59e02SInna Palant // Make global (globals = 1)
394*65c59e02SInna Palant auto global = weak.lockGlobal();
395*65c59e02SInna Palant // No new refs
396*65c59e02SInna Palant auto banana = std::move(weak);
397*65c59e02SInna Palant // No new refs
398*65c59e02SInna Palant auto& binini = banana;
399*65c59e02SInna Palant // Create a global of the local (keeping the local) (globals = 2)
400*65c59e02SInna Palant auto dubglob = make_global(local);
401*65c59e02SInna Palant // Create a weak (weaks = 2)
402*65c59e02SInna Palant auto dupweak = make_weak(local);
403*65c59e02SInna Palant // No new refs
404*65c59e02SInna Palant swap(local, local2);
405*65c59e02SInna Palant
406*65c59e02SInna Palant Use(binini);
407*65c59e02SInna Palant }
408*65c59e02SInna Palant
409*65c59e02SInna Palant FBJNI_LOGE("locals: %d", g_reference_stats.locals_deleted.load());
410*65c59e02SInna Palant FBJNI_LOGE("globals: %d", g_reference_stats.globals_deleted.load());
411*65c59e02SInna Palant FBJNI_LOGE("weaks: %d", g_reference_stats.weaks_deleted.load());
412*65c59e02SInna Palant
413*65c59e02SInna Palant return (g_reference_stats.locals_deleted == 2 &&
414*65c59e02SInna Palant g_reference_stats.globals_deleted == 2 &&
415*65c59e02SInna Palant g_reference_stats.weaks_deleted == 2)
416*65c59e02SInna Palant ? JNI_TRUE
417*65c59e02SInna Palant : JNI_FALSE;
418*65c59e02SInna Palant }
419*65c59e02SInna Palant
TestAlias(JNIEnv * env,jobject self)420*65c59e02SInna Palant jboolean TestAlias(JNIEnv* env, jobject self) {
421*65c59e02SInna Palant auto ref = alias_ref<jobject>{self};
422*65c59e02SInna Palant return ref->isInstanceOf(findClassLocal("java/lang/Object"));
423*65c59e02SInna Palant }
424*65c59e02SInna Palant
testAliasRefConversions(JNIEnv *,jobject self)425*65c59e02SInna Palant jboolean testAliasRefConversions(JNIEnv*, jobject self) {
426*65c59e02SInna Palant auto aLocalString = make_jstring("foo");
427*65c59e02SInna Palant alias_ref<jstring> aString = aLocalString;
428*65c59e02SInna Palant alias_ref<jobject> anObject = aLocalString;
429*65c59e02SInna Palant anObject = (jstring) nullptr;
430*65c59e02SInna Palant anObject = aString;
431*65c59e02SInna Palant // aString = anObject; // Shouldn't compile
432*65c59e02SInna Palant
433*65c59e02SInna Palant return isSameObject(aString, anObject) ? JNI_TRUE : JNI_FALSE;
434*65c59e02SInna Palant }
435*65c59e02SInna Palant
TestAutoAliasRefReturningVoid(facebook::jni::alias_ref<jobject> self)436*65c59e02SInna Palant void TestAutoAliasRefReturningVoid(facebook::jni::alias_ref<jobject> self) {
437*65c59e02SInna Palant // If this compiles, it succeeds.
438*65c59e02SInna Palant }
439*65c59e02SInna Palant
testNullJString(JNIEnv *,jobject)440*65c59e02SInna Palant jboolean testNullJString(JNIEnv*, jobject) {
441*65c59e02SInna Palant auto aNullJString = make_jstring(nullptr);
442*65c59e02SInna Palant EXPECT(aNullJString.get() == (jstring) nullptr);
443*65c59e02SInna Palant return JNI_TRUE;
444*65c59e02SInna Palant }
445*65c59e02SInna Palant
testSwap(JNIEnv *,jobject self,jobject other)446*65c59e02SInna Palant jboolean testSwap(JNIEnv*, jobject self, jobject other) {
447*65c59e02SInna Palant auto selfAlias = wrap_alias(self);
448*65c59e02SInna Palant auto otherAlias = wrap_alias(other);
449*65c59e02SInna Palant
450*65c59e02SInna Palant swap(selfAlias, otherAlias);
451*65c59e02SInna Palant EXPECT(self == otherAlias);
452*65c59e02SInna Palant EXPECT(other == selfAlias);
453*65c59e02SInna Palant EXPECT(self != selfAlias);
454*65c59e02SInna Palant EXPECT(other != otherAlias);
455*65c59e02SInna Palant
456*65c59e02SInna Palant auto selfLocal = make_local(self);
457*65c59e02SInna Palant auto otherLocal = make_local(other);
458*65c59e02SInna Palant swap(selfLocal, otherLocal);
459*65c59e02SInna Palant EXPECT(self == otherLocal);
460*65c59e02SInna Palant EXPECT(other == selfLocal);
461*65c59e02SInna Palant EXPECT(self != selfLocal);
462*65c59e02SInna Palant EXPECT(other != otherLocal);
463*65c59e02SInna Palant
464*65c59e02SInna Palant auto selfGlobal = make_global(self);
465*65c59e02SInna Palant auto otherGlobal = make_global(other);
466*65c59e02SInna Palant swap(selfGlobal, otherGlobal);
467*65c59e02SInna Palant EXPECT(self == otherGlobal);
468*65c59e02SInna Palant EXPECT(other == selfGlobal);
469*65c59e02SInna Palant EXPECT(self != selfGlobal);
470*65c59e02SInna Palant EXPECT(other != otherGlobal);
471*65c59e02SInna Palant
472*65c59e02SInna Palant auto selfWeak = make_weak(self);
473*65c59e02SInna Palant auto otherWeak = make_weak(other);
474*65c59e02SInna Palant swap(selfWeak, otherWeak);
475*65c59e02SInna Palant auto selfLockedWeak = selfWeak.lockLocal();
476*65c59e02SInna Palant auto otherLockedWeak = otherWeak.lockLocal();
477*65c59e02SInna Palant EXPECT(self == otherLockedWeak);
478*65c59e02SInna Palant EXPECT(other == selfLockedWeak);
479*65c59e02SInna Palant EXPECT(self != selfLockedWeak);
480*65c59e02SInna Palant EXPECT(other != otherLockedWeak);
481*65c59e02SInna Palant
482*65c59e02SInna Palant return JNI_TRUE;
483*65c59e02SInna Palant }
484*65c59e02SInna Palant
testEqualOperator(JNIEnv *,jobject self,jobject other)485*65c59e02SInna Palant jboolean testEqualOperator(JNIEnv*, jobject self, jobject other) {
486*65c59e02SInna Palant auto selfAlias = wrap_alias(self);
487*65c59e02SInna Palant auto otherAlias = wrap_alias(other);
488*65c59e02SInna Palant auto selfLocal = adopt_local(self);
489*65c59e02SInna Palant auto otherLocal = adopt_local(other);
490*65c59e02SInna Palant auto selfGlobal = make_global(self);
491*65c59e02SInna Palant auto otherGlobal = make_global(other);
492*65c59e02SInna Palant auto selfWeak = make_weak(self);
493*65c59e02SInna Palant auto otherWeak = make_weak(other);
494*65c59e02SInna Palant auto selfLockedWeak = selfWeak.lockLocal();
495*65c59e02SInna Palant auto otherLockedWeak = otherWeak.lockLocal();
496*65c59e02SInna Palant
497*65c59e02SInna Palant EXPECT(self == selfAlias);
498*65c59e02SInna Palant EXPECT(selfAlias == selfLocal);
499*65c59e02SInna Palant EXPECT(selfLocal == selfGlobal);
500*65c59e02SInna Palant EXPECT(selfGlobal == selfLockedWeak);
501*65c59e02SInna Palant EXPECT(self != other);
502*65c59e02SInna Palant EXPECT(self != otherAlias);
503*65c59e02SInna Palant EXPECT(self != otherLocal);
504*65c59e02SInna Palant EXPECT(self != otherGlobal);
505*65c59e02SInna Palant EXPECT(self != otherLockedWeak);
506*65c59e02SInna Palant EXPECT(selfAlias != nullptr);
507*65c59e02SInna Palant EXPECT(!(selfAlias == nullptr));
508*65c59e02SInna Palant EXPECT(nullptr != selfLocal);
509*65c59e02SInna Palant EXPECT(!(nullptr == selfGlobal));
510*65c59e02SInna Palant
511*65c59e02SInna Palant return JNI_TRUE;
512*65c59e02SInna Palant }
513*65c59e02SInna Palant
testReleaseAlias(JNIEnv *,jobject self)514*65c59e02SInna Palant jboolean testReleaseAlias(JNIEnv*, jobject self) {
515*65c59e02SInna Palant auto local = adopt_local(self);
516*65c59e02SInna Palant auto alias = local.releaseAlias();
517*65c59e02SInna Palant
518*65c59e02SInna Palant EXPECT(typeid(alias) == typeid(alias_ref<jobject>));
519*65c59e02SInna Palant EXPECT(isSameObject(self, alias.get()));
520*65c59e02SInna Palant
521*65c59e02SInna Palant return JNI_TRUE;
522*65c59e02SInna Palant }
523*65c59e02SInna Palant
testLockingWeakReferences(JNIEnv *,jobject self)524*65c59e02SInna Palant jboolean testLockingWeakReferences(JNIEnv*, jobject self) {
525*65c59e02SInna Palant auto weak = make_weak(self);
526*65c59e02SInna Palant auto local = weak.lockLocal();
527*65c59e02SInna Palant auto global = weak.lockGlobal();
528*65c59e02SInna Palant
529*65c59e02SInna Palant EXPECT(typeid(local) == typeid(local_ref<jobject>));
530*65c59e02SInna Palant EXPECT(typeid(global) == typeid(global_ref<jobject>));
531*65c59e02SInna Palant EXPECT(self == local);
532*65c59e02SInna Palant EXPECT(self == global);
533*65c59e02SInna Palant
534*65c59e02SInna Palant return JNI_TRUE;
535*65c59e02SInna Palant }
536*65c59e02SInna Palant
TestFieldAccess(alias_ref<jobject> self,const std::string & field_name,jint oldval,jint newval)537*65c59e02SInna Palant jboolean TestFieldAccess(
538*65c59e02SInna Palant alias_ref<jobject> self,
539*65c59e02SInna Palant const std::string& field_name,
540*65c59e02SInna Palant jint oldval,
541*65c59e02SInna Palant jint newval) {
542*65c59e02SInna Palant auto cls = self->getClass();
543*65c59e02SInna Palant auto fld = cls->getField<jint>(field_name.c_str());
544*65c59e02SInna Palant auto method = cls->getMethod<jint(jdouble)>("bar");
545*65c59e02SInna Palant
546*65c59e02SInna Palant if (method(self.get(), 17) != 42) {
547*65c59e02SInna Palant return JNI_FALSE;
548*65c59e02SInna Palant }
549*65c59e02SInna Palant
550*65c59e02SInna Palant if (method(self, 17) != 42) {
551*65c59e02SInna Palant return JNI_FALSE;
552*65c59e02SInna Palant }
553*65c59e02SInna Palant
554*65c59e02SInna Palant if (self->getFieldValue(fld) != oldval) {
555*65c59e02SInna Palant return JNI_FALSE;
556*65c59e02SInna Palant }
557*65c59e02SInna Palant
558*65c59e02SInna Palant self->setFieldValue(fld, newval);
559*65c59e02SInna Palant
560*65c59e02SInna Palant return JNI_TRUE;
561*65c59e02SInna Palant }
562*65c59e02SInna Palant
TestStringFieldAccess(JNIEnv * env,jobject self,jstring field_name,jstring oldval,jstring newval)563*65c59e02SInna Palant jboolean TestStringFieldAccess(
564*65c59e02SInna Palant JNIEnv* env,
565*65c59e02SInna Palant jobject self,
566*65c59e02SInna Palant jstring field_name,
567*65c59e02SInna Palant jstring oldval,
568*65c59e02SInna Palant jstring newval) {
569*65c59e02SInna Palant auto me = adopt_local(self);
570*65c59e02SInna Palant auto cls = me->getClass();
571*65c59e02SInna Palant auto fld = cls->getField<jstring>(ToString(env, field_name).c_str());
572*65c59e02SInna Palant auto oldvalStr = adopt_local(oldval)->toStdString();
573*65c59e02SInna Palant
574*65c59e02SInna Palant auto curvalRef = me->getFieldValue(fld);
575*65c59e02SInna Palant if (curvalRef->toStdString() != oldvalStr) {
576*65c59e02SInna Palant return JNI_FALSE;
577*65c59e02SInna Palant }
578*65c59e02SInna Palant
579*65c59e02SInna Palant const alias_ref<jobject> cme = me;
580*65c59e02SInna Palant if (cme->getFieldValue(fld)->toStdString() != oldvalStr) {
581*65c59e02SInna Palant return JNI_FALSE;
582*65c59e02SInna Palant }
583*65c59e02SInna Palant
584*65c59e02SInna Palant me->setFieldValue(fld, newval);
585*65c59e02SInna Palant
586*65c59e02SInna Palant return JNI_TRUE;
587*65c59e02SInna Palant }
588*65c59e02SInna Palant
TestReferenceFieldAccess(alias_ref<jobject> self,std::string const & field_name,jobject oldval,jobject newval,jboolean useWrapper)589*65c59e02SInna Palant jboolean TestReferenceFieldAccess(
590*65c59e02SInna Palant alias_ref<jobject> self,
591*65c59e02SInna Palant std::string const& field_name,
592*65c59e02SInna Palant jobject oldval,
593*65c59e02SInna Palant jobject newval,
594*65c59e02SInna Palant jboolean useWrapper) {
595*65c59e02SInna Palant auto cls = self->getClass();
596*65c59e02SInna Palant auto rawfld =
597*65c59e02SInna Palant cls->getField<jobject>(field_name.c_str(), TestThing::kJavaDescriptor);
598*65c59e02SInna Palant
599*65c59e02SInna Palant if (self->getFieldValue(rawfld) != oldval) {
600*65c59e02SInna Palant return JNI_FALSE;
601*65c59e02SInna Palant }
602*65c59e02SInna Palant
603*65c59e02SInna Palant alias_ref<jobject> const cself = self;
604*65c59e02SInna Palant if (cself->getFieldValue(rawfld) != oldval) {
605*65c59e02SInna Palant return JNI_FALSE;
606*65c59e02SInna Palant }
607*65c59e02SInna Palant
608*65c59e02SInna Palant if (useWrapper) {
609*65c59e02SInna Palant auto newvalRef = adopt_local(static_cast<TestThing::javaobject>(newval));
610*65c59e02SInna Palant auto fld = cls->getField<TestThing::javaobject>(field_name.c_str());
611*65c59e02SInna Palant self->setFieldValue<TestThing::javaobject>(fld, newvalRef);
612*65c59e02SInna Palant } else {
613*65c59e02SInna Palant self->setFieldValue(rawfld, newval);
614*65c59e02SInna Palant }
615*65c59e02SInna Palant
616*65c59e02SInna Palant return JNI_TRUE;
617*65c59e02SInna Palant }
618*65c59e02SInna Palant
TestStaticFieldAccess(JNIEnv * env,jobject self,jstring field_name,jint oldval,jint newval)619*65c59e02SInna Palant jboolean TestStaticFieldAccess(
620*65c59e02SInna Palant JNIEnv* env,
621*65c59e02SInna Palant jobject self,
622*65c59e02SInna Palant jstring field_name,
623*65c59e02SInna Palant jint oldval,
624*65c59e02SInna Palant jint newval) {
625*65c59e02SInna Palant auto me = adopt_local(self);
626*65c59e02SInna Palant auto cls = me->getClass();
627*65c59e02SInna Palant auto fld = cls->getStaticField<jint>(ToString(env, field_name).c_str());
628*65c59e02SInna Palant
629*65c59e02SInna Palant if (cls->getStaticFieldValue(fld) != oldval) {
630*65c59e02SInna Palant return JNI_FALSE;
631*65c59e02SInna Palant }
632*65c59e02SInna Palant cls->setStaticFieldValue(fld, newval);
633*65c59e02SInna Palant return JNI_TRUE;
634*65c59e02SInna Palant }
635*65c59e02SInna Palant
TestStaticStringFieldAccess(JNIEnv * env,jobject self,jstring field_name,jstring oldval,jstring newval)636*65c59e02SInna Palant jboolean TestStaticStringFieldAccess(
637*65c59e02SInna Palant JNIEnv* env,
638*65c59e02SInna Palant jobject self,
639*65c59e02SInna Palant jstring field_name,
640*65c59e02SInna Palant jstring oldval,
641*65c59e02SInna Palant jstring newval) {
642*65c59e02SInna Palant auto me = adopt_local(self);
643*65c59e02SInna Palant auto cls = me->getClass();
644*65c59e02SInna Palant auto fld = cls->getStaticField<jstring>(ToString(env, field_name).c_str());
645*65c59e02SInna Palant
646*65c59e02SInna Palant auto curvalRef = cls->getStaticFieldValue(fld);
647*65c59e02SInna Palant if (curvalRef->toStdString() != adopt_local(oldval)->toStdString()) {
648*65c59e02SInna Palant return JNI_FALSE;
649*65c59e02SInna Palant }
650*65c59e02SInna Palant cls->setStaticFieldValue(fld, newval);
651*65c59e02SInna Palant return JNI_TRUE;
652*65c59e02SInna Palant }
653*65c59e02SInna Palant
TestStaticReferenceFieldAccess(alias_ref<jobject> self,std::string const & field_name,jobject oldval,jobject newval,jboolean useWrapper)654*65c59e02SInna Palant jboolean TestStaticReferenceFieldAccess(
655*65c59e02SInna Palant alias_ref<jobject> self,
656*65c59e02SInna Palant std::string const& field_name,
657*65c59e02SInna Palant jobject oldval,
658*65c59e02SInna Palant jobject newval,
659*65c59e02SInna Palant jboolean useWrapper) {
660*65c59e02SInna Palant auto cls = self->getClass();
661*65c59e02SInna Palant auto rawfld = cls->getStaticField<jobject>(
662*65c59e02SInna Palant field_name.c_str(), TestThing::kJavaDescriptor);
663*65c59e02SInna Palant
664*65c59e02SInna Palant auto curvalRef = cls->getStaticFieldValue(rawfld);
665*65c59e02SInna Palant if (curvalRef != oldval) {
666*65c59e02SInna Palant return JNI_FALSE;
667*65c59e02SInna Palant }
668*65c59e02SInna Palant
669*65c59e02SInna Palant if (useWrapper) {
670*65c59e02SInna Palant auto newvalRef = adopt_local(static_cast<TestThing::javaobject>(newval));
671*65c59e02SInna Palant auto fld = cls->getStaticField<TestThing::javaobject>(field_name.c_str());
672*65c59e02SInna Palant cls->setStaticFieldValue<TestThing::javaobject>(fld, newvalRef);
673*65c59e02SInna Palant } else {
674*65c59e02SInna Palant cls->setStaticFieldValue(rawfld, newval);
675*65c59e02SInna Palant }
676*65c59e02SInna Palant
677*65c59e02SInna Palant return JNI_TRUE;
678*65c59e02SInna Palant }
679*65c59e02SInna Palant
TestNonVirtualMethod(JNIEnv * env,jobject self,jboolean s)680*65c59e02SInna Palant jboolean TestNonVirtualMethod(JNIEnv* env, jobject self, jboolean s) {
681*65c59e02SInna Palant auto me = adopt_local(self);
682*65c59e02SInna Palant if (!me) {
683*65c59e02SInna Palant return JNI_FALSE;
684*65c59e02SInna Palant }
685*65c59e02SInna Palant
686*65c59e02SInna Palant auto cls = me->getClass();
687*65c59e02SInna Palant if (!cls) {
688*65c59e02SInna Palant return JNI_FALSE;
689*65c59e02SInna Palant }
690*65c59e02SInna Palant auto method =
691*65c59e02SInna Palant cls->getNonvirtualMethod<jboolean(jboolean)>("nonVirtualMethod");
692*65c59e02SInna Palant
693*65c59e02SInna Palant jclass jcls = env->FindClass("com/facebook/jni/FBJniTests");
694*65c59e02SInna Palant
695*65c59e02SInna Palant return method(self, jcls, s);
696*65c59e02SInna Palant }
697*65c59e02SInna Palant
TestArrayCreation(JNIEnv * env,jobject self,jstring s0,jstring s1,jstring s2)698*65c59e02SInna Palant jtypeArray<jstring> TestArrayCreation(
699*65c59e02SInna Palant JNIEnv* env,
700*65c59e02SInna Palant jobject self,
701*65c59e02SInna Palant jstring s0,
702*65c59e02SInna Palant jstring s1,
703*65c59e02SInna Palant jstring s2) {
704*65c59e02SInna Palant auto array = JArrayClass<jstring>::newArray(3);
705*65c59e02SInna Palant array->setElement(0, s0);
706*65c59e02SInna Palant array->setElement(1, s1);
707*65c59e02SInna Palant array->setElement(2, s2);
708*65c59e02SInna Palant return static_cast<jtypeArray<jstring>>(array.release());
709*65c59e02SInna Palant }
710*65c59e02SInna Palant
TestMultidimensionalObjectArray(JNIEnv * env,jobject self,jstring s0,jstring s1,jstring s2)711*65c59e02SInna Palant jtypeArray<jtypeArray<jstring>> TestMultidimensionalObjectArray(
712*65c59e02SInna Palant JNIEnv* env,
713*65c59e02SInna Palant jobject self,
714*65c59e02SInna Palant jstring s0,
715*65c59e02SInna Palant jstring s1,
716*65c59e02SInna Palant jstring s2) {
717*65c59e02SInna Palant auto array = JArrayClass<jtypeArray<jstring>>::newArray(2);
718*65c59e02SInna Palant auto row = JArrayClass<jstring>::newArray(2);
719*65c59e02SInna Palant row->setElement(0, s0);
720*65c59e02SInna Palant row->setElement(1, s1);
721*65c59e02SInna Palant (*array)[0] = row;
722*65c59e02SInna Palant row = JArrayClass<jstring>::newArray(1);
723*65c59e02SInna Palant row->setElement(0, s2);
724*65c59e02SInna Palant (*array)[1] = row;
725*65c59e02SInna Palant return array.release();
726*65c59e02SInna Palant }
727*65c59e02SInna Palant
TestMultidimensionalPrimitiveArray(JNIEnv * env,jobject self,jint i0,jint i1,jint i2)728*65c59e02SInna Palant jtypeArray<jintArray> TestMultidimensionalPrimitiveArray(
729*65c59e02SInna Palant JNIEnv* env,
730*65c59e02SInna Palant jobject self,
731*65c59e02SInna Palant jint i0,
732*65c59e02SInna Palant jint i1,
733*65c59e02SInna Palant jint i2) {
734*65c59e02SInna Palant auto array = JArrayClass<jintArray>::newArray(2);
735*65c59e02SInna Palant auto row = JArrayInt::newArray(2);
736*65c59e02SInna Palant row->setRegion(0, 1, &i0);
737*65c59e02SInna Palant row->setRegion(1, 1, &i1);
738*65c59e02SInna Palant (*array)[0] = row;
739*65c59e02SInna Palant row = JArrayInt::newArray(1);
740*65c59e02SInna Palant row->setRegion(0, 1, &i2);
741*65c59e02SInna Palant (*array)[1] = row;
742*65c59e02SInna Palant return array.release();
743*65c59e02SInna Palant }
744*65c59e02SInna Palant
745*65c59e02SInna Palant jstring
TestBuildStringArray(JNIEnv * env,jobject self,jtypeArray<jstring> input)746*65c59e02SInna Palant TestBuildStringArray(JNIEnv* env, jobject self, jtypeArray<jstring> input) {
747*65c59e02SInna Palant auto me = adopt_local(self);
748*65c59e02SInna Palant auto cls = me->getClass();
749*65c59e02SInna Palant auto method =
750*65c59e02SInna Palant cls->getMethod<jstring(jtypeArray<jstring>)>("captureStringArray");
751*65c59e02SInna Palant
752*65c59e02SInna Palant auto niceInput = adopt_local_array<jstring>(input);
753*65c59e02SInna Palant auto length = niceInput->size();
754*65c59e02SInna Palant auto inputCopy = JArrayClass<jstring>::newArray(length);
755*65c59e02SInna Palant for (size_t idx = 0; idx < length; idx++) {
756*65c59e02SInna Palant switch (idx % 3) {
757*65c59e02SInna Palant case 0: {
758*65c59e02SInna Palant // Verify that assignment from a T works.
759*65c59e02SInna Palant jstring value = (jstring)env->GetObjectArrayElement(input, idx);
760*65c59e02SInna Palant (*inputCopy)[idx] = value; // Assignment from actual type.
761*65c59e02SInna Palant env->DeleteLocalRef(value);
762*65c59e02SInna Palant break;
763*65c59e02SInna Palant }
764*65c59e02SInna Palant case 1: {
765*65c59e02SInna Palant // Verify that direct assignment from an ElementProxy works.
766*65c59e02SInna Palant (*inputCopy)[idx] = (*niceInput)[idx];
767*65c59e02SInna Palant break;
768*65c59e02SInna Palant }
769*65c59e02SInna Palant case 2:
770*65c59e02SInna Palant default: {
771*65c59e02SInna Palant // Verify that assignment from a smart reference works.
772*65c59e02SInna Palant auto smartRef = adopt_local((*niceInput)[idx]);
773*65c59e02SInna Palant (*inputCopy)[idx] = smartRef;
774*65c59e02SInna Palant break;
775*65c59e02SInna Palant }
776*65c59e02SInna Palant }
777*65c59e02SInna Palant }
778*65c59e02SInna Palant
779*65c59e02SInna Palant return method(self, inputCopy.get()).release();
780*65c59e02SInna Palant }
781*65c59e02SInna Palant
782*65c59e02SInna Palant template <typename F, typename... Args>
tryResolveMethodWithCxxTypes(std::string sig,alias_ref<jobject> me,std::string methodName,Args...args)783*65c59e02SInna Palant void tryResolveMethodWithCxxTypes(
784*65c59e02SInna Palant std::string sig,
785*65c59e02SInna Palant alias_ref<jobject> me,
786*65c59e02SInna Palant std::string methodName,
787*65c59e02SInna Palant Args... args) {
788*65c59e02SInna Palant auto cls = me->getClass();
789*65c59e02SInna Palant auto method = cls->getMethod<F>(methodName.c_str());
790*65c59e02SInna Palant if (!method)
791*65c59e02SInna Palant throw std::runtime_error("method lookup failed with signature=" + sig);
792*65c59e02SInna Palant try {
793*65c59e02SInna Palant method(me, args...);
794*65c59e02SInna Palant } catch (std::exception&) {
795*65c59e02SInna Palant throw std::runtime_error("calling method failed with signature=" + sig);
796*65c59e02SInna Palant }
797*65c59e02SInna Palant
798*65c59e02SInna Palant auto nonVirtualMethod = cls->getNonvirtualMethod<F>(methodName.c_str());
799*65c59e02SInna Palant if (!nonVirtualMethod)
800*65c59e02SInna Palant throw std::runtime_error("method lookup failed with signature=" + sig);
801*65c59e02SInna Palant try {
802*65c59e02SInna Palant nonVirtualMethod(me, cls.get(), args...);
803*65c59e02SInna Palant } catch (std::exception&) {
804*65c59e02SInna Palant throw std::runtime_error("calling method failed with signature=" + sig);
805*65c59e02SInna Palant }
806*65c59e02SInna Palant
807*65c59e02SInna Palant auto staticMethod = cls->getStaticMethod<F>((methodName + "Static").c_str());
808*65c59e02SInna Palant if (!staticMethod)
809*65c59e02SInna Palant throw std::runtime_error(
810*65c59e02SInna Palant "static method lookup failed with signature=" + sig);
811*65c59e02SInna Palant try {
812*65c59e02SInna Palant staticMethod(cls, args...);
813*65c59e02SInna Palant } catch (std::exception&) {
814*65c59e02SInna Palant throw std::runtime_error(
815*65c59e02SInna Palant "calling static method failed with signature=" + sig);
816*65c59e02SInna Palant }
817*65c59e02SInna Palant }
818*65c59e02SInna Palant
819*65c59e02SInna Palant // Simple utility to give us a good error message.
820*65c59e02SInna Palant #define runTest(sig, ...) \
821*65c59e02SInna Palant tryResolveMethodWithCxxTypes<sig>(#sig, self, method, __VA_ARGS__);
822*65c59e02SInna Palant
TestMethodResolutionWithCxxTypes(alias_ref<jobject> self,alias_ref<jstring> jmethod,alias_ref<jstring> str,jlong v)823*65c59e02SInna Palant void TestMethodResolutionWithCxxTypes(
824*65c59e02SInna Palant alias_ref<jobject> self,
825*65c59e02SInna Palant alias_ref<jstring> jmethod,
826*65c59e02SInna Palant alias_ref<jstring> str,
827*65c59e02SInna Palant jlong v) {
828*65c59e02SInna Palant auto method = jmethod->toStdString();
829*65c59e02SInna Palant runTest(jobject(jstring, jlong), str.get(), v);
830*65c59e02SInna Palant runTest(local_ref<jobject>(jstring, jlong), str.get(), v);
831*65c59e02SInna Palant
832*65c59e02SInna Palant runTest(jobject(local_ref<jstring>, jlong), make_local(str), v);
833*65c59e02SInna Palant runTest(jobject(alias_ref<jstring>, jlong), str, v);
834*65c59e02SInna Palant
835*65c59e02SInna Palant runTest(jobject(alias_ref<jstring>, int64_t), str, (int64_t)v);
836*65c59e02SInna Palant runTest(jobject(alias_ref<jstring>, long long), str, (long long)v);
837*65c59e02SInna Palant
838*65c59e02SInna Palant runTest(
839*65c59e02SInna Palant jobject(const char*, int64_t), str->toStdString().c_str(), (int64_t)v);
840*65c59e02SInna Palant
841*65c59e02SInna Palant method = jmethod->toStdString() + "Void";
842*65c59e02SInna Palant runTest(void(jstring, int64_t), str.get(), v);
843*65c59e02SInna Palant
844*65c59e02SInna Palant method = jmethod->toStdString() + "Int";
845*65c59e02SInna Palant runTest(jint(jstring, int64_t), str.get(), v);
846*65c59e02SInna Palant }
847*65c59e02SInna Palant
848*65c59e02SInna Palant #undef runTest
849*65c59e02SInna Palant
TestHandleJavaCustomException(JNIEnv * env,jobject self)850*65c59e02SInna Palant void TestHandleJavaCustomException(JNIEnv* env, jobject self) {
851*65c59e02SInna Palant auto me = adopt_local(self);
852*65c59e02SInna Palant auto cls = me->getClass();
853*65c59e02SInna Palant auto method = cls->getMethod<void()>("customExceptionThrower");
854*65c59e02SInna Palant
855*65c59e02SInna Palant method(self);
856*65c59e02SInna Palant }
857*65c59e02SInna Palant
TestHandleNullExceptionMessage(JNIEnv * env,jobject self)858*65c59e02SInna Palant void TestHandleNullExceptionMessage(JNIEnv* env, jobject self) {
859*65c59e02SInna Palant auto me = adopt_local(self);
860*65c59e02SInna Palant auto cls = me->getClass();
861*65c59e02SInna Palant auto method = cls->getMethod<void()>("nullMessageThrower");
862*65c59e02SInna Palant
863*65c59e02SInna Palant try {
864*65c59e02SInna Palant method(self);
865*65c59e02SInna Palant } catch (const std::exception& ex) {
866*65c59e02SInna Palant ex.what();
867*65c59e02SInna Palant }
868*65c59e02SInna Palant }
869*65c59e02SInna Palant
TestHandleNestedException(JNIEnv * env,jobject self)870*65c59e02SInna Palant void TestHandleNestedException(JNIEnv* env, jobject self) {
871*65c59e02SInna Palant auto me = adopt_local(self);
872*65c59e02SInna Palant auto cls = me->getClass();
873*65c59e02SInna Palant auto method = cls->getMethod<void()>("customExceptionThrower");
874*65c59e02SInna Palant
875*65c59e02SInna Palant try {
876*65c59e02SInna Palant try {
877*65c59e02SInna Palant method(self);
878*65c59e02SInna Palant } catch (...) {
879*65c59e02SInna Palant std::throw_with_nested(std::runtime_error("middle"));
880*65c59e02SInna Palant }
881*65c59e02SInna Palant } catch (...) {
882*65c59e02SInna Palant std::throw_with_nested(std::out_of_range("outer"));
883*65c59e02SInna Palant }
884*65c59e02SInna Palant }
885*65c59e02SInna Palant
TestHandleNoRttiException(JNIEnv * env,jobject self)886*65c59e02SInna Palant void TestHandleNoRttiException(JNIEnv* env, jobject self) {
887*65c59e02SInna Palant nortti::throwException();
888*65c59e02SInna Palant }
889*65c59e02SInna Palant
TestCopyConstructor(JNIEnv * env,jobject self)890*65c59e02SInna Palant jstring TestCopyConstructor(JNIEnv* env, jobject self) {
891*65c59e02SInna Palant auto me = adopt_local(self);
892*65c59e02SInna Palant auto cls = me->getClass();
893*65c59e02SInna Palant auto method = cls->getMethod<void()>("customExceptionThrower");
894*65c59e02SInna Palant
895*65c59e02SInna Palant try {
896*65c59e02SInna Palant method(self);
897*65c59e02SInna Palant return env->NewStringUTF("method did not throw");
898*65c59e02SInna Palant } catch (JniException ex) { // No & -- we're intentionally invoking the copy
899*65c59e02SInna Palant // constructor.
900*65c59e02SInna Palant return env->NewStringUTF(ex.what());
901*65c59e02SInna Palant }
902*65c59e02SInna Palant }
903*65c59e02SInna Palant
TestMoveConstructorWithEmptyWhat(JNIEnv * env,jobject self)904*65c59e02SInna Palant jstring TestMoveConstructorWithEmptyWhat(JNIEnv* env, jobject self) {
905*65c59e02SInna Palant auto me = adopt_local(self);
906*65c59e02SInna Palant auto cls = me->getClass();
907*65c59e02SInna Palant auto method = cls->getMethod<void()>("customExceptionThrower");
908*65c59e02SInna Palant
909*65c59e02SInna Palant try {
910*65c59e02SInna Palant method(self);
911*65c59e02SInna Palant return env->NewStringUTF("method did not throw");
912*65c59e02SInna Palant } catch (JniException& ex) {
913*65c59e02SInna Palant auto replacement = JniException(std::move(ex));
914*65c59e02SInna Palant return env->NewStringUTF(replacement.what());
915*65c59e02SInna Palant }
916*65c59e02SInna Palant }
917*65c59e02SInna Palant
TestMoveConstructorWithPopulatedWhat(JNIEnv * env,jobject self)918*65c59e02SInna Palant jstring TestMoveConstructorWithPopulatedWhat(JNIEnv* env, jobject self) {
919*65c59e02SInna Palant auto me = adopt_local(self);
920*65c59e02SInna Palant auto cls = me->getClass();
921*65c59e02SInna Palant auto method = cls->getMethod<void()>("customExceptionThrower");
922*65c59e02SInna Palant
923*65c59e02SInna Palant try {
924*65c59e02SInna Palant method(self);
925*65c59e02SInna Palant return env->NewStringUTF("method did not throw");
926*65c59e02SInna Palant } catch (JniException& ex) {
927*65c59e02SInna Palant ex.what();
928*65c59e02SInna Palant auto replacement = JniException(std::move(ex));
929*65c59e02SInna Palant return env->NewStringUTF(replacement.what());
930*65c59e02SInna Palant }
931*65c59e02SInna Palant }
932*65c59e02SInna Palant
TestHandleCppRuntimeError(JNIEnv * env,jobject self,jstring message)933*65c59e02SInna Palant void TestHandleCppRuntimeError(JNIEnv* env, jobject self, jstring message) {
934*65c59e02SInna Palant throw std::runtime_error(ToString(env, message));
935*65c59e02SInna Palant }
936*65c59e02SInna Palant
TestHandleCppIOBaseFailure(JNIEnv * env,jobject self)937*65c59e02SInna Palant void TestHandleCppIOBaseFailure(JNIEnv* env, jobject self) {
938*65c59e02SInna Palant throw std::ios_base::failure("A C++ IO base failure.");
939*65c59e02SInna Palant }
940*65c59e02SInna Palant
TestHandleCppSystemError(JNIEnv * env,jobject self)941*65c59e02SInna Palant void TestHandleCppSystemError(JNIEnv* env, jobject self) {
942*65c59e02SInna Palant // Throw a sample std::system_error
943*65c59e02SInna Palant throw std::system_error(EFAULT, std::system_category());
944*65c59e02SInna Palant }
945*65c59e02SInna Palant
TestInterDsoExceptionHandlingA(JNIEnv * env,jobject self)946*65c59e02SInna Palant void TestInterDsoExceptionHandlingA(JNIEnv* env, jobject self) {
947*65c59e02SInna Palant inter_dso_exception_test_2a();
948*65c59e02SInna Palant }
949*65c59e02SInna Palant
TestInterDsoExceptionHandlingB(JNIEnv * env,jobject self)950*65c59e02SInna Palant jboolean TestInterDsoExceptionHandlingB(JNIEnv* env, jobject self) {
951*65c59e02SInna Palant return inter_dso_exception_test_2b();
952*65c59e02SInna Palant }
953*65c59e02SInna Palant
954*65c59e02SInna Palant struct NonStdException /* has no base class */ {};
955*65c59e02SInna Palant
TestHandleNonStdException(JNIEnv * env,jobject self)956*65c59e02SInna Palant void TestHandleNonStdException(JNIEnv* env, jobject self) {
957*65c59e02SInna Palant throw NonStdException();
958*65c59e02SInna Palant }
959*65c59e02SInna Palant
TestHandleCppIntThrow(JNIEnv * env,jobject self)960*65c59e02SInna Palant void TestHandleCppIntThrow(JNIEnv* env, jobject self) {
961*65c59e02SInna Palant throw 42;
962*65c59e02SInna Palant }
963*65c59e02SInna Palant
TestHandleCppCharPointerThrow(JNIEnv * env,jobject self)964*65c59e02SInna Palant void TestHandleCppCharPointerThrow(JNIEnv* env, jobject self) {
965*65c59e02SInna Palant throw "Some random message";
966*65c59e02SInna Palant }
967*65c59e02SInna Palant
TestThrowJavaExceptionByName(JNIEnv * env,jobject self)968*65c59e02SInna Palant void TestThrowJavaExceptionByName(JNIEnv* env, jobject self) {
969*65c59e02SInna Palant throwNewJavaException(
970*65c59e02SInna Palant "java/lang/IllegalArgumentException", "bad news: %s", "it didn't work");
971*65c59e02SInna Palant }
972*65c59e02SInna Palant
TestJThread(JNIEnv * env,jobject self)973*65c59e02SInna Palant jint TestJThread(JNIEnv* env, jobject self) {
974*65c59e02SInna Palant jint i = -1;
975*65c59e02SInna Palant auto thread = JThread::create([&] {
976*65c59e02SInna Palant i = 0;
977*65c59e02SInna Palant std::this_thread::sleep_for(std::chrono::milliseconds(20));
978*65c59e02SInna Palant i = 1;
979*65c59e02SInna Palant });
980*65c59e02SInna Palant thread->start();
981*65c59e02SInna Palant thread->join();
982*65c59e02SInna Palant return i;
983*65c59e02SInna Palant }
984*65c59e02SInna Palant
985*65c59e02SInna Palant // Global for simpleWorker tests. Relies on thread sync points (constructor,
986*65c59e02SInna Palant // join) for "locking".
987*65c59e02SInna Palant jint gWorkerValue;
988*65c59e02SInna Palant
simpleWorker(jobject grefSelf,jdouble input)989*65c59e02SInna Palant void simpleWorker(jobject grefSelf, jdouble input) {
990*65c59e02SInna Palant auto attachGuard = ThreadScope(); // This tests the move constructor.
991*65c59e02SInna Palant auto self = adopt_global(grefSelf);
992*65c59e02SInna Palant // Claw up from the object to avoid classloader issues.
993*65c59e02SInna Palant auto barMethod = self->getClass()->getMethod<jint(jdouble)>("bar");
994*65c59e02SInna Palant gWorkerValue = barMethod(self.get(), input);
995*65c59e02SInna Palant }
996*65c59e02SInna Palant
nestedSimpleWorker(jobject grefSelf,jdouble input)997*65c59e02SInna Palant void nestedSimpleWorker(jobject grefSelf, jdouble input) {
998*65c59e02SInna Palant ThreadScope attachGuard; // More efficient version of guard; no move
999*65c59e02SInna Palant // constructor required.
1000*65c59e02SInna Palant simpleWorker(grefSelf, input);
1001*65c59e02SInna Palant }
1002*65c59e02SInna Palant
TestThreadScopeGuard(JNIEnv * env,jobject self,jdouble input)1003*65c59e02SInna Palant jint TestThreadScopeGuard(JNIEnv* env, jobject self, jdouble input) {
1004*65c59e02SInna Palant // Turn self into a global reference before passing it to a working thread.
1005*65c59e02SInna Palant auto grefSelf = make_global(adopt_local(self));
1006*65c59e02SInna Palant auto childThread = std::thread(simpleWorker, grefSelf.release(), input);
1007*65c59e02SInna Palant childThread.join();
1008*65c59e02SInna Palant return gWorkerValue;
1009*65c59e02SInna Palant }
1010*65c59e02SInna Palant
TestNestedThreadScopeGuard(JNIEnv * env,jobject self,jdouble input)1011*65c59e02SInna Palant jint TestNestedThreadScopeGuard(JNIEnv* env, jobject self, jdouble input) {
1012*65c59e02SInna Palant // Turn self into a global reference before passing it to a working thread.
1013*65c59e02SInna Palant auto grefSelf = make_global(adopt_local(self));
1014*65c59e02SInna Palant auto childThread = std::thread(nestedSimpleWorker, grefSelf.release(), input);
1015*65c59e02SInna Palant childThread.join();
1016*65c59e02SInna Palant return gWorkerValue;
1017*65c59e02SInna Palant }
1018*65c59e02SInna Palant
classLoadWorker()1019*65c59e02SInna Palant void classLoadWorker() {
1020*65c59e02SInna Palant gWorkerValue = 0;
1021*65c59e02SInna Palant try {
1022*65c59e02SInna Palant // This should fail because we aren't attached.
1023*65c59e02SInna Palant Callbacks::javaClassLocal();
1024*65c59e02SInna Palant gWorkerValue = -1;
1025*65c59e02SInna Palant return;
1026*65c59e02SInna Palant } catch (std::exception& e) {
1027*65c59e02SInna Palant // ignored
1028*65c59e02SInna Palant }
1029*65c59e02SInna Palant try {
1030*65c59e02SInna Palant ThreadScope::WithClassLoader([&] {
1031*65c59e02SInna Palant // This should now succeed.
1032*65c59e02SInna Palant Callbacks::javaClassLocal();
1033*65c59e02SInna Palant gWorkerValue = 1;
1034*65c59e02SInna Palant });
1035*65c59e02SInna Palant } catch (std::exception& e) {
1036*65c59e02SInna Palant gWorkerValue = -2;
1037*65c59e02SInna Palant // Catch this and log it so that we get a test failure instead of a crash.
1038*65c59e02SInna Palant FBJNI_LOGE("%s", e.what());
1039*65c59e02SInna Palant }
1040*65c59e02SInna Palant }
1041*65c59e02SInna Palant
TestClassLoadInWorker(JNIEnv * env,jobject self)1042*65c59e02SInna Palant jint TestClassLoadInWorker(JNIEnv* env, jobject self) {
1043*65c59e02SInna Palant std::thread t(classLoadWorker);
1044*65c59e02SInna Palant t.join();
1045*65c59e02SInna Palant return gWorkerValue;
1046*65c59e02SInna Palant }
1047*65c59e02SInna Palant
TestClassLoadWorkerFastPath(JNIEnv * env,jobject self)1048*65c59e02SInna Palant jint TestClassLoadWorkerFastPath(JNIEnv* env, jobject self) {
1049*65c59e02SInna Palant jint i = 0;
1050*65c59e02SInna Palant ThreadScope::WithClassLoader([&] {
1051*65c59e02SInna Palant // Execute on the fast path
1052*65c59e02SInna Palant Callbacks::javaClassLocal();
1053*65c59e02SInna Palant i += 1;
1054*65c59e02SInna Palant });
1055*65c59e02SInna Palant
1056*65c59e02SInna Palant std::thread t([&] {
1057*65c59e02SInna Palant ThreadScope::WithClassLoader([&] {
1058*65c59e02SInna Palant // Execute on the slow path
1059*65c59e02SInna Palant Callbacks::javaClassLocal();
1060*65c59e02SInna Palant i += 1;
1061*65c59e02SInna Palant });
1062*65c59e02SInna Palant });
1063*65c59e02SInna Palant t.join();
1064*65c59e02SInna Palant
1065*65c59e02SInna Palant std::thread t2([&] {
1066*65c59e02SInna Palant ThreadScope scope;
1067*65c59e02SInna Palant ThreadScope::WithClassLoader([&] {
1068*65c59e02SInna Palant // Execute on the slow path even though thread is already attached.
1069*65c59e02SInna Palant Callbacks::javaClassLocal();
1070*65c59e02SInna Palant i += 1;
1071*65c59e02SInna Palant });
1072*65c59e02SInna Palant });
1073*65c59e02SInna Palant t2.join();
1074*65c59e02SInna Palant
1075*65c59e02SInna Palant return i;
1076*65c59e02SInna Palant }
1077*65c59e02SInna Palant
testNewObject(JNIEnv *,jobject self)1078*65c59e02SInna Palant void testNewObject(JNIEnv*, jobject self) {
1079*65c59e02SInna Palant // This is a compilation only test, verifies that all the types work out.
1080*65c59e02SInna Palant auto cls = findClassLocal("java/lang/String");
1081*65c59e02SInna Palant auto ctr = cls->getConstructor<jstring()>();
1082*65c59e02SInna Palant local_ref<jstring> obj = cls->newObject(ctr);
1083*65c59e02SInna Palant auto str = obj->toStdString();
1084*65c59e02SInna Palant Use(str);
1085*65c59e02SInna Palant }
1086*65c59e02SInna Palant
1087*65c59e02SInna Palant template <typename T>
copyAndVerify(T & orig)1088*65c59e02SInna Palant static jboolean copyAndVerify(T& orig) {
1089*65c59e02SInna Palant T copy{orig};
1090*65c59e02SInna Palant EXPECT(orig == copy);
1091*65c59e02SInna Palant
1092*65c59e02SInna Palant return JNI_TRUE;
1093*65c59e02SInna Palant }
1094*65c59e02SInna Palant
1095*65c59e02SInna Palant template <typename T>
assignAndVerify(T & orig)1096*65c59e02SInna Palant static jboolean assignAndVerify(T& orig) {
1097*65c59e02SInna Palant T copy{};
1098*65c59e02SInna Palant copy = orig;
1099*65c59e02SInna Palant EXPECT(orig == copy);
1100*65c59e02SInna Palant
1101*65c59e02SInna Palant return JNI_TRUE;
1102*65c59e02SInna Palant }
1103*65c59e02SInna Palant
testNullReferences(JNIEnv *,jobject)1104*65c59e02SInna Palant jboolean testNullReferences(JNIEnv*, jobject) {
1105*65c59e02SInna Palant jobject nullobject = nullptr;
1106*65c59e02SInna Palant
1107*65c59e02SInna Palant auto local = local_ref<jobject>{};
1108*65c59e02SInna Palant EXPECT(!local);
1109*65c59e02SInna Palant
1110*65c59e02SInna Palant auto localWrap = adopt_local(nullobject);
1111*65c59e02SInna Palant EXPECT(!localWrap);
1112*65c59e02SInna Palant
1113*65c59e02SInna Palant auto localMake = make_local(local);
1114*65c59e02SInna Palant EXPECT(!localMake);
1115*65c59e02SInna Palant EXPECT_SAME(local, localWrap, localMake);
1116*65c59e02SInna Palant
1117*65c59e02SInna Palant auto global = global_ref<jobject>{};
1118*65c59e02SInna Palant EXPECT(!global);
1119*65c59e02SInna Palant
1120*65c59e02SInna Palant auto globalWrap = adopt_global(nullobject);
1121*65c59e02SInna Palant EXPECT(!globalWrap);
1122*65c59e02SInna Palant
1123*65c59e02SInna Palant auto globalMake = make_global(global);
1124*65c59e02SInna Palant EXPECT(!globalMake);
1125*65c59e02SInna Palant EXPECT_SAME(global, globalWrap, globalMake);
1126*65c59e02SInna Palant
1127*65c59e02SInna Palant weak_ref<jobject> weak_global = weak_ref<jobject>{};
1128*65c59e02SInna Palant EXPECT(!weak_global.lockLocal());
1129*65c59e02SInna Palant
1130*65c59e02SInna Palant weak_ref<jobject> weak_globalWrap = adopt_weak_global(nullobject);
1131*65c59e02SInna Palant EXPECT(!weak_globalWrap.lockLocal());
1132*65c59e02SInna Palant EXPECT(weak_global.lockLocal() == weak_globalWrap.lockGlobal());
1133*65c59e02SInna Palant EXPECT(!make_local(adopt_local(nullobject)));
1134*65c59e02SInna Palant EXPECT(!make_global(nullobject));
1135*65c59e02SInna Palant
1136*65c59e02SInna Palant return JNI_TRUE;
1137*65c59e02SInna Palant }
1138*65c59e02SInna Palant
testCreatingReferences(JNIEnv *,jobject self)1139*65c59e02SInna Palant jboolean testCreatingReferences(JNIEnv*, jobject self) {
1140*65c59e02SInna Palant auto a = wrap_alias(self);
1141*65c59e02SInna Palant auto l = adopt_local(self);
1142*65c59e02SInna Palant auto g = make_global(l);
1143*65c59e02SInna Palant auto w = make_weak(l);
1144*65c59e02SInna Palant
1145*65c59e02SInna Palant EXPECT(a == l && a == g && a == w.lockLocal());
1146*65c59e02SInna Palant
1147*65c59e02SInna Palant auto lp = make_local(self);
1148*65c59e02SInna Palant auto la = make_local(a);
1149*65c59e02SInna Palant auto ll = make_local(l);
1150*65c59e02SInna Palant auto lg = make_local(g);
1151*65c59e02SInna Palant
1152*65c59e02SInna Palant EXPECT(a == lp && a == la && a == ll && a == lg);
1153*65c59e02SInna Palant
1154*65c59e02SInna Palant auto gp = make_global(self);
1155*65c59e02SInna Palant auto ga = make_global(a);
1156*65c59e02SInna Palant auto gl = make_global(l);
1157*65c59e02SInna Palant auto gg = make_global(g);
1158*65c59e02SInna Palant
1159*65c59e02SInna Palant EXPECT(a == gp && a == ga && a == gl && a == gg);
1160*65c59e02SInna Palant
1161*65c59e02SInna Palant return JNI_TRUE;
1162*65c59e02SInna Palant }
1163*65c59e02SInna Palant
testAssignmentAndCopyConstructors(JNIEnv *,jobject self)1164*65c59e02SInna Palant jboolean testAssignmentAndCopyConstructors(JNIEnv*, jobject self) {
1165*65c59e02SInna Palant using facebook::jni::internal::g_reference_stats;
1166*65c59e02SInna Palant
1167*65c59e02SInna Palant g_reference_stats.reset();
1168*65c59e02SInna Palant {
1169*65c59e02SInna Palant // Wrapping existing local that should be deleted (locals = 1)
1170*65c59e02SInna Palant auto local = adopt_local(self);
1171*65c59e02SInna Palant // Copy constructor (locals = 2)
1172*65c59e02SInna Palant EXPECT(copyAndVerify(local));
1173*65c59e02SInna Palant
1174*65c59e02SInna Palant // Assignment (locals = 3)
1175*65c59e02SInna Palant EXPECT(assignAndVerify(local));
1176*65c59e02SInna Palant
1177*65c59e02SInna Palant // Creating a new global (globals = 1)
1178*65c59e02SInna Palant auto global = make_global(local);
1179*65c59e02SInna Palant // Copy constructor (globals = 2)
1180*65c59e02SInna Palant EXPECT(copyAndVerify(global));
1181*65c59e02SInna Palant
1182*65c59e02SInna Palant // Assignment (globals = 3)
1183*65c59e02SInna Palant EXPECT(assignAndVerify(global));
1184*65c59e02SInna Palant
1185*65c59e02SInna Palant // Creating a new weak (weaks = 1)
1186*65c59e02SInna Palant auto weak = make_weak(local);
1187*65c59e02SInna Palant // Copy constructor (weaks = 2, globals = 5)
1188*65c59e02SInna Palant weak_ref<jobject> weakCopy{weak};
1189*65c59e02SInna Palant EXPECT(weak.lockGlobal() == weakCopy.lockGlobal());
1190*65c59e02SInna Palant
1191*65c59e02SInna Palant // Assignment (weaks = 3, globals = 7)
1192*65c59e02SInna Palant weakCopy = weak;
1193*65c59e02SInna Palant EXPECT(weak.lockGlobal() == weakCopy.lockGlobal());
1194*65c59e02SInna Palant
1195*65c59e02SInna Palant auto alias = alias_ref<jobject>{local};
1196*65c59e02SInna Palant alias_ref<jobject> aliasCopy{alias};
1197*65c59e02SInna Palant EXPECT(alias == aliasCopy);
1198*65c59e02SInna Palant
1199*65c59e02SInna Palant aliasCopy = alias;
1200*65c59e02SInna Palant EXPECT(alias == aliasCopy);
1201*65c59e02SInna Palant
1202*65c59e02SInna Palant alias = self;
1203*65c59e02SInna Palant alias = global;
1204*65c59e02SInna Palant // alias = weak; // Should not compile
1205*65c59e02SInna Palant }
1206*65c59e02SInna Palant
1207*65c59e02SInna Palant FBJNI_LOGE("locals: %d", g_reference_stats.locals_deleted.load());
1208*65c59e02SInna Palant FBJNI_LOGE("globals: %d", g_reference_stats.globals_deleted.load());
1209*65c59e02SInna Palant FBJNI_LOGE("weaks: %d", g_reference_stats.weaks_deleted.load());
1210*65c59e02SInna Palant
1211*65c59e02SInna Palant EXPECT(
1212*65c59e02SInna Palant g_reference_stats.locals_deleted == 3 &&
1213*65c59e02SInna Palant g_reference_stats.globals_deleted == 7 &&
1214*65c59e02SInna Palant g_reference_stats.weaks_deleted == 3);
1215*65c59e02SInna Palant
1216*65c59e02SInna Palant return JNI_TRUE;
1217*65c59e02SInna Palant }
1218*65c59e02SInna Palant
1219*65c59e02SInna Palant template <template <typename> class RefType, typename T>
copyAndVerifyCross(RefType<T> & orig)1220*65c59e02SInna Palant static jboolean copyAndVerifyCross(RefType<T>& orig) {
1221*65c59e02SInna Palant RefType<ReprType<T>> reprCopy{orig};
1222*65c59e02SInna Palant RefType<JniType<T>> jniCopy{orig};
1223*65c59e02SInna Palant EXPECT(orig == reprCopy);
1224*65c59e02SInna Palant EXPECT(orig == jniCopy);
1225*65c59e02SInna Palant return JNI_TRUE;
1226*65c59e02SInna Palant }
1227*65c59e02SInna Palant
1228*65c59e02SInna Palant template <template <typename> class RefType, typename T>
assignAndVerifyCross(RefType<T> & orig)1229*65c59e02SInna Palant static jboolean assignAndVerifyCross(RefType<T>& orig) {
1230*65c59e02SInna Palant RefType<ReprType<T>> reprCopy{};
1231*65c59e02SInna Palant reprCopy = orig;
1232*65c59e02SInna Palant RefType<JniType<T>> jniCopy{};
1233*65c59e02SInna Palant jniCopy = orig;
1234*65c59e02SInna Palant EXPECT(orig == reprCopy);
1235*65c59e02SInna Palant EXPECT(orig == jniCopy);
1236*65c59e02SInna Palant return JNI_TRUE;
1237*65c59e02SInna Palant }
1238*65c59e02SInna Palant
1239*65c59e02SInna Palant template <template <typename> class RefType, typename T>
verifyMakeCross(RefType<T> & orig)1240*65c59e02SInna Palant static jboolean verifyMakeCross(RefType<T>& orig) {
1241*65c59e02SInna Palant RefType<ReprType<T>> copy{orig};
1242*65c59e02SInna Palant {
1243*65c59e02SInna Palant local_ref<T> local = make_local(copy);
1244*65c59e02SInna Palant global_ref<T> global = make_global(copy);
1245*65c59e02SInna Palant weak_ref<T> weak = make_weak(copy);
1246*65c59e02SInna Palant }
1247*65c59e02SInna Palant
1248*65c59e02SInna Palant {
1249*65c59e02SInna Palant local_ref<ReprType<T>> local = make_local(copy);
1250*65c59e02SInna Palant global_ref<ReprType<T>> global = make_global(copy);
1251*65c59e02SInna Palant weak_ref<ReprType<T>> weak = make_weak(copy);
1252*65c59e02SInna Palant }
1253*65c59e02SInna Palant
1254*65c59e02SInna Palant {
1255*65c59e02SInna Palant local_ref<T> local = make_local(orig);
1256*65c59e02SInna Palant global_ref<T> global = make_global(orig);
1257*65c59e02SInna Palant weak_ref<T> weak = make_weak(orig);
1258*65c59e02SInna Palant }
1259*65c59e02SInna Palant
1260*65c59e02SInna Palant {
1261*65c59e02SInna Palant local_ref<ReprType<T>> local = make_local(orig);
1262*65c59e02SInna Palant global_ref<ReprType<T>> global = make_global(orig);
1263*65c59e02SInna Palant weak_ref<ReprType<T>> weak = make_weak(orig);
1264*65c59e02SInna Palant }
1265*65c59e02SInna Palant
1266*65c59e02SInna Palant return JNI_TRUE;
1267*65c59e02SInna Palant }
1268*65c59e02SInna Palant
testAssignmentAndCopyCrossTypes(JNIEnv *,jobject self)1269*65c59e02SInna Palant jboolean testAssignmentAndCopyCrossTypes(JNIEnv*, jobject self) {
1270*65c59e02SInna Palant using facebook::jni::internal::g_reference_stats;
1271*65c59e02SInna Palant
1272*65c59e02SInna Palant size_t locals = 0, globals = 0, weaks = 0;
1273*65c59e02SInna Palant g_reference_stats.reset();
1274*65c59e02SInna Palant #define VERIFY_REFERENCE_STATS() \
1275*65c59e02SInna Palant do { \
1276*65c59e02SInna Palant bool referenceStatsMatch = g_reference_stats.locals_deleted == locals && \
1277*65c59e02SInna Palant g_reference_stats.globals_deleted == globals && \
1278*65c59e02SInna Palant g_reference_stats.weaks_deleted == weaks; \
1279*65c59e02SInna Palant if (!referenceStatsMatch) { \
1280*65c59e02SInna Palant FBJNI_LOGE( \
1281*65c59e02SInna Palant "locals: %d, expected: %zd", \
1282*65c59e02SInna Palant g_reference_stats.locals_deleted.load(), \
1283*65c59e02SInna Palant locals); \
1284*65c59e02SInna Palant FBJNI_LOGE( \
1285*65c59e02SInna Palant "globals: %d, expected: %zd", \
1286*65c59e02SInna Palant g_reference_stats.globals_deleted.load(), \
1287*65c59e02SInna Palant globals); \
1288*65c59e02SInna Palant FBJNI_LOGE( \
1289*65c59e02SInna Palant "weaks: %d, expected: %zd", \
1290*65c59e02SInna Palant g_reference_stats.weaks_deleted.load(), \
1291*65c59e02SInna Palant weaks); \
1292*65c59e02SInna Palant } \
1293*65c59e02SInna Palant EXPECT(referenceStatsMatch); \
1294*65c59e02SInna Palant } while (0)
1295*65c59e02SInna Palant
1296*65c59e02SInna Palant {
1297*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1298*65c59e02SInna Palant
1299*65c59e02SInna Palant auto local = adopt_local(self);
1300*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1301*65c59e02SInna Palant
1302*65c59e02SInna Palant EXPECT(copyAndVerifyCross<local_ref>(local));
1303*65c59e02SInna Palant locals += 2;
1304*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1305*65c59e02SInna Palant
1306*65c59e02SInna Palant EXPECT(assignAndVerifyCross<local_ref>(local));
1307*65c59e02SInna Palant locals += 2;
1308*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1309*65c59e02SInna Palant
1310*65c59e02SInna Palant EXPECT(verifyMakeCross<local_ref>(local));
1311*65c59e02SInna Palant locals += 1;
1312*65c59e02SInna Palant locals += 4;
1313*65c59e02SInna Palant globals += 4;
1314*65c59e02SInna Palant weaks += 4;
1315*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1316*65c59e02SInna Palant
1317*65c59e02SInna Palant auto global = make_global(local);
1318*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1319*65c59e02SInna Palant
1320*65c59e02SInna Palant EXPECT(copyAndVerifyCross<global_ref>(global));
1321*65c59e02SInna Palant globals += 2;
1322*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1323*65c59e02SInna Palant
1324*65c59e02SInna Palant EXPECT(assignAndVerifyCross<global_ref>(global));
1325*65c59e02SInna Palant globals += 2;
1326*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1327*65c59e02SInna Palant
1328*65c59e02SInna Palant auto weak = make_weak(local);
1329*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1330*65c59e02SInna Palant
1331*65c59e02SInna Palant weak_ref<JObject> weakCopy{weak};
1332*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1333*65c59e02SInna Palant
1334*65c59e02SInna Palant EXPECT(weak.lockGlobal() == weakCopy.lockGlobal());
1335*65c59e02SInna Palant globals += 2;
1336*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1337*65c59e02SInna Palant
1338*65c59e02SInna Palant weakCopy = weak;
1339*65c59e02SInna Palant weaks += 1;
1340*65c59e02SInna Palant EXPECT(weak.lockGlobal() == weakCopy.lockGlobal());
1341*65c59e02SInna Palant globals += 2;
1342*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1343*65c59e02SInna Palant
1344*65c59e02SInna Palant auto alias = alias_ref<jobject>{local};
1345*65c59e02SInna Palant alias_ref<JObject>{local};
1346*65c59e02SInna Palant
1347*65c59e02SInna Palant alias_ref<JObject> aliasCopy{alias};
1348*65c59e02SInna Palant EXPECT(alias == aliasCopy);
1349*65c59e02SInna Palant
1350*65c59e02SInna Palant aliasCopy = alias;
1351*65c59e02SInna Palant alias = aliasCopy;
1352*65c59e02SInna Palant EXPECT(alias == aliasCopy);
1353*65c59e02SInna Palant
1354*65c59e02SInna Palant alias = self;
1355*65c59e02SInna Palant alias = global;
1356*65c59e02SInna Palant // alias = weak; // Should not compile
1357*65c59e02SInna Palant
1358*65c59e02SInna Palant weaks += 1; // `weakCopy` going out of scope
1359*65c59e02SInna Palant weaks += 1; // `weak` going out of scope
1360*65c59e02SInna Palant globals += 1; // `global` going out of scope
1361*65c59e02SInna Palant locals += 1; // `local` going out of scope
1362*65c59e02SInna Palant }
1363*65c59e02SInna Palant
1364*65c59e02SInna Palant VERIFY_REFERENCE_STATS();
1365*65c59e02SInna Palant
1366*65c59e02SInna Palant return JNI_TRUE;
1367*65c59e02SInna Palant }
1368*65c59e02SInna Palant
testToString(JNIEnv * env,jobject self)1369*65c59e02SInna Palant jboolean testToString(JNIEnv* env, jobject self) {
1370*65c59e02SInna Palant auto dateClass = findClassLocal("java/util/Date");
1371*65c59e02SInna Palant auto dateConstructor = dateClass->getConstructor<jobject()>();
1372*65c59e02SInna Palant auto date = dateClass->newObject(dateConstructor);
1373*65c59e02SInna Palant
1374*65c59e02SInna Palant auto objectClass = findClassLocal("java/lang/Object");
1375*65c59e02SInna Palant auto objectConstructor = objectClass->getConstructor<jobject()>();
1376*65c59e02SInna Palant auto object = objectClass->newObject(objectConstructor);
1377*65c59e02SInna Palant
1378*65c59e02SInna Palant // First call the date implementation of toString
1379*65c59e02SInna Palant auto dateString = date->toString();
1380*65c59e02SInna Palant // And ensure that we don't use Date's toString method when calling
1381*65c59e02SInna Palant // toString on the object. If this doesn't crash we are fine.
1382*65c59e02SInna Palant auto objectString = object->toString();
1383*65c59e02SInna Palant
1384*65c59e02SInna Palant return JNI_TRUE;
1385*65c59e02SInna Palant }
1386*65c59e02SInna Palant
testCriticalNativeMethodBindsAndCanBeInvoked(jint a,jfloat b)1387*65c59e02SInna Palant jboolean testCriticalNativeMethodBindsAndCanBeInvoked(jint a, jfloat b) {
1388*65c59e02SInna Palant return JNI_TRUE;
1389*65c59e02SInna Palant }
1390*65c59e02SInna Palant
1391*65c59e02SInna Palant // These implicit nullptr tests aren't called, the test is that it
1392*65c59e02SInna Palant // compiles.
returnNullAliasRef()1393*65c59e02SInna Palant alias_ref<JObject> returnNullAliasRef() {
1394*65c59e02SInna Palant return nullptr;
1395*65c59e02SInna Palant }
1396*65c59e02SInna Palant
returnNullLocalRef()1397*65c59e02SInna Palant local_ref<JObject> returnNullLocalRef() {
1398*65c59e02SInna Palant return nullptr;
1399*65c59e02SInna Palant }
1400*65c59e02SInna Palant
returnNullGlobalRef()1401*65c59e02SInna Palant global_ref<JObject> returnNullGlobalRef() {
1402*65c59e02SInna Palant return nullptr;
1403*65c59e02SInna Palant }
1404*65c59e02SInna Palant
takesAliasRef(alias_ref<JObject>)1405*65c59e02SInna Palant void takesAliasRef(alias_ref<JObject>) {}
takesLocalRef(local_ref<JObject>)1406*65c59e02SInna Palant void takesLocalRef(local_ref<JObject>) {}
takesGlobalRef(global_ref<JObject>)1407*65c59e02SInna Palant void takesGlobalRef(global_ref<JObject>) {}
1408*65c59e02SInna Palant
callWithNullRefs()1409*65c59e02SInna Palant void callWithNullRefs() {
1410*65c59e02SInna Palant takesAliasRef(nullptr);
1411*65c59e02SInna Palant takesLocalRef(nullptr);
1412*65c59e02SInna Palant takesGlobalRef(nullptr);
1413*65c59e02SInna Palant }
1414*65c59e02SInna Palant
1415*65c59e02SInna Palant struct SomeJavaFoo;
1416*65c59e02SInna Palant struct OtherJavaFoo;
1417*65c59e02SInna Palant
1418*65c59e02SInna Palant struct SomeJavaFoo : JavaClass<SomeJavaFoo> {
1419*65c59e02SInna Palant // Ensure that smart references can be used in declarations using
1420*65c59e02SInna Palant // forward-declared types.
1421*65c59e02SInna Palant alias_ref<OtherJavaFoo> call(alias_ref<SomeJavaFoo>);
1422*65c59e02SInna Palant static alias_ref<OtherJavaFoo> funcWithForwardDeclaredRefs(
1423*65c59e02SInna Palant local_ref<OtherJavaFoo> foo);
1424*65c59e02SInna Palant };
1425*65c59e02SInna Palant
1426*65c59e02SInna Palant using sjf = SomeJavaFoo::javaobject;
1427*65c59e02SInna Palant
1428*65c59e02SInna Palant static_assert(IsNonWeakReference<local_ref<jobject>>(), "");
1429*65c59e02SInna Palant static_assert(IsNonWeakReference<local_ref<sjf>>(), "");
1430*65c59e02SInna Palant static_assert(IsNonWeakReference<global_ref<jobject>>(), "");
1431*65c59e02SInna Palant static_assert(IsNonWeakReference<jobject>(), "");
1432*65c59e02SInna Palant static_assert(IsNonWeakReference<sjf>(), "");
1433*65c59e02SInna Palant static_assert(IsNonWeakReference<jintArray>(), "");
1434*65c59e02SInna Palant static_assert(IsNonWeakReference<jbooleanArray>(), "");
1435*65c59e02SInna Palant
1436*65c59e02SInna Palant static_assert(!IsNonWeakReference<weak_ref<jobject>>(), "");
1437*65c59e02SInna Palant static_assert(!IsNonWeakReference<weak_ref<sjf>>(), "");
1438*65c59e02SInna Palant static_assert(!IsNonWeakReference<std::string>(), "");
1439*65c59e02SInna Palant static_assert(!IsNonWeakReference<jint*>(), "");
1440*65c59e02SInna Palant static_assert(!IsNonWeakReference<void>(), "");
1441*65c59e02SInna Palant static_assert(!IsNonWeakReference<int>(), "");
1442*65c59e02SInna Palant
1443*65c59e02SInna Palant static_assert(IsAnyReference<local_ref<jobject>>(), "");
1444*65c59e02SInna Palant static_assert(IsAnyReference<local_ref<sjf>>(), "");
1445*65c59e02SInna Palant static_assert(IsAnyReference<global_ref<jobject>>(), "");
1446*65c59e02SInna Palant static_assert(IsAnyReference<jobject>(), "");
1447*65c59e02SInna Palant static_assert(IsAnyReference<sjf>(), "");
1448*65c59e02SInna Palant static_assert(IsAnyReference<jintArray>(), "");
1449*65c59e02SInna Palant static_assert(IsAnyReference<jbooleanArray>(), "");
1450*65c59e02SInna Palant static_assert(IsAnyReference<weak_ref<jobject>>(), "");
1451*65c59e02SInna Palant static_assert(IsAnyReference<weak_ref<sjf>>(), "");
1452*65c59e02SInna Palant
1453*65c59e02SInna Palant static_assert(!IsAnyReference<std::string>(), "");
1454*65c59e02SInna Palant static_assert(!IsAnyReference<jint*>(), "");
1455*65c59e02SInna Palant static_assert(!IsAnyReference<void>(), "");
1456*65c59e02SInna Palant static_assert(!IsAnyReference<int>(), "");
1457*65c59e02SInna Palant
1458*65c59e02SInna Palant static_assert(IsPlainJniReference<jobject>(), "");
1459*65c59e02SInna Palant static_assert(IsPlainJniReference<sjf>(), "");
1460*65c59e02SInna Palant static_assert(IsPlainJniReference<jintArray>(), "");
1461*65c59e02SInna Palant static_assert(IsPlainJniReference<jbooleanArray>(), "");
1462*65c59e02SInna Palant
1463*65c59e02SInna Palant static_assert(!IsPlainJniReference<local_ref<jobject>>(), "");
1464*65c59e02SInna Palant static_assert(!IsPlainJniReference<local_ref<sjf>>(), "");
1465*65c59e02SInna Palant static_assert(!IsPlainJniReference<global_ref<jobject>>(), "");
1466*65c59e02SInna Palant static_assert(!IsPlainJniReference<weak_ref<jobject>>(), "");
1467*65c59e02SInna Palant static_assert(!IsPlainJniReference<weak_ref<sjf>>(), "");
1468*65c59e02SInna Palant static_assert(!IsPlainJniReference<std::string>(), "");
1469*65c59e02SInna Palant static_assert(!IsPlainJniReference<jint*>(), "");
1470*65c59e02SInna Palant static_assert(!IsPlainJniReference<void>(), "");
1471*65c59e02SInna Palant static_assert(!IsPlainJniReference<int>(), "");
1472*65c59e02SInna Palant
1473*65c59e02SInna Palant static_assert(IsJniPrimitive<int>(), "");
1474*65c59e02SInna Palant static_assert(IsJniPrimitive<jint>(), "");
1475*65c59e02SInna Palant static_assert(IsJniPrimitive<jboolean>(), "");
1476*65c59e02SInna Palant
1477*65c59e02SInna Palant static_assert(!IsJniPrimitive<jobject>(), "");
1478*65c59e02SInna Palant static_assert(!IsJniPrimitive<sjf>(), "");
1479*65c59e02SInna Palant static_assert(!IsJniPrimitive<jintArray>(), "");
1480*65c59e02SInna Palant static_assert(!IsJniPrimitive<jbooleanArray>(), "");
1481*65c59e02SInna Palant static_assert(!IsJniPrimitive<local_ref<jobject>>(), "");
1482*65c59e02SInna Palant static_assert(!IsJniPrimitive<local_ref<sjf>>(), "");
1483*65c59e02SInna Palant static_assert(!IsJniPrimitive<global_ref<jobject>>(), "");
1484*65c59e02SInna Palant static_assert(!IsJniPrimitive<weak_ref<jobject>>(), "");
1485*65c59e02SInna Palant static_assert(!IsJniPrimitive<weak_ref<sjf>>(), "");
1486*65c59e02SInna Palant static_assert(!IsJniPrimitive<std::string>(), "");
1487*65c59e02SInna Palant static_assert(!IsJniPrimitive<jint*>(), "");
1488*65c59e02SInna Palant static_assert(!IsJniPrimitive<void>(), "");
1489*65c59e02SInna Palant
1490*65c59e02SInna Palant static_assert(IsJniPrimitiveArray<jintArray>(), "");
1491*65c59e02SInna Palant static_assert(IsJniPrimitiveArray<jbooleanArray>(), "");
1492*65c59e02SInna Palant
1493*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<int>(), "");
1494*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<jint>(), "");
1495*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<jboolean>(), "");
1496*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<jobject>(), "");
1497*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<sjf>(), "");
1498*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<local_ref<jobject>>(), "");
1499*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<local_ref<sjf>>(), "");
1500*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<global_ref<jobject>>(), "");
1501*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<weak_ref<jobject>>(), "");
1502*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<weak_ref<sjf>>(), "");
1503*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<std::string>(), "");
1504*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<jint*>(), "");
1505*65c59e02SInna Palant static_assert(!IsJniPrimitiveArray<void>(), "");
1506*65c59e02SInna Palant
1507*65c59e02SInna Palant static_assert(IsJniScalar<jintArray>(), "");
1508*65c59e02SInna Palant static_assert(IsJniScalar<jbooleanArray>(), "");
1509*65c59e02SInna Palant static_assert(IsJniScalar<int>(), "");
1510*65c59e02SInna Palant static_assert(IsJniScalar<jint>(), "");
1511*65c59e02SInna Palant static_assert(IsJniScalar<jboolean>(), "");
1512*65c59e02SInna Palant static_assert(IsJniScalar<jobject>(), "");
1513*65c59e02SInna Palant static_assert(IsJniScalar<sjf>(), "");
1514*65c59e02SInna Palant
1515*65c59e02SInna Palant static_assert(!IsJniScalar<local_ref<jobject>>(), "");
1516*65c59e02SInna Palant static_assert(!IsJniScalar<local_ref<sjf>>(), "");
1517*65c59e02SInna Palant static_assert(!IsJniScalar<global_ref<jobject>>(), "");
1518*65c59e02SInna Palant static_assert(!IsJniScalar<weak_ref<jobject>>(), "");
1519*65c59e02SInna Palant static_assert(!IsJniScalar<weak_ref<sjf>>(), "");
1520*65c59e02SInna Palant static_assert(!IsJniScalar<std::string>(), "");
1521*65c59e02SInna Palant static_assert(!IsJniScalar<jint*>(), "");
1522*65c59e02SInna Palant static_assert(!IsJniScalar<void>(), "");
1523*65c59e02SInna Palant
1524*65c59e02SInna Palant static_assert(IsJniType<jintArray>(), "");
1525*65c59e02SInna Palant static_assert(IsJniType<jbooleanArray>(), "");
1526*65c59e02SInna Palant static_assert(IsJniType<int>(), "");
1527*65c59e02SInna Palant static_assert(IsJniType<jint>(), "");
1528*65c59e02SInna Palant static_assert(IsJniType<jboolean>(), "");
1529*65c59e02SInna Palant static_assert(IsJniType<jobject>(), "");
1530*65c59e02SInna Palant static_assert(IsJniType<sjf>(), "");
1531*65c59e02SInna Palant static_assert(IsJniType<void>(), "");
1532*65c59e02SInna Palant
1533*65c59e02SInna Palant static_assert(!IsJniType<local_ref<jobject>>(), "");
1534*65c59e02SInna Palant static_assert(!IsJniType<local_ref<sjf>>(), "");
1535*65c59e02SInna Palant static_assert(!IsJniType<global_ref<jobject>>(), "");
1536*65c59e02SInna Palant static_assert(!IsJniType<weak_ref<jobject>>(), "");
1537*65c59e02SInna Palant static_assert(!IsJniType<weak_ref<sjf>>(), "");
1538*65c59e02SInna Palant static_assert(!IsJniType<std::string>(), "");
1539*65c59e02SInna Palant static_assert(!IsJniType<jint*>(), "");
1540*65c59e02SInna Palant
1541*65c59e02SInna Palant constexpr const char* jaccess_class_name = "com/facebook/jni/FBJniTests";
1542*65c59e02SInna Palant
1543*65c59e02SInna Palant struct _jfakeClass : _jobject {};
1544*65c59e02SInna Palant using jFakeClass = _jfakeClass*;
1545*65c59e02SInna Palant
1546*65c59e02SInna Palant // This gives a better error message than doing the static_assert inline
1547*65c59e02SInna Palant // (because it will contain the two resolved types).
1548*65c59e02SInna Palant template <typename T, typename F>
StaticAssertSame()1549*65c59e02SInna Palant void StaticAssertSame() {
1550*65c59e02SInna Palant static_assert(std::is_same<T, F>::value, "");
1551*65c59e02SInna Palant };
1552*65c59e02SInna Palant
1553*65c59e02SInna Palant } // namespace
1554*65c59e02SInna Palant
RegisterFbjniTests()1555*65c59e02SInna Palant void RegisterFbjniTests() {
1556*65c59e02SInna Palant StaticAssertSame<JniType<jFakeClass>, jFakeClass>();
1557*65c59e02SInna Palant
1558*65c59e02SInna Palant StaticAssertSame<PrimitiveOrJniType<JObject>, jobject>();
1559*65c59e02SInna Palant StaticAssertSame<PrimitiveOrJniType<JClass>, jclass>();
1560*65c59e02SInna Palant StaticAssertSame<PrimitiveOrJniType<JArrayInt>, jintArray>();
1561*65c59e02SInna Palant StaticAssertSame<PrimitiveOrJniType<jint>, jint>();
1562*65c59e02SInna Palant StaticAssertSame<PrimitiveOrJniType<TestThing>, TestThing::javaobject>();
1563*65c59e02SInna Palant
1564*65c59e02SInna Palant registerNatives(
1565*65c59e02SInna Palant jaccess_class_name,
1566*65c59e02SInna Palant {
1567*65c59e02SInna Palant makeNativeMethod("nativeTestClassResolution", TestClassResolution),
1568*65c59e02SInna Palant makeNativeMethod(
1569*65c59e02SInna Palant "nativeTestLazyClassResolution", TestLazyClassResolution),
1570*65c59e02SInna Palant makeNativeMethod("nativeCreateInstanceOf", TestCreateInstanceOf),
1571*65c59e02SInna Palant makeNativeMethod(
1572*65c59e02SInna Palant "nativeTestVirtualMethodResolution_I",
1573*65c59e02SInna Palant TestVirtualMethodResolution_I),
1574*65c59e02SInna Palant makeNativeMethod("nativeTestTypeDescriptors", TestTypeDescriptors),
1575*65c59e02SInna Palant makeNativeMethod(
1576*65c59e02SInna Palant "nativeTestVirtualMethodResolution_arrB",
1577*65c59e02SInna Palant TestVirtualMethodResolution_arrB),
1578*65c59e02SInna Palant makeNativeMethod(
1579*65c59e02SInna Palant "nativeTestVirtualMethodResolution_S_arrS",
1580*65c59e02SInna Palant TestVirtualMethodResolution_S_arrS),
1581*65c59e02SInna Palant makeNativeMethod(
1582*65c59e02SInna Palant "nativeTestVirtualMethodResolution_arrarrS",
1583*65c59e02SInna Palant TestVirtualMethodResolution_arrarrS),
1584*65c59e02SInna Palant makeNativeMethod(
1585*65c59e02SInna Palant "nativeTestVirtualMethodResolution_arrarrI",
1586*65c59e02SInna Palant TestVirtualMethodResolution_arrarrI),
1587*65c59e02SInna Palant makeNativeMethod(
1588*65c59e02SInna Palant "nativeTestLazyVirtualMethodResolution_I",
1589*65c59e02SInna Palant TestLazyVirtualMethodResolution_I),
1590*65c59e02SInna Palant makeNativeMethod(
1591*65c59e02SInna Palant "nativeTestJMethodCallbacks",
1592*65c59e02SInna Palant "(Lcom/facebook/jni/FBJniTests$Callbacks;)V",
1593*65c59e02SInna Palant TestJMethodCallbacks),
1594*65c59e02SInna Palant makeNativeMethod(
1595*65c59e02SInna Palant "nativeTestJStaticMethodCallbacks", TestJStaticMethodCallbacks),
1596*65c59e02SInna Palant makeNativeMethod("nativeTestIsAssignableFrom", TestIsAssignableFrom),
1597*65c59e02SInna Palant makeNativeMethod("nativeTestIsInstanceOf", TestIsInstanceOf),
1598*65c59e02SInna Palant makeNativeMethod("nativeTestIsSameObject", TestIsSameObject),
1599*65c59e02SInna Palant makeNativeMethod("nativeTestGetSuperclass", TestGetSuperclass),
1600*65c59e02SInna Palant makeNativeMethod("nativeTestWeakRefs", TestWeakRefs),
1601*65c59e02SInna Palant makeNativeMethod("nativeTestAlias", TestAlias),
1602*65c59e02SInna Palant makeNativeMethod(
1603*65c59e02SInna Palant "nativeTestAutoAliasRefReturningVoid",
1604*65c59e02SInna Palant TestAutoAliasRefReturningVoid),
1605*65c59e02SInna Palant makeNativeMethod(
1606*65c59e02SInna Palant "nativeTestAliasRefConversions", testAliasRefConversions),
1607*65c59e02SInna Palant makeNativeMethod(
1608*65c59e02SInna Palant "nativeTestCreatingReferences", testCreatingReferences),
1609*65c59e02SInna Palant makeNativeMethod(
1610*65c59e02SInna Palant "nativeTestAssignmentAndCopyConstructors",
1611*65c59e02SInna Palant testAssignmentAndCopyConstructors),
1612*65c59e02SInna Palant makeNativeMethod(
1613*65c59e02SInna Palant "nativeTestAssignmentAndCopyCrossTypes",
1614*65c59e02SInna Palant testAssignmentAndCopyCrossTypes),
1615*65c59e02SInna Palant makeNativeMethod("nativeTestNullReferences", testNullReferences),
1616*65c59e02SInna Palant makeNativeMethod("nativeTestFieldAccess", TestFieldAccess),
1617*65c59e02SInna Palant makeNativeMethod(
1618*65c59e02SInna Palant "nativeTestStringFieldAccess", TestStringFieldAccess),
1619*65c59e02SInna Palant makeNativeMethod(
1620*65c59e02SInna Palant "nativeTestReferenceFieldAccess", TestReferenceFieldAccess),
1621*65c59e02SInna Palant makeNativeMethod(
1622*65c59e02SInna Palant "nativeTestStaticFieldAccess", TestStaticFieldAccess),
1623*65c59e02SInna Palant makeNativeMethod(
1624*65c59e02SInna Palant "nativeTestStaticStringFieldAccess", TestStaticStringFieldAccess),
1625*65c59e02SInna Palant makeNativeMethod(
1626*65c59e02SInna Palant "nativeTestStaticReferenceFieldAccess",
1627*65c59e02SInna Palant TestStaticReferenceFieldAccess),
1628*65c59e02SInna Palant makeNativeMethod("nativeTestNonVirtualMethod", TestNonVirtualMethod),
1629*65c59e02SInna Palant makeNativeMethod("nativeTestArrayCreation", TestArrayCreation),
1630*65c59e02SInna Palant makeNativeMethod(
1631*65c59e02SInna Palant "nativeTestMultidimensionalObjectArray",
1632*65c59e02SInna Palant TestMultidimensionalObjectArray),
1633*65c59e02SInna Palant makeNativeMethod(
1634*65c59e02SInna Palant "nativeTestMultidimensionalPrimitiveArray",
1635*65c59e02SInna Palant TestMultidimensionalPrimitiveArray),
1636*65c59e02SInna Palant makeNativeMethod("nativeTestBuildStringArray", TestBuildStringArray),
1637*65c59e02SInna Palant makeNativeMethod(
1638*65c59e02SInna Palant "testHandleJavaCustomExceptionNative",
1639*65c59e02SInna Palant TestHandleJavaCustomException),
1640*65c59e02SInna Palant makeNativeMethod(
1641*65c59e02SInna Palant "testHandleNullExceptionMessageNative",
1642*65c59e02SInna Palant TestHandleNullExceptionMessage),
1643*65c59e02SInna Palant makeNativeMethod(
1644*65c59e02SInna Palant "nativeTestHandleNestedException", TestHandleNestedException),
1645*65c59e02SInna Palant makeNativeMethod(
1646*65c59e02SInna Palant "nativeTestHandleNoRttiException", TestHandleNoRttiException),
1647*65c59e02SInna Palant makeNativeMethod("nativeTestCopyConstructor", TestCopyConstructor),
1648*65c59e02SInna Palant makeNativeMethod(
1649*65c59e02SInna Palant "nativeTestMoveConstructorWithEmptyWhat",
1650*65c59e02SInna Palant TestMoveConstructorWithEmptyWhat),
1651*65c59e02SInna Palant makeNativeMethod(
1652*65c59e02SInna Palant "nativeTestMoveConstructorWithPopulatedWhat",
1653*65c59e02SInna Palant TestMoveConstructorWithPopulatedWhat),
1654*65c59e02SInna Palant makeNativeMethod(
1655*65c59e02SInna Palant "nativeTestHandleCppRuntimeError", TestHandleCppRuntimeError),
1656*65c59e02SInna Palant makeNativeMethod(
1657*65c59e02SInna Palant "nativeTestHandleCppIOBaseFailure", TestHandleCppIOBaseFailure),
1658*65c59e02SInna Palant makeNativeMethod(
1659*65c59e02SInna Palant "nativeTestHandleCppSystemError", TestHandleCppSystemError),
1660*65c59e02SInna Palant makeNativeMethod(
1661*65c59e02SInna Palant "nativeTestInterDsoExceptionHandlingA",
1662*65c59e02SInna Palant TestInterDsoExceptionHandlingA),
1663*65c59e02SInna Palant makeNativeMethod(
1664*65c59e02SInna Palant "nativeTestInterDsoExceptionHandlingB",
1665*65c59e02SInna Palant TestInterDsoExceptionHandlingB),
1666*65c59e02SInna Palant makeNativeMethod(
1667*65c59e02SInna Palant "nativeTestHandleNonStdExceptionThrow",
1668*65c59e02SInna Palant TestHandleNonStdException),
1669*65c59e02SInna Palant makeNativeMethod(
1670*65c59e02SInna Palant "nativeTestHandleCppIntThrow", TestHandleCppIntThrow),
1671*65c59e02SInna Palant makeNativeMethod(
1672*65c59e02SInna Palant "nativeTestHandleCppCharPointerThrow",
1673*65c59e02SInna Palant TestHandleCppCharPointerThrow),
1674*65c59e02SInna Palant makeNativeMethod(
1675*65c59e02SInna Palant "nativeTestThrowJavaExceptionByName",
1676*65c59e02SInna Palant TestThrowJavaExceptionByName),
1677*65c59e02SInna Palant makeNativeMethod("nativeTestJThread", TestJThread),
1678*65c59e02SInna Palant makeNativeMethod("nativeTestThreadScopeGuard", TestThreadScopeGuard),
1679*65c59e02SInna Palant makeNativeMethod(
1680*65c59e02SInna Palant "nativeTestNestedThreadScopeGuard", TestNestedThreadScopeGuard),
1681*65c59e02SInna Palant makeNativeMethod(
1682*65c59e02SInna Palant "nativeTestClassLoadInWorker", TestClassLoadInWorker),
1683*65c59e02SInna Palant makeNativeMethod(
1684*65c59e02SInna Palant "nativeTestClassLoadWorkerFastPath", TestClassLoadWorkerFastPath),
1685*65c59e02SInna Palant makeNativeMethod(
1686*65c59e02SInna Palant "nativeTestHandleCppCharPointerThrow",
1687*65c59e02SInna Palant TestHandleCppCharPointerThrow),
1688*65c59e02SInna Palant makeNativeMethod("nativeTestToString", testToString),
1689*65c59e02SInna Palant makeNativeMethod(
1690*65c59e02SInna Palant "nativeTestThrowJavaExceptionByName",
1691*65c59e02SInna Palant TestThrowJavaExceptionByName),
1692*65c59e02SInna Palant makeNativeMethod("nativeTestThreadScopeGuard", TestThreadScopeGuard),
1693*65c59e02SInna Palant makeNativeMethod(
1694*65c59e02SInna Palant "nativeTestNestedThreadScopeGuard", TestNestedThreadScopeGuard),
1695*65c59e02SInna Palant makeNativeMethod("nativeTestNullJString", testNullJString),
1696*65c59e02SInna Palant makeNativeMethod("nativeTestSwap", testSwap),
1697*65c59e02SInna Palant makeNativeMethod("nativeTestEqualOperator", testEqualOperator),
1698*65c59e02SInna Palant makeNativeMethod("nativeTestReleaseAlias", testReleaseAlias),
1699*65c59e02SInna Palant makeNativeMethod(
1700*65c59e02SInna Palant "nativeTestLockingWeakReferences", testLockingWeakReferences),
1701*65c59e02SInna Palant makeNativeMethod(
1702*65c59e02SInna Palant "nativeStaticCastAliasRefToString", StaticCastAliasRefToString),
1703*65c59e02SInna Palant makeNativeMethod(
1704*65c59e02SInna Palant "nativeDynamicCastAliasRefToThrowable",
1705*65c59e02SInna Palant DynamicCastAliasRefToThrowable),
1706*65c59e02SInna Palant makeNativeMethod(
1707*65c59e02SInna Palant "nativeStaticCastLocalRefToString", StaticCastLocalRefToString),
1708*65c59e02SInna Palant makeNativeMethod(
1709*65c59e02SInna Palant "nativeDynamicCastLocalRefToString", DynamicCastLocalRefToString),
1710*65c59e02SInna Palant makeNativeMethod(
1711*65c59e02SInna Palant "nativeStaticCastGlobalRefToString", StaticCastGlobalRefToString),
1712*65c59e02SInna Palant makeNativeMethod(
1713*65c59e02SInna Palant "nativeDynamicCastGlobalRefToString",
1714*65c59e02SInna Palant DynamicCastGlobalRefToString),
1715*65c59e02SInna Palant makeNativeMethod(
1716*65c59e02SInna Palant "testMethodResolutionWithCxxTypesNative",
1717*65c59e02SInna Palant TestMethodResolutionWithCxxTypes),
1718*65c59e02SInna Palant makeCriticalNativeMethod_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(
1719*65c59e02SInna Palant "nativeCriticalNativeMethodBindsAndCanBeInvoked",
1720*65c59e02SInna Palant testCriticalNativeMethodBindsAndCanBeInvoked),
1721*65c59e02SInna Palant });
1722*65c59e02SInna Palant }
1723