Home | History | Annotate | Line # | Download | only in lib
check-test-names.exp revision 1.1.1.2
      1  1.1.1.2  christos # Copyright 2020-2023 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.1.2  christos     # Check if MESSAGE is a well-formed test name.
     97  1.1.1.2  christos     proc _check_well_formed_name { message } {
     98  1.1.1.2  christos 	if { [regexp \n $message]} {
     99  1.1.1.2  christos 	    warning "Newline in test name"
    100  1.1.1.2  christos 	}
    101  1.1.1.2  christos     }
    102  1.1.1.2  christos 
    103      1.1  christos     # Check if MESSAGE contains either the source path or the build path.
    104      1.1  christos     # This will result in test names that can't easily be compared between
    105      1.1  christos     # different runs of GDB.
    106      1.1  christos     #
    107      1.1  christos     # Any offending test names cause the corresponding count to be
    108      1.1  christos     # incremented, and an extra message to be printed into the log
    109      1.1  christos     # file.
    110      1.1  christos     proc check { message } {
    111      1.1  christos 	set message [ _strip_status $message ]
    112      1.1  christos 
    113      1.1  christos 	if [ _check_paths $message ] {
    114      1.1  christos 	    clone_output "PATH: $message"
    115      1.1  christos 	}
    116      1.1  christos 
    117      1.1  christos 	if [ _check_duplicates $message ] {
    118      1.1  christos 	    clone_output "DUPLICATE: $message"
    119      1.1  christos 	}
    120  1.1.1.2  christos 
    121  1.1.1.2  christos 	_check_well_formed_name $message
    122      1.1  christos     }
    123      1.1  christos 
    124      1.1  christos     # If COUNT is greater than zero, disply PREFIX followed by COUNT.
    125      1.1  christos     proc maybe_show_count { prefix count } {
    126      1.1  christos 	if { $count > 0 } {
    127      1.1  christos 	    clone_output "$prefix$count"
    128      1.1  christos 	}
    129      1.1  christos     }
    130      1.1  christos 
    131      1.1  christos     # Rename Dejagnu's log_summary procedure, and create do_log_summary to
    132      1.1  christos     # replace it.  We arrange to have do_log_summary called later.
    133      1.1  christos     rename ::log_summary log_summary
    134      1.1  christos     proc do_log_summary { args } {
    135      1.1  christos 	variable counts
    136      1.1  christos 
    137      1.1  christos 	# If ARGS is the empty list then we don't want to pass a single
    138      1.1  christos 	# empty string as a parameter here.
    139      1.1  christos 	eval "CheckTestNames::log_summary $args"
    140      1.1  christos 
    141      1.1  christos 	if { [llength $args] == 0 } {
    142      1.1  christos 	    set which "count"
    143      1.1  christos 	} else {
    144      1.1  christos 	    set which [lindex $args 0]
    145      1.1  christos 	}
    146      1.1  christos 
    147      1.1  christos 	maybe_show_count "# of paths in test names\t" \
    148      1.1  christos 	    $counts(paths,$which)
    149      1.1  christos 	maybe_show_count "# of duplicate test names\t" \
    150      1.1  christos 	    $counts(duplicates,$which)
    151      1.1  christos     }
    152      1.1  christos 
    153      1.1  christos     # Rename Dejagnu's reset_vars procedure, and create do_reset_vars to
    154      1.1  christos     # replace it.  We arrange to have do_reset_vars called later.
    155      1.1  christos     rename ::reset_vars reset_vars
    156      1.1  christos     proc do_reset_vars {} {
    157      1.1  christos 	variable all_test_names
    158      1.1  christos 	variable counts
    159      1.1  christos 
    160      1.1  christos 	CheckTestNames::reset_vars
    161      1.1  christos 
    162      1.1  christos 	array unset all_test_names
    163      1.1  christos 	foreach nm {paths duplicates} {
    164      1.1  christos 	    set counts($nm,count) 0
    165      1.1  christos 	}
    166      1.1  christos     }
    167      1.1  christos }
    168      1.1  christos 
    169      1.1  christos # Arrange for Dejagnu to call CheckTestNames::check for each test result.
    170      1.1  christos foreach nm {pass fail xfail kfail xpass kpass unresolved untested \
    171      1.1  christos 		unsupported} {
    172      1.1  christos     set local_record_procs($nm) "CheckTestNames::check"
    173      1.1  christos }
    174      1.1  christos 
    175      1.1  christos # Create new global log_summary to replace Dejagnu's.
    176      1.1  christos proc log_summary { args } {
    177      1.1  christos     eval "CheckTestNames::do_log_summary $args"
    178      1.1  christos }
    179      1.1  christos 
    180      1.1  christos # Create new global reset_vars to replace Dejagnu's.
    181      1.1  christos proc reset_vars {} {
    182      1.1  christos     eval "CheckTestNames::do_reset_vars"
    183      1.1  christos }
    184