1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import org.testng.annotations.Test; 25 26 import java.lang.reflect.Field; 27 import java.lang.reflect.Method; 28 import java.foreign.annotations.NativeHeader; 29 import java.foreign.annotations.NativeLocation; 30 import java.foreign.memory.Pointer; 31 import java.nio.file.Files; 32 import java.nio.file.Path; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.stream.Stream; 36 37 import static org.testng.Assert.assertEquals; 38 import static org.testng.Assert.assertFalse; 39 import static org.testng.Assert.assertNotNull; 40 import static org.testng.Assert.assertNull; 41 import static org.testng.Assert.assertTrue; 42 43 /* 44 * @test 45 * @modules jdk.jextract 46 * @build JextractToolProviderTest 47 * @run testng/othervm -Duser.language=en JextractToolProviderTest 48 */ 49 public class JextractToolProviderTest extends JextractToolRunner { 50 @Test 51 public void testHelp() { 52 run().checkFailure(); // no options 53 run("--help").checkSuccess(); 54 run("-h").checkSuccess(); 55 run("-?").checkSuccess(); 56 } 57 58 // error for non-existent header file 59 @Test 60 public void testNonExistentHeader() { 61 run("--dry-run", getInputFilePath("non_existent.h").toString()) 62 .checkFailure() 63 .checkContainsOutput("Cannot open header file"); 64 } 65 66 @Test 67 public void testDryRun() { 68 // only dry-run, don't produce any output 69 Path simpleJar = getOutputFilePath("simple.jar"); 70 deleteFile(simpleJar); 71 run("--dry-run", getInputFilePath("simple.h").toString()).checkSuccess(); 72 try { 73 assertFalse(Files.isRegularFile(simpleJar)); 74 } finally { 75 deleteFile(simpleJar); 76 } 77 } 78 79 @Test 80 public void testOutputFileOption() { 81 // simple output file check 82 Path simpleJar = getOutputFilePath("simple.jar"); 83 deleteFile(simpleJar); 84 run("-o", simpleJar.toString(), 85 getInputFilePath("simple.h").toString()).checkSuccess(); 86 try { 87 assertTrue(Files.isRegularFile(simpleJar)); 88 } finally { 89 deleteFile(simpleJar); 90 } 91 } 92 93 @Test 94 public void testOutputClass() { 95 Path helloJar = getOutputFilePath("hello.jar"); 96 deleteFile(helloJar); 97 Path helloH = getInputFilePath("hello.h"); 98 run("-o", helloJar.toString(), helloH.toString()).checkSuccess(); 99 try { 100 Class<?> cls = loadClass("hello", helloJar); 101 // check NativeHeader annotation 102 NativeHeader header = cls.getAnnotation(NativeHeader.class); 103 assertNotNull(header); 104 assertEquals(header.path(), helloH.toString()); 105 assertFalse(header.declarations().isEmpty()); 106 107 // check a method for "void func()" 108 assertNotNull(findMethod(cls, "func", Object[].class)); 109 } finally { 110 deleteFile(helloJar); 111 } 112 } 113 114 private void testTargetPackage(String targetPkgOption) { 115 Path helloJar = getOutputFilePath("hello.jar"); 116 deleteFile(helloJar); 117 Path helloH = getInputFilePath("hello.h"); 118 run(targetPkgOption, "com.acme", "-o", helloJar.toString(), helloH.toString()).checkSuccess(); 119 try { 120 Class<?> cls = loadClass("com.acme.hello", helloJar); 121 // check NativeHeader annotation 122 NativeHeader header = cls.getAnnotation(NativeHeader.class); 123 assertNotNull(header); 124 assertEquals(header.path(), helloH.toString()); 125 126 // check a method for "void func()" 127 assertNotNull(findMethod(cls, "func", Object[].class)); 128 } finally { 129 deleteFile(helloJar); 130 } 131 } 132 133 @Test 134 public void testTargetPackageOption() { 135 testTargetPackage("-t"); 136 } 137 138 @Test 139 public void testTargetPackageLongOption() { 140 testTargetPackage("--target-package"); 141 } 142 143 private void testPackageMapping(String pkgMapOption) { 144 Path worldJar = getOutputFilePath("world.jar"); 145 deleteFile(worldJar); 146 Path worldH = getInputFilePath("world.h"); 147 Path include = getInputFilePath("include"); 148 // world.h include mytypes.h, use appropriate package for stuff from mytypes.h 149 run("-I", include.toString(), pkgMapOption, include.toString() + "=com.acme", 150 "-o", worldJar.toString(), worldH.toString()).checkSuccess(); 151 try { 152 Class<?> cls = loadClass("world", worldJar); 153 Method m = findFirstMethod(cls, "distance"); 154 Class<?>[] params = m.getParameterTypes(); 155 assertEquals(params[0].getName(), "com.acme.mytypes$Point"); 156 } finally { 157 deleteFile(worldJar); 158 } 159 } 160 161 @Test 162 public void testPackageDirMappingOption() { 163 testPackageMapping("-m"); 164 } 165 166 @Test 167 public void testPackageDirMappingLongOption() { 168 testPackageMapping("--package-map"); 169 } 170 171 @Test 172 public void test_no_input_files() { 173 run("-L", "foo") 174 .checkContainsOutput("No input files") 175 .checkFailure(); 176 } 177 178 @Test 179 public void test_option_L_without_l() { 180 Path helloJar = getOutputFilePath("hello.jar"); 181 deleteFile(helloJar); 182 Path helloH = getInputFilePath("hello.h"); 183 Path linkDir = getInputFilePath("libs"); 184 String warning = "WARNING: -L option specified without any -l option"; 185 run("-L", linkDir.toString(), "-o", helloJar.toString(), helloH.toString()) 186 .checkContainsOutput(warning) 187 .checkSuccess(); 188 } 189 190 @Test 191 public void test_option_rpath_without_l() { 192 Path helloJar = getOutputFilePath("hello.jar"); 193 deleteFile(helloJar); 194 Path helloH = getInputFilePath("hello.h"); 195 Path rpathDir = getInputFilePath("libs"); 196 String warning = "WARNING: -rpath option specified without any -l option"; 197 try { 198 run("-rpath", rpathDir.toString(), "-o", helloJar.toString(), helloH.toString()) 199 .checkContainsOutput(warning) 200 .checkSuccess(); 201 } finally { 202 deleteFile(helloJar); 203 } 204 } 205 206 @Test 207 public void test_option_conflicting_rpaths() { 208 Path helloJar = getOutputFilePath("hello.jar"); 209 deleteFile(helloJar); 210 Path helloH = getInputFilePath("hello.h"); 211 Path rpathDir = getInputFilePath("libs"); 212 String warning = "WARNING: -infer-rpath used in conjunction with explicit -rpath paths"; 213 try { 214 run("-rpath", rpathDir.toString(), 215 "-infer-rpath", 216 "-o", helloJar.toString(), helloH.toString()) 217 .checkContainsOutput(warning) 218 .checkSuccess(); 219 } finally { 220 deleteFile(helloJar); 221 } 222 } 223 224 @Test 225 public void test_option_rpath_no_libs() { 226 Path helloJar = getOutputFilePath("hello.jar"); 227 deleteFile(helloJar); 228 Path helloH = getInputFilePath("hello.h"); 229 String warning = "WARNING: -infer-rpath option specified without any -L option"; 230 try { 231 run("-infer-rpath", 232 "-o", helloJar.toString(), helloH.toString()) 233 .checkContainsOutput(warning) 234 .checkSuccess(); 235 } finally { 236 deleteFile(helloJar); 237 } 238 } 239 240 @Test 241 public void test_option_l_no_crash_missing_lib() { 242 Path helloJar = getOutputFilePath("hello.jar"); 243 deleteFile(helloJar); 244 Path helloH = getInputFilePath("hello.h"); 245 String warning = "WARNING: Some library names could not be resolved"; 246 try { 247 run("-L", "nonExistent", 248 "-l", "nonExistent", 249 "-o", helloJar.toString(), helloH.toString()) 250 .checkContainsOutput(warning) 251 .checkSuccess(); 252 } finally { 253 deleteFile(helloJar); 254 } 255 } 256 257 @Test 258 public void test_option_l() { 259 Path helloJar = getOutputFilePath("hello.jar"); 260 deleteFile(helloJar); 261 Path helloH = getInputFilePath("hello.h"); 262 run("-l", "hello", "-o", helloJar.toString(), helloH.toString()).checkSuccess(); 263 try { 264 Class<?> cls = loadClass("hello", helloJar); 265 // check that NativeHeader annotation captures -l value 266 NativeHeader header = cls.getAnnotation(NativeHeader.class); 267 assertNotNull(header); 268 assertEquals(header.libraries().length, 1); 269 assertEquals(header.libraries()[0], "hello"); 270 // no library paths (rpath) set 271 assertEquals(header.libraryPaths().length, 0); 272 } finally { 273 deleteFile(helloJar); 274 } 275 } 276 277 @Test 278 public void test_option_l_and_rpath() { 279 Path helloJar = getOutputFilePath("hello.jar"); 280 deleteFile(helloJar); 281 Path helloH = getInputFilePath("hello.h"); 282 Path rpathDir = getInputFilePath("libs"); 283 run("-l", "hello", "-rpath", rpathDir.toString(), 284 "-o", helloJar.toString(), helloH.toString()).checkSuccess(); 285 try { 286 Class<?> cls = loadClass("hello", helloJar); 287 // check that NativeHeader annotation captures -l and -rpath values 288 NativeHeader header = cls.getAnnotation(NativeHeader.class); 289 assertNotNull(header); 290 assertEquals(header.libraries().length, 1); 291 assertEquals(header.libraries()[0], "hello"); 292 assertEquals(header.libraryPaths().length, 1); 293 assertEquals(header.libraryPaths()[0], rpathDir.toString()); 294 } finally { 295 deleteFile(helloJar); 296 } 297 } 298 299 @Test 300 public void testUnionDeclaration() { 301 Path uniondeclJar = getOutputFilePath("uniondecl.jar"); 302 deleteFile(uniondeclJar); 303 Path uniondeclH = getInputFilePath("uniondecl.h"); 304 try { 305 run("-o", uniondeclJar.toString(), uniondeclH.toString()).checkSuccess(); 306 Class<?> unionCls = loadClass("uniondecl", uniondeclJar); 307 assertNotNull(unionCls); 308 boolean found = Arrays.stream(unionCls.getClasses()). 309 map(Class::getSimpleName). 310 filter(n -> n.equals("IntOrFloat")). 311 findFirst().isPresent(); 312 assertTrue(found, "uniondecl.IntOrFloat not found"); 313 } finally { 314 deleteFile(uniondeclJar); 315 } 316 } 317 318 private void testEnumConstGetters(Class<?> enumCls, List<String> names) { 319 for (String name : names) { 320 if (findEnumConstGet(enumCls, name) == null) { 321 throw new RuntimeException(enumCls.getName() + " misses " + name); 322 } 323 } 324 } 325 326 @Test 327 public void testAnonymousEnum() { 328 Path anonenumJar = getOutputFilePath("anonenum.jar"); 329 deleteFile(anonenumJar); 330 Path anonenumH = getInputFilePath("anonenum.h"); 331 try { 332 run("-o", anonenumJar.toString(), anonenumH.toString()).checkSuccess(); 333 Class<?> anonenumCls = loadClass("anonenum", anonenumJar); 334 assertNotNull(anonenumCls); 335 testEnumConstGetters(anonenumCls, List.of("RED", "GREEN", "BLUE")); 336 testEnumConstGetters(anonenumCls, List.of( 337 "Java", "C", "CPP", "Python", "Ruby")); 338 testEnumConstGetters(anonenumCls, List.of( 339 "XS", "S", "M", "L", "XL", "XXL")); 340 testEnumConstGetters(anonenumCls, List.of( 341 "ONE", "TWO")); 342 343 Class<?> enumClz[] = anonenumCls.getClasses(); 344 assert(enumClz.length >= 4); 345 346 Class<?> enumCls = findClass(enumClz, "codetype_t"); 347 assertNotNull(enumCls); 348 349 enumCls = findClass(enumClz, "SIZE"); 350 assertNotNull(enumCls); 351 352 enumCls = findClass(enumClz, "temp"); 353 assertNotNull(enumCls); 354 355 enumCls = findClass(enumClz, "temp_t"); 356 assertNotNull(enumCls); 357 } finally { 358 deleteFile(anonenumJar); 359 } 360 } 361 362 @Test 363 public void testExcludeSymbols() { 364 Path helloJar = getOutputFilePath("hello.jar"); 365 deleteFile(helloJar); 366 Path helloH = getInputFilePath("hello.h"); 367 run("-o", helloJar.toString(), helloH.toString()).checkSuccess(); 368 try { 369 Class<?> cls = loadClass("hello", helloJar); 370 // check a method for "void func()" 371 assertNotNull(findMethod(cls, "func", Object[].class)); 372 assertNotNull(findMethod(cls, "func2", Object[].class)); 373 assertNotNull(findMethod(cls, "func3", Object[].class)); 374 // check a method for "void junk()" 375 assertNotNull(findMethod(cls, "junk", Object[].class)); 376 assertNotNull(findMethod(cls, "junk2", Object[].class)); 377 assertNotNull(findMethod(cls, "junk3", Object[].class)); 378 } finally { 379 deleteFile(helloJar); 380 } 381 382 // try with --exclude-symbols" this time. 383 run("--exclude-symbols", "junk.*", "-o", helloJar.toString(), helloH.toString()) 384 .checkSuccess(); 385 try { 386 Class<?> cls = loadClass("hello", helloJar); 387 // check a method for "void func()" 388 assertNotNull(findMethod(cls, "func", Object[].class)); 389 assertNotNull(findMethod(cls, "func2", Object[].class)); 390 assertNotNull(findMethod(cls, "func3", Object[].class)); 391 // check a method for "void junk()" 392 assertNull(findMethod(cls, "junk", Object[].class)); 393 assertNull(findMethod(cls, "junk2", Object[].class)); 394 assertNull(findMethod(cls, "junk3", Object[].class)); 395 } finally { 396 deleteFile(helloJar); 397 } 398 } 399 400 @Test 401 public void testIncludeSymbols() { 402 Path helloJar = getOutputFilePath("hello.jar"); 403 deleteFile(helloJar); 404 Path helloH = getInputFilePath("hello.h"); 405 run("-o", helloJar.toString(), helloH.toString()).checkSuccess(); 406 try { 407 Class<?> cls = loadClass("hello", helloJar); 408 // check a method for "void func()" 409 assertNotNull(findMethod(cls, "func", Object[].class)); 410 assertNotNull(findMethod(cls, "func2", Object[].class)); 411 assertNotNull(findMethod(cls, "func3", Object[].class)); 412 // check a method for "void junk()" 413 assertNotNull(findMethod(cls, "junk", Object[].class)); 414 assertNotNull(findMethod(cls, "junk2", Object[].class)); 415 assertNotNull(findMethod(cls, "junk3", Object[].class)); 416 } finally { 417 deleteFile(helloJar); 418 } 419 420 // try with --include-symbols" this time. 421 run("--include-symbols", "junk.*", "-o", helloJar.toString(), helloH.toString()).checkSuccess(); 422 try { 423 Class<?> cls = loadClass("hello", helloJar); 424 // check a method for "void junk()" 425 assertNotNull(findMethod(cls, "junk", Object[].class)); 426 assertNotNull(findMethod(cls, "junk2", Object[].class)); 427 assertNotNull(findMethod(cls, "junk3", Object[].class)); 428 // check a method for "void func()" 429 assertNull(findMethod(cls, "func", Object[].class)); 430 assertNull(findMethod(cls, "func2", Object[].class)); 431 assertNull(findMethod(cls, "func3", Object[].class)); 432 } finally { 433 deleteFile(helloJar); 434 } 435 } 436 437 @Test 438 public void testNoLocations() { 439 Path simpleJar = getOutputFilePath("simple.jar"); 440 deleteFile(simpleJar); 441 Path simpleH = getInputFilePath("simple.h"); 442 run("--no-locations", "-o", simpleJar.toString(), simpleH.toString()).checkSuccess(); 443 try { 444 Class<?> simpleCls = loadClass("simple", simpleJar); 445 Method func = findFirstMethod(simpleCls, "func"); 446 assertFalse(func.isAnnotationPresent(NativeLocation.class)); 447 Class<?> anonymousCls = loadClass("simple$anonymous", simpleJar); 448 assertFalse(simpleCls.isAnnotationPresent(NativeLocation.class)); 449 } finally { 450 deleteFile(simpleJar); 451 } 452 } 453 454 @Test 455 public void testIncludeExcludeSymbols() { 456 Path helloJar = getOutputFilePath("hello.jar"); 457 deleteFile(helloJar); 458 Path helloH = getInputFilePath("hello.h"); 459 run("-o", helloJar.toString(), helloH.toString()).checkSuccess(); 460 try { 461 Class<?> cls = loadClass("hello", helloJar); 462 // check a method for "void func()" 463 assertNotNull(findMethod(cls, "func", Object[].class)); 464 assertNotNull(findMethod(cls, "func2", Object[].class)); 465 assertNotNull(findMethod(cls, "func3", Object[].class)); 466 // check a method for "void junk()" 467 assertNotNull(findMethod(cls, "junk", Object[].class)); 468 assertNotNull(findMethod(cls, "junk2", Object[].class)); 469 assertNotNull(findMethod(cls, "junk3", Object[].class)); 470 } finally { 471 deleteFile(helloJar); 472 } 473 474 // try with --include-symbols" this time. 475 run("--include-symbols", "junk.*", "--exclude-symbols", "junk3", 476 "-o", helloJar.toString(), helloH.toString()).checkSuccess(); 477 try { 478 Class<?> cls = loadClass("hello", helloJar); 479 // check a method for "void junk()" 480 assertNotNull(findMethod(cls, "junk", Object[].class)); 481 assertNotNull(findMethod(cls, "junk2", Object[].class)); 482 // check a method for "void func()" - not included 483 assertNull(findMethod(cls, "func", Object[].class)); 484 assertNull(findMethod(cls, "func2", Object[].class)); 485 assertNull(findMethod(cls, "func3", Object[].class)); 486 // excluded among the included set! 487 assertNull(findMethod(cls, "junk3", Object[].class)); 488 } finally { 489 deleteFile(helloJar); 490 } 491 } 492 493 @Test 494 public void testNestedStructsUnions() { 495 Path nestedJar = getOutputFilePath("nested.jar"); 496 deleteFile(nestedJar); 497 Path nestedH = getInputFilePath("nested.h"); 498 try { 499 run("-o", nestedJar.toString(), nestedH.toString()).checkSuccess(); 500 Class<?> headerCls = loadClass("nested", nestedJar); 501 assertNotNull(headerCls); 502 503 Class<?> fooCls = loadClass("nested$Foo", nestedJar); 504 assertNotNull(fooCls); 505 // struct Foo has no getters for "x", "y" etc. 506 assertNull(findStructFieldGet(fooCls, "x")); 507 assertNull(findStructFieldGet(fooCls, "y")); 508 // struct Foo has getters for bar and color 509 assertNotNull(findStructFieldGet(fooCls, "bar")); 510 assertNotNull(findStructFieldGet(fooCls, "color")); 511 // make sure nested types are handled without nested namespace! 512 assertNotNull(loadClass("nested$Bar", nestedJar)); 513 assertNotNull(loadClass("nested$Color", nestedJar)); 514 515 Class<?> uCls = loadClass("nested$U", nestedJar); 516 assertNotNull(uCls); 517 // union U has no getters for "x", "y" etc. 518 assertNull(findStructFieldGet(uCls, "x")); 519 assertNull(findStructFieldGet(uCls, "y")); 520 // union U has getters for point, rgb, i 521 assertNotNull(findStructFieldGet(uCls, "point")); 522 assertNotNull(findStructFieldGet(uCls, "rgb")); 523 assertNotNull(findStructFieldGet(uCls, "i")); 524 // make sure nested types are handled without nested namespace! 525 assertNotNull(loadClass("nested$Point", nestedJar)); 526 assertNotNull(loadClass("nested$RGB", nestedJar)); 527 528 Class<?> myStructCls = loadClass("nested$MyStruct", nestedJar); 529 assertNotNull(findStructFieldGet(myStructCls, "a")); 530 assertNotNull(findStructFieldGet(myStructCls, "b")); 531 assertNotNull(findStructFieldGet(myStructCls, "c")); 532 assertNotNull(findStructFieldGet(myStructCls, "d")); 533 // 'e' is named struct element - should not be in MyStruct 534 assertNull(findStructFieldGet(myStructCls, "e")); 535 assertNotNull(findStructFieldGet(myStructCls, "f")); 536 assertNotNull(findStructFieldGet(myStructCls, "g")); 537 assertNotNull(findStructFieldGet(myStructCls, "h")); 538 // 'i' is named struct element - should not be in MyStruct 539 assertNull(findStructFieldGet(myStructCls, "i")); 540 // 'j' is named struct element - should not be in MyStruct 541 assertNull(findStructFieldGet(myStructCls, "j")); 542 assertNotNull(findStructFieldGet(myStructCls, "k")); 543 // "X", "Y", "Z" are enum constants -should not be in MyStruct 544 assertNull(findStructFieldGet(myStructCls, "X")); 545 assertNull(findStructFieldGet(myStructCls, "Y")); 546 assertNull(findStructFieldGet(myStructCls, "Z")); 547 // anonymous enum constants are hoisted to containing scope 548 assertNotNull(findEnumConstGet(headerCls, "X")); 549 assertNotNull(findEnumConstGet(headerCls, "Y")); 550 assertNotNull(findEnumConstGet(headerCls, "Z")); 551 552 Class<?> myUnionCls = loadClass("nested$MyUnion", nestedJar); 553 assertNotNull(findStructFieldGet(myUnionCls, "a")); 554 assertNotNull(findStructFieldGet(myUnionCls, "b")); 555 assertNotNull(findStructFieldGet(myUnionCls, "c")); 556 assertNotNull(findStructFieldGet(myUnionCls, "d")); 557 // 'e' is named struct element - should not be in MyUnion 558 assertNull(findStructFieldGet(myUnionCls, "e")); 559 assertNotNull(findStructFieldGet(myUnionCls, "f")); 560 assertNotNull(findStructFieldGet(myUnionCls, "g")); 561 assertNotNull(findStructFieldGet(myUnionCls, "h")); 562 // 'i' is named struct element - should not be in MyUnion 563 assertNull(findStructFieldGet(myUnionCls, "i")); 564 // 'j' is named struct element - should not be in MyUnion 565 assertNull(findStructFieldGet(myUnionCls, "j")); 566 assertNotNull(findStructFieldGet(myUnionCls, "k")); 567 // "A", "B", "C" are enum constants -should not be in MyUnion 568 assertNull(findStructFieldGet(myUnionCls, "A")); 569 assertNull(findStructFieldGet(myUnionCls, "B")); 570 assertNull(findStructFieldGet(myUnionCls, "C")); 571 // anonymous enum constants are hoisted to containing scope 572 assertNotNull(findEnumConstGet(headerCls, "A")); 573 assertNotNull(findEnumConstGet(headerCls, "B")); 574 assertNotNull(findEnumConstGet(headerCls, "C")); 575 } finally { 576 deleteFile(nestedJar); 577 } 578 } 579 580 @Test 581 public void testAnonymousStructTypeGlobalVar() { 582 Path elaboratedTypeJar = getOutputFilePath("elaboratedtype.jar"); 583 deleteFile(elaboratedTypeJar); 584 Path elaboratedTypeH = getInputFilePath("elaboratedtype.h"); 585 try { 586 run("-o", elaboratedTypeJar.toString(), elaboratedTypeH.toString()).checkSuccess(); 587 Class<?> headerCls = loadClass("elaboratedtype", elaboratedTypeJar); 588 assertNotNull(findGlobalVariableGet(headerCls, "point")); 589 assertNotNull(findGlobalVariableGet(headerCls, "long_or_int")); 590 assertNotNull(findMethod(headerCls, "func", Pointer.class)); 591 } finally { 592 deleteFile(elaboratedTypeJar); 593 } 594 } 595 596 private void testBuiltinInclude(String name) { 597 Path fileJar = getOutputFilePath(name + "inc.jar"); 598 deleteFile(fileJar); 599 Path fileH = getInputFilePath(name + "inc.h"); 600 run("-o", fileJar.toString(), fileH.toString()).checkSuccess(); 601 deleteFile(fileJar); 602 } 603 604 @Test 605 public void testBuiltinHeader() { 606 testBuiltinInclude("stdarg"); 607 testBuiltinInclude("stdbool"); 608 } 609 610 @Test 611 public void testGlobalFuncPointerCallback() { 612 Path globalFuncPointerJar = getOutputFilePath("globalFuncPointer.jar"); 613 deleteFile(globalFuncPointerJar); 614 Path globalFuncPointerH = getInputFilePath("globalFuncPointer.h"); 615 run("-o", globalFuncPointerJar.toString(), globalFuncPointerH.toString()).checkSuccess(); 616 Class<?> callbackCls = loadClass("globalFuncPointer$FI1", globalFuncPointerJar); 617 Method callback = findFirstMethod(callbackCls, "fn"); 618 assertNotNull(callback); 619 assertTrue(callback.isVarArgs()); 620 deleteFile(globalFuncPointerJar); 621 } 622 623 @Test 624 public void testFuncPtrTypedef() { 625 Path funcPtrTypedefJar = getOutputFilePath("funcPtrTypedef.jar"); 626 deleteFile(funcPtrTypedefJar); 627 Path funcPtrTypedefH = getInputFilePath("funcPtrTypedef.h"); 628 run("-o", funcPtrTypedefJar.toString(), funcPtrTypedefH.toString()).checkSuccess(); 629 // force parsing of class, method 630 Class<?> headerCls = loadClass("funcPtrTypedef", funcPtrTypedefJar); 631 Method getter = findFirstMethod(headerCls, "my_function$get"); 632 assertNotNull(getter); 633 assertNotNull(getter.getGenericParameterTypes()); 634 deleteFile(funcPtrTypedefJar); 635 } 636 637 @Test 638 public void testDuplicatedecls() { 639 Path duplicatedeclsJar = getOutputFilePath("duplicatedecls.jar"); 640 deleteFile(duplicatedeclsJar); 641 Path duplicatedeclsH = getInputFilePath("duplicatedecls.h"); 642 run("-o", duplicatedeclsJar.toString(), duplicatedeclsH.toString()).checkSuccess(); 643 // load the class to make sure no duplicate methods generated in it 644 Class<?> headerCls = loadClass("duplicatedecls", duplicatedeclsJar); 645 assertNotNull(headerCls); 646 deleteFile(duplicatedeclsJar); 647 } 648 } --- EOF ---