[gdb/testsuite] Fix gdb.base/info-macros.exp timeout with check-run1

Message ID 20190801120441.GA19981@delia
State New, archived
Headers

Commit Message

Tom de Vries Aug. 1, 2019, 12:04 p.m. UTC
  Hi,

With gdb.base/info-macros.exp and check-run1 we get:
...
FAIL: gdb.base/info-macros.exp: info macros 2 (timeout)
FAIL: gdb.base/info-macros.exp: next (timeout)
FAIL: gdb.base/info-macros.exp: info macros 3 (timeout)
FAIL: gdb.base/info-macros.exp: next (timeout)
FAIL: gdb.base/info-macros.exp: next (timeout)
FAIL: gdb.base/info-macros.exp: info macros (timeout)
FAIL: gdb.base/info-macros.exp: next (timeout)
FAIL: gdb.base/info-macros.exp: next (timeout)
FAIL: gdb.base/info-macros.exp: info macros 7 (timeout)
...

Fix this by using gdb_test_sequence.

Tested on x86_64-linux.

OK for trunk?

Thanks,
- Tom

[gdb/testsuite] Fix gdb.base/info-macros.exp timeout with check-run1

gdb/testsuite/ChangeLog:

2019-07-31  Tom de Vries  <tdevries@suse.de>

	* gdb.base/info-macros.exp: Fix check-read1 timeout using
	gdb_test_sequence.
	* lib/gdb.exp (gdb_test_sequence, gdb_expect_list): Add and handle
	fail and sep parameter.
	(regexp_or): New proc.

---
 gdb/testsuite/gdb.base/info-macros.exp | 201 ++++++++++++---------------------
 gdb/testsuite/lib/gdb.exp              |  47 +++++++-
 2 files changed, 118 insertions(+), 130 deletions(-)
  

Comments

Tom de Vries Aug. 5, 2019, 2:15 p.m. UTC | #1
On 01-08-19 14:04, Tom de Vries wrote:
> Hi,
> 
> With gdb.base/info-macros.exp and check-run1 we get:
> ...
> FAIL: gdb.base/info-macros.exp: info macros 2 (timeout)
> FAIL: gdb.base/info-macros.exp: next (timeout)
> FAIL: gdb.base/info-macros.exp: info macros 3 (timeout)
> FAIL: gdb.base/info-macros.exp: next (timeout)
> FAIL: gdb.base/info-macros.exp: next (timeout)
> FAIL: gdb.base/info-macros.exp: info macros (timeout)
> FAIL: gdb.base/info-macros.exp: next (timeout)
> FAIL: gdb.base/info-macros.exp: next (timeout)
> FAIL: gdb.base/info-macros.exp: info macros 7 (timeout)
> ...
> 
> Fix this by using gdb_test_sequence.
> 
> Tested on x86_64-linux.
> 
> OK for trunk?
> 

