From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1255 invoked by alias); 15 Sep 2002 19:18:59 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 1246 invoked from network); 15 Sep 2002 19:18:58 -0000 Received: from unknown (HELO localhost.redhat.com) (66.30.197.194) by sources.redhat.com with SMTP; 15 Sep 2002 19:18:58 -0000 Received: by localhost.redhat.com (Postfix, from userid 469) id D1E20106CC; Sun, 15 Sep 2002 15:17:05 -0400 (EDT) From: Elena Zannoni MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15748.56497.711652.479802@localhost.redhat.com> Date: Sun, 15 Sep 2002 12:18:00 -0000 To: Keith Seitz Cc: gdb-patches@sources.redhat.com Subject: Re: [RFA/MI testsuite] Add pthreads tests In-Reply-To: References: X-SW-Source: 2002-09/txt/msg00304.txt.bz2 Keith Seitz writes: > Hi, > > This is a first stab at some pthreads tests for MI. It mainly checks to > see that the MI thread commands and the console agree about threads > (gdb/669), but it also checks the syntax of MI thread commands and the > like. It will add several new failures to the testsuite, since there are > bugs! RFAs and RFCs on those to follow once these tests are committed. > > The pthreads.c file was largely stolen from > testsuite/gdb.thread/pthreads.c but modified to demonstrate gdb/669. > I wonder if we should name the file gdb669.exp. OK otherwise. Elena > Keith > > ChangeLog > 2002-09-10 Keith Seitz > > * configure.in: Add config header. > Check for pthread.h. > * configure: Regenerate. > * config.in: New file. > * mi-pthreads.exp: New file to test thread functionality. > * pthreads.c: New file. > > Patch > Index: testsuite/gdb.mi/config.in > =================================================================== > RCS file: testsuite/gdb.mi/config.in > diff -N testsuite/gdb.mi/config.in > *** testsuite/gdb.mi/config.in 1 Jan 1970 00:00:00 -0000 > --- testsuite/gdb.mi/config.in 10 Sep 2002 23:12:35 -0000 > *************** > *** 0 **** > --- 1,4 ---- > + /* config.h.in. Generated automatically from configure.in by autoheader. */ > + > + /* Define if you have the header file. */ > + #undef HAVE_PTHREAD_H > Index: testsuite/gdb.mi/configure.in > =================================================================== > RCS file: /cvs/src/src/gdb/testsuite/gdb.mi/configure.in,v > retrieving revision 1.1 > diff -p -r1.1 configure.in > *** testsuite/gdb.mi/configure.in 23 Feb 2000 00:25:43 -0000 1.1 > --- testsuite/gdb.mi/configure.in 10 Sep 2002 23:12:35 -0000 > *************** dnl any existing configure script. > *** 6,15 **** > --- 6,19 ---- > > AC_PREREQ(2.5) > AC_INIT(mi-basics.exp) > + AC_CONFIG_HEADER(config.h:config.in) > > CC=${CC-cc} > AC_SUBST(CC) > AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../../..) > AC_CANONICAL_SYSTEM > + > + # Check for pthread.h > + AC_CHECK_HEADERS(pthread.h) > > AC_OUTPUT(Makefile) > Index: testsuite/gdb.mi/mi-pthreads.exp > =================================================================== > RCS file: testsuite/gdb.mi/mi-pthreads.exp > diff -N testsuite/gdb.mi/mi-pthreads.exp > *** testsuite/gdb.mi/mi-pthreads.exp 1 Jan 1970 00:00:00 -0000 > --- testsuite/gdb.mi/mi-pthreads.exp 10 Sep 2002 23:12:35 -0000 > *************** > *** 0 **** > --- 1,219 ---- > + # Copyright 2002 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 2 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, write to the Free Software > + # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > + > + # Please email any bugs, comments, and/or additions to this file to: > + # bug-gdb@prep.ai.mit.edu > + > + # This file tests MI thread commands. > + # Specifically, we are testing the MI command set and the console (in MI) > + # command set ("interpreter-exec") and that the commands that are executed > + # via these command pathways are properly executed. Console commands > + # executed via MI should use MI output wrappers, MI event handlers, etc. > + > + # This only works with native configurations > + if {![isnative]} { > + return > + } > + > + load_lib mi-support.exp > + set MIFLAGS "-i=mi" > + > + gdb_exit > + if {[mi_gdb_start]} { > + continue > + } > + > + proc get_mi_thread_list {name} { > + global expect_out > + > + # MI will return a list of thread ids: > + # > + # -thread-list-ids > + # ^done,thread-ids=[thread-id="1",thread-id="2",...],number-of-threads="N" > + # (gdb) > + mi_gdb_test "-thread-list-ids" \ > + {\^done,thread-ids={(thread-id="[0-9]+"(,)?)+},number-of-threads="[0-9]+"} \ > + "-thread_list_ids ($name)" > + > + set thread_list {} > + if {![regexp {thread-ids=\{(thread-id="[0-9]+"(,)?)*\}} $expect_out(buffer) threads]} { > + fail "finding threads in MI output ($name)" > + } else { > + pass "finding threads in MI output ($name)" > + > + # Make list of console threads > + set start [expr {[string first \{ $threads] + 1}] > + set end [expr {[string first \} $threads] - 1}] > + set threads [string range $threads $start $end] > + foreach thread [split $threads ,] { > + if {[scan $thread {thread-id="%d"} num]} { > + lappend thread_list $num > + } > + } > + } > + > + return $thread_list > + } > + > + # Check that MI and the console know of the same threads. > + # Appends NAME to all test names. > + proc check_mi_and_console_threads {name} { > + global expect_out > + > + mi_gdb_test "-thread-list-ids" \ > + {\^done,thread-ids={(thread-id="[0-9]+"(,)*)+},number-of-threads="[0-9]+"} \ > + "-thread-list-ids ($name)" > + set mi_output $expect_out(buffer) > + > + # GDB will return a list of thread ids and some more info: > + # > + # (gdb) > + # -interpreter-exec console "info threads" > + # ~" 4 Thread 2051 (LWP 7734) 0x401166b1 in __libc_nanosleep () at __libc_nanosleep:-1" > + # ~" 3 Thread 1026 (LWP 7733) () at __libc_nanosleep:-1" > + # ~" 2 Thread 2049 (LWP 7732) 0x401411f8 in __poll (fds=0x804bb24, nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:63" > + # ~"* 1 Thread 1024 (LWP 7731) main (argc=1, argv=0xbfffdd94) at ../../../src/gdb/testsuite/gdb.mi/pthreads.c:160" > + # FIXME: kseitz/2002-09-05: Don't use the hack-cli method. > + mi_gdb_test "info threads" \ > + {.*(~".*"[\r\n]*)+.*} \ > + "info threads ($name)" > + set console_output $expect_out(buffer) > + > + # Make a list of all known threads to console (gdb's thread IDs) > + set console_thread_list {} > + foreach line [split $console_output \n] { > + if {[string index $line 0] == "~"} { > + # This is a line from the console; trim off "~", " ", "*", and "\"" > + set line [string trim $line ~\ \"\*] > + if {[scan $line "%d" id] == 1} { > + lappend console_thread_list $id > + } > + } > + } > + > + # Now find the result string from MI > + set mi_result "" > + foreach line [split $mi_output \n] { > + if {[string range $line 0 4] == "^done"} { > + set mi_result $line > + } > + } > + if {$mi_result == ""} { > + fail "finding MI result string ($name)" > + } else { > + pass "finding MI result string ($name)" > + } > + > + # Finally, extract the thread ids and compare them to the console > + set num_mi_threads_str "" > + if {![regexp {number-of-threads="[0-9]+"} $mi_result num_mi_threads_str]} { > + fail "finding number of threads in MI output ($name)" > + } else { > + pass "finding number of threads in MI output ($name)" > + > + # Extract the number of threads from the MI result > + if {![scan $num_mi_threads_str {number-of-threads="%d"} num_mi_threads]} { > + fail "got number of threads from MI ($name)" > + } else { > + pass "got number of threads from MI ($name)" > + > + # Check if MI and console have same number of threads > + if {$num_mi_threads != [llength $console_thread_list]} { > + fail "console and MI have same number of threads ($name)" > + } else { > + pass "console and MI have same number of threads ($name)" > + > + # Get MI thread list > + set mi_thread_list [get_mi_thread_list $name] > + > + # Check if MI and console have the same threads > + set fails 0 > + foreach ct [lsort $console_thread_list] mt [lsort $mi_thread_list] { > + if {$ct != $mt} { > + incr fails > + } > + } > + if {$fails > 0} { > + fail "MI and console have same threads ($name)" > + > + # Send a list of failures to the log > + send_log "Console has thread ids: $console_thread_list\n" > + send_log "MI has thread ids: $mi_thread_list\n" > + } else { > + pass "MI and console have same threads ($name)" > + } > + } > + } > + } > + } > + > + # This procedure checks for the bug gdb/669, where the console > + # command "info threads" and the MI command "-thread-list-ids" > + # return different threads in the system. > + proc check_for_gdb669_bug {} { > + mi_run_to_main > + check_mi_and_console_threads "at main" > + > + for {set i 0} {$i < 4} {incr i} { > + mi_next "next, try $i" > + check_mi_and_console_threads "try $i" > + } > + } > + > + # This procedure tests the various thread commands in MI. > + proc check_mi_thread_command_set {} { > + > + mi_runto done_making_threads > + > + set thread_list [get_mi_thread_list "in check_mi_thread_command_set"] > + > + mi_gdb_test "-thread-select" \ > + {\^error,msg="mi_cmd_thread_select: USAGE: threadnum."} \ > + "check_mi_thread_command_set: -thread-select" > + > + mi_gdb_test "-thread-select 123456789" \ > + {\^error,msg="Thread ID 123456789 not known\."} \ > + "check_mi_thread_command_set: -thread-select 123456789" > + > + foreach thread $thread_list { > + mi_gdb_test "-thread-select $thread" \ > + "\\^done,new-thread-id=\"$thread\",frame={.*},line=\"(-)?\[0-9\]+\",file=\".*\"" \ > + "check_mi_thread_command_set: -thread-select $thread" > + } > + } > + > + # > + # Start here > + # > + set testfile "pthreads" > + set srcfile "$testfile.c" > + set binfile "$objdir/$subdir/$testfile" > + > + set options [list debug incdir=$subdir] > + if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] > + != "" } { > + gdb_suppress_entire_file \ > + "Testcase compile failed, so all tests in this file will automatically fail." > + } > + > + mi_gdb_reinitialize_dir $srcdir/$subdir > + mi_gdb_load $binfile > + > + check_mi_thread_command_set > + check_for_gdb669_bug > + > + mi_gdb_exit > + > Index: testsuite/gdb.mi/pthreads.c > =================================================================== > RCS file: testsuite/gdb.mi/pthreads.c > diff -N testsuite/gdb.mi/pthreads.c > *** testsuite/gdb.mi/pthreads.c 1 Jan 1970 00:00:00 -0000 > --- testsuite/gdb.mi/pthreads.c 10 Sep 2002 23:12:35 -0000 > *************** > *** 0 **** > --- 1,80 ---- > + #include > + > + #include "config.h" > + > + #ifndef HAVE_PTHREAD_H > + > + /* Don't even try to compile. In fact, cause a syntax error that we can > + look for as a compiler error message and know that we have no pthread > + support. In that case we can just suppress the test completely. */ > + > + #error "no posix threads support" > + > + #else > + > + /* OK. We have the right header. If we try to compile this and fail, then > + there is something wrong and the user should know about it so the testsuite > + should issue an ERROR result.. */ > + > + #ifdef __linux__ > + #define _MIT_POSIX_THREADS 1 /* GNU/Linux (or at least RedHat 4.0) > + needs this */ > + #endif > + > + #include > + > + /* Under OSF 2.0 & 3.0 and HPUX 10, the second arg of pthread_create > + is prototyped to be just a "pthread_attr_t", while under Solaris it > + is a "pthread_attr_t *". Arg! */ > + > + #if defined (__osf__) || defined (__hpux__) > + #define PTHREAD_CREATE_ARG2(arg) arg > + #define PTHREAD_CREATE_NULL_ARG2 null_attr > + static pthread_attr_t null_attr; > + #else > + #define PTHREAD_CREATE_ARG2(arg) &arg > + #define PTHREAD_CREATE_NULL_ARG2 NULL > + #endif > + > + void * > + routine (void *arg) > + { > + sleep (9); > + printf ("hello thread\n"); > + } > + > + /* Marker function for the testsuite */ > + void > + done_making_threads (void) > + { > + /* Nothing */ > + }; > + > + void > + create_thread (void) > + { > + pthread_t tid; > + > + if (pthread_create (&tid, PTHREAD_CREATE_NULL_ARG2, routine, (void *) 0xfeedface)) > + { > + perror ("pthread_create 1"); > + exit (1); > + } > + } > + > + int > + main (int argc, char *argv[]) > + { > + int i; > + > + /* Create a few threads */ > + for (i = 0; i < 5; i++) > + create_thread (); > + done_making_threads (); > + > + printf ("hello\n"); > + printf ("hello\n"); > + return 0; > + } > + > + #endif /* ifndef HAVE_PTHREAD_H */