1# Copyright 2002, 2003, 2004 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 2 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program; if not, write to the Free Software 15# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 17# Please email any bugs, comments, and/or additions to this file to: 18# bug-gdb@prep.ai.mit.edu 19 20# This file tests MI thread commands. 21# Specifically, we are testing the MI command set and the console (in MI) 22# command set ("interpreter-exec") and that the commands that are executed 23# via these command pathways are properly executed. Console commands 24# executed via MI should use MI output wrappers, MI event handlers, etc. 25 26# This only works with native configurations 27if {![isnative]} { 28 return 29} 30 31load_lib mi-support.exp 32set MIFLAGS "-i=mi" 33 34gdb_exit 35if {[mi_gdb_start]} { 36 continue 37} 38 39# The procs below dealing with parsing cli/mi output for the threadlist 40# is duplicated in gdb669.exp. Any changes here will probably need to 41# be made there as well. 42 43proc get_mi_thread_list {name} { 44 global expect_out 45 46 # MI will return a list of thread ids: 47 # 48 # -thread-list-ids 49 # ^done,thread-ids=[thread-id="1",thread-id="2",...],number-of-threads="N" 50 # (gdb) 51 mi_gdb_test "-thread-list-ids" \ 52 {\^done,thread-ids={(thread-id="[0-9]+"(,)?)+},number-of-threads="[0-9]+"} \ 53 "-thread_list_ids ($name)" 54 55 set output {} 56 if {[info exists expect_out(buffer)]} { 57 set output $expect_out(buffer) 58 } 59 60 set thread_list {} 61 if {![regexp {thread-ids=\{(thread-id="[0-9]+"(,)?)*\}} $output threads]} { 62 fail "finding threads in MI output ($name)" 63 } else { 64 pass "finding threads in MI output ($name)" 65 66 # Make list of console threads 67 set start [expr {[string first \{ $threads] + 1}] 68 set end [expr {[string first \} $threads] - 1}] 69 set threads [string range $threads $start $end] 70 foreach thread [split $threads ,] { 71 if {[scan $thread {thread-id="%d"} num]} { 72 lappend thread_list $num 73 } 74 } 75 } 76 77 return $thread_list 78} 79 80# Check that MI and the console know of the same threads. 81# Appends NAME to all test names. 82proc check_mi_and_console_threads {name} { 83 global expect_out 84 85 mi_gdb_test "-thread-list-ids" \ 86 {\^done,thread-ids={(thread-id="[0-9]+"(,)*)+},number-of-threads="[0-9]+"} \ 87 "-thread-list-ids ($name)" 88 set mi_output {} 89 if {[info exists expect_out(buffer)]} { 90 set mi_output $expect_out(buffer) 91 } 92 93 # GDB will return a list of thread ids and some more info: 94 # 95 # (gdb) 96 # -interpreter-exec console "info threads" 97 # ~" 4 Thread 2051 (LWP 7734) 0x401166b1 in __libc_nanosleep () at __libc_nanosleep:-1" 98 # ~" 3 Thread 1026 (LWP 7733) () at __libc_nanosleep:-1" 99 # ~" 2 Thread 2049 (LWP 7732) 0x401411f8 in __poll (fds=0x804bb24, nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:63" 100 # ~"* 1 Thread 1024 (LWP 7731) main (argc=1, argv=0xbfffdd94) at ../../../src/gdb/testsuite/gdb.mi/pthreads.c:160" 101 # FIXME: kseitz/2002-09-05: Don't use the hack-cli method. 102 mi_gdb_test "info threads" \ 103 {.*(~".*"[\r\n]*)+.*} \ 104 "info threads ($name)" 105 set console_output {} 106 if {[info exists $expect_out(buffer)]} { 107 set console_output $expect_out(buffer) 108 } 109 110 # Make a list of all known threads to console (gdb's thread IDs) 111 set console_thread_list {} 112 foreach line [split $console_output \n] { 113 if {[string index $line 0] == "~"} { 114 # This is a line from the console; trim off "~", " ", "*", and "\"" 115 set line [string trim $line ~\ \"\*] 116 if {[scan $line "%d" id] == 1} { 117 lappend console_thread_list $id 118 } 119 } 120 } 121 122 # Now find the result string from MI 123 set mi_result "" 124 foreach line [split $mi_output \n] { 125 if {[string range $line 0 4] == "^done"} { 126 set mi_result $line 127 } 128 } 129 if {$mi_result == ""} { 130 fail "finding MI result string ($name)" 131 } else { 132 pass "finding MI result string ($name)" 133 } 134 135 # Finally, extract the thread ids and compare them to the console 136 set num_mi_threads_str "" 137 if {![regexp {number-of-threads="[0-9]+"} $mi_result num_mi_threads_str]} { 138 fail "finding number of threads in MI output ($name)" 139 } else { 140 pass "finding number of threads in MI output ($name)" 141 142 # Extract the number of threads from the MI result 143 if {![scan $num_mi_threads_str {number-of-threads="%d"} num_mi_threads]} { 144 fail "got number of threads from MI ($name)" 145 } else { 146 pass "got number of threads from MI ($name)" 147 148 # Check if MI and console have same number of threads 149 if {$num_mi_threads != [llength $console_thread_list]} { 150 fail "console and MI have same number of threads ($name)" 151 } else { 152 pass "console and MI have same number of threads ($name)" 153 154 # Get MI thread list 155 set mi_thread_list [get_mi_thread_list $name] 156 157 # Check if MI and console have the same threads 158 set fails 0 159 foreach ct [lsort $console_thread_list] mt [lsort $mi_thread_list] { 160 if {$ct != $mt} { 161 incr fails 162 } 163 } 164 if {$fails > 0} { 165 fail "MI and console have same threads ($name)" 166 167 # Send a list of failures to the log 168 send_log "Console has thread ids: $console_thread_list\n" 169 send_log "MI has thread ids: $mi_thread_list\n" 170 } else { 171 pass "MI and console have same threads ($name)" 172 } 173 } 174 } 175 } 176} 177 178# This procedure tests the various thread commands in MI. 179proc check_mi_thread_command_set {} { 180 181 mi_runto done_making_threads 182 183 set thread_list [get_mi_thread_list "in check_mi_thread_command_set"] 184 185 mi_gdb_test "-thread-select" \ 186 {\^error,msg="mi_cmd_thread_select: USAGE: threadnum."} \ 187 "check_mi_thread_command_set: -thread-select" 188 189 mi_gdb_test "-thread-select 123456789" \ 190 {\^error,msg="Thread ID 123456789 not known\."} \ 191 "check_mi_thread_command_set: -thread-select 123456789" 192 193 foreach thread $thread_list { 194 # line and file are optional. 195 # many of the threads are blocked in libc calls, 196 # and many people have libc's with no symbols. 197 mi_gdb_test "-thread-select $thread" \ 198 "\\^done,new-thread-id=\"$thread\",frame={.*}(,line=\"(-)?\[0-9\]+\",file=\".*\")?" \ 199 "check_mi_thread_command_set: -thread-select $thread" 200 } 201} 202 203# 204# Start here 205# 206set testfile "pthreads" 207set srcfile "$testfile.c" 208set binfile "$objdir/$subdir/mi-$testfile" 209 210set options [list debug incdir=$objdir] 211if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] != "" } { 212 return -1 213} 214 215mi_gdb_reinitialize_dir $srcdir/$subdir 216mi_gdb_load $binfile 217 218check_mi_thread_command_set 219 220mi_gdb_exit 221 222