Home | History | Annotate | Line # | Download | only in lib
check-test-names.exp revision 1.1
      1  1.1  christos # Copyright 2020 Free Software Foundation, Inc.
      2  1.1  christos 
      3  1.1  christos # This program is free software; you can redistribute it and/or modify
      4  1.1  christos # it under the terms of the GNU General Public License as published by
      5  1.1  christos # the Free Software Foundation; either version 3 of the License, or
      6  1.1  christos # (at your option) any later version.
      7  1.1  christos #
      8  1.1  christos # This program is distributed in the hope that it will be useful,
      9  1.1  christos # but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  1.1  christos # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  1.1  christos # GNU General Public License for more details.
     12  1.1  christos #
     13  1.1  christos # You should have received a copy of the GNU General Public License
     14  1.1  christos # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  1.1  christos 
     16  1.1  christos # This library provides some protection against the introduction of
     17  1.1  christos # tests that include either the source of build paths in the test
     18  1.1  christos # name.  When a test includes the path in its test name it is harder
     19  1.1  christos # to compare results between two runs of GDB from different trees.
     20  1.1  christos 
     21  1.1  christos namespace eval ::CheckTestNames {
     22  1.1  christos     # An associative array of all test names to the number of times each
     23  1.1  christos     # name is seen.  Used to detect duplicate test names.
     24  1.1  christos     variable all_test_names
     25  1.1  christos     array set all_test_names {}
     26  1.1  christos 
     27  1.1  christos     # An associative array of counts of tests that either include a path in
     28  1.1  christos     # their test name, or have a duplicate test name.  There are two counts
     29  1.1  christos     # for each issue, 'count', which counts occurrences within a single
     30  1.1  christos     # variant run, and 'total', which counts across all variants.
     31  1.1  christos     variable counts
     32  1.1  christos     array set counts {}
     33  1.1  christos     foreach nm {paths duplicates} {
     34  1.1  christos 	set counts($nm,count) 0
     35  1.1  christos 	set counts($nm,total) 0
     36  1.1  christos     }
     37  1.1  christos 
     38  1.1  christos     # Increment the count, and total count for TYPE.
     39  1.1  christos     proc inc_count { type } {
     40  1.1  christos 	variable counts
     41  1.1  christos 
     42  1.1  christos 	incr counts($type,count)
     43  1.1  christos 	incr counts($type,total)
     44  1.1  christos     }
     45  1.1  christos 
     46  1.1  christos     # Check if MESSAGE contains a build or source path, if it does increment
     47  1.1  christos     # the relevant counter and return true, otherwise, return false.
     48  1.1  christos     proc _check_paths { message } {
     49  1.1  christos 	global srcdir objdir
     50  1.1  christos 
     51  1.1  christos 	foreach path [list $srcdir $objdir] {
     52  1.1  christos 	    if { [ string first $path $message ] >= 0 } {
     53  1.1  christos 		# Count each test just once.
     54  1.1  christos 		inc_count paths
     55  1.1  christos 		return true
     56  1.1  christos 	    }
     57  1.1  christos 	}
     58  1.1  christos 
     59  1.1  christos 	return false
     60  1.1  christos     }
     61  1.1  christos 
     62  1.1  christos     # Check if MESSAGE is a duplicate, if it is then increment the
     63  1.1  christos     # duplicates counter and return true, otherwise, return false.
     64  1.1  christos     proc _check_duplicates { message } {
     65  1.1  christos 	variable all_test_names
     66  1.1  christos 
     67  1.1  christos 	# Initialise a count, or increment the count for this test name.
     68  1.1  christos 	if {![info exists all_test_names($message)]} {
     69  1.1  christos 	    set all_test_names($message) 0
     70  1.1  christos 	} else {
     71  1.1  christos 	    if {$all_test_names($message) == 0} {
     72  1.1  christos 		inc_count duplicates
     73  1.1  christos 	    }
     74  1.1  christos 	    incr all_test_names($message)
     75  1.1  christos 	    return true
     76  1.1  christos 	}
     77  1.1  christos 
     78  1.1  christos 	return false
     79  1.1  christos     }
     80  1.1  christos 
     81  1.1  christos     # Remove the leading Dejagnu status marker from MESSAGE, and
     82  1.1  christos     # return the remainder of MESSAGE.  A status marker is something
     83  1.1  christos     # like 'PASS: '.  It is assumed that MESSAGE does contain such a
     84  1.1  christos     # marker.  If it doesn't then MESSAGE is returned unmodified.
     85  1.1  christos     proc _strip_status { message } {
     86  1.1  christos 	# Find the position of the first ': ' string.
     87  1.1  christos 	set pos [string first ": " $message]
     88  1.1  christos 	if { $pos > -1 } {
     89  1.1  christos 	    # The '+ 2' is so we skip the ': ' we found above.
     90  1.1  christos 	    return  [string range $message [expr $pos + 2] end]
     91  1.1  christos 	}
     92  1.1  christos 
     93  1.1  christos 	return $message
     94  1.1  christos     }
     95  1.1  christos 
     96  1.1  christos     # Check if MESSAGE contains either the source path or the build path.
     97  1.1  christos     # This will result in test names that can't easily be compared between
     98  1.1  christos     # different runs of GDB.
     99  1.1  christos     #
    100  1.1  christos     # Any offending test names cause the corresponding count to be
    101  1.1  christos     # incremented, and an extra message to be printed into the log
    102  1.1  christos     # file.
    103  1.1  christos     proc check { message } {
    104  1.1  christos 	set message [ _strip_status $message ]
    105  1.1  christos 
    106  1.1  christos 	if [ _check_paths $message ] {
    107  1.1  christos 	    clone_output "PATH: $message"
    108  1.1  christos 	}
    109  1.1  christos 
    110  1.1  christos 	if [ _check_duplicates $message ] {
    111  1.1  christos 	    clone_output "DUPLICATE: $message"
    112  1.1  christos 	}
    113  1.1  christos     }
    114  1.1  christos 
    115  1.1  christos     # If COUNT is greater than zero, disply PREFIX followed by COUNT.
    116  1.1  christos     proc maybe_show_count { prefix count } {
    117  1.1  christos 	if { $count > 0 } {
    118  1.1  christos 	    clone_output "$prefix$count"
    119  1.1  christos 	}
    120  1.1  christos     }
    121  1.1  christos 
    122  1.1  christos     # Rename Dejagnu's log_summary procedure, and create do_log_summary to
    123  1.1  christos     # replace it.  We arrange to have do_log_summary called later.
    124  1.1  christos     rename ::log_summary log_summary
    125  1.1  christos     proc do_log_summary { args } {
    126  1.1  christos 	variable counts
    127  1.1  christos 
    128  1.1  christos 	# If ARGS is the empty list then we don't want to pass a single
    129  1.1  christos 	# empty string as a parameter here.
    130  1.1  christos 	eval "CheckTestNames::log_summary $args"
    131  1.1  christos 
    132  1.1  christos 	if { [llength $args] == 0 } {
    133  1.1  christos 	    set which "count"
    134  1.1  christos 	} else {
    135  1.1  christos 	    set which [lindex $args 0]
    136  1.1  christos 	}
    137  1.1  christos 
    138  1.1  christos 	maybe_show_count "# of paths in test names\t" \
    139  1.1  christos 	    $counts(paths,$which)
    140  1.1  christos 	maybe_show_count "# of duplicate test names\t" \
    141  1.1  christos 	    $counts(duplicates,$which)
    142  1.1  christos     }
    143  1.1  christos 
    144  1.1  christos     # Rename Dejagnu's reset_vars procedure, and create do_reset_vars to
    145  1.1  christos     # replace it.  We arrange to have do_reset_vars called later.
    146  1.1  christos     rename ::reset_vars reset_vars
    147  1.1  christos     proc do_reset_vars {} {
    148  1.1  christos 	variable all_test_names
    149  1.1  christos 	variable counts
    150  1.1  christos 
    151  1.1  christos 	CheckTestNames::reset_vars
    152  1.1  christos 
    153  1.1  christos 	array unset all_test_names
    154  1.1  christos 	foreach nm {paths duplicates} {
    155  1.1  christos 	    set counts($nm,count) 0
    156  1.1  christos 	}
    157  1.1  christos     }
    158  1.1  christos }
    159  1.1  christos 
    160  1.1  christos # Arrange for Dejagnu to call CheckTestNames::check for each test result.
    161  1.1  christos foreach nm {pass fail xfail kfail xpass kpass unresolved untested \
    162  1.1  christos 		unsupported} {
    163  1.1  christos     set local_record_procs($nm) "CheckTestNames::check"
    164  1.1  christos }
    165  1.1  christos 
    166  1.1  christos # Create new global log_summary to replace Dejagnu's.
    167  1.1  christos proc log_summary { args } {
    168  1.1  christos     eval "CheckTestNames::do_log_summary $args"
    169  1.1  christos }
    170  1.1  christos 
    171  1.1  christos # Create new global reset_vars to replace Dejagnu's.
    172  1.1  christos proc reset_vars {} {
    173  1.1  christos     eval "CheckTestNames::do_reset_vars"
    174  1.1  christos }
    175