[PATCH 0/8] Testing for the TUI

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/8] Testing for the TUI

Tom Tromey-2
While working on another long set of TUI patches, I started
introducing bugs as I made less cosmetic changes.

So, I added a way to test the TUI.  I was keeping this in my
development series, but I realized it would be better to land it
sooner, and then update the tests in the new series.

This series adds a terminal emulator to the gdb test suite, then
provides a few tests to exercise the TUI.  The emulator isn't perfect
by any means -- occasionally I've had to implement a new CSI function
while writing a test -- but it's good enough so far.

If you examine the tests here, you'll see a few uses of setup_xfail.
These were all introduced when backporting to trunk, and will be
removed by my next TUI series.

There are plenty of tests that could still be written.  Coverage in
the TUI is still just 63%.

Tom


Reply | Threaded
Open this post in threaded view
|

[PATCH 1/8] A virtual terminal for the test suite

Tom Tromey-2
This patch implements a simple ANSI terminal emulator for the test
suite.  It is still quite basic, but it is good enough to allow some
simple TUI testing to be done.

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * lib/tuiterm.exp: New file.
        * gdb.tui/basic.exp: New file.
---
 gdb/testsuite/ChangeLog         |   5 +
 gdb/testsuite/gdb.tui/basic.exp |  49 +++
 gdb/testsuite/lib/tuiterm.exp   | 517 ++++++++++++++++++++++++++++++++
 3 files changed, 571 insertions(+)
 create mode 100644 gdb/testsuite/gdb.tui/basic.exp
 create mode 100644 gdb/testsuite/lib/tuiterm.exp

diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
new file mode 100644
index 00000000000..48d39741ba5
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/basic.exp
@@ -0,0 +1,49 @@
+# Copyright 2019 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/>.
+
+# Basic TUI tests.
+
+load_lib "tuiterm.exp"
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+}
+
+set text [Term::get_all_lines]
+if {[string match "No Source Available" $text]} {
+    fail "initial source listing"
+} else {
+    pass "initial source listing"
+}
+
+Term::command "list main"
+set text [Term::get_all_lines]
+if {[regexp "21 *return 0" $text]} {
+    pass "list main"
+} else {
+    fail "list main"
+}
+
+# This check fails because the file name in the title overwrites the
+# box.
+setup_xfail *-*-*
+Term::check_box "source box" 3 0 77 15
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
new file mode 100644
index 00000000000..2b0af86c48c
--- /dev/null
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -0,0 +1,517 @@
+# Copyright 2019 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/>.
+
+# An ANSI terminal emulator for expect.
+
+namespace eval Term {
+    variable _rows
+    variable _cols
+    variable _chars
+
+    variable _cur_x
+    variable _cur_y
+
+    variable _attrs
+
+    variable _last_char
+
+    # If ARG is empty, return DEF: otherwise ARG.  This is useful for
+    # defaulting arguments in CSIs.
+    proc _default {arg def} {
+ if {$arg == ""} {
+    return $def
+ }
+ return $arg
+    }
+
+    # Erase in the line Y from SX to just before EX.
+    proc _clear_in_line {sx ex y} {
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ while {$sx < $ex} {
+    set _chars($sx,$y) [list " " $lattr]
+    incr sx
+ }
+    }
+
+    # Erase the lines from SY to just before EY.
+    proc _clear_lines {sy ey} {
+ variable _cols
+ while {$sy < $ey} {
+    _clear_in_line 0 $_cols $sy
+    incr sy
+ }
+    }
+
+    # Beep.
+    proc _ctl_0x07 {} {
+    }
+
+    # Backspace.
+    proc _ctl_0x08 {} {
+ variable _cur_x
+ incr _cur_x -1
+ if {$_cur_x < 0} {
+    variable _cur_y
+    variable _cols
+    set _cur_x [expr {$_cols - 1}]
+    incr _cur_y -1
+    if {$_cur_y < 0} {
+ set _cur_y 0
+    }
+ }
+    }
+
+    # Linefeed.
+    proc _ctl_0x0a {} {
+ variable _cur_y
+ variable _rows
+ incr _cur_y 1
+ if {$_cur_y >= $_rows} {
+    error "FIXME scroll"
+ }
+    }
+
+    # Carriage return.
+    proc _ctl_0x0d {} {
+ variable _cur_x
+ set _cur_x 0
+    }
+
+    # Cursor Up.
+    proc _csi_A {args} {
+ variable _cur_y
+ set arg [_default [lindex $args 0] 1]
+ set _cur_y [expr {max ($_cur_y - $arg, 0)}]
+    }
+
+    # Cursor Down.
+    proc _csi_B {args} {
+ variable _cur_y
+ variable _rows
+ set arg [_default [lindex $args 0] 1]
+ set _cur_y [expr {min ($_cur_y + $arg, $_rows)}]
+    }
+
+    # Cursor Forward.
+    proc _csi_C {args} {
+ variable _cur_x
+ variable _cols
+ set arg [_default [lindex $args 0] 1]
+ set _cur_x [expr {min ($_cur_x + $arg, $_cols)}]
+    }
+
+    # Cursor Back.
+    proc _csi_D {args} {
+ variable _cur_x
+ set arg [_default [lindex $args 0] 1]
+ set _cur_x [expr {max ($_cur_x - $arg, 0)}]
+    }
+
+    # Cursor Next Line.
+    proc _csi_E {args} {
+ variable _cur_x
+ variable _cur_y
+ variable _rows
+ set arg [_default [lindex $args 0] 1]
+ set _cur_x 0
+ set _cur_y [expr {min ($_cur_y + $arg, $_rows)}]
+    }
+
+    # Cursor Previous Line.
+    proc _csi_F {args} {
+ variable _cur_x
+ variable _cur_y
+ variable _rows
+ set arg [_default [lindex $args 0] 1]
+ set _cur_x 0
+ set _cur_y [expr {max ($_cur_y - $arg, 0)}]
+    }
+
+    # Cursor Horizontal Absolute.
+    proc _csi_G {args} {
+ variable _cur_x
+ variable _cols
+ set arg [_default [lindex $args 0] 1]
+ set _cur_x [expr {min ($arg - 1, $_cols)}]
+    }
+
+    # Move cursor (don't know the official name of this one).
+    proc _csi_H {args} {
+ variable _cur_x
+ variable _cur_y
+ set _cur_y [expr {[_default [lindex $args 0] 1] - 1}]
+ set _cur_x [expr {[_default [lindex $args 1] 1] - 1}]
+    }
+
+    # Cursor Forward Tabulation.
+    proc _csi_I {args} {
+ set n [_default [lindex $args 0] 1]
+ variable _cur_x
+ variable _cols
+ incr _cur_x [expr {$n * 8 - $_cur_x % 8}]
+ if {$_cur_x >= $_cols} {
+    set _cur_x [expr {$_cols - 1}]
+ }
+    }
+
+    # Erase.
+    proc _csi_J {args} {
+ variable _cur_x
+ variable _cur_y
+ variable _rows
+ variable _cols
+ set arg [_default [lindex $args 0] 0]
+ if {$arg == 0} {
+    _clear_in_line $_cur_x $_cols $_cur_y
+    _clear_lines [expr {$_cur_y + 1}] $_rows
+ } elseif {$arg == 1} {
+    _clear_lines 0 [expr {$_cur_y - 1}]
+    _clear_in_line 0 $_cur_x $_cur_y
+ } elseif {$arg == 2} {
+    _clear_lines 0 $_rows
+ }
+    }
+
+    # Erase Line.
+    proc _csi_K {args} {
+ variable _cur_x
+ variable _cur_y
+ variable _cols
+ set arg [_default [lindex $args 0] 0]
+ if {$arg == 0} {
+    # From cursor to end.
+    _clear_in_line $_cur_x $_cols $_cur_y
+ } elseif {$arg == 1} {
+    _clear_in_line 0 $_cur_x $_cur_y
+ } elseif {$arg == 2} {
+    _clear_in_line 0 $_cols $_cur_y
+ }
+    }
+
+    # Delete lines.
+    proc _csi_M {args} {
+ variable _cur_y
+ variable _rows
+ variable _cols
+ variable _chars
+ set count [_default [lindex $args 0] 1]
+ set y $_cur_y
+ set next_y [expr {$y + 1}]
+ while {$count > 0 && $next_y < $_rows} {
+    for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$y) $_chars($x,$next_y)
+    }
+    incr y
+    incr next_y
+    incr count -1
+ }
+ _clear_lines $next_y $_rows
+    }
+
+    # Erase chars.
+    proc _csi_X {args} {
+ set n [_default [lindex $args 0] 1]
+ _insert [string repeat " " $n]
+    }
+
+    # Repeat.
+    proc _csi_b {args} {
+ variable _last_char
+ set n [_default [lindex $args 0] 1]
+ _insert [string repeat $_last_char $n]
+    }
+
+    # Line Position Absolute.
+    proc _csi_d {args} {
+ variable _cur_y
+ set _cur_y [expr {[_default [lindex $args 0] 1] - 1}]
+    }
+
+    # Select Graphic Rendition.
+    proc _csi_m {args} {
+ variable _attrs
+ foreach item $args {
+    switch -exact -- $item {
+ "" - 0 {
+    set _attrs(intensity) normal
+    set _attrs(fg) default
+    set _attrs(bg) default
+    set _attrs(underline) 0
+    set _attrs(reverse) 0
+ }
+ 1 {
+    set _attrs(intensity) bold
+ }
+ 2 {
+    set _attrs(intensity) dim
+ }
+ 4 {
+    set _attrs(underline) 1
+ }
+ 7 {
+    set _attrs(reverse) 1
+ }
+ 22 {
+    set _attrs(intensity) normal
+ }
+ 24 {
+    set _attrs(underline) 0
+ }
+ 27 {
+    set _attrs(reverse) 1
+ }
+ 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
+    set _attrs(fg) $item
+ }
+ 39 {
+    set _attrs(fg) default
+ }
+ 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 {
+    set _attrs(bg) $item
+ }
+ 49 {
+    set _attrs(bg) default
+ }
+    }
+ }
+    }
+
+    # Insert string at the cursor location.
+    proc _insert {str} {
+ verbose "INSERT <<$str>>"
+ variable _cur_x
+ variable _cur_y
+ variable _rows
+ variable _cols
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ foreach char [split $str {}] {
+    set _chars($_cur_x,$_cur_y) [list $char $lattr]
+    incr _cur_x
+    if {$_cur_x >= $_cols} {
+ set _cur_x 0
+ incr _cur_y
+ if {$_cur_y >= $_rows} {
+    error "FIXME scroll"
+ }
+    }
+ }
+    }
+
+    # Initialize.
+    proc _setup {rows cols} {
+ global stty_init
+ set stty_init "rows $rows columns $cols"
+
+ variable _rows
+ variable _cols
+ variable _cur_x
+ variable _cur_y
+ variable _attrs
+
+ set _rows $rows
+ set _cols $cols
+ set _cur_x 0
+ set _cur_y 0
+ array set _attrs {
+    intensity normal
+    fg default
+    bg default
+    underline 0
+    reverse 0
+ }
+
+ _clear_lines 0 $_rows
+    }
+
+    # Accept some output from gdb and update the screen.
+    proc _accept {} {
+ global expect_out
+ gdb_expect {
+    -re "^\[\x07\x08\x0a\x0d\]" {
+ scan $expect_out(0,string) %c val
+ set hexval [format "%02x" $val]
+ verbose "+++ _ctl_0x${hexval}"
+ _ctl_0x${hexval}
+ exp_continue
+    }
+    -re "^\x1b(\[0-9a-zA-Z\])" {
+ verbose "+++ unsupported escape"
+ error "unsupported escape"
+    }
+    -re "^\x1b\\\[(\[0-9;\]*)(\[0-9a-zA-Z@\])" {
+ set cmd $expect_out(2,string)
+ set params [split $expect_out(1,string) ";"]
+ verbose "+++ _csi_$cmd <<<$expect_out(1,string)>>>"
+ eval _csi_$cmd $params
+ exp_continue
+    }
+    -re "^\[^\x07\x08\x0a\x0d\x1b\]+" {
+ _insert $expect_out(0,string)
+ variable _last_char
+ set _last_char [string index $expect_out(0,string) end]
+ # If the prompt was just inserted, return.
+ variable _cur_x
+ variable _cur_y
+ global gdb_prompt
+ set prev [get_line $_cur_y $_cur_x]
+ if {![regexp -- "$gdb_prompt \$" $prev]} {
+    exp_continue
+ }
+    }
+ }
+    }
+
+    # Like ::clean_restart, but ensures that gdb starts in an
+    # environment where the TUI can work.  ROWS and COLS are the size
+    # of the terminal.  EXECUTABLE is passed to clean_restart.
+    proc clean_restart {rows cols executable} {
+ global env stty_init
+ save_vars {env(TERM) stty_init} {
+    setenv TERM ansi
+    _setup $rows $cols
+    ::clean_restart $executable
+ }
+    }
+
+    # Start the TUI.  Returns 1 on success, 0 if TUI tests should be
+    # skipped.
+    proc enter_tui {} {
+ if {[skip_tui_tests]} {
+    return 0
+ }
+
+ gdb_test_no_output "set tui border-kind ascii"
+ command "tui enable"
+ return 1
+    }
+
+    # Send the command CMD to gdb, then wait for a gdb prompt to be
+    # seen in the TUI.  CMD should not end with a newline -- that will
+    # be supplied by this function.
+    proc command {cmd} {
+ send_gdb "$cmd\n"
+ _accept
+    }
+
+    # Return the text of screen line N, without attributes.  Lines are
+    # 0-based.  If C is given, stop before column C.  Columns are also
+    # zero-based.
+    proc get_line {n {c ""}} {
+ set result ""
+ variable _cols
+ variable _chars
+ set c [_default $c $_cols]
+ set x 0
+ while {$x < $c} {
+    append result [lindex $_chars($x,$n) 0]
+    incr x
+ }
+ return $result
+    }
+
+    # Get just the character at (X, Y).
+    proc get_char {x y} {
+ variable _chars
+ return [lindex $_chars($x,$y) 0]
+    }
+
+    # Get the entire screen as a string.
+    proc get_all_lines {} {
+ variable _rows
+ variable _cols
+ variable _chars
+
+ set result ""
+ for {set y 0} {$y < $_rows} {incr y} {
+    for {set x 0} {$x < $_cols} {incr x} {
+ append result [lindex $_chars($x,$y) 0]
+    }
+    append result "\n"
+ }
+
+ return $result
+    }
+
+    # Get the text just before the cursor.
+    proc get_current_line {} {
+ variable _cur_x
+ variable _cur_y
+ return [get_line $_cur_y $_cur_x]
+    }
+
+    # Helper function for check_box.  Returns empty string if the box
+    # is found, description of why not otherwise.
+    proc _check_box {x y width height} {
+ set x2 [expr {$x + $width - 1}]
+ set y2 [expr {$y + $height - 1}]
+
+ if {[get_char $x $y] != "+"} {
+    return "ul corner"
+ }
+ if {[get_char $x $y2] != "+"} {
+    return "ll corner"
+ }
+ if {[get_char $x2 $y] != "+"} {
+    return "ur corner"
+ }
+ if {[get_char $x2 $y2] != "+"} {
+    return "lr corner"
+ }
+
+ for {set i [expr {$x + 1}]} {$i < $x2 - 1} {incr i} {
+    # Note we do not check the top border of the box, because
+    # it will contain a title.
+    if {[get_char $i $y2] != "-"} {
+ return "bottom border $i"
+    }
+ }
+ for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} {
+    if {[get_char $x $i] != "|"} {
+ return "left side $i"
+    }
+    if {[get_char $x2 $i] != "|"} {
+ return "right side $i"
+    }
+ }
+
+ return ""
+    }
+
+    # Check for a box at the given coordinates.
+    proc check_box {test_name x y width height} {
+ set why [_check_box $x $y $width $height]
+ if {$why == ""} {
+    pass $test_name
+ } else {
+    dump_screen
+    fail "$test_name ($why)"
+ }
+    }
+
+    # A debugging function to dump the current screen, with line
+    # numbers.
+    proc dump_screen {} {
+ variable _rows
+ verbose "Screen Dump:"
+ for {set y 0} {$y < $_rows} {incr y} {
+    set fmt [format %5d $y]
+    verbose "$fmt [get_line $y]"
+ }
+    }
+}
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/8] Add test for "layout asm"

Tom Tromey-2
In reply to this post by Tom Tromey-2
This adds a very simple test for "layout asm".

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * gdb.tui/basic.exp: Add "layout asm" test.
---
 gdb/testsuite/ChangeLog         |  4 ++++
 gdb/testsuite/gdb.tui/basic.exp | 10 ++++++++++
 2 files changed, 14 insertions(+)

diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
index 48d39741ba5..1eeeaa77606 100644
--- a/gdb/testsuite/gdb.tui/basic.exp
+++ b/gdb/testsuite/gdb.tui/basic.exp
@@ -47,3 +47,13 @@ if {[regexp "21 *return 0" $text]} {
 # box.
 setup_xfail *-*-*
 Term::check_box "source box" 3 0 77 15
+
+Term::command "layout asm"
+set text [Term::get_all_lines]
+if {[regexp "$hex <main>" $text]} {
+    pass "asm window shows main"
+} else {
+    fail "asm window shows main"
+}
+
+Term::check_box "asm box" 3 0 77 15
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

[PATCH 3/8] Add "layout split" test

Tom Tromey-2
In reply to this post by Tom Tromey-2
This adds a test of "layout split" to the TUI test suite.

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * gdb.tui/basic.exp: Add "layout split" test.
---
 gdb/testsuite/ChangeLog         |  4 ++++
 gdb/testsuite/gdb.tui/basic.exp | 14 ++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
index 1eeeaa77606..086a6b7d820 100644
--- a/gdb/testsuite/gdb.tui/basic.exp
+++ b/gdb/testsuite/gdb.tui/basic.exp
@@ -57,3 +57,17 @@ if {[regexp "$hex <main>" $text]} {
 }
 
 Term::check_box "asm box" 3 0 77 15
+
+Term::command "layout split"
+set text [Term::get_all_lines]
+if {[regexp "21 *return 0.*$hex <main>" $text]} {
+    pass "split layout contents"
+} else {
+    fail "split layout contents"
+}
+
+# This check fails because the file name in the title overwrites the
+# box.
+setup_xfail *-*-*
+Term::check_box "source box in split layout" 3 0 77 8
+Term::check_box "asm box in split layout" 3 7 77 8
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

[PATCH 4/8] Add TUI register window test

Tom Tromey-2
In reply to this post by Tom Tromey-2
This adds a very simple test of the TUI register window.

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * gdb.tui/regs.exp: New file.
---
 gdb/testsuite/ChangeLog        |  4 +++
 gdb/testsuite/gdb.tui/regs.exp | 58 ++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)
 create mode 100644 gdb/testsuite/gdb.tui/regs.exp

