2022-01-07 22:25:10 +01:00
# OpenSTA, Static Timing Analyzer
2025-01-22 02:54:33 +01:00
# Copyright (c) 2025, Parallax Software, Inc.
2022-01-07 22:25:10 +01:00
#
# 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
2023-02-19 01:55:40 +01:00
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2022-01-07 22:25:10 +01:00
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
2023-02-19 01:55:40 +01:00
# along with this program. If not, see <https://www.gnu.org/licenses/>.
2025-01-22 02:54:33 +01:00
#
# The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software.
#
# Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
#
# This notice may not be removed or altered from any source distribution.
#
# The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software.
#
# Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
#
# This notice may not be removed or altered from any source distribution.
2022-01-07 22:25:10 +01:00
2026-03-21 18:18:55 +01:00
# Usage: regression -help | [-threads threads] [-j jobs] [-valgrind] [-report_stats]
# test1 [test2...]
2022-01-07 22:25:10 +01:00
proc regression_main { } {
setup
parse_args
run_tests
show_summary
exit [ found_errors ]
}
proc setup { } {
2026-03-21 18:18:55 +01:00
global result_dir diff_file failure_file errors failed_tests
2022-01-07 22:25:10 +01:00
global use_valgrind valgrind_shared_lib_failure
2026-03-21 18:18:55 +01:00
global report_stats max_jobs app_path
2022-01-07 22:25:10 +01:00
set use_valgrind 0
set report_stats 0
2026-03-21 18:18:55 +01:00
set max_jobs 1
2022-01-07 22:25:10 +01:00
if { ! ( [ file exists $result_dir ] && [ file isdirectory $result_dir ] ) } {
file mkdir $result_dir
}
file delete $diff_file
file delete $failure_file
set errors( error ) 0
set errors( memory ) 0
set errors( leak ) 0
set errors( fail ) 0
set errors( no_cmd ) 0
set errors( no_ok ) 0
2026-03-21 18:18:55 +01:00
set failed_tests { }
2022-01-07 22:25:10 +01:00
set valgrind_shared_lib_failure 0
2026-03-21 18:18:55 +01:00
if { ! [ file exists $app_path ] } {
error " $ a p p _ p a t h n o t f o u n d . "
} elseif { ! [ file executable $app_path ] } {
error " $ a p p _ p a t h i s n o t e x e c u t a b l e . "
}
2022-01-07 22:25:10 +01:00
}
proc parse_args { } {
global argv app_options tests test_groups cmd_paths
global use_valgrind
global result_dir tests
2026-03-21 18:18:55 +01:00
global report_stats max_jobs
2022-01-07 22:25:10 +01:00
while { $argv != { } } {
set arg [ lindex $argv 0 ]
if { $arg == " h e l p " || $arg == " - h e l p " } {
2026-03-21 18:18:55 +01:00
puts { Usage : regression [ -help ] [ -threads threads] [ -j jobs] [ -valgrind ] [ -report_stats ] tests...}
2022-01-07 22:25:10 +01:00
puts " - t h r e a d s m a x | i n t e g e r - n u m b e r o f t h r e a d s t o u s e "
2026-03-21 18:18:55 +01:00
puts " - j j o b s - n u m b e r o f p a r a l l e l j o b s ( p r o c e s s e s ) t o r u n "
2022-01-07 22:25:10 +01:00
puts " - v a l g r i n d - r u n v a l g r i n d ( l i n u x m e m o r y c h e c k e r ) "
puts " - r e p o r t _ s t a t s - r e p o r t r u n t i m e a n d m e m o r y "
puts " W i l d c a r d i n g f o r t e s t n a m e s i s s u p p o r t e d ( e n c l o s e i n \" ' s ) "
puts " T e s t s a r e : a l l , f a s t , m e d , s l o w , o r a t e s t g r o u p o r t e s t n a m e "
puts " "
puts " I f ' l i m i t c o r e d u m p s i z e u n l i m i t e d ' c o r e f i l e s a r e s a v e d i n $ r e s u l t _ d i r / t e s t . c o r e "
exit
} elseif { $arg == " - t h r e a d s " } {
set threads [ lindex $argv 1 ]
if { ! ( [ string is integer $threads ] || $threads == " m a x " ) } {
2026-03-21 18:18:55 +01:00
puts " E r r o r : - t h r e a d s a r g $ t h r e a d s i s n o t a n i n t e g e r o r m a x . "
exit 0
2022-01-07 22:25:10 +01:00
}
lappend app_options " - t h r e a d s "
lappend app_options $threads
set argv [ lrange $argv 2 end]
2026-03-21 18:18:55 +01:00
} elseif { $arg == " - j " } {
set jobs [ lindex $argv 1 ]
if { ! [ string is integer $jobs ] || $jobs < 1 } {
puts " E r r o r : - j a r g $ j o b s m u s t b e a p o s i t i v e i n t e g e r . "
exit 0
}
set max_jobs $jobs
set argv [ lrange $argv 2 end]
2022-01-07 22:25:10 +01:00
} elseif { $arg == " - v a l g r i n d " } {
2025-01-10 19:14:52 +01:00
if { ! [ find_valgrind ] } {
error " v a l g r i n d n o t f o u n d . "
}
2022-01-07 22:25:10 +01:00
set use_valgrind 1
set argv [ lrange $argv 1 end]
} elseif { $arg == " - r e p o r t _ s t a t s " } {
set report_stats 1
set argv [ lrange $argv 1 end]
} else {
break
}
}
if { $argv == { } } {
# Default is to run fast tests.
set tests [ group_tests fast]
} else {
set tests [ expand_tests $argv ]
}
}
2025-01-10 19:14:52 +01:00
# Find valgrind in $PATH.
proc find_valgrind { } {
global env
foreach dir [ regsub - all " : " $env ( PATH ) " " ] {
if { [ file executable [ file join $dir " v a l g r i n d " ] ] } {
return 1
}
}
return 0
}
2022-01-07 22:25:10 +01:00
proc expand_tests { argv } {
2023-03-28 03:15:18 +02:00
global test_groups errors
2022-01-07 22:25:10 +01:00
set tests { }
foreach arg $argv {
if { [ info exists test_groups( $arg ) ] } {
set tests [ concat $tests $test_groups ( $arg ) ]
} elseif { [ string first " * " $arg ] != -1 \
2026-03-21 18:18:55 +01:00
|| [ string first " ? " $arg ] != -1 } {
2022-01-07 22:25:10 +01:00
# Find wildcard matches.
foreach test [ group_tests " a l l " ] {
2026-01-04 01:59:35 +01:00
if [ string match $arg $test ] {
lappend tests $test
}
2022-01-07 22:25:10 +01:00
}
} elseif { [ lsearch [ group_tests " a l l " ] $arg ] != -1 } {
lappend tests $arg
} else {
puts " E r r o r : t e s t $ a r g n o t f o u n d . "
2023-03-28 03:15:18 +02:00
incr errors( no_cmd )
2026-03-21 18:18:55 +01:00
}
2022-01-07 22:25:10 +01:00
}
return $tests
}
proc run_tests { } {
2026-03-21 18:18:55 +01:00
global tests errors app_path max_jobs
2022-01-07 22:25:10 +01:00
2026-03-21 18:18:55 +01:00
if { $max_jobs > 1 } {
run_tests_parallel
} else {
foreach test $tests {
run_test $test
}
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
write_failure_file
write_diff_file
2022-01-07 22:25:10 +01:00
}
proc run_test { test } {
2026-03-21 18:18:55 +01:00
global result_dir diff_file errors diff_options
2022-01-07 22:25:10 +01:00
2026-03-21 18:18:55 +01:00
puts - nonewline $test
flush stdout
set exit_code 0
if { [ test_cmd_file_exists $test ] } {
set cmd [ make_cmd_file $test ]
2022-01-07 22:25:10 +01:00
set log_file [ test_log_file $test ]
2026-03-21 18:18:55 +01:00
if { [ catch [ concat " e x e c " " $ c m d > & $ l o g _ f i l e " ] result result_options] } {
set details [ dict get $result_options - errorcode]
set exit_signal [ lindex $details 2 ]
if { $exit_signal == " S I G S E G V " } {
set exit_code 139
2022-01-07 22:25:10 +01:00
} else {
2026-03-21 18:18:55 +01:00
set exit_code 128
2022-01-07 22:25:10 +01:00
}
}
}
2026-03-21 18:18:55 +01:00
puts " [ t e s t _ s t a t u s $ t e s t $ e x i t _ c o d e ] "
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
# ###############################################################
# Parallel runs use one pipeline per test; close() yields the real exit status.
# (Non-blocking channels must be switched to blocking before close - see Tcl manual.)
proc regression_parallel_close_pipe { fh } {
fconfigure $fh - blocking 1
if { [ catch { close $fh } err opts] } {
set ec [ dict get $opts - errorcode]
if { [ lindex $ec 0 ] == " C H I L D S T A T U S " } {
return [ lindex $ec 2 ]
}
return 128
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
return 0
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
proc regression_pipe_readable { fh test } {
global reg_parallel_active reg_parallel_job_done
read $fh
if { [ eof $fh ] } {
fileevent $fh readable { }
set exit_code [ regression_parallel_close_pipe $fh ]
puts " $ t e s t [ t e s t _ s t a t u s $ t e s t $ e x i t _ c o d e ] "
incr reg_parallel_active - 1
incr reg_parallel_job_done
2022-01-07 22:25:10 +01:00
}
}
2026-03-21 18:18:55 +01:00
proc open_test_pipeline { test } {
set cmd [ make_cmd_file $test ]
set log [ test_log_file $test ]
set inner [ format { % s > % s 2 > & 1 } $cmd [ file nativename $log ] ]
set fh [ open [ format { | / bin / sh - c % s} [ list $inner ] ] r]
fconfigure $fh - blocking 0
return $fh
}
proc run_tests_parallel { } {
global tests max_jobs reg_parallel_active reg_parallel_job_done
set reg_parallel_active 0
set reg_parallel_job_done 0
set test_idx 0
set test_count [ llength $tests ]
while { $test_idx < $test_count || $reg_parallel_active > 0 } {
while { $reg_parallel_active < $max_jobs && $test_idx < $test_count } {
set test [ lindex $tests $test_idx ]
incr test_idx
if { ! [ test_cmd_file_exists $test ] } {
puts - nonewline $test
flush stdout
puts " [ t e s t _ s t a t u s $ t e s t 0 ] "
continue
}
set fh [ open_test_pipeline $test ]
fileevent $fh readable [ list regression_pipe_readable $fh $test ]
incr reg_parallel_active
}
if { $reg_parallel_active > 0 } {
set before $reg_parallel_job_done
while { $reg_parallel_job_done == $before } {
vwait reg_parallel_job_done
}
}
}
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
proc make_cmd_file { test } {
global app_path app_options result_dir use_valgrind report_stats
foreach file [ glob - nocomplain [ file join $result_dir $test. * ] ] {
file delete - force $file
}
set cmd_file [ test_cmd_file $test ]
set ok_file [ test_ok_file $test ]
set log_file [ test_log_file $test ]
set run_file [ test_run_file $test ]
set run_stream [ open $run_file " w " ]
puts $run_stream " c d [ f i l e d i r n a m e $ c m d _ f i l e ] "
puts $run_stream " i n c l u d e [ f i l e t a i l $ c m d _ f i l e ] "
if { $use_valgrind } {
puts $run_stream " s t a : : d e l e t e _ a l l _ m e m o r y "
}
if { $report_stats } {
puts $run_stream " s t a : : w r i t e _ s t a t s [ t e s t _ s t a t s _ f i l e $ t e s t ] "
}
close $run_stream
2022-01-07 22:25:10 +01:00
if { $use_valgrind } {
2026-03-21 18:18:55 +01:00
global valgrind_options
set cmd " v a l g r i n d $ v a l g r i n d _ o p t i o n s $ a p p _ p a t h $ a p p _ o p t i o n s $ r u n _ f i l e "
2022-01-07 22:25:10 +01:00
} else {
2026-03-21 18:18:55 +01:00
set cmd " $ a p p _ p a t h $ a p p _ o p t i o n s $ r u n _ f i l e "
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
return $cmd
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
proc test_cmd_file_exists { test } {
set cmd_file [ test_cmd_file $test ]
return [ file exists $cmd_file ]
}
2022-01-07 22:25:10 +01:00
2026-03-21 18:18:55 +01:00
proc test_status { test exit_code } {
global result_dir diff_options errors
global use_valgrind report_stats test_status
set test_status { }
if { ! [ test_cmd_file_exists $test ] } {
test_failed $test " n o _ c m d "
2022-01-07 22:25:10 +01:00
} else {
2026-03-21 18:18:55 +01:00
set log_file [ test_log_file $test ]
if { [ file exists $log_file ] } {
# Check log file for error patterns
set log_ch [ open $log_file " r " ]
set log_content [ read $log_ch ]
close $log_ch
# Check if exit code indicates a segfault or signal termination
# Exit codes >= 128 typically indicate termination by a signal
# 139 = 128 + 11 (SIGSEGV), 134 = 128 + 6 (SIGABRT), etc.
if { $exit_code >= 128
|| [ string match " * S e g m e n t a t i o n f a u l t * " $log_content ] \
|| [ string match " * D E A D L Y S I G N A L * " $log_content ] \
|| [ string match " * A b o r t * " $log_content ] \
|| [ string match " * F a t a l * " $log_content ] } {
test_failed $test " e r r o r "
} elseif { [ string match " * h e a p - u s e - a f t e r - f r e e * " $log_content ] } {
# ASAN error
test_failed $test " m e m o r y "
}
set ok_file [ test_ok_file $test ]
if { [ file exists $ok_file ] } {
if { $use_valgrind } {
cleanse_valgrind_logfile $test
}
if { [ catch [ concat exec diff $diff_options $ok_file $log_file ] ] } {
if { $test_status == " " } {
test_failed $test " f a i l "
}
}
} else {
if { $test_status == " " } {
test_failed $test " n o _ o k "
2026-01-04 01:59:35 +01:00
}
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
} else {
# Log file doesn't exist, likely an error
test_failed $test " e r r o r " " * E R R O R * n o l o g f i l e "
2022-01-07 22:25:10 +01:00
}
2026-03-21 18:18:55 +01:00
}
if { $test_status == { } } {
append test_status " p a s s "
}
if { $report_stats } {
append test_status " [ t e s t _ s t a t s _ s u m m a r y $ t e s t ] "
}
return $test_status
}
proc test_exit_code { test } {
# Read exit code
set test_error " "
set exit_code_file [ test_exit_code_file $test ]
if { [ file exists $exit_code_file ] } {
set exit_code_ch [ open $exit_code_file " r " ]
set exit_code [ string trim [ read $exit_code_ch ] ]
close $exit_code_ch
if { [ string is integer $exit_code ] } {
return $exit_code
}
}
return 0
}
proc test_stats_summary { test } {
if { ! [ catch { open [ test_stats_file $test ] r} stream] } {
gets $stream stats
close $stream
set elapsed_time [ lindex $stats 0 ]
set user_time [ lindex $stats 1 ]
set memory [ lindex $stats 2 ]
if { [ string is double $elapsed_time ] } {
set elapsed [ format " % . 1 f e " $elapsed_time ]
} else {
set elapsed " ? "
}
if { [ string is double $user_time ] } {
set user [ format " % . 1 f u " $user_time ]
} else {
set user " ? "
}
if { [ string is double $memory ] } {
set mem [ format " % . 0 f m b " [ expr $memory * 1 e-6] ]
} else {
set mem " ? "
}
return " $ e l a p s e d $ u s e r $ m e m "
} else {
2022-01-07 22:25:10 +01:00
return " "
}
}
2026-03-21 18:18:55 +01:00
proc test_failed { test reason } {
global errors test_status failed_tests
2022-01-07 22:25:10 +01:00
2026-03-21 18:18:55 +01:00
if { $reason == " e r r o r " } {
set test_status " * E R R O R * "
} elseif { $reason == " n o _ c m d " } {
set test_status " * N O C M D F I L E * "
} elseif { $reason == " m e m o r y " } {
set test_status " * M E M O R Y * "
} elseif { $reason == " l e a k " } {
set test_status " * L E A K * "
} elseif { $reason == " f a i l " } {
set test_status " * F A I L * "
} elseif { $reason == " n o _ o k " } {
set test_status " * N O O K F I L E * "
} else {
error " u n k n o w n t e s t f a i l u r e r e a s o n $ r e a s o n "
}
lappend failed_tests $test
incr errors( $reason )
}
proc write_failure_file { } {
global failure_file failed_tests
set ch [ open $failure_file " w " ]
foreach test $failed_tests {
puts $ch $test
}
close $ch
}
proc write_diff_file { } {
global diff_file diff_options failed_tests
foreach test $failed_tests {
set log_file [ test_log_file $test ]
set ok_file [ test_ok_file $test ]
catch [ concat exec diff $diff_options $ok_file $log_file >> $diff_file ]
2022-01-07 22:25:10 +01:00
}
}
# Error messages can be found in "valgrind/memcheck/mc_errcontext.c".
#
# "Conditional jump or move depends on uninitialised value(s)"
# "%s contains unaddressable byte(s)"
# "%s contains uninitialised or unaddressable byte(s)"
# "Use of uninitialised value of size %d"
# "Invalid read of size %d"
# "Syscall param %s contains uninitialised or unaddressable byte(s)"
# "Unaddressable byte(s) found during client check request"
# "Uninitialised or unaddressable byte(s) found during client check request"
# "Invalid free() / delete / delete[]"
# "Mismatched free() / delete / delete []"
set valgrind_mem_regexp " ( d e p e n d s o n u n i n i t i a l i s e d v a l u e ) | ( c o n t a i n s u n a d d r e s s a b l e ) | ( c o n t a i n s u n i n i t i a l i s e d ) | ( U s e o f u n i n i t i a l i s e d v a l u e ) | ( I n v a l i d r e a d ) | ( U n a d d r e s s a b l e b y t e ) | ( U n i n i t i a l i s e d o r u n a d d r e s s a b l e ) | ( I n v a l i d f r e e ) | ( M i s m a t c h e d f r e e ) "
# "%d bytes in %d blocks are definitely lost in loss record %d of %d"
# "%d bytes in %d blocks are possibly lost in loss record %d of %d"
# set valgrind_leak_regexp "blocks are (possibly|definitely) lost"
set valgrind_leak_regexp " b l o c k s a r e d e f i n i t e l y l o s t "
# Valgrind fails on executables using shared libraries.
set valgrind_shared_lib_failure_regexp " N o m a l l o c ' d b l o c k s - - n o l e a k s a r e p o s s i b l e "
# Scan the log file to separate valgrind notifications and check for
# valgrind errors.
2026-03-21 18:18:55 +01:00
proc cleanse_valgrind_logfile { test } {
2022-01-07 22:25:10 +01:00
global valgrind_mem_regexp valgrind_leak_regexp
global valgrind_shared_lib_failure_regexp
2026-03-21 18:18:55 +01:00
global valgrind_shared_lib_failure error
2022-01-07 22:25:10 +01:00
2026-03-21 18:18:55 +01:00
set log_file [ test_log_file $test ]
2022-01-07 22:25:10 +01:00
set tmp_file [ test_tmp_file $test ]
set valgrind_log_file [ test_valgrind_file $test ]
file copy - force $log_file $tmp_file
set tmp [ open $tmp_file " r " ]
set log [ open $log_file " w " ]
set valgrind [ open $valgrind_log_file " w " ]
2026-03-21 18:18:55 +01:00
set leak 0
2022-01-07 22:25:10 +01:00
set mem_errors 0
gets $tmp line
while { ! [ eof $tmp ] } {
if { [ regexp " ^ = = " $line ] } {
puts $valgrind $line
if { [ regexp $valgrind_leak_regexp $line ] } {
2026-03-21 18:18:55 +01:00
set leak 1
2022-01-07 22:25:10 +01:00
}
if { [ regexp $valgrind_mem_regexp $line ] } {
2026-01-04 01:59:35 +01:00
set mem_errors 1
2022-01-07 22:25:10 +01:00
}
if { [ regexp $valgrind_shared_lib_failure_regexp $line ] } {
2026-01-04 01:59:35 +01:00
set valgrind_shared_lib_failure 1
2022-01-07 22:25:10 +01:00
}
} elseif { [ regexp { ^ -- [ 0-9 ] + } $line ] } {
# Valgrind notification line.
} else {
puts $log $line
}
gets $tmp line
}
close $log
close $tmp
close $valgrind
if { $mem_errors } {
2026-03-21 18:18:55 +01:00
test_failed $test " m e m o r y "
} elseif { $leak } {
test_failed $test " l e a k "
2022-01-07 22:25:10 +01:00
}
}
# ###############################################################
proc show_summary { } {
global errors tests diff_file result_dir valgrind_shared_lib_failure
global app_path app
puts " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "
set test_count [ llength $tests ]
if { [ found_errors ] } {
if { $errors ( error ) != 0 } {
puts " E r r o r e d $ e r r o r s ( e r r o r ) / $ t e s t _ c o u n t "
}
if { $errors ( fail ) != 0 } {
puts " F a i l e d $ e r r o r s ( f a i l ) / $ t e s t _ c o u n t "
}
if { $errors ( leak ) != 0 } {
puts " M e m o r y l e a k s i n $ e r r o r s ( l e a k ) / $ t e s t _ c o u n t "
}
if { $errors ( memory ) != 0 } {
puts " M e m o r y c o r r u p t i o n i n $ e r r o r s ( m e m o r y ) / $ t e s t _ c o u n t "
}
if { $errors ( no_ok ) != 0 } {
puts " N o o k f i l e f o r $ e r r o r s ( n o _ o k ) / $ t e s t _ c o u n t "
}
if { $errors ( no_cmd ) != 0 } {
puts " N o c m d t c l f i l e f o r $ e r r o r s ( n o _ c m d ) / $ t e s t _ c o u n t "
}
if { $errors ( fail ) != 0 } {
puts " S e e $ d i f f _ f i l e f o r d i f f e r e n c e s "
}
} else {
puts " P a s s e d $ t e s t _ c o u n t "
}
if { $valgrind_shared_lib_failure } {
puts " W A R N I N G : v a l g r i n d f a i l e d b e c a u s e t h e e x e c u t a b l e i s n o t s t a t i c a l l y l i n k e d . "
}
puts " S e e $ r e s u l t _ d i r f o r l o g f i l e s "
}
proc found_errors { } {
global errors
return [ expr $errors ( error ) != 0 || $errors ( fail ) != 0 \
2026-01-04 01:59:35 +01:00
|| $errors ( no_cmd ) != 0 || $errors ( no_ok ) != 0 \
|| $errors ( memory ) != 0 || $errors ( leak ) != 0 ]
2022-01-07 22:25:10 +01:00
}
# ###############################################################
proc save_ok_main { } {
global argv
if { $argv == " h e l p " || $argv == " - h e l p " } {
puts { Usage : save_ok [ failures ] test1 [ test2 ] ...}
} elseif { $argv == " f a i l u r e s " } {
global failure_file
if [ file exists $failure_file ] {
set fail_ch [ open $failure_file " r " ]
while { ! [ eof $fail_ch ] } {
2026-01-04 01:59:35 +01:00
set test [ gets $fail_ch ]
if { $test != " " } {
save_ok $test
}
2022-01-07 22:25:10 +01:00
}
close $fail_ch
}
} else {
foreach test $argv {
save_ok $test
}
}
}
proc save_ok { test } {
if { [ lsearch [ group_tests " a l l " ] $test ] == -1 } {
puts " E r r o r : t e s t $ t e s t n o t f o u n d . "
} else {
set ok_file [ test_ok_file $test ]
set log_file [ test_log_file $test ]
if { ! [ file exists $log_file ] } {
puts " E r r o r : l o g f i l e $ l o g _ f i l e n o t f o u n d . "
} else {
file copy - force $log_file $ok_file
}
}
}
# ###############################################################
proc test_cmd_dir { test } {
global cmd_dirs
if { [ info exists cmd_dirs( $test ) ] } {
return $cmd_dirs ( $test )
} else {
return " "
}
}
proc test_cmd_file { test } {
return [ file join [ test_cmd_dir $test ] " $ t e s t . t c l " ]
}
proc test_ok_file { test } {
global test_dir
return [ file join $test_dir " $ t e s t . o k " ]
}
proc test_log_file { test } {
global result_dir
return [ file join $result_dir " $ t e s t . l o g " ]
}
proc test_run_file { test } {
global result_dir
return [ file join $result_dir $test.run ]
}
proc test_tmp_file { test } {
global result_dir
return [ file join $result_dir $test.tmp ]
}
proc test_valgrind_file { test } {
global result_dir
return [ file join $result_dir $test.valgrind ]
}
proc test_stats_file { test } {
global result_dir
return [ file join $result_dir " $ t e s t . s t a t s " ]
}
proc test_core_file { test } {
global result_dir
return [ file join $result_dir $test.core ]
}
proc test_sys_core_file { test pid } {
global cmd_dirs
# macos
# return [file join "/cores" "core.$pid"]
# Suse
return [ file join [ test_cmd_dir $test ] " c o r e " ]
}
2026-03-21 18:18:55 +01:00
proc test_exit_code_file { test } {
global result_dir
return [ file join $result_dir " $ t e s t . e x i t c o d e " ]
}
2022-01-07 22:25:10 +01:00
# ###############################################################
# Local Variables:
# mode:tcl
# End: