binutils-gdb/gdb/testsuite/lib/gdb-utils.exp
Tom de Vries c479e964a8 [gdb/testsuite] Use unique portnum in parallel testing (check//% case)
Make target check//% is the gdb variant of a similar gcc make target [1].

When running tests using check//%:
...
$ cd build/gdb
$ make check//unix/{-fPIE/-pie,-fno-PIE/-no-pie} -j2 TESTS=gdb.server/*.exp
...
we get:
...
$ cat build/gdb/testsuite.unix.-fPIE.-pie/cache/portnum
2427
$ cat build/gdb/testsuite.unix.-fno-PIE.-no-pie/cache/portnum
2423
...

The problem is that there are two portnum files used in parallel.

Fix this by:
- creating a common lockdir build/gdb/testsuite.lockdir for make target
  check//%,
- passing this down to the runtests invocations using variable GDB_LOCK_DIR,
  and
- using GDB_LOCK_DIR in lock_dir.

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

PR testsuite/31632
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31632

[1] https://gcc.gnu.org/install/test.html
2024-05-04 10:41:09 +02:00

211 lines
5.4 KiB
Text

# Copyright 2014-2024 Free Software Foundation, Inc.
# 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
# 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 this program. If not, see <http://www.gnu.org/licenses/>.
# Utility procedures, shared between test suite domains.
# A helper procedure to retrieve commands to send to GDB before a program
# is started.
proc gdb_init_commands {} {
set commands ""
if [target_info exists gdb_init_command] {
lappend commands [target_info gdb_init_command]
}
if [target_info exists gdb_init_commands] {
set commands [concat $commands [target_info gdb_init_commands]]
}
return $commands
}
# Given an input string, adds backslashes as needed to create a
# regexp that will match the string.
proc string_to_regexp {str} {
set result $str
regsub -all {[]?*+.|(){}^$\[\\]} $str {\\&} result
return $result
}
# Given a list of strings, adds backslashes as needed to each string to
# create a regexp that will match the string, and join the result.
proc string_list_to_regexp { args } {
set result ""
foreach arg $args {
set arg [string_to_regexp $arg]
append result $arg
}
return $result
}
# Wrap STR in an ANSI terminal escape sequences -- one to set the
# style to STYLE, and one to reset the style to the default. The
# return value is suitable for use as a regular expression.
# STYLE can either be the payload part of an ANSI terminal sequence,
# or a shorthand for one of the gdb standard styles: "file",
# "function", "variable", or "address".
proc style {str style} {
switch -exact -- $style {
title { set style 1 }
file { set style 32 }
function { set style 33 }
highlight { set style 31 }
variable { set style 36 }
address { set style 34 }
metadata { set style 2 }
version { set style "35;1" }
none { return $str }
}
return "\033\\\[${style}m${str}\033\\\[m"
}
# gdb_get_bp_addr num
#
# Purpose:
# Get address of a particular breakpoint.
#
# Parameter:
# The parameter "num" indicates the number of the breakpoint to get.
# Note that *currently* this parameter must be an integer value.
# E.g., -1 means that we're gonna get the first internal breakpoint;
# 2 means to get the second user-defined breakpoint.
#
# Return:
# First address for a particular breakpoint.
#
# TODO:
# It would be nice if this procedure could accept floating point value.
# E.g., 'gdb_get_bp_addr 1.2' means to get the address of the second
# location of breakpoint #1.
#
proc gdb_get_bp_addr { num } {
gdb_test_multiple "maint info break $num" "find address of specified bp $num" {
-re -wrap ".*(0x\[0-9a-f\]+).*" {
return $expect_out(1,string)
}
}
return ""
}
# Compare the version numbers in L1 to those in L2 using OP, and
# return 1 if the comparison is true. OP can be "<", "<=", or "==".
# It is ok if the lengths of the lists differ.
proc version_compare { l1 op l2 } {
switch -exact $op {
"==" -
"<=" -
"<" {}
default { error "unsupported op: $op" }
}
# Handle ops < and ==.
foreach v1 $l1 v2 $l2 {
if {$v1 == ""} {
# This is: "1.2 OP 1.2.1".
if {$op != "=="} {
return 1
}
return 0
}
if {$v2 == ""} {
# This is: "1.2.1 OP 1.2".
return 0
}
if {$v1 == $v2} {
continue
}
return [expr $v1 $op $v2]
}
if {$op == "<"} {
# They are equal.
return 0
}
return 1
}
# Acquire lock file LOCKFILE. Tries forever until the lock file is
# successfully created.
proc lock_file_acquire {lockfile} {
verbose -log "acquiring lock file: $::subdir/${::gdb_test_file_name}.exp"
while {true} {
if {![catch {open $lockfile {WRONLY CREAT EXCL}} rc]} {
set msg "locked by $::subdir/${::gdb_test_file_name}.exp"
verbose -log "lock file: $msg"
# For debugging, put info in the lockfile about who owns
# it.
puts $rc $msg
flush $rc
return [list $rc $lockfile]
}
after 10
}
}
# Release a lock file.
proc lock_file_release {info} {
verbose -log "releasing lock file: $::subdir/${::gdb_test_file_name}.exp"
if {![catch {fconfigure [lindex $info 0]}]} {
if {![catch {
close [lindex $info 0]
file delete -force [lindex $info 1]
} rc]} {
return ""
} else {
return -code error "Error releasing lockfile: '$rc'"
}
} else {
error "invalid lock"
}
}
# Return directory where we keep lock files.
proc lock_dir {} {
if { [info exists ::GDB_LOCK_DIR] } {
# When using check//.
return $::GDB_LOCK_DIR
}
return [make_gdb_parallel_path cache]
}
# Run body under lock LOCK_FILE.
proc with_lock { lock_file body } {
if {[info exists ::GDB_PARALLEL]} {
set lock_file [file join [lock_dir] $lock_file]
set lock_rc [lock_file_acquire $lock_file]
}
set code [catch {uplevel 1 $body} result]
if {[info exists ::GDB_PARALLEL]} {
lock_file_release $lock_rc
}
if {$code == 1} {
global errorInfo errorCode
return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
} else {
return -code $code $result
}
}