diff --git a/gdb/testsuite/gdb.tui/regs.exp b/gdb/testsuite/gdb.tui/regs.exp
new file mode 100644
index 00000000000..8fc466865c1
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/regs.exp
@@ -0,0 +1,58 @@
+# Copyright 2019 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/>.
+
+# Simple test of TUI register window.
+
+load_lib "tuiterm.exp"
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+
+if {![runto_main]} {
+    perror "test suppressed"
+    return
+}
+
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+}
+
+set text [Term::get_all_lines]
+if {[regexp ">|21 *return 0" $text]} {
+    pass "source at startup"
+} else {
+    Term::dump_screen
+    fail "source at startup"
+}
+
+Term::command "layout regs"
+Term::check_box "register box" 0 0 80 8
+# This check fails because the file name in the title overwrites the
+# box.
+setup_xfail *-*-*
+Term::check_box "source box in regs layout" 0 7 80 8
+
+set text [Term::get_line 1]
+# Just check for any register window content at all.
+if {[regexp "^|.*\[^ \].*|$" $text]} {
+    pass "any register contents"
+} else {
+    fail "any register contents"
+}
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

[PATCH 5/8] Add TUI test for "list"

Tom Tromey-2
In reply to this post by Tom Tromey-2
This adds a test to check that the "list" command will update the TUI
source window.

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * gdb.tui/list.exp: New file.
---
 gdb/testsuite/ChangeLog        |  4 +++
 gdb/testsuite/gdb.tui/list.exp | 52 ++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 gdb/testsuite/gdb.tui/list.exp

