diff options
Diffstat (limited to 'testsuite')
-rw-r--r-- | testsuite/lib/bohman_ssd.exp | 225 | ||||
-rw-r--r-- | testsuite/lib/report-card.exp | 39 | ||||
-rw-r--r-- | testsuite/report-card.all/onetest.exp | 209 | ||||
-rw-r--r-- | testsuite/report-card.all/passes.exp | 276 |
4 files changed, 749 insertions, 0 deletions
diff --git a/testsuite/lib/bohman_ssd.exp b/testsuite/lib/bohman_ssd.exp new file mode 100644 index 0000000..25b1072 --- /dev/null +++ b/testsuite/lib/bohman_ssd.exp @@ -0,0 +1,225 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu 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. +# +# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +# This file was written by Jacob Bachmeyer. + +# This library provides functions for generating subset-sum-distinct sets +# using a construction published by Tom Bohman in: +# T. Bohman, A construction for sets of integers with distinct subset sums, +# The Electronic. Journal of Combinatorics 5 (1998) /#R3 +# <URL:http://www.combinatorics.org/Volume_5/PDF/v5i1r3.pdf>, +# retrieved 2018-12-28 SHA-1 1c35035427b3406a44f7290f13ec8fbc3d105041 +namespace eval ::math_utils::Bohman_SSD { + + # b_n(i) + proc b { n i } { + if { $n <= 1 } { error "invalid parameter n: $n" } + if { $i <= 2*$n } { error "invalid parameter i: $i" } + + if { $i >= 2*$n + 4 } { + return [expr { round(sqrt(2*($i + 2 - 2*$n))) }] + } elseif { $i == 2*$n + 3 } { + return [expr { $n + 2 }] + } else { # $i == 2*$n + 1 || $i == 2*$n + 2 + return [expr { $n + 1 }] + } + } + + variable d_memo + array unset d_memo + array set d_memo {} + + # d_n(i) + proc d { n i } { + variable d_memo + if { [info exists d_memo($n,$i)] } { return $d_memo($n,$i) } + + if { $n <= 1 } { error "invalid parameter n: $n" } + if { $i < 1 } { error "invalid parameter i: $i" } + + if { $i == $n } { + return 1 + } elseif { $i < $n } { + set j [expr { $n - $i }] + return [expr { 2 * round(pow(4,($j - 1))) }] + } elseif { $i <= 2*$n } { + set j [expr { $i - $n }] + return [expr { round(pow(4,($j - 1))) }] + } else { # $i > 2*$n + set sum 0 + for { set j [expr { $i - [b $n $i] }] } { $j < $i } { incr j } { + incr sum [d $n $j] + } + set d_memo($n,$i) $sum + return $sum + } + } + + # S_{n,m} returns list + proc S { n m } { + if { $n <= 1 } { error "invalid parameter n: $n" } + if { $m < 2*$n } { error "invalid parameter m: $m" } + + set dv [list] + for { set i 1 } { $i <= $m } { incr i } { lappend dv [d $n $i] } + set sum 0 + foreach d $dv { incr sum $d } + set result [list] + foreach d $dv { + lappend result $sum + incr sum -$d + } + return $result + } + + # b'_n(i) + proc bp { n i } { + if { $n < 1 } { error "invalid parameter n: $n" } + if { $i <= 2*$n + 1 } { error "invalid parameter i: $i" } + + if { $i >= 2*$n + 5 } { + return [expr { round(sqrt(2*($i + 1 - 2*$n))) }] + } elseif { $i == 2*$n + 2 } { + return [expr { $n + 1 }] + } else { # $i == 2*$n + 3 || $i == 2*$n + 4 + return [expr { $n + 2 }] + } + } + + variable dp_memo + array unset dp_memo + array set dp_memo {} + + # d'_n(i) + proc dp { n i } { + variable dp_memo + if { [info exists dp_memo($n,$i)] } { return $dp_memo($n,$i) } + + if { $n < 1 } { error "invalid parameter n: $n" } + if { $i < 1 } { error "invalid parameter i: $i" } + + if { $i == $n + 1 } { + return 1 + } elseif { $i < $n + 1 } { + set j [expr { $n + 1 - $i }] + return [expr { round(pow(4,($j - 1))) }] + } elseif { $i <= 2*$n + 1 } { + set j [expr { $i - $n - 1 }] + return [expr { 2 * round(pow(4,($j - 1))) }] + } else { # $i > 2*$n + 1 + set sum 0 + for { set j [expr { $i - [bp $n $i] }] } { $j < $i } { incr j } { + incr sum [dp $n $j] + } + set dp_memo($n,$i) $sum + return $sum + } + } + # The example for d'_3 in the paper is wrong starting at i=11. The + # paper says that it is 200, but it is actually 300. + + # S'_{n,m} returns list + proc Sp { n m } { + if { $n < 1 } { error "invalid parameter n: $n" } + if { $m < 2*$n + 1 } { error "invalid parameter m: $m" } + + set dv [list] + for { set i 1 } { $i <= $m } { incr i } { lappend dv [dp $n $i] } + set sum 0 + foreach d $dv { incr sum $d } + set result [list] + foreach d $dv { + lappend result $sum + incr sum -$d + } + return $result + } + + # Given a list of numbers, verify that all sums of all subsets are in + # fact unique. + # + # This is a brute force search and not based on Bohman's paper. This + # quickly becomes impractical for large lists, requiring inordinate + # amounts of both time and space. + proc check { base } { + set bound [expr { int(pow(2,[llength $base])) }] + for { set i 0 } { $i < $bound } { incr i } { + set R $i + set sum 0 + foreach v $base { + if { $R & 1 } { incr sum $v } + set R [expr { $R >> 1 }] + } + if { [info exists output($sum)] } { + # emit counterexample + set cexl [list] + set R $i + foreach v $base { + if { $R & 1 } { lappend cexl $v } + set R [expr { $R >> 1 }] + } + set cex [join $cexl "+"] + append cex "=" $sum "=" + set cexl [list] + set R $output($sum) + foreach v $base { + if { $R & 1 } { lappend cexl $v } + set R [expr { $R >> 1 }] + } + append cex [join $cexl "+"] + error "list is not subset-sum-distinct: $cex" + } + set output($sum) $i + } + return 1 + } + + # Given a list of numbers and a sum of a subset of that list, find a + # subset that produces the given sum. If the list of numbers is + # subset-sum-distinct, this will return the unique solution. + # Otherwise, an unspecified solution is returned. If the sum is not + # actually a sum of a subset of the list, an empty list is returned. + # + # This is a brute force search and not based on Bohman's paper. This + # requires constant space, but quickly becomes impractical for large + # lists, requiring inordinate time to complete. + proc summands { base goal } { + set bound [expr { int(pow(2,[llength $base])) }] + for { set i 0 } { $i < $bound } { incr i } { + set R $i + set sum 0 + foreach v $base { + if { $R & 1 } { incr sum $v } + set R [expr { $R >> 1 }] + } + if { $sum == $goal } { + set resl [list] + set R $i + foreach v $base { + if { $R & 1 } { lappend resl $v } + set R [expr { $R >> 1 }] + } + return $resl + } + } + return [list] + } + +} + +#EOF diff --git a/testsuite/lib/report-card.exp b/testsuite/lib/report-card.exp new file mode 100644 index 0000000..7fa8838 --- /dev/null +++ b/testsuite/lib/report-card.exp @@ -0,0 +1,39 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu 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. +# +# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +# This file was written by Jacob Bachmeyer. + +# Ensure that the dejagnu(1) launcher is available for testing. +if { ![info exists LAUNCHER] } { + set LAUNCHER \ + [file join [file dirname [testsuite file -source -top]] dejagnu] +} +verbose "Using LAUNCHER $LAUNCHER" 2 + +if { [which $LAUNCHER] == 0 } { + perror "Can't find LAUNCHER = $LAUNCHER" + exit 2 +} + +# stub: dejagnu-report-card is non-interactive +proc report-card_exit {} {} + +# stub: dejagnu-report-card does not have a separate version number +proc report-card_version {} {} + +#EOF diff --git a/testsuite/report-card.all/onetest.exp b/testsuite/report-card.all/onetest.exp new file mode 100644 index 0000000..b2ae814 --- /dev/null +++ b/testsuite/report-card.all/onetest.exp @@ -0,0 +1,209 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu 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. +# +# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +# This file was written by Jacob Bachmeyer. + +set header_column_names { PASS FAIL ?PASS ?FAIL UNSUP UNRES UNTEST } +set separator_count 0 +set re_digit_columns {} +for { set i 0 } { $i < 7 } { incr i } { + append re_digit_columns {[[:space:]]+([[:digit:]]+)} +} + +set test_names { pass fail kpass kfail xpass xfail + unsupported unresolved untested + note warning error } +set test_results { PASS FAIL KPASS KFAIL XPASS XFAIL + UNSUPPORTED UNRESOLVED UNTESTED + NOTE WARNING ERROR } + +foreach name $test_names result $test_results { + set fd [open [testsuite file -object -test onetest one-${name}.sum] w] + puts $fd "${result}: one test" + close $fd +} + +set stty_init { -onlcr -onlret } + +spawn /bin/sh -c \ + "cd [testsuite file -object -test onetest]\ + && exec $LAUNCHER report-card" + +# check header +expect { + -re {^[[:space:]]+_+[\r\n]+} { + # discard initial header line + exp_continue + } + -re {^[[:space:]]+/([^\r\n]*)[\r\n]+} { + # check column labels + foreach want $header_column_names have $expect_out(1,string) { + if { $have eq $want } { + pass "header item $want" + } else { + fail "header item $want" + } + } + exp_continue + } + -re {^[[:space:]]+\|-+[\r\n]+} { + incr separator_count + } +} + +# check results +array unset scoreboard +array set scoreboard { + pass 0 fail 0 kpass 0 kfail 0 xpass 0 xfail 0 + unsupported 0 unresolved 0 untested 0 + note 0 warning 0 error 0 +} +array unset column_subexp_map +array set column_subexp_map { + pass 2 fail 3 kpass 4 kfail 5 xpass 4 xfail 5 + unsupported 6 unresolved 7 untested 8 + note 0 warning 9 error 9 +} +set re_table_row {^[[:space:]]*one-([[:alpha:]]+)[[:space:]]+\|} +append re_table_row $re_digit_columns +append re_table_row {((?:[[:space:]]+![EW]!)*)[\r\n]+} +expect { + -re $re_table_row { + for { set i 2 } { $i < 9 } { incr i } { + if { $expect_out($i,string)\ + == ( $i == $column_subexp_map($expect_out(1,string))\ + ? 1 : 0 ) } { + incr scoreboard($expect_out(1,string)) + } else { + incr scoreboard($expect_out(1,string)) -1 + } + } + set have_warning_tag [string match "*!W!*" $expect_out(9,string)] + set have_error_tag [string match "*!E!*" $expect_out(9,string)] + if { $column_subexp_map($expect_out(1,string)) == 9 } { + # testing an after-row tag + switch -- $expect_out(1,string) { + warning { + incr scoreboard(warning) \ + [expr { $have_warning_tag ? 1 : -1 }] + incr scoreboard(error) \ + [expr { $have_error_tag ? -1 : 1 }] + } + error { + incr scoreboard(warning) \ + [expr { $have_warning_tag ? -1 : 1 }] + incr scoreboard(error) \ + [expr { $have_error_tag ? 1 : -1 }] + } + default { error "unknown tag $expect_out(1,string)" } + } + } else { + incr scoreboard(warning) [expr { $have_warning_tag ? -1 : 1 }] + incr scoreboard(error) [expr { $have_error_tag ? -1 : 1 }] + } + exp_continue + } + -re {^[[:space:]]+\|-+[\r\n]+} { + incr separator_count + } +} +foreach result [lsort [array names scoreboard]] { + verbose -log "scoreboard($result) = $scoreboard($result)" +} +foreach result [array names scoreboard] { + if { $scoreboard($result) == ( 7 + ( $column_subexp_map($result) == 9\ + ? [llength $test_names] : 0 ) ) } { + pass "count result $result" + } else { + fail "count result $result" + } +} + +# check totals +set column_totals { pad 1 1 2 2 1 1 1 } +set re_totals_row {^[[:space:]]+\|} +append re_totals_row $re_digit_columns +append re_totals_row {[\r\n]+} +set totals_matched 0 +expect { + -re $re_totals_row { + for { set i 1 } { $i < 8 } { incr i } { + if { [lindex $column_totals $i] == $expect_out($i,string) } { + incr totals_matched + } + } + exp_continue + } + -re {^[[:space:]]+\|-+[\r\n]+} { + incr separator_count + } + -re {^[[:space:]]+\\_+[\r\n]+} { + # all done + } +} + +if { $totals_matched == 7 } { + pass "expected total count" +} else { + fail "expected total count" +} + +if { $separator_count == 2 } { + pass "expected separator lines" +} else { + fail "expected separator lines" +} + +# Ensure that totals map correctly by reading each file one at a time +foreach name $test_names { + set separator_count 0 + spawn /bin/sh -c \ + "cd [testsuite file -object -test onetest]\ + && exec $LAUNCHER report-card one-${name}.sum" + # skip header + expect { + -re {^[[:space:]]+_+[\r\n]+} { exp_continue } + -re {^[[:space:]]+/([^\r\n]*)[\r\n]+} { exp_continue } + -re {^[[:space:]]+\|-+[\r\n]+} { incr separator_count } + } + # capture the item line + expect -re {^one-[^|]+(\|[[:space:][:digit:]]*)[[:space:]!EW]*[\r\n]+} { + regsub {[[:space:]]*$} $expect_out(1,string) "" item_line + } + # skip the separator + expect -re {^[[:space:]]+\|-+[\r\n]+} { incr separator_count } + # capture the totals line + expect -re {^[[:space:]]+(\|[[:space:][:digit:]]*)[\r\n]+} { + regsub {[[:space:]]*$} $expect_out(1,string) "" totals_line + } + # skip the footer + expect -re {.+} { exp_continue } + # do the item and totals lines match? + if { $item_line eq $totals_line } { + pass "verify total for $name" + } else { + fail "verify total for $name" + } + if { $separator_count == 2 } { + pass "expected separator lines for $name" + } else { + fail "expected separator lines for $name" + } +} + +#EOF diff --git a/testsuite/report-card.all/passes.exp b/testsuite/report-card.all/passes.exp new file mode 100644 index 0000000..012e9ac --- /dev/null +++ b/testsuite/report-card.all/passes.exp @@ -0,0 +1,276 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu 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. +# +# DejaGnu 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 DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +# This file was written by Jacob Bachmeyer. + +load_lib bohman_ssd.exp + +set header_column_names { PASS FAIL ?PASS ?FAIL UNSUP UNRES UNTEST } +set result_column_map { + PASS FAIL { KPASS XPASS } { KFAIL XFAIL } + UNSUPPORTED UNRESOLVED UNTESTED +} + +set test_results { PASS FAIL KPASS KFAIL XPASS XFAIL + UNSUPPORTED UNRESOLVED UNTESTED } + +# each entry: { {mode n} { suffix_tag... } { pass... } { { result name }... } } +array unset tuplemap +array set tuplemap { + basic { {S 3} { a b } { foo bar } + { { PASS pass } { FAIL fail } } } + kxpass { {S 2} { a b } { foo bar } + { { KPASS kpass } { XPASS xpass } } } + kxfail { {Sp 2} { a b } { foo bar } + { { KFAIL kfail } { XFAIL xfail } } } + unresult { {S 2} { a b } { foo bar } + { { UNSUPPORTED unsupported } + { UNRESOLVED unresolved } { UNTESTED untested } } } +} + +# Given: TUPLES: { { result ... }... }, PASSES: { pass... } +# Return: Cartesian product TUPLES x PASSES: { { result pass ... }... } +proc build_tuple_list { tuples passes } { + set result [list] + foreach cell $tuples { + foreach pass $passes { + lappend result [linsert $cell 1 $pass] + } + } + return $result +} + +# Given: TUPLES: { { result pass name }... }, MODE: S | Sp, N +# Return: { { result pass name count }... } where COUNT is from an SSD-set +proc annotate_tuple_list { tuples mode n } { + set m [llength $tuples] + set ssd [switch -- $mode { + S { ::math_utils::Bohman_SSD::S $n $m } + Sp { ::math_utils::Bohman_SSD::Sp $n $m } + }] + set result [list] + foreach cell $tuples ssdterm $ssd { + lappend result [linsert $cell end $ssdterm] + } + return $result +} + +# Given: TUPLES: { { result pass name count }... }; (RESULT,PASS) not unique +# Return: { { result pass expected_total }... } where (RESULT,PASS) is unique +proc compute_expected_pass_totals { tuples } { + foreach cell $tuples { set count([lrange $cell 0 1]) 0 } + foreach cell $tuples { incr count([lrange $cell 0 1]) [lindex $cell 3] } + set result [list] + foreach name [lsort [array names count]] { + lappend result [concat $name $count($name)] + } + return $result +} + +# Given: TUPLES: { { result pass name count }... }; (RESULT,PASS) not unique +# Return: { { result expected_grand_total }... } +proc compute_expected_grand_totals { tuples } { + foreach cell $tuples { set count([lindex $cell 0]) 0 } + foreach cell $tuples { incr count([lindex $cell 0]) [lindex $cell 3] } + set result [list] + foreach name [lsort [array names count]] { + lappend result [list $name $count($name)] + } + return $result +} + +# Given: TUPLES: { { result pass ... }... } where (RESULT,PASS) repeats later +# Return: { { { result pass ... }... }... }; (RESULT,PASS) unique per sublist +proc split_tuple_list { tuples } { + set result [list] + set sublist [list] + foreach cell $tuples { + if { [info exists seen([lrange $cell 0 1])] } { + # split here + lappend result $sublist + set sublist [list] + array unset seen + } + lappend sublist $cell + set seen([lrange $cell 0 1]) 1 + } + lappend result $sublist + return $result +} + +# TUPLES is: { { result pass name count }... } +proc write_file { basename tuples } { + set fd [open [testsuite file -object -test passes ${basename}.sum] w] + set pass {} + foreach cell [lsort -index 1 $tuples] { + if { $pass ne [lindex $cell 1] } { + puts $fd "Running pass `[lindex $cell 1]' ..." + set pass [lindex $cell 1] + } + for { set i 1 } { $i <= [lindex $cell 3] } { incr i } { + puts $fd "[lindex $cell 0]: [lindex $cell 1]:\ + [lindex $cell 2] test ${i}/[lindex $cell 3]" + } + } + close $fd +} + +proc run_multipass_output_test { filetag } { + global LAUNCHER + global header_column_names + global result_column_map + global test_results + global tuplemap + + set ssdpar [lindex $tuplemap($filetag) 0] + set tags [lindex $tuplemap($filetag) 1] + set passes [lindex $tuplemap($filetag) 2] + set results {} + foreach dummy $tags { lappend results [lindex $tuplemap($filetag) 3] } + set results [join $results] + + # initialize totals arrays to zero + foreach result $test_results { set have_grand_totals($result) 0 } + array set want_grand_totals [array get have_grand_totals] + foreach cell [build_tuple_list $test_results $passes] { + set have_pass_totals([join [lrange $cell 0 1] ","]) 0 + } + array set want_pass_totals [array get have_pass_totals] + + # get the test list + set list [build_tuple_list $results $passes] + set list [annotate_tuple_list $list [lindex $ssdpar 0] [lindex $ssdpar 1]] + + # compute expected totals + # note that this only fills non-zero array positions + foreach cell [compute_expected_pass_totals $list] { + set want_pass_totals([join [lrange $cell 0 1] ","]) [lindex $cell 2] + } + array set want_grand_totals [join [compute_expected_grand_totals $list]] + + # write the test data files and store expected per-file counts + foreach tag $tags fileset [split_tuple_list $list] { + # write test file + write_file "${filetag}-${tag}" $fileset + # initialize test results for this file + foreach result $test_results { + foreach pass $passes { + set want_file_counts(${filetag}-${tag},$result,$pass) 0 + set have_file_counts(${filetag}-${tag},$result,$pass) 0 + } + } + # store expected results for this file + foreach cell $fileset { + set want_file_counts(${filetag}-${tag},[join [lrange $cell 0 1] \ + ","]) [lindex $cell 3] + } + } + + # run the dejagnu-report-card tool + set separator_count 0 + spawn /bin/sh -c \ + "cd [testsuite file -object -test passes]\ + && exec $LAUNCHER report-card ${filetag}-*.sum" + + # skip header + expect { + -re {^[[:space:]]+_+[\r\n]+} { exp_continue } + -re {^[[:space:]]+/([^\r\n]*)[\r\n]+} { exp_continue } + -re {^[[:space:]]+\|-+[\r\n]+} { incr separator_count } + } + + # read individual file lines + set re_file_row {^[[:space:]]*} + append re_file_row {(} $filetag {-[[:alpha:]]+)[[:space:]]+} + append re_file_row {/[[:space:]]+([[:alpha:]]+)[[:space:]]+\|} + append re_file_row {[[:space:]]*([[:digit:][:space:]]+)[\r\n]+} + expect { + -re $re_file_row { + foreach column $result_column_map colname $header_column_names \ + have $expect_out(3,string) { + set want 0 + foreach rs $column { + set tmp $expect_out(1,string),$rs,$expect_out(2,string) + incr want $want_file_counts($tmp) + } + if { $have == $want } { + pass "count $colname\ + for pass $expect_out(2,string)\ + in file $expect_out(1,string)" + } else { + fail "count $colname\ + for pass $expect_out(2,string)\ + in file $expect_out(1,string)" + } + } + exp_continue + } + -re {^[[:space:]]+\|-+[\r\n]+} { incr separator_count } + } + + # read pass totals lines + set re_pass_row {^[[:space:]]+([[:alpha:]]+)[[:space:]]+\|} + append re_pass_row {[[:space:]]*([[:digit:][:space:]]+)[\r\n]+} + expect { + -re $re_pass_row { + foreach column $result_column_map colname $header_column_names \ + have $expect_out(2,string) { + set want 0 + foreach rs $column { + incr want $want_pass_totals($rs,$expect_out(1,string)) + } + if { $have == $want } { + pass "total $colname for pass $expect_out(1,string)" + } else { + fail "total $colname for pass $expect_out(1,string)" + } + } + exp_continue + } + -re {^[[:space:]]+\|-+[\r\n]+} { incr separator_count } + } + + # read grand totals line + expect -re {^[[:space:]]+\|[[:space:]]*([[:digit:][:space:]]+)[\r\n]+} { + foreach column $result_column_map colname $header_column_names \ + have $expect_out(1,string) { + set want 0 + foreach rs $column { incr want $want_grand_totals($rs) } + if { $have == $want } { + pass "grand total $colname" + } else { + fail "grand total $colname" + } + } + } + + # skip the footer + expect -re {.+} { exp_continue } + + if { $separator_count == 3 } { + pass "expected separator lines" + } else { + fail "expected separator lines" + } +} + +foreach filetag [lsort [array names tuplemap]] { + run_multipass_output_test $filetag +} + +#EOF |