For now I fixed this by increasing timeout (
https://sourceware.org/ml/gdb-patches/2019-08/msg00107.html ).

Thanks,
- Tom

> [gdb/testsuite] Fix gdb.base/info-macros.exp timeout with check-run1
> 
> gdb/testsuite/ChangeLog:
> 
> 2019-07-31  Tom de Vries  <tdevries@suse.de>
> 
> 	* gdb.base/info-macros.exp: Fix check-read1 timeout using
> 	gdb_test_sequence.
> 	* lib/gdb.exp (gdb_test_sequence, gdb_expect_list): Add and handle
> 	fail and sep parameter.
> 	(regexp_or): New proc.
> 
> ---
>  gdb/testsuite/gdb.base/info-macros.exp | 201 ++++++++++++---------------------
>  gdb/testsuite/lib/gdb.exp              |  47 +++++++-
>  2 files changed, 118 insertions(+), 130 deletions(-)
> 
> diff --git a/gdb/testsuite/gdb.base/info-macros.exp b/gdb/testsuite/gdb.base/info-macros.exp
> index b76a5bbeef..9f61bd3f2e 100644
> --- a/gdb/testsuite/gdb.base/info-macros.exp
> +++ b/gdb/testsuite/gdb.base/info-macros.exp
> @@ -133,153 +133,102 @@ set testname "$test"
>  gdb_test "$test" "$r1$r2$r3$r4" "$testname"
>  
>  set test "info macros"
> -set r1 ".*#define FOO \"hello\""
> -set r2 ".*#define ONE"
> -set r3 ".*\r\n$gdb_prompt"
>  set testname "$test 2"
> -gdb_test_multiple "$test" $testname {
> -  -re "$r1$r2$r3" {
> -     pass $testname
> -  }
> -  -re ".*#define TWO.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define THREE.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOUR.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -}
> +gdb_test_sequence "$test" $testname \
> +    [list \
> +	 "#define FOO \"hello\"" \
> +	 "#define ONE"] \
> +    [list \
> +	 "#define TWO" \
> +	 "#define THREE" \
> +	 "#define FOUR"] \
> +    "\r\nDefined at "
> +
>  gdb_test "next" ".*" ""
>  
> -set r1 ".*#define FOO \" \""
> -set r2 ".*#define ONE"
> -set r3 ".*#define TWO"
> -set r4 ".*\r\n$gdb_prompt"
>  set testname "$test 3"
> -gdb_test_multiple "$test" $testname {
> -  -re ".*#define THREE.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOUR.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re "$r1$r2$r3$r4" {
> -     pass $testname
> -  }
> -}
> +gdb_test_sequence "$test" $testname \
> +    [list \
> +	 "#define FOO \" \"" \
> +	 "#define ONE" \
> +	 "#define TWO"] \
> +    [list \
> +	 "#define THREE" \
> +	 "#define FOUR"] \
> +    "\r\nDefined at "
> +
>  gdb_test "next" ".*" ""
>  
>  # in alpabetical order...
> -set r1 ".*#define FOO \"world\""
> -set r2 ".*#define ONE"
> -set r3 ".*#define THREE"
> -set r4 ".*#define TWO"
> -set r5 ".*\r\n$gdb_prompt"
>  set testname "$test 4"
> -gdb_test_multiple "$test" $testname {
> -  -re ".*#define FOUR.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re "$r1$r2$r3$r4$r5" {
> -     pass $testname
> -  }
> -}
> +gdb_test_sequence "$test" $testname \
> +    [list \
> +	 "#define FOO \"world\"" \
> +	 "#define ONE" \
> +	 "#define THREE" \
> +	 "#define TWO"] \
> +    [list "#define FOUR"] \
> +    "\r\nDefined at "
> +
>  # same as above with a linespec.
>  set test "info macros *\$pc"
> -gdb_test_multiple "$test" $test {
> -  -re ".*#define FOUR.*\r\n$gdb_prompt" {
> -     fail $test
> -  }
> -  -re "$r1$r2$r3$r4$r5" {
> -     pass $test
> -  }
> -}
> +gdb_test_sequence "$test" $test \
> +    [list \
> +	 "#define FOO \"world\"" \
> +	 "#define ONE" \
> +	 "#define THREE" \
> +	 "#define TWO"] \
> +    [list "#define FOUR"] \
> +    "\r\nDefined at "
> +
>  gdb_test "next" ".*" ""
>  
> -set r1 ".*#define FOO \" \""
> -set r2 ".*#define ONE"
> -set r3 ".*#define TWO."
> -set r4 ".*\r\n$gdb_prompt"
>  set test "info macros"
>  set testname "$test 5"
> -gdb_test_multiple "$test" $test {
> -  -re ".*#define THREE.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOUR.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re "$r1$r2$r3$r4" {
> -     pass $testname
> -  }
> -}
> +gdb_test_sequence "$test" $testname \
> +    [list \
> +	 "#define FOO \" \"" \
> +	 "#define ONE" \
> +	 "#define TWO."] \
> +    [list \
> +	 "#define THREE" \
> +	 "#define FOUR"] \
> +    "\r\nDefined at "
> +
>  gdb_test "next" ".*" ""
>  gdb_test "next" ".*" ""
>  
> -set r1 ".*#define DEF_MACROS"
> -set r2 ".*\r\n$gdb_prompt"
> +set r2 "\r\n$gdb_prompt"
>  set testname "$test 6"
> -gdb_test_multiple "$test" $testname {
> -  -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOO\\(a\\) foo = a.*" {
> -     fail $testname
> -  }
> -  -re ".*#define ONE.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define TWO.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define THREE.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOUR.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re "$r1$r2" {
> -     pass $testname
> -  }
> -}
> +gdb_test_sequence "$test" $testname \
> +    [list \
> +	 "#define DEF_MACROS"] \
> +    [list \
> +	 "#define FOO \" \"" \
> +	 "#define FOO \"hello\"" \
> +	 "#define FOO \"world\"" \
> +	 "#define FOO\\(a\\) foo = a" \
> +	 "#define ONE" \
> +	 "#define TWO" \
> +	 "#define THREE" \
> +	 "#define FOUR"] \
> +    "\r\nDefined at "
>  
>  gdb_test "next" ".*" ""
> -set r1 ".*#define DEF_MACROS"
> -set r2 ".*#define FOO\\(a\\) foo = a"
> -set r3 ".*#define FOUR"
> -set r4 ".*\r\n$gdb_prompt"
>  set testname "$test 7"
> -gdb_test_multiple "$test" $testname {
> -  -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define ONE.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define TWO.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re ".*#define THREE.*\r\n$gdb_prompt" {
> -     fail $testname
> -  }
> -  -re "$r1$r2$r3$r4" {
> -     pass $testname
> -  }
> -}
> +gdb_test_sequence "$test" $testname \
> +    [list \
> +	 "#define DEF_MACROS" \
> +	 "#define FOO\\(a\\) foo = a" \
> +	 "#define FOUR"] \
> +    [list \
> +	 "#define FOO \" \"" \
> +	 "#define FOO \"hello\"" \
> +	 "#define FOO \"world\"" \
> +	 "#define ONE" \
> +	 "#define TWO" \
> +	 "#define THREE"] \
> +    "\r\nDefined at "
>  
>  set test "info macros info-macros.c:42"
>  
> diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
> index 9ca34d8b15..cc907c3ac6 100644
> --- a/gdb/testsuite/lib/gdb.exp
> +++ b/gdb/testsuite/lib/gdb.exp
> @@ -1171,6 +1171,9 @@ proc gdb_test_no_output { args } {
>  # TEST_NAME is passed to pass/fail.  COMMAND is used if TEST_NAME is "".
>  # EXPECTED_OUTPUT_LIST is a list of regexps of expected output, which are
>  # processed in order, and all must be present in the output.
> +# FAIL_LIST is a list or regexps that cause the test to fail
> +# SEP is a regexp that indicates where the output can be discarded using an
> +#   exp_continue
>  #
>  # It is unnecessary to specify ".*" at the beginning or end of any regexp,
>  # there is an implicit ".*" between each element of EXPECTED_OUTPUT_LIST.
> @@ -1184,7 +1187,8 @@ proc gdb_test_no_output { args } {
>  #    0 if the test passes,
>  #   -1 if there was an internal error.
>  
> -proc gdb_test_sequence { command test_name expected_output_list } {
> +proc gdb_test_sequence { command test_name expected_output_list \
> +			     {fail_list "" } {sep ""}} {
>      global gdb_prompt
>      if { $test_name == "" } {
>  	set test_name $command
> @@ -1193,7 +1197,8 @@ proc gdb_test_sequence { command test_name expected_output_list } {
>      if { $command != "" } {
>  	send_gdb "$command\n"
>      }
> -    return [gdb_expect_list $test_name "$gdb_prompt $" $expected_output_list]
> +    return [gdb_expect_list $test_name "$gdb_prompt $" $expected_output_list \
> +		$fail_list $sep]
>  }
>  
>  
> @@ -4103,12 +4108,24 @@ proc gdb_expect { args } {
>      }
>  }
>  
> -# gdb_expect_list TEST SENTINEL LIST -- expect a sequence of outputs
> +# Return a regexp that matches any of the regexp elements in L.
> +proc regexp_or { l } {
> +    if { [llength $l] == 1 } {
> +	return [lindex $l 0]
> +    }
> +    return [join [list "(" [join $l "|" ] ")"] ""]
> +}
> +
> +# gdb_expect_list TEST SENTINEL LIST FAIL_LIST SEP
> +#   -- expect a sequence of outputs
>  #
>  # Check for long sequence of output by parts.
>  # TEST: is the test message to be printed with the test success/fail.
>  # SENTINEL: Is the terminal pattern indicating that output has finished.
>  # LIST: is the sequence of outputs to match.
> +# FAIL_LIST: is a list or regexps that cause the test to fail
> +# SEP: is a regexp that indicates where the output can be discarded using an
> +#   exp_continue
>  # If the sentinel is recognized early, it is considered an error.
>  #
>  # Returns:
> @@ -4116,7 +4133,7 @@ proc gdb_expect { args } {
>  #    0 if the test passes,
>  #   -1 if there was an internal error.
>  
> -proc gdb_expect_list {test sentinel list} {
> +proc gdb_expect_list {test sentinel list {fail_list ""} {sep ""} } {
>      global gdb_prompt
>      global suppress_flag
>      set index 0
> @@ -4125,6 +4142,14 @@ proc gdb_expect_list {test sentinel list} {
>  	set ok 0
>  	unresolved "${test}"
>      }
> +    if { $fail_list == "" } {
> +	set fail_pat {\$^}
> +    } else {
> +	set fail_pat [regexp_or $fail_list]
> +    }
> +    if { $sep == "" } {
> +	set sep {\$^}
> +    }
>      while { ${index} < [llength ${list}] } {
>  	set pattern [lindex ${list} ${index}]
>          set index [expr ${index} + 1]
> @@ -4132,6 +4157,10 @@ proc gdb_expect_list {test sentinel list} {
>  	if { ${index} == [llength ${list}] } {
>  	    if { ${ok} } {
>  		gdb_expect {
> +		    -re "${fail_pat}" {
> +			fail "${test}"
> +			set ok 0
> +		    }
>  		    -re "${pattern}${sentinel}" {
>  			# pass "${test}, pattern ${index} + sentinel"
>  		    }
> @@ -4148,6 +4177,9 @@ proc gdb_expect_list {test sentinel list} {
>  			fail "${test} (pattern ${index} + sentinel) (timeout)"
>  			set ok 0
>  		    }
> +		    -re "${sep}" {
> +			exp_continue
> +		    }
>  		}
>  	    } else {
>  		# unresolved "${test}, pattern ${index} + sentinel"
> @@ -4155,6 +4187,10 @@ proc gdb_expect_list {test sentinel list} {
>  	} else {
>  	    if { ${ok} } {
>  		gdb_expect {
> +		    -re "${fail_pat}" {
> +			fail "${test}"
> +			set ok 0
> +		    }
>  		    -re "${pattern}" {
>  			# pass "${test}, pattern ${index}"
>  		    }
> @@ -4171,6 +4207,9 @@ proc gdb_expect_list {test sentinel list} {
>  			fail "${test} (pattern ${index}) (timeout)"
>  			set ok 0
>  		    }
> +		    -re "${sep}" {
> +			exp_continue
> +		    }
>  		}
>  	    } else {
>  		# unresolved "${test}, pattern ${index}"
>
  

Patch

diff --git a/gdb/testsuite/gdb.base/info-macros.exp b/gdb/testsuite/gdb.base/info-macros.exp
index b76a5bbeef..9f61bd3f2e 100644
--- a/gdb/testsuite/gdb.base/info-macros.exp
+++ b/gdb/testsuite/gdb.base/info-macros.exp
@@ -133,153 +133,102 @@  set testname "$test"
 gdb_test "$test" "$r1$r2$r3$r4" "$testname"
 
 set test "info macros"
-set r1 ".*#define FOO \"hello\""
-set r2 ".*#define ONE"
-set r3 ".*\r\n$gdb_prompt"
 set testname "$test 2"
-gdb_test_multiple "$test" $testname {
-  -re "$r1$r2$r3" {
-     pass $testname
-  }
-  -re ".*#define TWO.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define THREE.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOUR.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-}
+gdb_test_sequence "$test" $testname \
+    [list \
+	 "#define FOO \"hello\"" \
+	 "#define ONE"] \
+    [list \
+	 "#define TWO" \
+	 "#define THREE" \
+	 "#define FOUR"] \
+    "\r\nDefined at "
+
 gdb_test "next" ".*" ""
 
-set r1 ".*#define FOO \" \""
-set r2 ".*#define ONE"
-set r3 ".*#define TWO"
-set r4 ".*\r\n$gdb_prompt"
 set testname "$test 3"
-gdb_test_multiple "$test" $testname {
-  -re ".*#define THREE.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOUR.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re "$r1$r2$r3$r4" {
-     pass $testname
-  }
-}
+gdb_test_sequence "$test" $testname \
+    [list \
+	 "#define FOO \" \"" \
+	 "#define ONE" \
+	 "#define TWO"] \
+    [list \
+	 "#define THREE" \
+	 "#define FOUR"] \
+    "\r\nDefined at "
+
 gdb_test "next" ".*" ""
 
 # in alpabetical order...
-set r1 ".*#define FOO \"world\""
-set r2 ".*#define ONE"
-set r3 ".*#define THREE"
-set r4 ".*#define TWO"
-set r5 ".*\r\n$gdb_prompt"
 set testname "$test 4"
-gdb_test_multiple "$test" $testname {
-  -re ".*#define FOUR.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re "$r1$r2$r3$r4$r5" {
-     pass $testname
-  }
-}
+gdb_test_sequence "$test" $testname \
+    [list \
+	 "#define FOO \"world\"" \
+	 "#define ONE" \
+	 "#define THREE" \
+	 "#define TWO"] \
+    [list "#define FOUR"] \
+    "\r\nDefined at "
+
 # same as above with a linespec.
 set test "info macros *\$pc"
-gdb_test_multiple "$test" $test {
-  -re ".*#define FOUR.*\r\n$gdb_prompt" {
-     fail $test
-  }
-  -re "$r1$r2$r3$r4$r5" {
-     pass $test
-  }
-}
+gdb_test_sequence "$test" $test \
+    [list \
+	 "#define FOO \"world\"" \
+	 "#define ONE" \
+	 "#define THREE" \
+	 "#define TWO"] \
+    [list "#define FOUR"] \
+    "\r\nDefined at "
+
 gdb_test "next" ".*" ""
 
-set r1 ".*#define FOO \" \""
-set r2 ".*#define ONE"
-set r3 ".*#define TWO."
-set r4 ".*\r\n$gdb_prompt"
 set test "info macros"
 set testname "$test 5"
-gdb_test_multiple "$test" $test {
-  -re ".*#define THREE.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOUR.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re "$r1$r2$r3$r4" {
-     pass $testname
-  }
-}
+gdb_test_sequence "$test" $testname \
+    [list \
+	 "#define FOO \" \"" \
+	 "#define ONE" \
+	 "#define TWO."] \
+    [list \
+	 "#define THREE" \
+	 "#define FOUR"] \
+    "\r\nDefined at "
+
 gdb_test "next" ".*" ""
 gdb_test "next" ".*" ""
 
-set r1 ".*#define DEF_MACROS"
-set r2 ".*\r\n$gdb_prompt"
+set r2 "\r\n$gdb_prompt"
 set testname "$test 6"
-gdb_test_multiple "$test" $testname {
-  -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOO\\(a\\) foo = a.*" {
-     fail $testname
-  }
-  -re ".*#define ONE.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define TWO.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define THREE.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOUR.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re "$r1$r2" {
-     pass $testname
-  }
-}
+gdb_test_sequence "$test" $testname \
+    [list \
+	 "#define DEF_MACROS"] \
+    [list \
+	 "#define FOO \" \"" \
+	 "#define FOO \"hello\"" \
+	 "#define FOO \"world\"" \
+	 "#define FOO\\(a\\) foo = a" \
+	 "#define ONE" \
+	 "#define TWO" \
+	 "#define THREE" \
+	 "#define FOUR"] \
+    "\r\nDefined at "
 
 gdb_test "next" ".*" ""
-set r1 ".*#define DEF_MACROS"
-set r2 ".*#define FOO\\(a\\) foo = a"
-set r3 ".*#define FOUR"
-set r4 ".*\r\n$gdb_prompt"
 set testname "$test 7"
-gdb_test_multiple "$test" $testname {
-  -re ".*#define FOO \" \".*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOO \"hello\".*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define FOO \"world\".*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define ONE.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define TWO.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re ".*#define THREE.*\r\n$gdb_prompt" {
-     fail $testname
-  }
-  -re "$r1$r2$r3$r4" {
-     pass $testname
-  }
-}
+gdb_test_sequence "$test" $testname \
+    [list \
+	 "#define DEF_MACROS" \
+	 "#define FOO\\(a\\) foo = a" \
+	 "#define FOUR"] \
+    [list \
+	 "#define FOO \" \"" \
+	 "#define FOO \"hello\"" \
+	 "#define FOO \"world\"" \
+	 "#define ONE" \
+	 "#define TWO" \
+	 "#define THREE"] \
+    "\r\nDefined at "
 
 set test "info macros info-macros.c:42"
 
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 9ca34d8b15..cc907c3ac6 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1171,6 +1171,9 @@  proc gdb_test_no_output { args } {
 # TEST_NAME is passed to pass/fail.  COMMAND is used if TEST_NAME is "".
 # EXPECTED_OUTPUT_LIST is a list of regexps of expected output, which are
 # processed in order, and all must be present in the output.
+# FAIL_LIST is a list or regexps that cause the test to fail
+# SEP is a regexp that indicates where the output can be discarded using an
+#   exp_continue
 #
 # It is unnecessary to specify ".*" at the beginning or end of any regexp,
 # there is an implicit ".*" between each element of EXPECTED_OUTPUT_LIST.
@@ -1184,7 +1187,8 @@  proc gdb_test_no_output { args } {
 #    0 if the test passes,
 #   -1 if there was an internal error.
 
-proc gdb_test_sequence { command test_name expected_output_list } {
+proc gdb_test_sequence { command test_name expected_output_list \
+			     {fail_list "" } {sep ""}} {
     global gdb_prompt
     if { $test_name == "" } {
 	set test_name $command
@@ -1193,7 +1197,8 @@  proc gdb_test_sequence { command test_name expected_output_list } {
     if { $command != "" } {
 	send_gdb "$command\n"
     }
-    return [gdb_expect_list $test_name "$gdb_prompt $" $expected_output_list]
+    return [gdb_expect_list $test_name "$gdb_prompt $" $expected_output_list \
+		$fail_list $sep]
 }
 
 
@@ -4103,12 +4108,24 @@  proc gdb_expect { args } {
     }
 }
 
-# gdb_expect_list TEST SENTINEL LIST -- expect a sequence of outputs
+# Return a regexp that matches any of the regexp elements in L.
+proc regexp_or { l } {
+    if { [llength $l] == 1 } {
+	return [lindex $l 0]
+    }
+    return [join [list "(" [join $l "|" ] ")"] ""]
+}
+
+# gdb_expect_list TEST SENTINEL LIST FAIL_LIST SEP
+#   -- expect a sequence of outputs
 #
 # Check for long sequence of output by parts.
 # TEST: is the test message to be printed with the test success/fail.
 # SENTINEL: Is the terminal pattern indicating that output has finished.
 # LIST: is the sequence of outputs to match.
+# FAIL_LIST: is a list or regexps that cause the test to fail
+# SEP: is a regexp that indicates where the output can be discarded using an
+#   exp_continue
 # If the sentinel is recognized early, it is considered an error.
 #
 # Returns:
@@ -4116,7 +4133,7 @@  proc gdb_expect { args } {
 #    0 if the test passes,
 #   -1 if there was an internal error.
 
-proc gdb_expect_list {test sentinel list} {
+proc gdb_expect_list {test sentinel list {fail_list ""} {sep ""} } {
     global gdb_prompt
     global suppress_flag
     set index 0
@@ -4125,6 +4142,14 @@  proc gdb_expect_list {test sentinel list} {
 	set ok 0
 	unresolved "${test}"
     }
+    if { $fail_list == "" } {
+	set fail_pat {\$^}
+    } else {
+	set fail_pat [regexp_or $fail_list]
+    }
+    if { $sep == "" } {
+	set sep {\$^}
+    }
     while { ${index} < [llength ${list}] } {
 	set pattern [lindex ${list} ${index}]
         set index [expr ${index} + 1]
@@ -4132,6 +4157,10 @@  proc gdb_expect_list {test sentinel list} {
 	if { ${index} == [llength ${list}] } {
 	    if { ${ok} } {
 		gdb_expect {
+		    -re "${fail_pat}" {
+			fail "${test}"
+			set ok 0
+		    }
 		    -re "${pattern}${sentinel}" {
 			# pass "${test}, pattern ${index} + sentinel"
 		    }
@@ -4148,6 +4177,9 @@  proc gdb_expect_list {test sentinel list} {
 			fail "${test} (pattern ${index} + sentinel) (timeout)"
 			set ok 0
 		    }
+		    -re "${sep}" {
+			exp_continue
+		    }
 		}
 	    } else {
 		# unresolved "${test}, pattern ${index} + sentinel"
@@ -4155,6 +4187,10 @@  proc gdb_expect_list {test sentinel list} {
 	} else {
 	    if { ${ok} } {
 		gdb_expect {
+		    -re "${fail_pat}" {
+			fail "${test}"
+			set ok 0
+		    }
 		    -re "${pattern}" {
 			# pass "${test}, pattern ${index}"
 		    }
@@ -4171,6 +4207,9 @@  proc gdb_expect_list {test sentinel list} {
 			fail "${test} (pattern ${index}) (timeout)"
 			set ok 0
 		    }
+		    -re "${sep}" {
+			exp_continue
+		    }
 		}
 	    } else {
 		# unresolved "${test}, pattern ${index}"