diff --git a/gdb/testsuite/gdb.tui/list.exp b/gdb/testsuite/gdb.tui/list.exp
new file mode 100644
index 00000000000..cd9f0717daf
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/list.exp
@@ -0,0 +1,52 @@
+# Copyright 2019 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/>.
+
+# Ensure that "list" will switch to the source view.
+
+load_lib "tuiterm.exp"
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+}
+
+set text [Term::get_all_lines]
+if {[regexp "No Source Available" $text]} {
+    pass "initial source listing"
+} else {
+    fail "initial source listing"
+}
+
+Term::command "layout asm"
+set text [Term::get_all_lines]
+if {[regexp "$hex <main>" $text]} {
+    pass "asm window shows main"
+} else {
+    fail "asm window shows main"
+}
+
+Term::command "list main"
+set text [Term::get_all_lines]
+if {[regexp "21 *return 0" $text]} {
+    pass "list main"
+} else {
+    fail "list main"
+}
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

[PATCH 6/8] Add TUI resizing test

Tom Tromey-2
In reply to this post by Tom Tromey-2
This adds a test case that resizes the terminal and then checks that
the TUI updates properly.

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * lib/tuiterm.exp (spawn): New proc.
        (Term::resize): New proc.
        * gdb.tui/resize.exp: New file.
