aboutsummaryrefslogtreecommitdiff
path: root/testsuite
diff options
context:
space:
mode:
authorJacob Bachmeyer <jcb62281@gmail.com>2019-01-02 22:48:20 +1100
committerBen Elliston <bje@gnu.org>2019-01-02 22:48:20 +1100
commitdc67c894db920e8f145de970ac2e61396d8db9db (patch)
tree64c09e5a1d95bf68b5737f057f716db3dad0ef45 /testsuite
parentb51a38c4410bbff17d4296fcb1fda13313b251ac (diff)
downloaddejagnu-dc67c894db920e8f145de970ac2e61396d8db9db.zip
dejagnu-dc67c894db920e8f145de970ac2e61396d8db9db.tar.gz
dejagnu-dc67c894db920e8f145de970ac2e61396d8db9db.tar.bz2
* NEWS: Document report card.
* Makefile.am (clean-local): Add target. (clean-local-check): Add target; mark as PHONY. (commands_DATA): Add "report-card" scripts. (dist_man_MANS): Add dejagnu-report-card.1 and split. (DEJATOOL): Add "report-card" tool. (TESTSUITE_FILES): Add testsuite for "report-card" tool. * commands/report-card.awk: New command script. * doc/dejagnu.texi (Invoking dejagnu report card): New node. * doc/dejagnu-report-card.1: New man page. * testsuite/lib/bohman_ssd.exp: New file. * testsuite/lib/report-card.exp: New file. * testsuite/report-card.all/onetest.exp: New file. * testsuite/report-card.all/passes.exp: New file. Signed-off-by: Ben Elliston <bje@gnu.org>
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/lib/bohman_ssd.exp225
-rw-r--r--testsuite/lib/report-card.exp39
-rw-r--r--testsuite/report-card.all/onetest.exp209
-rw-r--r--testsuite/report-card.all/passes.exp276
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