xref: /aosp_15_r20/external/fbjni/test/jni/fbjni_tests.cpp (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
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