diff options
author | Philip Herron <philip.herron@embecosm.com> | 2020-11-28 20:19:24 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2020-11-28 21:13:22 +0000 |
commit | f28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2 (patch) | |
tree | 96c155ee48eef74c82336f2b4da3b1a92381f549 /gcc | |
parent | 0db8774645244b08d0e0cd18275ea64ff96f6911 (diff) | |
download | gcc-f28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2.zip gcc-f28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2.tar.gz gcc-f28325125b7ea31e5cbfd3269a3ee6a4b79ddfd2.tar.bz2 |
Initial TestSuite setup for make check-rust
This is an initial basic testsuite with one file with expected failures
for now.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 6 | ||||
-rw-r--r-- | gcc/testsuite/lib/rust-dg.exp | 106 | ||||
-rw-r--r-- | gcc/testsuite/lib/rust.exp | 213 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/conditional.rs | 11 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/impl_block.rs | 14 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/static_function.rs | 7 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/struct_init.rs | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/type_infer1.rs | 19 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/rust-test.exp | 449 |
9 files changed, 832 insertions, 1 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 3293f90..d35b41f 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -30,7 +30,7 @@ GCCRS_INSTALL_NAME := $(shell echo gccrs|sed '$(program_transform_name)') GCCRS_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrs|sed '$(program_transform_name)') # Define the names for selecting rust in LANGUAGES. -rust: gccrs$(exeext) rust1$(exeext) +rust: rust1$(exeext) # Tell GNU make to ignore files by these names if they exist. .PHONY: rust @@ -88,6 +88,10 @@ rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) # Build hooks. +lang_checks += check-rust +lang_checks_parallelized += check-rust +check_rust_parallelize = 10 + # Copies its dependencies into the source directory. This generally should be used for generated files # such as Bison output files which are not version-controlled, but should be included in any release # tarballs. This target will be executed during a bootstrap if ‘--enable-generated-files-in-srcdir’ diff --git a/gcc/testsuite/lib/rust-dg.exp b/gcc/testsuite/lib/rust-dg.exp new file mode 100644 index 0000000..e7c9852 --- /dev/null +++ b/gcc/testsuite/lib/rust-dg.exp @@ -0,0 +1,106 @@ +# Copyright (C) 2012-2019 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +load_lib gcc-dg.exp + +# Define rust callbacks for dg.exp. + +proc rust-dg-test { prog do_what extra_tool_flags } { + upvar dg-do-what dg-do-what + + # Demote link and run tests to compile-only if D runtime is missing. + if ![check_effective_target_d_runtime] { + switch $do_what { + link - + run { + set do_what compile + set dg-do-what compile + } + } + } + + # Strip rust.test prefix off test names to avoid pathname failures in + # some tests. + set prog [dg-trim-dirname rust.test $prog] + + set result \ + [gcc-dg-test-1 rust_target_compile $prog $do_what $extra_tool_flags] + + set comp_output [lindex $result 0] + set output_file [lindex $result 1] + + return [list $comp_output $output_file] +} + +proc rust-dg-prune { system text } { + return [gcc-dg-prune $system $text] +} + +# Utility routines. + +# +# Modified dg-runtest that can cycle through a list of optimization options +# as c-torture does. +# + +proc rust-dg-runtest { testcases flags default-extra-flags } { + global runtests + + foreach test $testcases { + # If we're only testing specific files and this isn't one of + # them, skip it. + + if ![runtest_file_p $runtests $test] { + continue + } + + # Use TORTURE_OPTIONS to cycle through an option list. + if [torture-options-exist] then { + global torture_with_loops + set option_list $torture_with_loops + } else { + set option_list { "" } + } + + set nshort [file tail [file dirname $test]]/[file tail $test] + + foreach flags_t $option_list { + verbose "Testing $nshort, $flags $flags_t" 1 + dg-test $test "$flags $flags_t" ${default-extra-flags} + } + } +} + +# +# rust_load -- wrapper around default rust_load to handle tests that +# require program arguments passed to them. +# + +if { [info procs rust_load] != [list] \ + && [info procs prev_rust_load] == [list] } { + rename rust_load prev_rust_load + + proc rust_load { program args } { + global RUST_EXECUTE_ARGS + if [info exists RUST_EXECUTE_ARGS] then { + set args [concat "{$RUST_EXECUTE_ARGS}"] + } + #print "Running: $program [lindex $args 0]" + set result [eval [list prev_rust_load $program] $args ] + return $result + } +} + diff --git a/gcc/testsuite/lib/rust.exp b/gcc/testsuite/lib/rust.exp new file mode 100644 index 0000000..541b052 --- /dev/null +++ b/gcc/testsuite/lib/rust.exp @@ -0,0 +1,213 @@ +# Copyright (C) 2012-2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# +# rust support library routines +# + +load_lib prune.exp +load_lib gcc-defs.exp +load_lib timeout.exp +load_lib target-libpath.exp + +# +# RUST_UNDER_TEST is the compiler under test. +# + +set rust_compile_options "" + + +# +# rust_version -- extract and print the version number of the compiler +# + +proc rust_version { } { + global RUST_UNDER_TEST + + rust_init + + # ignore any arguments after the command + set compiler [lindex $RUST_UNDER_TEST 0] + + # verify that the compiler exists + if { [is_remote host] || [which $compiler] != 0 } then { + set tmp [remote_exec host "$compiler -v"] + set status [lindex $tmp 0] + set output [lindex $tmp 1] + regexp " version \[^\n\r\]*" $output version + if { $status == 0 && [info exists version] } then { + if [is_remote host] { + clone_output "$compiler $version\n" + } else { + clone_output "[which $compiler] $version\n" + } + } else { + clone_output "Couldn't determine version of $output [which $compiler]\n" + } + } else { + # compiler does not exist (this should have already been detected) + warning "$compiler does not exist" + } +} + +# +# rust_include_flags -- include flags for the gcc tree structure +# + +proc rust_include_flags { paths } { + global srcdir + global TESTING_IN_BUILD_TREE + + set flags "" + + if { [is_remote host] || ![info exists TESTING_IN_BUILD_TREE] } { + return "${flags}" + } + + set gccpath ${paths} + + return "$flags" +} + +# +# rust_link_flags -- linker flags for the gcc tree structure +# + +proc rust_link_flags { paths } { + global srcdir + global ld_library_path + global RUST_UNDER_TEST + global shlib_ext + global SHARED_OPTION + + set gccpath ${paths} + set libio_dir "" + set flags "" + set ld_library_path "." + set shlib_ext [get_shlib_extension] + set SHARED_OPTION "" + verbose "shared lib extension: $shlib_ext" + + set_ld_library_path_env_vars + + return "$flags" +} + +# +# rust_init -- called at the start of each subdir of tests +# + +proc rust_init { args } { + global subdir + global rust_initialized + global base_dir + global tmpdir + global libdir + global gluefile wrap_flags + global objdir srcdir + global ALWAYS_DFLAGS + global TOOL_EXECUTABLE TOOL_OPTIONS + global RUST_UNDER_TEST + global TESTING_IN_BUILD_TREE + global TEST_ALWAYS_FLAGS + global gcc_warning_prefix + global gcc_error_prefix + + # We set LC_ALL and LANG to C so that we get the same error messages as expected. + setenv LC_ALL C + setenv LANG C + + if ![info exists RUST_UNDER_TEST] then { + if [info exists TOOL_EXECUTABLE] { + set RUST_UNDER_TEST $TOOL_EXECUTABLE + } else { + if { [is_remote host] || ! [info exists TESTING_IN_BUILD_TREE] } { + set RUST_UNDER_TEST [transform gccrs] + } else { + set RUST_UNDER_TEST [findfile $base_dir/../../gccrs "$base_dir/../../gccrs -B$base_dir/../../" [findfile $base_dir/gccrs "$base_dir/gccrs -B$base_dir/" [transform gccrs]]] + } + } + } + + if ![is_remote host] { + if { [which $RUST_UNDER_TEST] == 0 } then { + perror "RUST_UNDER_TEST ($RUST_UNDER_TEST) does not exist" + exit 1 + } + } + if ![info exists tmpdir] { + set tmpdir "/tmp" + } + + if [info exists gluefile] { + unset gluefile + } + + rust_maybe_build_wrapper "${tmpdir}/rust-testglue.o" + + set ALWAYS_RUSTFLAGS "" + + # TEST_ALWAYS_FLAGS are flags that should be passed to every + # compilation. They are passed first to allow individual + # tests to override them. + if [info exists TEST_ALWAYS_FLAGS] { + lappend ALWAYS_DFLAGS "additional_flags=$TEST_ALWAYS_FLAGS" + } + + if ![is_remote host] { + if [info exists TOOL_OPTIONS] { + lappend ALWAYS_DFLAGS "additional_flags=[rust_include_flags [get_multilibs ${TOOL_OPTIONS}] ]" + lappend ALWAYS_DFLAGS "ldflags=[rust_link_flags [get_multilibs ${TOOL_OPTIONS}] ]" + } else { + lappend ALWAYS_DFLAGS "additional_flags=[rust_include_flags [get_multilibs] ]" + lappend ALWAYS_DFLAGS "ldflags=[rust_link_flags [get_multilibs] ]" + } + } + + if [info exists TOOL_OPTIONS] { + lappend ALWAYS_DFLAGS "additional_flags=$TOOL_OPTIONS" + } + + verbose -log "ALWAYS_DFLAGS set to $ALWAYS_DFLAGS" + + set gcc_warning_prefix "warning:" + set gcc_error_prefix "(fatal )?error:" + + verbose "rust is initialized" 3 +} + +# +# rust_target_compile -- compile a source file +# + +proc rust_target_compile { source dest type options } { + global tmpdir + global gluefile wrap_flags + global ALWAYS_DFLAGS + global RUST_UNDER_TEST + + if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } { + lappend options "libs=${gluefile}" + lappend options "ldflags=${wrap_flags}" + } + + lappend options "timeout=[timeout_value]" + lappend options "compiler=$RUST_UNDER_TEST" + + set options [concat "$ALWAYS_DFLAGS" $options] + set options [dg-additional-files-options $options $source] + return [target_compile $source $dest $type $options] +} diff --git a/gcc/testsuite/rust.test/compilable/conditional.rs b/gcc/testsuite/rust.test/compilable/conditional.rs new file mode 100644 index 0000000..2bb3a95 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/conditional.rs @@ -0,0 +1,11 @@ +fn main() { + let mut x = 5; + + if x == 5 { + x = 1; + } else if x == 3 { + x = 2; + } else { + x = 3; + } +} diff --git a/gcc/testsuite/rust.test/compilable/impl_block.rs b/gcc/testsuite/rust.test/compilable/impl_block.rs new file mode 100644 index 0000000..51ed74b --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/impl_block.rs @@ -0,0 +1,14 @@ +struct Foo { + one: i32, + two: i32, +} + +impl Foo { + fn new(a: i32, b: i32) -> Foo { + return Foo { one: a, two: b }; + } +} + +fn main() { + let cake = Foo::new(3, 4); +} diff --git a/gcc/testsuite/rust.test/compilable/static_function.rs b/gcc/testsuite/rust.test/compilable/static_function.rs new file mode 100644 index 0000000..7a564af --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/static_function.rs @@ -0,0 +1,7 @@ +fn test(x: i32) -> i32 { + return x + 1; +} + +fn main() { + let call_test = test(1); +} diff --git a/gcc/testsuite/rust.test/compilable/struct_init.rs b/gcc/testsuite/rust.test/compilable/struct_init.rs new file mode 100644 index 0000000..6081476 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/struct_init.rs @@ -0,0 +1,8 @@ +struct Foo { + one: i32, + two: i32, +} + +fn main() { + let struct_test = Foo { one: 1, two: 2 }; +} diff --git a/gcc/testsuite/rust.test/compilable/type_infer1.rs b/gcc/testsuite/rust.test/compilable/type_infer1.rs new file mode 100644 index 0000000..bc4b09a --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/type_infer1.rs @@ -0,0 +1,19 @@ +struct Foo { + one: i32, + two: i32, +} + +fn test(x: i32) -> i32 { + return x + 1; +} + +fn main() { + let logical: bool = true; + let an_integer = 5; + let mut default_integer = 7; + + default_integer = 1 + an_integer; + + let call_test = test(1); + let struct_test = Foo { one: 1, two: 2 }; +} diff --git a/gcc/testsuite/rust.test/rust-test.exp b/gcc/testsuite/rust.test/rust-test.exp new file mode 100644 index 0000000..fca3f16 --- /dev/null +++ b/gcc/testsuite/rust.test/rust-test.exp @@ -0,0 +1,449 @@ +# Copyright (C) 2012-2019 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# Test using the DMD testsuite. +# Load support procs. +load_lib rust-dg.exp + +# +# Convert DMD arguments to RUST equivalent +# + +proc rust-convert-args { args } { + set out "" + + foreach arg [split [lindex $args 0] " "] { + # List of switches kept in ASCII collated order. + if [string match "-D" $arg] { + lappend out "-fdoc" + + } elseif { [regexp -- {^-I([\w+/-]+)} $arg pattern path] } { + lappend out "-I$path" + + } elseif { [regexp -- {^-J([\w+/-]+)} $arg pattern path] } { + lappend out "-J$path" + + } elseif [string match "-allinst" $arg] { + lappend out "-fall-instantiations" + + } elseif [string match "-betterC" $arg] { + lappend out "-fno-druntime" + + } elseif { [string match "-boundscheck" $arg] + || [string match "-boundscheck=on" $arg] } { + lappend out "-fbounds-check" + + } elseif { [string match "-boundscheck=off" $arg] + || [string match "-noboundscheck" $arg] } { + lappend out "-fno-bounds-check" + + } elseif [string match "-boundscheck=safeonly" $arg] { + lappend out "-fbounds-check=safeonly" + + } elseif [string match "-c" $arg] { + lappend out "-c" + + } elseif [string match "-d" $arg] { + lappend out "-Wno-deprecated" + + } elseif [string match "-de" $arg] { + lappend out "-Wdeprecated" + lappend out "-Werror" + + } elseif [string match "-debug" $arg] { + lappend out "-fdebug" + + } elseif [regexp -- {^-debug=(\w+)} $arg pattern value] { + lappend out "-fdebug=$value" + + } elseif [string match "-dip1000" $arg] { + lappend out "-ftransition=dip1000" + + } elseif [string match "-dip25" $arg] { + lappend out "-ftransition=dip25" + + } elseif [string match "-dw" $arg] { + lappend out "-Wdeprecated" + lappend out "-Wno-error" + + } elseif [string match "-fPIC" $arg] { + lappend out "-fPIC" + + } elseif { [string match "-g" $arg] + || [string match "-gc" $arg] } { + lappend out "-g" + + } elseif [string match "-inline" $arg] { + lappend out "-finline-functions" + + } elseif [string match "-main" $arg] { + lappend out "-fmain" + + } elseif [regexp -- {^-mv=([\w+=./-]+)} $arg pattern value] { + lappend out "-fmodule-file=$value" + + } elseif [string match "-O" $arg] { + lappend out "-O2" + + } elseif [string match "-release" $arg] { + lappend out "-frelease" + + } elseif [regexp -- {^-transition=(\w+)} $arg pattern value] { + lappend out "-ftransition=$value" + + } elseif [string match "-unittest" $arg] { + lappend out "-funittest" + + } elseif [string match "-verrors=spec" $arg] { + lappend out "-Wspeculative" + + } elseif [regexp -- {^-verrors=(\d+)} $arg pattern num] { + lappend out "-fmax-errors=$num" + + } elseif [regexp -- {^-version=(\w+)} $arg pattern value] { + lappend out "-fversion=$value" + + } elseif [string match "-vtls" $arg] { + lappend out "-ftransition=tls" + + } elseif [string match "-w" $arg] { + lappend out "-Wall" + lappend out "-Werror" + + } elseif [string match "-wi" $arg] { + lappend out "-Wall" + lappend out "-Wno-error" + + } else { + # print "Unhandled Argument: $arg" + } + } + + return $out +} + +proc rust-copy-extra { base extra } { + # Split base, folder/file. + set type [file dirname $extra] + + # print "Filename: $base - $extra" + + set fdin [open $base/$extra r] + fconfigure $fdin -encoding binary + + file mkdir $type + set fdout [open $extra w] + fconfigure $fdout -encoding binary + + while { [gets $fdin copy_line] >= 0 } { + set out_line $copy_line + puts $fdout $out_line + } + + close $fdin + close $fdout + + # Remove file once test is finished. + upvar 2 cleanup_extra_files cleanups + lappend cleanups $extra + + return $extra +} + +# +# Translate DMD test directives to dejagnu equivalent. +# +# COMPILE_SEPARATELY: Not handled. +# EXECUTE_ARGS: Parameters to add to the execution of the test. +# COMPILED_IMPORTS: List of modules files that are imported by the main +# source file that should be included in compilation. +# Currently handled the same as EXTRA_SOURCES. +# EXTRA_SOURCES: List of extra sources to build and link along with +# the test. +# EXTRA_FILES: List of extra files to copy for the test runs. +# PERMUTE_ARGS: The set of arguments to permute in multiple compiler +# invocations. An empty set means only one permutation +# with no arguments. +# TEST_OUTPUT: The output expected from the compilation. +# POST_SCRIPT: Not handled. +# REQUIRED_ARGS: Arguments to add to the compiler command line. +# DISABLED: Not handled. +# + +proc dmd2dg { base test } { + global DEFAULT_DFLAGS + global PERMUTE_ARGS + global RUST_EXECUTE_ARGS + + set PERMUTE_ARGS $DEFAULT_DFLAGS + set RUST_EXECUTE_ARGS "" + + set extra_sources "" + set extra_files "" + + # Split base, folder/file. + set type [file dirname $test] + set name [file tail $test] + + print "Filename: $base - $test" + + set fdin [open $base/$test r] + #fconfigure $fdin -encoding binary + + file mkdir $type + set fdout [open $test w] + #fconfigure $fdout -encoding binary + + while { [gets $fdin copy_line] >= 0 } { + set out_line $copy_line + + if [regexp -- {COMPILE_SEPARATELY} $copy_line] { + # COMPILE_SEPARATELY is not handled. + regsub -- {COMPILE_SEPARATELY.*$} $copy_line "" out_line + + } elseif [regexp -- {DISABLED} $copy_line] { + # DISABLED is not handled. + regsub -- {DISABLED.*$} $copy_line "" out_line + + } elseif [regexp -- {POST_SCRIPT} $copy_line] { + # POST_SCRIPT is not handled + regsub -- {POST_SCRIPT.*$} $copy_line "" out_line + + } elseif [regexp -- {PERMUTE_ARGS\s*:\s*(.*)} $copy_line match args] { + # PERMUTE_ARGS is handled by rust-do-test. + set PERMUTE_ARGS [rust-convert-args $args] + regsub -- {PERMUTE_ARGS.*$} $copy_line "" out_line + + } elseif [regexp -- {EXECUTE_ARGS\s*:\s*(.*)} $copy_line match args] { + # EXECUTE_ARGS is handled by rust_load. + foreach arg $args { + lappend RUST_EXECUTE_ARGS $arg + } + regsub -- {EXECUTE_ARGS.*$} $copy_line "" out_line + + } elseif [regexp -- {REQUIRED_ARGS\s*:\s*(.*)} $copy_line match args] { + # Convert all listed arguments to from dmd to rust-style. + set new_option "{ dg-additional-options \"[rust-convert-args $args]\" }" + regsub -- {REQUIRED_ARGS.*$} $copy_line $new_option out_line + + } elseif [regexp -- {EXTRA_SOURCES\s*:\s*(.*)} $copy_line match sources] { + # EXTRA_SOURCES are appended to extra_sources list + foreach srcfile $sources { + lappend extra_sources $srcfile + } + regsub -- {EXTRA_SOURCES.*$} $copy_line "" out_line + + } elseif [regexp -- {EXTRA_CPP_SOURCES\s*:\s*(.*)} $copy_line match sources] { + # EXTRA_CPP_SOURCES are appended to extra_sources list + foreach srcfile $sources { + # C++ sources are found in the extra-files directory. + lappend extra_sources "extra-files/$srcfile" + } + regsub -- {EXTRA_CPP_SOURCES.*$} $copy_line "" out_line + + } elseif [regexp -- {EXTRA_FILES\s*:\s*(.*)} $copy_line match files] { + # EXTRA_FILES are appended to extra_files list + foreach file $files { + lappend extra_files $file + } + regsub -- {EXTRA_FILES.*$} $copy_line "" out_line + + } elseif [regexp -- {COMPILED_IMPORTS\s*:\s*(.*)} $copy_line match sources] { + # COMPILED_IMPORTS are appended to extra_sources list + foreach import $sources { + lappend extra_sources $import + } + regsub -- {COMPILED_IMPORTS.*$} $copy_line "" out_line + + } + + puts $fdout $out_line + } + + # Now that all extra sources and files have been collected, copy them all + # to the testsuite build directory. + if { [llength $extra_sources] > 0 } { + foreach srcfile $extra_sources { + rust-copy-extra $base "$type/$srcfile" + } + set out_line "// { dg-additional-sources \"$extra_sources\" }" + puts $fdout $out_line + } + + if { [llength $extra_files] > 0 } { + foreach file $extra_files { + rust-copy-extra $base "$type/$file" + } + set out_line "// { dg-additional-files \"$extra_files\" }" + puts $fdout $out_line + } + + # Add specific options for test type + + # DMD's testsuite is extremely verbose, compiler messages from constructs + # such as pragma(msg, ...) would otherwise cause tests to fail. + set out_line "// { dg-prune-output .* }" + puts $fdout $out_line + + # Compilable files are successful if an output is generated. + # Fail compilable are successful if an output is not generated. + # Runnable must compile, link, and return 0 to be successful by default. + switch $type { + runnable { + if ![isnative] { + set out_line "// { dg-final { output-exists } }" + puts $fdout $out_line + } + } + + compilable { + set out_line "// { dg-final { output-exists } }" + puts $fdout $out_line + + # Check that Ddoc tests also generate a html file. + if [regexp -- "ddoc.*" $name] { + set ddocfile "[file rootname $name].html" + set out_line "// { dg-final { scan-file $ddocfile \"Generated by Ddoc from $test\" } }" + puts $fdout $out_line + # Cleanup extra generated files. + set out_line "// { dg-final { file delete $ddocfile } }" + puts $fdout $out_line + } + } + + fail_compilation { + set out_line "// { dg-final { output-exists-not } }" + puts $fdout $out_line + } + } + + close $fdin + close $fdout + + return $test +} + +proc rust-permute-options { options } { + set result { } + set n [expr 1<<[llength $options]] + for { set i 0 } { $i<$n } { incr i } { + set option "" + for { set j 0 } { $j<[llength $options] } { incr j } { + if [expr $i & 1 << $j] { + append option [lindex $options $j] + append option " " + } + } + lappend result $option + + } + return $result +} + + +proc rust-do-test { } { + global srcdir subdir + global dg-do-what-default + global verbose + + # If a testcase doesn't have special options, use these. + global DEFAULT_DFLAGS + if ![info exists DEFAULT_DFLAGS] then { + set DEFAULT_DFLAGS "-g -O2" + } + + # These are special options to use on testcase, and override DEFAULT_DFLAGS + global PERMUTE_ARGS + + # Set if an extra option should be passed to link to shared druntime. + global SHARED_OPTION + + # Additional arguments for rust_load + global RUST_EXECUTE_ARGS + + # Initialize `dg'. + dg-init + + # Allow blank linkes in output for all of rust.test. + global allow_blank_lines + set save_allow_blank_lines $allow_blank_lines + if { !$allow_blank_lines } { + set allow_blank_lines 2 + } + + # Create rust.test link so test names include that subdir. + catch { file link $subdir . } + + # Main loop. + + # set verbose 1 + # set dg-final-code "" + # Find all tests and pass to routine. + foreach test [lsort [find $srcdir/$subdir *]] { + regexp -- "(.*)/(.+)/(.+)\.rs$" $test match base dir name ext + set ext "rs" + + # Skip invalid test directory + if { [lsearch "compilable" $dir] == -1 } { + continue + } + + # Skip invalid test extensions + if { [lsearch "rs" $ext] == -1 } { + continue + } + + # Convert to DG test. + set imports [format "-I%s/%s" $base $dir] + set cleanup_extra_files "" + # Include $subdir prefix so test names follow DejaGnu conventions. + set filename "$subdir/[dmd2dg $base $dir/$name.$ext]" + + if { $dir == "runnable" } { + append PERMUTE_ARGS " $SHARED_OPTION" + } + set options [rust-permute-options [lsort -unique $PERMUTE_ARGS]] + + switch $dir { + compilable { + for { set i 0 } { $i<[llength $options] } { incr i } { + set flags [lindex $options $i] + # Compilable test may require checking another kind of output file. + if [regexp -- "ddoc.*" $name] { + set dg-do-what-default "compile" + } else { + set dg-do-what-default "assemble" + } + rust-dg-runtest $filename $flags $imports + } + } + } + + # Cleanup test directory. + foreach srcfile $cleanup_extra_files { + file delete $subdir/$srcfile + } + file delete $filename + } + + set allow_blank_lines $save_allow_blank_lines + + # All done. + dg-finish +} + +rust-do-test + |