---
 gdb/testsuite/ChangeLog          |  6 ++++
 gdb/testsuite/gdb.tui/resize.exp | 48 ++++++++++++++++++++++++++++++++
 gdb/testsuite/lib/tuiterm.exp    | 45 ++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 gdb/testsuite/gdb.tui/resize.exp

diff --git a/gdb/testsuite/gdb.tui/resize.exp b/gdb/testsuite/gdb.tui/resize.exp
new file mode 100644
index 00000000000..675fce8ab0c
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/resize.exp
@@ -0,0 +1,48 @@
+# Copyright 2019 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/>.
+
+# Test TUI resizing.
+
+load_lib "tuiterm.exp"
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+Term::clean_restart 24 80 $testfile
+
+if {![runto_main]} {
+    perror "test suppressed"
+    return
+}
+
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+}
+
+set text [Term::get_all_lines]
+if {[regexp ">|21 *return 0" $text]} {
+    pass "source at startup"
+} else {
+    Term::dump_screen
+    fail "source at startup"
+}
+
+Term::resize 40 90
+# Resizing seems to be somewhat broken.
+setup_xfail *-*-*
+Term::check_box "source box after resize" 0 0 90 23
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index 2b0af86c48c..3fc4fcb614a 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -15,6 +15,19 @@
 
 # An ANSI terminal emulator for expect.
 
+# The expect "spawn" function puts the tty name into the spawn_out
+# array; but dejagnu doesn't export this globally.  So, we have to
+# wrap spawn with our own function, so that we can capture this value.
+# The value is later used in calls to stty.
+rename spawn builtin_spawn
+proc spawn {args} {
+    set result [uplevel builtin_spawn $args]
+    global gdb_spawn_name
+    upvar spawn_out spawn_out
+    set gdb_spawn_name $spawn_out(slave,name)
+    return $result
+}
+
 namespace eval Term {
     variable _rows
     variable _cols
@@ -514,4 +527,36 @@ namespace eval Term {
     verbose "$fmt [get_line $y]"
  }
     }
+
+    # Resize the terminal.
+    proc resize {rows cols} {
+ variable _chars
+ variable _rows
+ variable _cols
+
+ set old_rows [expr {min ($_rows, $rows)}]
+ set old_cols [expr {min ($_cols, $cols)}]
+
+ # Copy locally.
+ array set local_chars [array get _chars]
+ unset _chars
+
+ set _rows $rows
+ set _cols $cols
+ _clear_lines 0 $_rows
+
+ for {set x 0} {$x < $old_cols} {incr x} {
+    for {set y 0} {$y < $old_rows} {incr y} {
+ set _chars($x,$y) $local_chars($x,$y)
+    }
+ }
+
+ global gdb_spawn_name
+ # Somehow the number of columns transmitted to gdb is one less
+ # than what we request from expect.  We hide this weird
+ # details from the caller.
+ stty rows $_rows columns [expr {$_cols + 1}] \
+    < $gdb_spawn_name
+ _accept
+    }
 }
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

[PATCH 7/8] Add test case for empty TUI windows

