| # Test code for libgdiagnostics.so |
| # |
| # We will compile each of libgdiagnostics.dg/test-*.{c,cc} into an executable |
| # dynamically linked against libgdiagnostics.so, and then run each |
| # such executable. |
| # |
| # These executables call into the libgdiagnostics.so API to emit diagnostics, |
| # sometimes in text form, and other times in SARIF form. |
| |
| # Kludge alert: |
| # We need g++_init so that it can find the stdlib include path. |
| # |
| # g++_init (in lib/g++.exp) uses g++_maybe_build_wrapper, |
| # which normally comes from the definition of |
| # ${tool}_maybe_build_wrapper within lib/wrapper.exp. |
| # |
| # However, for us, ${tool} is "libgdiagnostics". |
| # Hence we load wrapper.exp with tool == "g++", so that |
| # g++_maybe_build_wrapper is defined. |
| set tool g++ |
| load_lib wrapper.exp |
| set tool libgdiagnostics |
| |
| load_lib dg.exp |
| load_lib prune.exp |
| load_lib target-supports.exp |
| load_lib gcc-defs.exp |
| load_lib timeout.exp |
| load_lib target-libpath.exp |
| load_lib gcc.exp |
| load_lib g++.exp |
| load_lib dejagnu.exp |
| load_lib target-supports-dg.exp |
| load_lib valgrind.exp |
| load_lib scansarif.exp |
| load_lib dg-test-cleanup.exp |
| |
| # The default do-what keyword. |
| set dg-do-what-default compile |
| |
| # Adapted from jit.exp. |
| # |
| # Execute the executable file. |
| # Returns: |
| # A "" (empty) string if everything worked, or an error message |
| # if there was a problem. |
| # |
| proc fixed_host_execute {args} { |
| global env |
| global text |
| global spawn_id |
| |
| verbose "fixed_host_execute: $args" |
| |
| set timeoutmsg "Timed out: Never got started, " |
| set timeout 100 |
| set file all |
| set timetol 0 |
| set arguments "" |
| |
| if { [llength $args] == 0} { |
| set executable $args |
| } else { |
| set executable [lindex $args 0] |
| set params [lindex $args 1] |
| } |
| |
| verbose "The executable is $executable" 2 |
| if {![file exists ${executable}]} { |
| perror "The executable, \"$executable\" is missing" 0 |
| return "No source file found" |
| } elseif {![file executable ${executable}]} { |
| perror "The executable, \"$executable\" is not usable" 0 |
| return "Bad executable found" |
| } |
| |
| verbose "params: $params" 2 |
| |
| # spawn the executable and look for the DejaGnu output messages from the |
| # test case. |
| # spawn -noecho -open [open "|./${executable}" "r"] |
| |
| # Run under valgrind if RUN_UNDER_VALGRIND is present in the environment. |
| # Note that it's best to configure gcc with --enable-valgrind-annotations |
| # when testing under valgrind. |
| set run_under_valgrind [info exists env(RUN_UNDER_VALGRIND)] |
| if $run_under_valgrind { |
| set valgrind_logfile "${executable}.valgrind.txt" |
| set valgrind_params {"valgrind"} |
| lappend valgrind_params "--leak-check=full" |
| lappend valgrind_params "--log-file=${valgrind_logfile}" |
| } else { |
| set valgrind_params {} |
| } |
| verbose "valgrind_params: $valgrind_params" 2 |
| |
| set args ${valgrind_params} |
| lappend args "./${executable}" |
| set args [concat $args ${params}] |
| verbose "args: $args" 2 |
| |
| set status [catch "exec -keepnewline $args" exe_output] |
| verbose "Test program returned $exe_output" 2 |
| |
| if $run_under_valgrind { |
| upvar 2 name name |
| parse_valgrind_logfile $name $valgrind_logfile fail |
| } |
| |
| # We don't do prune_gcc_output here, as we want |
| # to check *exactly* what we get from libgdiagnostics |
| |
| return $exe_output |
| } |
| |
| # (end of code from dejagnu.exp) |
| |
| # GCC_UNDER_TEST is needed by gcc_target_compile |
| global GCC_UNDER_TEST |
| if ![info exists GCC_UNDER_TEST] { |
| set GCC_UNDER_TEST "[find_gcc]" |
| } |
| |
| g++_init |
| |
| # Initialize dg. |
| dg-init |
| |
| # Gather a list of all tests. |
| |
| # C and C++ tests within the testsuite: gcc/testsuite/libgdiagnostics.dg/test-*.{c,c++} |
| set c_tests [find $srcdir/$subdir test-*.c] |
| set cxx_tests [find $srcdir/$subdir test-*.cc] |
| set tests [concat $c_tests $cxx_tests] |
| |
| verbose "tests: $tests" |
| |
| # Expand "SRCDIR" within ARG to the location of the top-level |
| # src directory |
| |
| proc diagnostics-expand-vars {arg} { |
| verbose "diagnostics-expand-vars: $arg" |
| global srcdir |
| verbose " srcdir: $srcdir" |
| # "srcdir" is that of the gcc/testsuite directory, so |
| # we need to go up two levels. |
| set arg [string map [list "SRCDIR" $srcdir/../..] $arg] |
| verbose " new arg: $arg" |
| return $arg |
| } |
| |
| # Parameters used when invoking the executables built from the test cases. |
| |
| global diagnostics-exe-params |
| set diagnostics-exe-params {} |
| |
| # Set "diagnostics-exe-params", expanding "SRCDIR" in each arg to the location of |
| # the top-level srcdir. |
| |
| proc dg-diagnostics-set-exe-params { args } { |
| verbose "dg-diagnostics-set-exe-params: $args" |
| |
| global diagnostics-exe-params |
| set diagnostics-exe-params {} |
| # Skip initial arg (line number) |
| foreach arg [lrange $args 1 [llength $args] ] { |
| lappend diagnostics-exe-params [diagnostics-expand-vars $arg] |
| } |
| } |
| |
| proc libgdiagnostics-dg-test { prog do_what extra_tool_flags } { |
| verbose "within libgdiagnostics-dg-test..." |
| verbose " prog: $prog" |
| verbose " do_what: $do_what" |
| verbose " extra_tool_flags: $extra_tool_flags" |
| |
| global dg-do-what-default |
| set dg-do-what [list ${dg-do-what-default} "" P] |
| |
| # If we're not supposed to try this test on this target, we're done. |
| if { [lindex ${dg-do-what} 1] == "N" } { |
| unsupported "$name" |
| verbose "$name not supported on this target, skipping it" 3 |
| return |
| } |
| |
| # Determine what to name the built executable. |
| # |
| # We simply append .exe to the filename, e.g. |
| # "test-foo.c.exe" |
| # since some testcases exist in both |
| # "test-foo.c" and |
| # "test-foo.cc" |
| # variants, and we don't want them to clobber each other's |
| # executables. |
| # |
| # This also ensures that the source name makes it into the |
| # pass/fail output, so that we can distinguish e.g. which test-foo |
| # is failing. |
| set output_file "[file tail $prog].exe" |
| verbose "output_file: $output_file" |
| |
| # Create the test executable: |
| set extension [file extension $prog] |
| if {$extension == ".cc"} { |
| set compilation_function "g++_target_compile" |
| } else { |
| set compilation_function "gcc_target_compile" |
| } |
| set options "{additional_flags=$extra_tool_flags}" |
| verbose "compilation_function=$compilation_function" |
| verbose "options=$options" |
| |
| set comp_output [$compilation_function $prog $output_file \ |
| "executable" $options] |
| upvar 1 name name |
| if ![libgdiagnostics_check_compile "$name" "initial compilation" \ |
| $output_file $comp_output] then { |
| return |
| } |
| |
| # Run the test executable. |
| |
| # We need to set LD_LIBRARY_PATH so that the test files can find |
| # libgdiagnostics.so |
| # Do this using set_ld_library_path_env_vars from target-libpath.exp |
| # We will restore the old value later using |
| # restore_ld_library_path_env_vars. |
| |
| # Unfortunately this API only supports a single saved value, rather |
| # than a stack, and g++_init has already called into this API, |
| # injecting the appropriate value for LD_LIBRARY_PATH for finding |
| # the built copy of libstdc++. |
| # Hence the call to restore_ld_library_path_env_vars would restore |
| # the *initial* value of LD_LIBRARY_PATH, and attempts to run |
| # a C++ testcase after running any prior testcases would thus look |
| # in the wrong place for libstdc++. This led to failures at startup |
| # of the form: |
| # ./tut01-hello-world.cc.exe: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./tut01-hello-world.cc.exe) |
| # when the built libstdc++ is more recent that the system libstdc++. |
| # |
| # As a workaround, reset the variable "orig_environment_saved" within |
| # target-libpath.exp, so that the {set|restore}_ld_library_path_env_vars |
| # API saves/restores the current value of LD_LIBRARY_PATH (as set up |
| # by g++_init). |
| global orig_environment_saved |
| set orig_environment_saved 0 |
| |
| global ld_library_path |
| global base_dir |
| set ld_library_path "$base_dir/../../" |
| set_ld_library_path_env_vars |
| |
| global diagnostics-exe-params |
| set args ${diagnostics-exe-params} |
| set diagnostics-exe-params {} |
| |
| set exe_output [fixed_host_execute $output_file $args ] |
| verbose "exe_output: $exe_output" |
| |
| restore_ld_library_path_env_vars |
| |
| # Analyze the output from the executable. To some what extent this |
| # is duplicating prune_gcc_output, but we're looking for *precise* |
| # output, so we can't reuse prune_gcc_output. |
| |
| global testname_with_flags |
| set testname_with_flags $name |
| |
| # Handle any freeform regexps. |
| set exe_output [handle-dg-regexps $exe_output] |
| |
| # Call into multiline.exp to handle any multiline output directives. |
| set exe_output [handle-multiline-outputs $exe_output] |
| |
| # Normally we would return $exe_output and $output_file to the |
| # caller, which would delete $output_file, the generated executable. |
| # If we need to debug, it's handy to be able to suppress this behavior, |
| # keeping the executable around. |
| |
| global env |
| set preserve_executables [info exists env(PRESERVE_EXECUTABLES)] |
| if $preserve_executables { |
| set output_file "" |
| } |
| |
| return [list $exe_output $output_file] |
| } |
| |
| set DEFAULT_CFLAGS "-I$srcdir/.. -lgdiagnostics -g -Wall -Werror" |
| |
| # Main loop. This will invoke jig-dg-test on each test-*.c file. |
| dg-runtest $tests "" $DEFAULT_CFLAGS |
| |
| # All done. |
| dg-finish |