# Tests for JNI code. # Compile a single C file and produce a .so file. OPTIONS is a list # of options to pass to the compiler. Returns 0 on failure, 1 on # success. proc gcj_jni_compile_c_to_so {file {options {}}} { global srcdir set name [file rootname [file tail $file]] set soname lib${name}.so lappend options "additional_flags=-shared -fPIC" # Find the generated header. lappend options "additional_flags=-I." # Find jni.h. lappend options "additional_flags=-I$srcdir/../include" set x [prune_warnings [target_compile $file $soname executable $options]] if {$x != ""} { verbose "target_compile failed: $x" 2 fail "$name.c compilation" return 0 } pass "$name.c compilation" return 1 } # Build a header file from a .class file. Return 0 on failure. proc gcj_jni_build_header {file} { set gcjh [find_gcjh] set file [file rootname $file] set options [list "compiler=$gcjh" \ "additional_flags=-jni"] set x [prune_warnings [target_compile $file "" none $options]] if {$x != ""} { verbose "target_compile failed: $x" 2 fail "$file header generation" return 0 } pass "$file header generation" return 1 } # Invoke the program and see what happens. Return 0 on failure. proc gcj_invoke {program expectFile} { global env set lib_path $env(LD_LIBRARY_PATH) setenv LD_LIBRARY_PATH .:$lib_path setenv SHLIB_PATH .:$lib_path verbose "LD_LIBRARY_PATH=$env(LD_LIBRARY_PATH)" set result [libjava_load ./$program] set status [lindex $result 0] set output [lindex $result 1] # Restore setting setenv LD_LIBRARY_PATH $lib_path setenv SHLIB_PATH $lib_path if {$status != "pass"} { verbose "got $output" fail "$program run" untested "$program output" return 0 } set id [open $expectFile r] set expected [read $id] close $id if {! [string compare $output $expected]} { pass "$program output" return 1 } else { fail "$program output" return 0 } } # Do all the work for a single JNI test. Return 0 on failure. proc gcj_jni_test_one {file} { global runtests # The base name. We use it for several purposes. set main [file rootname [file tail $file]] if {! [runtest_file_p $runtests $main]} { # Simply skip it. return 1 } if {! [bytecompile_file $file [pwd]]} { fail "bytecompile $file" # FIXME - should use `untested' on all remaining tests. # But that is hard. return 0 } pass "bytecompile $file" set bytefile [file rootname [file tail $file]].class if {! [gcj_jni_build_header $bytefile]} { # FIXME return 0 } set cfile [file rootname $file].c if {! [gcj_jni_compile_c_to_so $cfile]} { # FIXME return 0 } # We use -l$main because the .so is named the same as the main # program. set args [list "additional_flags=-fjni -L. -l$main"] if {! [gcj_link $main $main $file $args]} { # FIXME return 0 } if {! [gcj_invoke $main [file rootname $file].out]} { # FIXME return 0 } # When we succeed we remove all our clutter. eval gcj_cleanup [glob -nocomplain -- ${main}.*] [list $main lib${main}.so] return 1 } # Run the JNI tests. proc gcj_jni_run {} { global srcdir subdir global target_triplet host_triplet # For now we only test JNI on native builds. if {$target_triplet == $host_triplet} { catch "glob -nocomplain ${srcdir}/${subdir}/*.java" srcfiles foreach x $srcfiles { gcj_jni_test_one $x } } else { verbose "JNI tests not run in cross-compilation environment" } } gcj_jni_run