Tom Tromey-2
In reply to this post by Tom Tromey-2
My original intent here was to add a test case to test that empty TUI
windows re-render their contents after a resize.  However, this seems
pretty broken at the moment, so a lot of the test is actually
disabled.

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * lib/tuiterm.exp (Term::clean_restart): Make "executable"
        optional.
        * gdb.tui/empty.exp: New file.
---
 gdb/testsuite/ChangeLog         |   6 ++
 gdb/testsuite/gdb.tui/empty.exp | 108 ++++++++++++++++++++++++++++++++
 gdb/testsuite/lib/tuiterm.exp   |  11 +++-
 3 files changed, 122 insertions(+), 3 deletions(-)
 create mode 100644 gdb/testsuite/gdb.tui/empty.exp

diff --git a/gdb/testsuite/gdb.tui/empty.exp b/gdb/testsuite/gdb.tui/empty.exp
new file mode 100644
index 00000000000..e24ac58f718
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/empty.exp
@@ -0,0 +1,108 @@
+# Copyright 2019 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/>.
+
+# Test TUI resizing with empty windows.
+
+load_lib "tuiterm.exp"
+
+standard_testfile
+
+Term::clean_restart 24 80
+
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+}
+
+# Each entry describes a layout.  It has these items:
+# 1. Layout name
+# 2. Test name
+# 3. List of boxes in 80x24 mode
+# 4. List of boxes in 90x40 mode
+# 5. List of test name and text for the empty window
+set layouts {
+    {src src {{3 0 77 15}} {{3 0 87 23}}
+ {{"no source" "No Source Available"}}}
+    {regs src-regs {{0 0 80 8} {3 7 77 8}} {{0 0 90 13} {3 13 87 13}}
+ {
+    {"no source" "No Source Available"}
+    {"no regs" "Register Values Unavailable"}
+ }}
+    {asm asm {{3 0 77 15}} {{3 0 87 24}}
+ {"no asm" "No Assembly Available"}}
+    {regs asm-regs {{0 0 80 8} {3 7 77 9}} {{0 0 90 13} {3 13 87 14}}
+ {
+    {"no asm" "No Assembly Available"}
+    {"no regs" "Register Values Unavailable"}
+ }}
+    {split split {{3 0 77 8} {3 7 77 9}} {{3 0 87 14} {3 14 87 14}}
+ {
+    {"no source" "No Source Available"}
+    {"no asm" "No Assembly Available"}
+ }}
+    {regs split-regs {{0 0 80 8} {3 7 77 9}} {{0 0 90 13} {3 13 87 14}}
+ {
+    {"no asm" "No Assembly Available"}
+    {"no regs" "Register Values Unavailable"}
+ }}
+}
+
+# Helper function to verify a list of boxes.
+proc check_boxes {boxes} {
+    set boxno 1
+    foreach box $boxes {
+ if {$boxno > 1} {
+    # The upper-left corner of the second box may not render
+    # properly, due to overlap.
+    setup_xfail *-*-*
+ }
+ eval Term::check_box [list "box $boxno"] $box
+ incr boxno
+    }
+}
+
+# Helper function to verify text.
+proc check_text {text_list} {
+    set text [Term::get_all_lines]
+    foreach item $text_list {
+ lassign $item testname check
+ if {[string first $check $text]} {
+    pass $testname
+ } else {
+    fail $testname
+ }
+    }
+
+}
+
+foreach layout $layouts {
+    lassign $layout name testname small_boxes large_boxes text_list
+
+    with_test_prefix $testname {
+ Term::command "layout $name"
+ with_test_prefix 80x24 {
+    check_boxes $small_boxes
+    check_text $text_list
+ }
+
+ # FIXME: resizing is broken enough that we don't test it for
+ # now.
+ # Term::resize 40 90
+ # with_test_prefix 90x40 {
+ #     check_boxes $large_boxes
+ #     check_text $text_list
+ # }
+ # Term::resize 24 80
+    }
+}
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index 3fc4fcb614a..e56e4a48952 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -392,13 +392,18 @@ namespace eval Term {
 
     # Like ::clean_restart, but ensures that gdb starts in an
     # environment where the TUI can work.  ROWS and COLS are the size
-    # of the terminal.  EXECUTABLE is passed to clean_restart.
-    proc clean_restart {rows cols executable} {
+    # of the terminal.  EXECUTABLE, if given, is passed to
+    # clean_restart.
+    proc clean_restart {rows cols {executable {}}} {
  global env stty_init
  save_vars {env(TERM) stty_init} {
     setenv TERM ansi
     _setup $rows $cols
-    ::clean_restart $executable
+    if {$executable == ""} {
+ ::clean_restart
+    } else {
+ ::clean_restart $executable
+    }
  }
     }
 
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

[PATCH 8/8] Add test that "file" shows "main"

Tom Tromey-2
In reply to this post by Tom Tromey-2
This adds a new test that checks that the "file" command will show the
program's "main".

gdb/testsuite/ChangeLog
2019-07-21  Tom Tromey  <[hidden email]>

        * gdb.tui/main.exp: New file.
---
 gdb/testsuite/ChangeLog        |  4 ++++
 gdb/testsuite/gdb.tui/main.exp | 40 ++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)
 create mode 100644 gdb/testsuite/gdb.tui/main.exp

diff --git a/gdb/testsuite/gdb.tui/main.exp b/gdb/testsuite/gdb.tui/main.exp
new file mode 100644
index 00000000000..5e2424a2fe4
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/main.exp
@@ -0,0 +1,40 @@
+# Copyright 2019 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/>.
+
+# Test that "file" shows "main".
+
+load_lib "tuiterm.exp"
+
+standard_testfile tui-layout.c
+
+if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} {
+    return -1
+}
+
+# Note: don't pass the executable here
+Term::clean_restart 24 80
+
+if {![Term::enter_tui]} {
+    unsupported "TUI not supported"
+}
+
+Term::command "file [standard_output_file $testfile]"
+set text [Term::get_all_lines]
+if {[regexp ">|21 *return 0" $text]} {
+    pass "show main after file"
+} else {
+    Term::dump_screen
+    fail "show main after file"
+}
--
2.17.2

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/8] Add test for "layout asm"

