1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.facebook.jni; 18 19 import static org.assertj.core.api.Assertions.assertThat; 20 import static org.mockito.Mockito.verify; 21 22 import com.facebook.jni.annotations.DoNotStrip; 23 import java.io.IOException; 24 import java.util.ArrayList; 25 import java.util.concurrent.Callable; 26 import javax.annotation.Nullable; 27 import org.assertj.core.api.Fail; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.mockito.Mock; 31 import org.mockito.runners.MockitoJUnitRunner; 32 33 @RunWith(MockitoJUnitRunner.class) 34 public class FBJniTests extends BaseFBJniTests { 35 class CustomException extends Throwable { 36 int mGetMessageCalls = 0; 37 38 @Override getMessage()39 public String getMessage() { 40 return "getMessages: " + (++mGetMessageCalls); 41 } 42 } 43 44 public interface Callbacks { voidFoo()45 void voidFoo(); 46 booleanFoo()47 boolean booleanFoo(); 48 byteFoo()49 byte byteFoo(); 50 charFoo()51 char charFoo(); 52 shortFoo()53 short shortFoo(); 54 intFoo()55 int intFoo(); 56 longFoo()57 long longFoo(); 58 floatFoo()59 float floatFoo(); 60 doubleFoo()61 double doubleFoo(); 62 objectFoo()63 Object objectFoo(); 64 stringFoo()65 String stringFoo(); 66 } 67 68 public static class TestThing { 69 int foo; 70 } 71 72 @Mock private static Callbacks mCallbacksMock; 73 74 private int mIntFieldTest; 75 private String mStringFieldTest; 76 private TestThing mReferenceFieldTest; 77 private static int sIntFieldTest; 78 private static String sStringFieldTest; 79 private static TestThing sReferenceFieldTest; 80 81 @DoNotStrip // Resolved from fbjni_tests::TestFieldAccess bar(double d)82 int bar(double d) { 83 return 42; 84 } 85 86 // Test case for nonvirtual function nonVirtualMethod(boolean s)87 public boolean nonVirtualMethod(boolean s) { 88 return s; 89 } 90 verifyAllCallbacksCalled(Callbacks mock)91 private static void verifyAllCallbacksCalled(Callbacks mock) { 92 verify(mock).voidFoo(); 93 verify(mock).booleanFoo(); 94 verify(mock).byteFoo(); 95 verify(mock).charFoo(); 96 verify(mock).shortFoo(); 97 verify(mock).intFoo(); 98 verify(mock).longFoo(); 99 verify(mock).floatFoo(); 100 verify(mock).doubleFoo(); 101 verify(mock).objectFoo(); 102 verify(mock).stringFoo(); 103 } 104 105 // Instead of mocking, lets call non-static functions and verify them. voidFooStatic()106 public static void voidFooStatic() { 107 mCallbacksMock.voidFoo(); 108 } 109 booleanFooStatic()110 public static boolean booleanFooStatic() { 111 return mCallbacksMock.booleanFoo(); 112 } 113 byteFooStatic()114 public static byte byteFooStatic() { 115 return mCallbacksMock.byteFoo(); 116 } 117 charFooStatic(char c, int s)118 public static char charFooStatic(char c, int s) { 119 return mCallbacksMock.charFoo(); 120 } 121 shortFooStatic(short s, short t)122 public static short shortFooStatic(short s, short t) { 123 return mCallbacksMock.shortFoo(); 124 } 125 intFooStatic(int s)126 public static int intFooStatic(int s) { 127 return mCallbacksMock.intFoo(); 128 } 129 longFooStatic()130 public static long longFooStatic() { 131 return mCallbacksMock.longFoo(); 132 } 133 floatFooStatic()134 public static float floatFooStatic() { 135 return mCallbacksMock.floatFoo(); 136 } 137 doubleFooStatic()138 public static double doubleFooStatic() { 139 return mCallbacksMock.doubleFoo(); 140 } 141 objectFooStatic()142 public static Object objectFooStatic() { 143 return mCallbacksMock.objectFoo(); 144 } 145 stringFooStatic()146 public static String stringFooStatic() { 147 return mCallbacksMock.stringFoo(); 148 } 149 150 @Test resolveClass()151 public void resolveClass() throws ClassNotFoundException { 152 assertThat(nativeTestClassResolution("java/lang/Object")).isTrue(); 153 } 154 155 // Some versions of Android throw ClassNotFoundException while others throw NoClassDefFoundError. 156 // Flatten that to always be ClassNotFoundException. wrapClassLoadingErrors(Callable<?> code)157 private static void wrapClassLoadingErrors(Callable<?> code) throws Exception { 158 try { 159 code.call(); 160 } catch (NoClassDefFoundError ex) { 161 throw new ClassNotFoundException("chained NoClassDefFoundError", ex); 162 } 163 } 164 165 @Test(expected = ClassNotFoundException.class) failingToResolveClass()166 public void failingToResolveClass() throws Exception { 167 wrapClassLoadingErrors( 168 new Callable<Boolean>() { 169 @Override 170 public Boolean call() throws Exception { 171 return nativeTestClassResolution("ThisClassDoesNotExist"); 172 } 173 }); 174 } 175 nativeTestClassResolution(String className)176 private native boolean nativeTestClassResolution(String className) throws ClassNotFoundException; 177 178 @Test lazyClassResolution()179 public void lazyClassResolution() throws ClassNotFoundException { 180 assertThat(nativeTestLazyClassResolution("java/lang/Object")).isTrue(); 181 } 182 183 @Test(expected = ClassNotFoundException.class) failedLazyClassResolution()184 public void failedLazyClassResolution() throws Exception { 185 wrapClassLoadingErrors( 186 new Callable<Boolean>() { 187 @Override 188 public Boolean call() throws Exception { 189 return nativeTestLazyClassResolution("ThisClassDoesNotExist"); 190 } 191 }); 192 } 193 nativeTestLazyClassResolution(String className)194 private native boolean nativeTestLazyClassResolution(String className) 195 throws ClassNotFoundException; 196 197 @Test instanceCreation()198 public void instanceCreation() { 199 assertThat(nativeCreateInstanceOf("java/lang/String")) 200 .isInstanceOf(String.class) 201 .isEqualTo("java/lang/String"); 202 } 203 nativeCreateInstanceOf(String className)204 private native Object nativeCreateInstanceOf(String className); 205 206 @Test typeDescriptors()207 public void typeDescriptors() { 208 assertThat(nativeTestTypeDescriptors()).isTrue(); 209 } 210 nativeTestTypeDescriptors()211 private native boolean nativeTestTypeDescriptors(); 212 213 @Test resolveVirtualMethod()214 public void resolveVirtualMethod() throws ClassNotFoundException, NoSuchMethodException { 215 assertThat(nativeTestVirtualMethodResolution_I("java/lang/Object", "hashCode")).isTrue(); 216 } 217 218 @Test resolveVirtualMethodWithArray()219 public void resolveVirtualMethodWithArray() throws ClassNotFoundException, NoSuchMethodException { 220 assertThat(nativeTestVirtualMethodResolution_arrB("java/lang/String", "getBytes")).isTrue(); 221 } 222 223 @Test resolveVirtualMethodWithObjectArray()224 public void resolveVirtualMethodWithObjectArray() 225 throws ClassNotFoundException, NoSuchMethodException { 226 assertThat(nativeTestVirtualMethodResolution_S_arrS("java/lang/String", "split")).isTrue(); 227 } 228 229 @Test resolveVirtualMethodWithObjectArrayArray()230 public void resolveVirtualMethodWithObjectArrayArray() 231 throws ClassNotFoundException, NoSuchMethodException { 232 assertThat( 233 nativeTestVirtualMethodResolution_arrarrS( 234 "com/facebook/jni/FBJniTests", "returnMultidimensionalObjectArray")) 235 .isTrue(); 236 } 237 returnMultidimensionalObjectArray()238 public static String[][] returnMultidimensionalObjectArray() { 239 return null; 240 } 241 242 @Test resolveVirtualMethodWithPrimitiveArrayArray()243 public void resolveVirtualMethodWithPrimitiveArrayArray() 244 throws ClassNotFoundException, NoSuchMethodException { 245 assertThat( 246 nativeTestVirtualMethodResolution_arrarrI( 247 "com/facebook/jni/FBJniTests", "returnMultidimensionalPrimitiveArray")) 248 .isTrue(); 249 } 250 returnMultidimensionalPrimitiveArray()251 public static int[][] returnMultidimensionalPrimitiveArray() { 252 return null; 253 } 254 255 @Test(expected = NoSuchMethodError.class) failingToResolveVirtualMethod()256 public void failingToResolveVirtualMethod() throws ClassNotFoundException, NoSuchMethodError { 257 nativeTestVirtualMethodResolution_I("java/lang/Object", "ThisMethodDoesNotExist"); 258 } 259 nativeTestVirtualMethodResolution_I(String className, String methodName)260 private native boolean nativeTestVirtualMethodResolution_I(String className, String methodName) 261 throws ClassNotFoundException, NoSuchMethodError; 262 nativeTestVirtualMethodResolution_arrB(String className, String methodName)263 private native boolean nativeTestVirtualMethodResolution_arrB(String className, String methodName) 264 throws ClassNotFoundException, NoSuchMethodError; 265 nativeTestVirtualMethodResolution_S_arrS( String className, String methodName)266 private native boolean nativeTestVirtualMethodResolution_S_arrS( 267 String className, String methodName) throws ClassNotFoundException, NoSuchMethodError; 268 nativeTestVirtualMethodResolution_arrarrS( String className, String methodName)269 private native boolean nativeTestVirtualMethodResolution_arrarrS( 270 String className, String methodName) throws ClassNotFoundException, NoSuchMethodError; 271 nativeTestVirtualMethodResolution_arrarrI( String className, String methodName)272 private native boolean nativeTestVirtualMethodResolution_arrarrI( 273 String className, String methodName) throws ClassNotFoundException, NoSuchMethodError; 274 275 @Test lazyMethodResolution()276 public void lazyMethodResolution() throws ClassNotFoundException, NoSuchMethodError { 277 assertThat(nativeTestLazyVirtualMethodResolution_I("java/lang/Object", "hashCode")).isTrue(); 278 } 279 280 @Test(expected = NoSuchMethodError.class) failedLazyMethodResolution()281 public void failedLazyMethodResolution() throws ClassNotFoundException, NoSuchMethodError { 282 nativeTestLazyVirtualMethodResolution_I("java/lang/Object", "ThisMethodDoesNotExist"); 283 } 284 nativeTestLazyVirtualMethodResolution_I( String className, String methodName)285 private native boolean nativeTestLazyVirtualMethodResolution_I( 286 String className, String methodName); 287 288 @Test callbacksUsingJMethod()289 public void callbacksUsingJMethod() { 290 nativeTestJMethodCallbacks(mCallbacksMock); 291 verifyAllCallbacksCalled(mCallbacksMock); 292 } 293 nativeTestJMethodCallbacks(Callbacks callbacks)294 private native void nativeTestJMethodCallbacks(Callbacks callbacks); 295 296 @Test callbacksUsingJStaticMethod()297 public void callbacksUsingJStaticMethod() { 298 nativeTestJStaticMethodCallbacks(); 299 verifyAllCallbacksCalled(mCallbacksMock); 300 } 301 nativeTestJStaticMethodCallbacks()302 private native void nativeTestJStaticMethodCallbacks(); 303 304 @Test isAssignableFrom()305 public void isAssignableFrom() { 306 assertThat(nativeTestIsAssignableFrom(String.class, String.class)).isTrue(); 307 assertThat(nativeTestIsAssignableFrom(String.class, Object.class)).isFalse(); 308 assertThat(nativeTestIsAssignableFrom(Object.class, String.class)).isTrue(); 309 assertThat(nativeTestIsAssignableFrom(ArrayList.class, Iterable.class)).isFalse(); 310 assertThat(nativeTestIsAssignableFrom(Iterable.class, ArrayList.class)).isTrue(); 311 } 312 nativeTestIsAssignableFrom(Class cls1, Class cls2)313 private native boolean nativeTestIsAssignableFrom(Class cls1, Class cls2); 314 315 @Test isInstanceOf()316 public void isInstanceOf() { 317 assertThat(nativeTestIsInstanceOf("", String.class)).isTrue(); 318 assertThat(nativeTestIsInstanceOf("", Object.class)).isTrue(); 319 assertThat(nativeTestIsInstanceOf(new Object(), String.class)).isFalse(); 320 assertThat(nativeTestIsInstanceOf(new ArrayList(), Iterable.class)).isTrue(); 321 assertThat(nativeTestIsInstanceOf(null, Iterable.class)).isTrue(); 322 } 323 nativeTestIsInstanceOf(Object object, Class cls)324 private native boolean nativeTestIsInstanceOf(Object object, Class cls); 325 326 @Test isSameObject()327 public void isSameObject() { 328 Object anObject = new Object(); 329 Object anotherObject = new Object(); 330 assertThat(nativeTestIsSameObject(anObject, anObject)).isTrue(); 331 assertThat(nativeTestIsSameObject(anObject, anotherObject)).isFalse(); 332 assertThat(nativeTestIsSameObject(null, anObject)).isFalse(); 333 assertThat(nativeTestIsSameObject(anObject, null)).isFalse(); 334 assertThat(nativeTestIsSameObject(null, null)).isTrue(); 335 } 336 nativeTestIsSameObject(Object a, Object b)337 private native boolean nativeTestIsSameObject(Object a, Object b); 338 339 @Test testGetSuperClass()340 public void testGetSuperClass() { 341 Class testClass = String.class; 342 Class superClass = Object.class; 343 Class notSuperClass = Integer.class; 344 345 assertThat(nativeTestGetSuperclass(testClass, superClass)).isTrue(); 346 assertThat(nativeTestGetSuperclass(testClass, notSuperClass)).isFalse(); 347 } 348 nativeTestGetSuperclass(Class testClass, Class superOfTest)349 private native boolean nativeTestGetSuperclass(Class testClass, Class superOfTest); 350 351 @Test testWeakRefs()352 public void testWeakRefs() { 353 assertThat(nativeTestWeakRefs()).isTrue(); 354 } 355 nativeTestWeakRefs()356 private native boolean nativeTestWeakRefs(); 357 358 @Test testAliasRefs()359 public void testAliasRefs() { 360 assertThat(nativeTestAlias()).isTrue(); 361 } 362 nativeTestAlias()363 private native boolean nativeTestAlias(); 364 365 @Test testAliasRefConversions()366 public void testAliasRefConversions() { 367 assertThat(nativeTestAliasRefConversions()).isTrue(); 368 } 369 nativeTestAliasRefConversions()370 private native boolean nativeTestAliasRefConversions(); 371 372 @Test testNullJString()373 public void testNullJString() { 374 assertThat(nativeTestNullJString()).isTrue(); 375 } 376 nativeTestNullJString()377 private native boolean nativeTestNullJString(); 378 379 @Test testSwap()380 public void testSwap() { 381 assertThat(nativeTestSwap(new Object())).isTrue(); 382 } 383 nativeTestSwap(Object other)384 private native boolean nativeTestSwap(Object other); 385 386 @Test testEqualOperator()387 public void testEqualOperator() { 388 assertThat(nativeTestEqualOperator(new Object())).isTrue(); 389 } 390 nativeTestEqualOperator(Object other)391 private native boolean nativeTestEqualOperator(Object other); 392 393 @Test testRelaseAlias()394 public void testRelaseAlias() { 395 assertThat(nativeTestReleaseAlias()).isTrue(); 396 } 397 nativeTestReleaseAlias()398 private native boolean nativeTestReleaseAlias(); 399 400 @Test testLockingWeakReferences()401 public void testLockingWeakReferences() { 402 assertThat(nativeTestLockingWeakReferences()).isTrue(); 403 } 404 nativeTestLockingWeakReferences()405 private native boolean nativeTestLockingWeakReferences(); 406 407 @Test testCreatingReferences()408 public void testCreatingReferences() { 409 assertThat(nativeTestCreatingReferences()).isTrue(); 410 } 411 nativeTestCreatingReferences()412 private native boolean nativeTestCreatingReferences(); 413 414 @Test testAssignmentAndCopyConstructors()415 public void testAssignmentAndCopyConstructors() { 416 assertThat(nativeTestAssignmentAndCopyConstructors()).isTrue(); 417 } 418 nativeTestAssignmentAndCopyConstructors()419 private native boolean nativeTestAssignmentAndCopyConstructors(); 420 421 @Test testAssignmentAndCopyCrossTypes()422 public void testAssignmentAndCopyCrossTypes() { 423 assertThat(nativeTestAssignmentAndCopyCrossTypes()).isTrue(); 424 } 425 nativeTestAssignmentAndCopyCrossTypes()426 private native boolean nativeTestAssignmentAndCopyCrossTypes(); 427 428 @Test testNullReferences()429 public void testNullReferences() { 430 assertThat(nativeTestNullReferences()).isTrue(); 431 } 432 nativeTestNullReferences()433 private native boolean nativeTestNullReferences(); 434 435 @Test testAutoAliasRefReturningVoid()436 public void testAutoAliasRefReturningVoid() { 437 nativeTestAutoAliasRefReturningVoid(); 438 } 439 nativeTestAutoAliasRefReturningVoid()440 private native void nativeTestAutoAliasRefReturningVoid(); 441 442 @Test testFieldAccess()443 public void testFieldAccess() { 444 mIntFieldTest = 17; 445 assertThat(nativeTestFieldAccess("mIntFieldTest", mIntFieldTest, 42)).isTrue(); 446 assertThat(mIntFieldTest).isEqualTo(42); 447 } 448 nativeTestFieldAccess(String name, int oldVal, int newVal)449 private native boolean nativeTestFieldAccess(String name, int oldVal, int newVal); 450 451 @Test testStringFieldAccess()452 public void testStringFieldAccess() { 453 mStringFieldTest = "initial"; 454 assertThat(nativeTestStringFieldAccess("mStringFieldTest", mStringFieldTest, "final")).isTrue(); 455 assertThat(mStringFieldTest).isEqualTo("final"); 456 } 457 nativeTestStringFieldAccess(String name, String oldVal, String newVal)458 private native boolean nativeTestStringFieldAccess(String name, String oldVal, String newVal); 459 460 @Test testReferenceFieldAccess()461 public void testReferenceFieldAccess() { 462 for (boolean useWrapper : new boolean[] {false, true}) { 463 mReferenceFieldTest = new TestThing(); 464 TestThing newthing = new TestThing(); 465 466 assertThat( 467 nativeTestReferenceFieldAccess( 468 "mReferenceFieldTest", mReferenceFieldTest, newthing, useWrapper)) 469 .isTrue(); 470 assertThat(mReferenceFieldTest).isEqualTo(newthing); 471 } 472 } 473 nativeTestReferenceFieldAccess( String name, Object oldVal, Object newVal, boolean useWrapper)474 private native boolean nativeTestReferenceFieldAccess( 475 String name, Object oldVal, Object newVal, boolean useWrapper); 476 477 @Test testStaticFieldAccess()478 public void testStaticFieldAccess() { 479 sIntFieldTest = 17; 480 assertThat(nativeTestStaticFieldAccess("sIntFieldTest", sIntFieldTest, 42)).isTrue(); 481 assertThat(sIntFieldTest).isEqualTo(42); 482 } 483 nativeTestStaticFieldAccess(String name, int oldVal, int newVal)484 private native boolean nativeTestStaticFieldAccess(String name, int oldVal, int newVal); 485 486 @Test testStaticStringFieldAccess()487 public void testStaticStringFieldAccess() { 488 sStringFieldTest = "initial"; 489 assertThat(nativeTestStaticStringFieldAccess("sStringFieldTest", sStringFieldTest, "final")) 490 .isTrue(); 491 assertThat(sStringFieldTest).isEqualTo("final"); 492 } 493 nativeTestStaticStringFieldAccess(String name, String oVal, String nVal)494 private native boolean nativeTestStaticStringFieldAccess(String name, String oVal, String nVal); 495 496 @Test testStaticReferenceFieldAccess()497 public void testStaticReferenceFieldAccess() { 498 for (boolean useWrapper : new boolean[] {false, true}) { 499 sReferenceFieldTest = new TestThing(); 500 TestThing newthing = new TestThing(); 501 502 assertThat( 503 nativeTestStaticReferenceFieldAccess( 504 "sReferenceFieldTest", sReferenceFieldTest, newthing, useWrapper)) 505 .isTrue(); 506 assertThat(sReferenceFieldTest).isEqualTo(newthing); 507 } 508 } 509 nativeTestStaticReferenceFieldAccess( String name, Object oldVal, Object newVal, boolean useWrapper)510 private native boolean nativeTestStaticReferenceFieldAccess( 511 String name, Object oldVal, Object newVal, boolean useWrapper); 512 513 @Test testNonVirtualMethod()514 public void testNonVirtualMethod() { 515 assertThat(nativeTestNonVirtualMethod(true)).isTrue(); 516 } 517 nativeTestNonVirtualMethod(boolean s)518 private native boolean nativeTestNonVirtualMethod(boolean s); 519 520 @Test testArrayCreation()521 public void testArrayCreation() { 522 String[] expectedStrings = {"one", "two", "three"}; 523 String[] joinedStrings = 524 nativeTestArrayCreation(expectedStrings[0], expectedStrings[1], expectedStrings[2]); 525 assertThat(joinedStrings).isEqualTo(expectedStrings); 526 } 527 nativeTestArrayCreation(String s0, String s1, String s2)528 private native String[] nativeTestArrayCreation(String s0, String s1, String s2); 529 530 @Test testMultidimensionalObjectArray()531 public void testMultidimensionalObjectArray() { 532 String[] strings = {"one", "two", "three"}; 533 String[][] expectedStrings = {{"one", "two"}, {"three"}}; 534 String[][] joinedStrings = 535 nativeTestMultidimensionalObjectArray(strings[0], strings[1], strings[2]); 536 assertThat(joinedStrings).isEqualTo(expectedStrings); 537 } 538 nativeTestMultidimensionalObjectArray(String s0, String s1, String s2)539 private native String[][] nativeTestMultidimensionalObjectArray(String s0, String s1, String s2); 540 541 @Test testMultidimensionalPrimitiveArray()542 public void testMultidimensionalPrimitiveArray() { 543 int[] nums = {1, 2, 3}; 544 int[][] expectedNums = {{1, 2}, {3}}; 545 int[][] gotNums = nativeTestMultidimensionalPrimitiveArray(nums[0], nums[1], nums[2]); 546 assertThat(gotNums).isEqualTo(expectedNums); 547 } 548 nativeTestMultidimensionalPrimitiveArray(int i0, int i1, int i2)549 private native int[][] nativeTestMultidimensionalPrimitiveArray(int i0, int i1, int i2); 550 551 @Nullable private String[] mCapturedStringArray = null; 552 553 @DoNotStrip captureStringArray(String[] input)554 String captureStringArray(String[] input) { 555 mCapturedStringArray = input; 556 return "Stub"; 557 } 558 559 @Test testBuildStringArray()560 public void testBuildStringArray() throws Exception { 561 String[] input = {"Four", "score", "and", "seven", "beers", "ago"}; 562 nativeTestBuildStringArray(input); 563 assertThat(mCapturedStringArray).isEqualTo(input); 564 } 565 nativeTestBuildStringArray(String... input)566 private native String nativeTestBuildStringArray(String... input); 567 methodResolutionWithCxxTypes(String t, long val)568 public Object methodResolutionWithCxxTypes(String t, long val) { 569 if (!"test".equals(t) || val != 3) throw new RuntimeException(); 570 return null; 571 } 572 methodResolutionWithCxxTypesVoid(String t, long val)573 public void methodResolutionWithCxxTypesVoid(String t, long val) { 574 if (!"test".equals(t) || val != 3) throw new RuntimeException(); 575 } 576 methodResolutionWithCxxTypesInt(String t, long val)577 public int methodResolutionWithCxxTypesInt(String t, long val) { 578 if (!"test".equals(t) || val != 3) throw new RuntimeException(); 579 return 0; 580 } 581 methodResolutionWithCxxTypesStatic(String t, long val)582 public static Object methodResolutionWithCxxTypesStatic(String t, long val) { 583 if (!"test".equals(t) || val != 3) throw new RuntimeException(); 584 return null; 585 } 586 methodResolutionWithCxxTypesVoidStatic(String t, long val)587 public static void methodResolutionWithCxxTypesVoidStatic(String t, long val) { 588 if (!"test".equals(t) || val != 3) throw new RuntimeException(); 589 } 590 methodResolutionWithCxxTypesIntStatic(String t, long val)591 public static int methodResolutionWithCxxTypesIntStatic(String t, long val) { 592 if (!"test".equals(t) || val != 3) throw new RuntimeException(); 593 return 0; 594 } 595 596 @Test testMethodResolutionWithCxxTypes()597 public void testMethodResolutionWithCxxTypes() { 598 testMethodResolutionWithCxxTypesNative("methodResolutionWithCxxTypes", "test", 3); 599 } 600 testMethodResolutionWithCxxTypesNative( String callbackName, String str, long val)601 private native void testMethodResolutionWithCxxTypesNative( 602 String callbackName, String str, long val); 603 604 @Test(expected = CustomException.class) testHandleJavaCustomException()605 public void testHandleJavaCustomException() { 606 testHandleJavaCustomExceptionNative(); 607 } 608 testHandleJavaCustomExceptionNative()609 private native void testHandleJavaCustomExceptionNative(); 610 611 @Test testHandleNullExceptionMessage()612 public void testHandleNullExceptionMessage() { 613 testHandleNullExceptionMessageNative(); 614 } 615 testHandleNullExceptionMessageNative()616 private native void testHandleNullExceptionMessageNative(); 617 618 @Test testHandleNestedException()619 public void testHandleNestedException() { 620 try { 621 nativeTestHandleNestedException(); 622 } catch (Throwable e) { 623 assertThat(e).isInstanceOf(ArrayIndexOutOfBoundsException.class); 624 e = e.getCause(); 625 assertThat(e).isInstanceOf(RuntimeException.class); 626 e = e.getCause(); 627 assertThat(e).isInstanceOf(CustomException.class).hasNoCause(); 628 } 629 } 630 nativeTestHandleNestedException()631 private native void nativeTestHandleNestedException(); 632 633 @Test(expected = CppException.class) testHandleNoRttiException()634 public void testHandleNoRttiException() { 635 nativeTestHandleNoRttiException(); 636 } 637 nativeTestHandleNoRttiException()638 private native void nativeTestHandleNoRttiException(); 639 640 @Test testCopyConstructor()641 public void testCopyConstructor() { 642 assertThat(nativeTestCopyConstructor()) 643 .startsWith( 644 "com.facebook.jni.FBJniTests$CustomException: getMessages: 1\n" 645 + "\tat com.facebook.jni.FBJniTests.customExceptionThrower(FBJniTests.java:") 646 .contains( 647 ")\n" 648 + "\tat com.facebook.jni.FBJniTests.nativeTestCopyConstructor(Native Method)\n" 649 + "\tat com.facebook.jni.FBJniTests.testCopyConstructor(FBJniTests.java:"); 650 } 651 nativeTestCopyConstructor()652 private native String nativeTestCopyConstructor(); 653 654 @Test testMoveConstructorWithEmptyWhat()655 public void testMoveConstructorWithEmptyWhat() { 656 assertThat(nativeTestMoveConstructorWithEmptyWhat()) 657 .startsWith( 658 "com.facebook.jni.FBJniTests$CustomException: getMessages: 1\n" 659 + "\tat com.facebook.jni.FBJniTests.customExceptionThrower(FBJniTests.java:") 660 .contains( 661 ")\n" 662 + "\tat com.facebook.jni.FBJniTests.nativeTestMoveConstructorWithEmptyWhat(Native" 663 + " Method)\n" 664 + "\tat com.facebook.jni.FBJniTests.testMoveConstructorWithEmptyWhat(FBJniTests.java:"); 665 } 666 nativeTestMoveConstructorWithEmptyWhat()667 private native String nativeTestMoveConstructorWithEmptyWhat(); 668 669 @Test testMoveConstructorWithPopulatedWhat()670 public void testMoveConstructorWithPopulatedWhat() { 671 assertThat(nativeTestMoveConstructorWithPopulatedWhat()) 672 .startsWith( 673 "com.facebook.jni.FBJniTests$CustomException: getMessages: 1\n" 674 + "\tat com.facebook.jni.FBJniTests.customExceptionThrower(FBJniTests.java:") 675 .contains( 676 ")\n" 677 + "\tat com.facebook.jni.FBJniTests.nativeTestMoveConstructorWithPopulatedWhat(Native" 678 + " Method)\n" 679 + "\tat com.facebook.jni.FBJniTests.testMoveConstructorWithPopulatedWhat(FBJniTests.java:"); 680 } 681 nativeTestMoveConstructorWithPopulatedWhat()682 private native String nativeTestMoveConstructorWithPopulatedWhat(); 683 684 @DoNotStrip // Used in native code. customExceptionThrower()685 protected void customExceptionThrower() throws CustomException { 686 throw new CustomException(); 687 } 688 689 @DoNotStrip // Used in native code. nullMessageThrower()690 protected void nullMessageThrower() throws NullPointerException { 691 // just like Preconditions.checkNotNull() does 692 throw new NullPointerException(); 693 } 694 695 @Test testHandleCppRuntimeError()696 public void testHandleCppRuntimeError() { 697 String message = "Sample runtime error."; 698 thrown.expect(RuntimeException.class); 699 thrown.expectMessage(message); 700 nativeTestHandleCppRuntimeError(message); 701 } 702 nativeTestHandleCppRuntimeError(String message)703 private native void nativeTestHandleCppRuntimeError(String message); 704 705 @Test(expected = IOException.class) testHandleCppIOBaseFailure()706 public void testHandleCppIOBaseFailure() { 707 nativeTestHandleCppIOBaseFailure(); 708 } 709 nativeTestHandleCppIOBaseFailure()710 private native void nativeTestHandleCppIOBaseFailure(); 711 712 @Test(expected = CppSystemErrorException.class) testHandleCppSystemError()713 public void testHandleCppSystemError() { 714 nativeTestHandleCppSystemError(); 715 } 716 nativeTestHandleCppSystemError()717 private native void nativeTestHandleCppSystemError(); 718 719 @Test(expected = RuntimeException.class) testInterDsoExceptionHandlingA()720 public void testInterDsoExceptionHandlingA() { 721 nativeTestInterDsoExceptionHandlingA(); 722 } 723 nativeTestInterDsoExceptionHandlingA()724 private native void nativeTestInterDsoExceptionHandlingA(); 725 726 @Test testInterDsoExceptionHandlingB()727 public void testInterDsoExceptionHandlingB() { 728 assertThat(nativeTestInterDsoExceptionHandlingB()).isTrue(); 729 } 730 nativeTestInterDsoExceptionHandlingB()731 private native boolean nativeTestInterDsoExceptionHandlingB(); 732 733 @Test testHandleNonStdExceptionThrow()734 public void testHandleNonStdExceptionThrow() { 735 try { 736 nativeTestHandleNonStdExceptionThrow(); 737 Fail.failBecauseExceptionWasNotThrown(UnknownCppException.class); 738 } catch (UnknownCppException ex) { 739 if (System.getProperty("os.name").startsWith("Windows")) { 740 // Unknown exception types not supported on Windows. 741 assertThat(ex.getMessage()).isEqualTo("Unknown"); 742 return; 743 } 744 // the actual string is implementation-defined and mangled, but in practice, 745 // it has the name of the C++ type in it somewhere. 746 assertThat(ex.getMessage()).startsWith("Unknown: ").contains("NonStdException"); 747 } 748 } 749 nativeTestHandleNonStdExceptionThrow()750 private native void nativeTestHandleNonStdExceptionThrow(); 751 752 @Test(expected = UnknownCppException.class) testHandleCppCharPointerThrow()753 public void testHandleCppCharPointerThrow() { 754 nativeTestHandleCppCharPointerThrow(); 755 } 756 nativeTestHandleCppCharPointerThrow()757 private native void nativeTestHandleCppCharPointerThrow(); 758 759 @Test(expected = IllegalArgumentException.class) testThrowJavaExceptionByName()760 public void testThrowJavaExceptionByName() { 761 nativeTestThrowJavaExceptionByName(); 762 } 763 nativeTestThrowJavaExceptionByName()764 private native void nativeTestThrowJavaExceptionByName(); 765 766 @Test(expected = UnknownCppException.class) testHandleCppIntThrow()767 public void testHandleCppIntThrow() { 768 nativeTestHandleCppIntThrow(); 769 } 770 nativeTestHandleCppIntThrow()771 private native void nativeTestHandleCppIntThrow(); 772 773 @Test testJThread()774 public void testJThread() { 775 assertThat(nativeTestJThread()).isEqualTo(1); 776 } 777 nativeTestJThread()778 private native int nativeTestJThread(); 779 780 @Test testThreadScopeGuard()781 public void testThreadScopeGuard() { 782 assertThat(nativeTestThreadScopeGuard(17)).isEqualTo(42); 783 } 784 nativeTestThreadScopeGuard(double input)785 private native int nativeTestThreadScopeGuard(double input); 786 787 @Test testNestedThreadScopeGuard()788 public void testNestedThreadScopeGuard() { 789 assertThat(nativeTestNestedThreadScopeGuard(17)).isEqualTo(42); 790 } 791 nativeTestNestedThreadScopeGuard(double input)792 private native int nativeTestNestedThreadScopeGuard(double input); 793 794 @Test testClassLoadInWorker()795 public void testClassLoadInWorker() { 796 assertThat(nativeTestClassLoadInWorker()).isEqualTo(1); 797 } 798 nativeTestClassLoadInWorker()799 private native int nativeTestClassLoadInWorker(); 800 801 @Test testClassLoadWorkerFastPath()802 public void testClassLoadWorkerFastPath() { 803 assertThat(nativeTestClassLoadWorkerFastPath()).isEqualTo(3); 804 } 805 nativeTestClassLoadWorkerFastPath()806 private native int nativeTestClassLoadWorkerFastPath(); 807 808 @Test testToString()809 public void testToString() { 810 assertThat(nativeTestToString()).isTrue(); 811 } 812 nativeTestToString()813 private native boolean nativeTestToString(); 814 815 // Casting alias_ref 816 817 @Test testCorrectStaticCastAliasRef()818 public void testCorrectStaticCastAliasRef() { 819 // Static cast can't fail at run time. If the object isn't actually 820 // of that type, we just get undefined behaviour, which we can't 821 // check for. So we only do a positive test. 822 assertThat(nativeStaticCastAliasRefToString("hello")).isTrue(); 823 } 824 825 @Test testNullStaticCastAliasRef()826 public void testNullStaticCastAliasRef() { 827 assertThat(nativeStaticCastAliasRefToString(null)).isTrue(); 828 } 829 nativeStaticCastAliasRefToString(Object a)830 private native boolean nativeStaticCastAliasRefToString(Object a); 831 832 @Test testDynamicCastAliasRefToSame()833 public void testDynamicCastAliasRefToSame() { 834 assertThat(nativeDynamicCastAliasRefToThrowable(new Throwable())).isTrue(); 835 } 836 testDynamicCastAliasRefToBase()837 public void testDynamicCastAliasRefToBase() { 838 assertThat(nativeDynamicCastAliasRefToThrowable(new Exception())).isTrue(); 839 } 840 841 @Test(expected = ClassCastException.class) testDynamicCastAliasRefToDerived()842 public void testDynamicCastAliasRefToDerived() { 843 nativeDynamicCastAliasRefToThrowable(new Object()); 844 } 845 846 @Test(expected = ClassCastException.class) testDynamicCastAliasRefToUnrelated()847 public void testDynamicCastAliasRefToUnrelated() { 848 nativeDynamicCastAliasRefToThrowable(new Integer(23)); 849 } 850 851 @Test testNullDynamicCastAliasRef()852 public void testNullDynamicCastAliasRef() { 853 assertThat(nativeDynamicCastAliasRefToThrowable(null)).isTrue(); 854 } 855 nativeDynamicCastAliasRefToThrowable(Object a)856 private native boolean nativeDynamicCastAliasRefToThrowable(Object a); 857 858 // Casting local_ref 859 860 @Test testCorrectStaticCastLocalRef()861 public void testCorrectStaticCastLocalRef() { 862 // Static cast can't fail at run time. If the object isn't actually 863 // of that type, we just get undefined behaviour, which we can't 864 // check for. So we only do a positive test. 865 assertThat(nativeStaticCastLocalRefToString("hello")).isTrue(); 866 } 867 868 @Test testNullStaticCastLocalRef()869 public void testNullStaticCastLocalRef() { 870 assertThat(nativeStaticCastLocalRefToString(null)).isTrue(); 871 } 872 nativeStaticCastLocalRefToString(Object a)873 private native boolean nativeStaticCastLocalRefToString(Object a); 874 875 @Test testCorrectDynamicCastLocalRef()876 public void testCorrectDynamicCastLocalRef() { 877 assertThat(nativeDynamicCastLocalRefToString("hello")).isTrue(); 878 } 879 880 @Test(expected = ClassCastException.class) testIncorrectDynamicCastLocalRef()881 public void testIncorrectDynamicCastLocalRef() { 882 nativeDynamicCastLocalRefToString(new Integer(23)); 883 } 884 885 @Test testNullDynamicCastLocalRef()886 public void testNullDynamicCastLocalRef() { 887 assertThat(nativeDynamicCastLocalRefToString(null)).isTrue(); 888 } 889 nativeDynamicCastLocalRefToString(Object a)890 private native boolean nativeDynamicCastLocalRefToString(Object a); 891 892 // Casting global_ref 893 894 @Test testCorrectStaticCastGlobalRef()895 public void testCorrectStaticCastGlobalRef() { 896 // Static cast can't fail at run time. If the object isn't actually 897 // of that type, we just get undefined behaviour, which we can't 898 // check for. So we only do a positive test. 899 assertThat(nativeStaticCastGlobalRefToString("hello")).isTrue(); 900 } 901 902 @Test testNullStaticCastGlobalRef()903 public void testNullStaticCastGlobalRef() { 904 assertThat(nativeStaticCastGlobalRefToString(null)).isTrue(); 905 } 906 nativeStaticCastGlobalRefToString(Object a)907 private native boolean nativeStaticCastGlobalRefToString(Object a); 908 909 @Test testCorrectDynamicCastGlobalRef()910 public void testCorrectDynamicCastGlobalRef() { 911 assertThat(nativeDynamicCastGlobalRefToString("hello")).isTrue(); 912 } 913 914 @Test(expected = ClassCastException.class) testIncorrectDynamicCastGlobalRef()915 public void testIncorrectDynamicCastGlobalRef() { 916 nativeDynamicCastGlobalRefToString(new Integer(23)); 917 } 918 919 @Test testNullDynamicCastGlobalRef()920 public void testNullDynamicCastGlobalRef() { 921 assertThat(nativeDynamicCastGlobalRefToString(null)).isTrue(); 922 } 923 nativeDynamicCastGlobalRefToString(Object a)924 private native boolean nativeDynamicCastGlobalRefToString(Object a); 925 926 @Test testCriticalNativeMethodBindsAndCanBeInvoked()927 public void testCriticalNativeMethodBindsAndCanBeInvoked() { 928 assertThat(nativeCriticalNativeMethodBindsAndCanBeInvoked(12, 3.45f)).isTrue(); 929 } 930 nativeCriticalNativeMethodBindsAndCanBeInvoked(int a, float b)931 private static native boolean nativeCriticalNativeMethodBindsAndCanBeInvoked(int a, float b); 932 } 933