Andrew Burgess
In reply to this post by Tom Tromey-2
* Tom Tromey <[hidden email]> [2019-07-21 12:49:04 -0600]:

> This adds a very simple test for "layout asm".
>
> gdb/testsuite/ChangeLog
> 2019-07-21  Tom Tromey  <[hidden email]>
>
> * gdb.tui/basic.exp: Add "layout asm" test.
> ---
>  gdb/testsuite/ChangeLog         |  4 ++++
>  gdb/testsuite/gdb.tui/basic.exp | 10 ++++++++++
>  2 files changed, 14 insertions(+)
>
> diff --git a/gdb/testsuite/gdb.tui/basic.exp b/gdb/testsuite/gdb.tui/basic.exp
> index 48d39741ba5..1eeeaa77606 100644
> --- a/gdb/testsuite/gdb.tui/basic.exp
> +++ b/gdb/testsuite/gdb.tui/basic.exp
> @@ -47,3 +47,13 @@ if {[regexp "21 *return 0" $text]} {
>  # box.
>  setup_xfail *-*-*
>  Term::check_box "source box" 3 0 77 15
> +
> +Term::command "layout asm"
> +set text [Term::get_all_lines]
> +if {[regexp "$hex <main>" $text]} {
> +    pass "asm window shows main"
> +} else {
> +    fail "asm window shows main"
> +}

Wow! This is awesome!  Hopefully this can really drive TUI testing
forward.

I noticed this pattern a lot in this series, I wonder if using
'gdb_assert' would be cleaner?

It even returns true/false so you can do (looking at patch #5 if in
the series):

  if {![gdb_assert {[...condition]} "test name"]} {
    Term::dump_screen
  }

Thanks,
Andrew

> +
> +Term::check_box "asm box" 3 0 77 15
> --
> 2.17.2
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/8] Add test for "layout asm"

Tom Tromey-2
>>>>> "Andrew" == Andrew Burgess <[hidden email]> writes:

Andrew> I noticed this pattern a lot in this series, I wonder if using
Andrew> 'gdb_assert' would be cleaner?

Thanks for mentioning this.  I wasn't aware of gdb_assert.

I've made this change and I'll send the new series momentarily.
I'd like to land this soon, because my next round of TUI refactorings is
about ready to send, and it needs the tests.

Tom