[PATCH 5/5] ITSET test case.

Yao Qi yao@codesourcery.com
Tue Apr 2 14:46:00 GMT 2013


gdb/testsuite:

2013-04-02  Yao Qi  <yao@codesourcery.com>

	* gdb.base/itset.exp, gdb.base/itset.c: New.
	* gdb.multi/itset.exp, gdb.multi/itset.c: New.
---
 gdb/testsuite/gdb.base/itset.c    |   95 ++++++++++++
 gdb/testsuite/gdb.base/itset.exp  |  295 +++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.multi/itset.c   |   70 +++++++++
 gdb/testsuite/gdb.multi/itset.exp |  151 +++++++++++++++++++
 4 files changed, 611 insertions(+), 0 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/itset.c
 create mode 100644 gdb/testsuite/gdb.base/itset.exp
 create mode 100644 gdb/testsuite/gdb.multi/itset.c
 create mode 100644 gdb/testsuite/gdb.multi/itset.exp

diff --git a/gdb/testsuite/gdb.base/itset.c b/gdb/testsuite/gdb.base/itset.c
new file mode 100644
index 0000000..bf80b51
--- /dev/null
+++ b/gdb/testsuite/gdb.base/itset.c
@@ -0,0 +1,95 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 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/>.  */
+
+#include <pthread.h>
+#include <unistd.h>
+
+static void
+marker1 (void)
+{}
+
+static void
+marker2 (void)
+{}
+
+static void
+end (void)
+{}
+
+#define NR_THREADS 2
+static pthread_mutex_t lock1;
+static pthread_mutex_t lock2;
+static pthread_cond_t cond1;
+static pthread_cond_t cond2;
+
+static void *
+thread_function (void *arg)
+{
+  int *flag = (int *) arg;
+  static int counter = 0;
+
+  /* Wait until all child threads are running.  */
+  pthread_mutex_lock (&lock1);
+  ++counter;
+  if (counter < NR_THREADS)
+    pthread_cond_wait (&cond1, &lock1);
+  else
+    pthread_cond_broadcast (&cond1);
+  pthread_mutex_unlock (&lock1);
+
+  if (*flag == 0)
+    marker2 ();
+
+  /* Make sure no thread exists when GDB is examining the threads.  */
+  pthread_mutex_lock (&lock2);
+  ++counter;
+  if (counter < 2 * NR_THREADS)
+    pthread_cond_wait (&cond2, &lock2);
+  else
+    pthread_cond_signal (&cond2);
+  pthread_mutex_unlock (&lock2);
+
+}
+
+int
+main (int argc, char *argv[], char *envp[])
+{
+  pthread_t threads[NR_THREADS];
+  int flags[NR_THREADS];
+  int i, j;
+
+  pthread_mutex_init (&lock1, NULL);
+  pthread_mutex_init (&lock2, NULL);
+  pthread_cond_init (&cond1, NULL);
+  pthread_cond_init (&cond2, NULL);
+
+  for (i = 0; i < NR_THREADS; i++)
+    {
+      flags[i] = i;
+      pthread_create (&threads[i], NULL, thread_function,
+		      (void *) (&flags[i]));
+    }
+
+  marker1 ();
+
+  for (j = 0; j < NR_THREADS; j++)
+    pthread_join (threads[j], NULL);
+
+  end ();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/itset.exp b/gdb/testsuite/gdb.base/itset.exp
new file mode 100644
index 0000000..a76dda6
--- /dev/null
+++ b/gdb/testsuite/gdb.base/itset.exp
@@ -0,0 +1,295 @@
+# Copyright 2013 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/>.
+
+standard_testfile .c
+set executable $testfile
+
+if  { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" \
+	   "${binfile}" executable [list nowarnings debug]] != "" } {
+     untested itset.exp
+     return -1
+}
+
+# Test the behaviour of ITSET without any running process.
+
+proc test_itset_without_running_process { } {
+    with_test_prefix "wo run" {
+	global srcdir
+	global subdir
+	global binfile
+
+	gdb_exit
+	gdb_start
+	gdb_reinitialize_dir $srcdir/$subdir
+	gdb_load ${binfile}
+
+	# Test `maint info itsets'
+	gdb_test_sequence "maint info itsets" "maint info itsets 1" {
+	    "\[\r\n\]Num\[ \]+Name\[ \]+What"
+	    "\[\r\n\]\-1\[ \]+all\[ \]+all"
+	}
+
+	# Test `info itsets'
+	with_test_prefix "info itsets" {
+	    gdb_test "info itsets" "No named itsets\." \
+		"no itsets no arg"
+	    gdb_test "info itsets 1" "No named itset found with number 1\." \
+		"no itsets with number"
+	}
+
+	# Test defset and undefset
+	gdb_test_no_output "defset itset-t1 t1"
+	gdb_test_no_output "defset itset-t2 t2"
+
+	with_test_prefix "viewset" {
+	    if [ gdb_test_sequence "viewset" "no arg" {
+		"\[\n\r\]all contains:"
+		"\[\n\r\]  inferiors: 1"
+		"\[\n\r\]itset-t1 contains:"
+		"\[\n\r\]itset-t2 contains:"
+	    } ] {
+		fail "no arg"
+	    }
+
+	    gdb_test_sequence "viewset i1" "arg i1" {
+		"\[\n\r\]i1 contains:"
+		"\[\n\r\]  inferiors: 1"
+	    }
+	}
+
+	gdb_test "whichsets itset-t1" ".*"
+
+	with_test_prefix "info itsets" {
+	    gdb_test_sequence "info itsets" "itset-t1" {
+		"\[\n\r\]1\[ \]+itset-t1\[ \]+t1"
+		"\[\n\r\]2\[ \]+itset-t2\[ \]+t2"
+	    }
+	}
+
+	with_test_prefix "maint info itsets" {
+	    if [ gdb_test_sequence "maint info itsets" "2" {
+		"\[\n\r\]\Num\[ \]+Name\[ \]+What"
+		"\[\n\r\]1\[ \]+itset-t1\[ \]+t1"
+		"\[\n\r\]2\[ \]+itset-t2\[ \]+t2"
+	    } ] {
+		fail "2"
+	    }
+	}
+
+	# Test undefset
+	gdb_test_no_output "undefset itset-t1"
+	gdb_test_no_output "undefset -all"
+
+	# Test whichsets.  Is it correct to output nothing in this case?
+	gdb_test_no_output "whichsets i1"
+
+	with_test_prefix "scope" {
+	    gdb_test "scope" "Focus is `all\' \\(current inferior is 1\\)" \
+		"no arg"
+	    gdb_test "scope i10" "warning: focus set is empty\[\r\n\]+Current inferior is 1\." \
+		"empty focus"
+	    gdb_test "scope i1" "Current inferior is 1\." "i1"
+	}
+    }
+}
+
+# Test various error messages from ITSET related commands.
+
+proc test_itset_check_error { } {
+    with_test_prefix "error message" {
+	global srcdir
+	global subdir
+	global binfile
+
+	gdb_exit
+	gdb_start
+	gdb_reinitialize_dir $srcdir/$subdir
+	gdb_load ${binfile}
+
+	with_test_prefix "defset" {
+	    gdb_test "defset" "Argument required \\(no args\\)\." \
+		"without args"
+
+	    gdb_test_no_output "defset itset-i1 i1"
+	    gdb_test "defset itset-i1 i2" "itset itset-i1 already exists" \
+		"already exists"
+
+	    gdb_test_no_output "undefset -all"
+	}
+
+	with_test_prefix "undefset" {
+	    gdb_test "undefset" "Argument required \\(no args\\)\." \
+		"without args"
+	    gdb_test "undefset itset-c1" "itset itset-c1 does not exist" \
+		"does not exist"
+
+	    gdb_test_no_output "defset itset-i1 i1"
+	    gdb_test_no_output "undefset -all"
+	}
+
+	gdb_test "info itsets foo" "No named itset found with number foo\."
+    }
+}
+
+proc test_itset_check_syntax { } {
+    with_test_prefix "syntax" {
+	global srcdir
+	global subdir
+	global binfile
+
+	gdb_exit
+	gdb_start
+	gdb_reinitialize_dir $srcdir/$subdir
+	gdb_load ${binfile}
+
+	gdb_test "defset itset-t1 t2-a" "Expected digit in I/T set, at `a'"
+
+	gdb_test "defset itset1 all,other" "Unknown named I/T set: `other\'"
+    }
+}
+
+test_itset_without_running_process
+
+test_itset_check_error
+
+test_itset_check_syntax
+
+# Test the behaviour of ITSET in single-thread.
+
+proc test_itset_with_running_single_thread { } {
+    with_test_prefix "w run st" {
+	global executable
+	global binfile
+
+	# Start with a fresh gdb.
+	clean_restart ${executable}
+	if ![runto_main] {
+	    fail "Can't run to main"
+	    return -1
+	}
+
+	gdb_test_no_output "defset itset-t1 t1"
+	gdb_test_no_output "defset itset-t2 t2"
+	gdb_test_no_output "defset itset-t1-t2 t1-2"
+
+	gdb_test "whichsets t1" \
+	    "i1\.t1 \\(Thread .*\\) is in: all, itset-t1, itset-t1-t2"
+	# whichsets for current itset.
+	gdb_test "whichsets" \
+	    "i1\.t1 \\(Thread .*\\) is in: all, itset-t1, itset-t1-t2"
+
+	# Test viewset
+	set test "viewset t1"
+	if [ gdb_test_sequence "viewset t1" $test {
+	    "\[\n\r\]t1 contains:"
+	    "\[\n\r\]  inferiors: 1"
+	    "\[\n\r\]  threads: 1"
+	} ] {
+	    fail $test
+	}
+
+	with_test_prefix "scope" {
+	    gdb_test "scope i1" "Current inferior is 1\." "i1"
+	    gdb_test "scope t1-2" "Current inferior is 1\." "t1-2"
+	}
+
+    }
+}
+
+test_itset_with_running_single_thread
+
+proc test_target_set { } {
+    with_test_prefix "target set" {
+	global executable
+	global binfile
+	global gdb_prompt
+
+	# Start with a fresh gdb.
+	clean_restart ${executable}
+	if ![runto_main] {
+	    fail "Can't run to main"
+	    return -1
+	}
+
+	gdb_test "break end" "Breakpoint 2 at .*"
+	gdb_test "scope t1-2 break marker2" "Breakpoint 3 at .*"
+	gdb_test "scope t1 break marker2" "Breakpoint 4 at .*"
+	gdb_test "scope t2 break marker2" "Breakpoint 5 at .*"
+
+	set nonstop 0
+	gdb_test_multiple "show non-stop" "show non-stop" {
+	    -re "Controlling the inferior in non-stop mode is off\..*$gdb_prompt $" {
+		set nonstop 0
+	    }
+	    -re "Controlling the inferior in non-stop mode is on\..*$gdb_prompt $" {
+		set nonstop 1
+	    }
+	}
+
+	# Thread 2 hits the breakpoint on marker2.
+	gdb_test  "continue" ".*Breakpoint 3, marker2.*" \
+	    "continue to marker2"
+	if { $nonstop } {
+	    # In non-stop mode, switch to the thread hits breakpoint.
+	    gdb_test "thread 2"
+	}
+	gdb_test  "continue" ".*Breakpoint 2, end.*" \
+	    "continue to end"
+
+	# Check the hit count of breakpoints.  Hit count of breakpoint
+	# 4 should zero.
+	gdb_test_sequence "info breakpoints" "info break" {
+	    "\[\r\n\]Num     Type           Disp Enb Address +What"
+	    "\[\r\n\]1       breakpoint"
+	    "\[\r\n\]\tbreakpoint already hit 1 time"
+	    "\[\r\n\]2       breakpoint"
+	    "\[\r\n\]\tbreakpoint already hit 1 time"
+	    "\[\r\n\]3       breakpoint"
+	    "\[\r\n\]\tbreakpoint already hit 1 time"
+	    "\[\r\n\]4       breakpoint"
+	    "\[\r\n\]5       breakpoint"
+	    "\[\r\n\]\tbreakpoint already hit 1 time"
+	}
+
+	# Start with a fresh gdb.
+	clean_restart ${executable}
+	if ![runto_main] {
+	    fail "Can't run to main"
+	    return -1
+	}
+	gdb_test "scope t2 break marker2" "Breakpoint 2 at .*"
+	# Thread 2 hits the breakpoint on marker2.
+	gdb_test  "continue" ".*Breakpoint 2, marker2.*" \
+	    "continue to marker2"
+
+	# Update GDB's knowledge on existing threads.
+	gdb_test "info threads"
+	global hex
+
+	# Thread 2 is stopped due to hitting a breakpoint, it should
+	# appear in the output unconditionally.  Thread 1 and thread
+	# 3 don't hit breakpoint, so they are stopped in all-stop
+	# mode, or running in non-stop mode.  In other words, the
+	# backtrace output has thread 1 and thread 3 in all-stop mode.
+	if { $nonstop } {
+	    gdb_test "scope all bt" \
+		"Thread 2 .*#0  marker2 \\(\\).*#1  ${hex} in thread_function .*"
+	} else {
+	    gdb_test "scope all bt" \
+		"Thread 3 .* ${hex} in thread_function .*Thread 2 .*#0  marker2 \\(\\).*#1  ${hex} in thread_function .*Thread 1 .* ${hex} in pthread_join.*  ${hex} in main .*"
+	}
+    }
+}
+
+test_target_set
diff --git a/gdb/testsuite/gdb.multi/itset.c b/gdb/testsuite/gdb.multi/itset.c
new file mode 100644
index 0000000..4af8ebc
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/itset.c
@@ -0,0 +1,70 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 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/>.  */
+
+#include <pthread.h>
+#include <unistd.h>
+
+static void
+end (void)
+{}
+
+#define NR_THREADS 2
+
+static pthread_mutex_t lock;
+static pthread_cond_t cond;
+static int counter = 0;
+
+static void *
+thread_function (void *arg)
+{
+  /* Wait until all threads are running.  */
+  pthread_mutex_lock (&lock);
+  ++counter;
+
+  if (counter < NR_THREADS)
+    pthread_cond_wait (&cond, &lock);
+  else
+    pthread_cond_broadcast (&cond);
+
+  pthread_mutex_unlock (&lock);
+
+  /* Don't exit when GDB is examining threads.  */
+  sleep (10);
+}
+
+int
+main (int argc, char *argv[], char *envp[])
+{
+  pthread_t threads[NR_THREADS];
+  int i;
+
+  pthread_mutex_init (&lock, NULL);
+  pthread_cond_init (&cond, NULL);
+
+  for (i = 0; i < NR_THREADS; i++)
+    pthread_create (&threads[i], NULL, thread_function, NULL);
+
+  /* Wait until all threads are running.  */
+  pthread_mutex_lock (&lock);
+  if (counter < NR_THREADS)
+    pthread_cond_wait (&cond, &lock);
+  pthread_mutex_unlock (&lock);
+
+  end ();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.multi/itset.exp b/gdb/testsuite/gdb.multi/itset.exp
new file mode 100644
index 0000000..b92c852
--- /dev/null
+++ b/gdb/testsuite/gdb.multi/itset.exp
@@ -0,0 +1,151 @@
+# Copyright 2013 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/>.
+
+# The plain remote target can't do multiple inferiors.
+if [target_info exists use_gdb_stub] {
+    return
+}
+standard_testfile .c
+set executable ${testfile}
+
+if  { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+	   executable [list nowarnings debug]] != "" } {
+     untested itset.exp
+     return -1
+}
+
+# Test the behaviour of itset in multi-inferior and mulit-thread.
+
+proc test_itset { } {
+    with_test_prefix "/w run" {
+	global executable
+	global binfile
+	global srcfile
+	global gdb_prompt
+
+	# Start with a fresh gdb.
+	clean_restart ${executable}
+	if ![runto_main] {
+	    fail "Can't run to main 1"
+	    return -1
+	}
+
+	gdb_test "add-inferior -exec ${binfile}" \
+	    "Added inferior 2.*" \
+	    "add inferior 2 with -exec ${binfile}"
+
+	gdb_test "inferior 2"
+	if ![runto_main] {
+	    fail "Can't run to main 2"
+	    return -1
+	}
+
+	# So far, there are two inferiors i1 and i2.  Each of them has
+	# only one thread.
+	gdb_test_no_output "defset s1 i1.t1,i2.t2-10"
+	gdb_test "whichsets t1" "i1\.t1 \\(Thread .*\\) is in: all, s1" \
+	    "1 thread: s1 contains i1.t1"
+	gdb_test "whichsets t2" "i2\.t2 \\(Thread .*\\) is in: all, s1" \
+	    "1 thread: s1 contains i2.t2"
+
+	# This breakpoint is set to both inferior 1 and inferior 2.
+	gdb_test "break end" \
+	    "Breakpoint \[0-9\] at .* end.*"
+
+	gdb_test "inferior 1"
+	gdb_test "continue" ".*Breakpoint \[0-9\], end.*" \
+	    "continue to end"
+
+	# Now, there are three threads in inferior 1, t1, t3, t4, and
+	# still only one thread t2 in inferior 2.
+	# Update GDB's knowledge on existing threads.
+	gdb_test "info threads" ".*"
+	gdb_test "whichsets t2" "i2\.t2 \\(Thread .*\\) is in: all, s1" \
+	    "1 thread: s1 contains i1.t2"
+	gdb_test "whichsets t3" "i1\.t3 \\(Thread .*\\) is in: all" \
+	    "1 thread: s1 contains i1.t3"
+	gdb_test "whichsets t4" "i1\.t4 \\(Thread .*\\) is in: all" \
+	    "1 thread: s1 contains i1.t4"
+
+
+    }
+}
+
+# Test the target set of commands.
+
+proc test_target_set { } {
+    with_test_prefix "target set" {
+	global executable
+	global binfile
+	global srcfile
+	global gdb_prompt
+
+	# Start with a fresh gdb.
+	clean_restart ${executable}
+	if ![runto_main] {
+	    fail "Can't run to main 1"
+	    return -1
+	}
+
+	gdb_test "add-inferior -exec ${binfile}" \
+	    "Added inferior 2.*" \
+	    "add inferior 2 with -exec ${binfile}"
+
+	gdb_test "inferior 2"
+	if ![runto_main] {
+	    fail "Can't run to main 2"
+	    return -1
+	}
+
+	# This breakpoint is set to both inferior 1 and inferior 2.
+	gdb_test "break end" \
+	    "Breakpoint \[0-9\] at .* end.*"
+
+	gdb_test "inferior 1"
+	gdb_test "continue" ".*Breakpoint \[0-9\], end.*" \
+	    "continue to end"
+
+	set nonstop 0
+	gdb_test_multiple "show non-stop" "show non-stop" {
+	    -re "Controlling the inferior in non-stop mode is off\..*$gdb_prompt $" {
+		set nonstop 0
+	    }
+	    -re "Controlling the inferior in non-stop mode is on\..*$gdb_prompt $" {
+		set nonstop 1
+	    }
+	}
+
+	# Fore GDB to refresh its thread list.
+	gdb_test "info threads"
+
+	# Thread 1, 3, and 4.
+	global hex
+
+	# Thread 1 in inferior 1 hits the breakpoint, and is stopped.
+	# Thread 2 in inferior 2 is stopped.
+	# Thread 3 and 4 don't hit breakpoint, so they are stopped in
+	# all-stop, or running in non-stop mode.
+	if { $nonstop } {
+	    gdb_test "scope all bt" \
+		"Thread 2 .*#0  main \\(.*Thread 1 .*#0  end \\(\\) .*  ${hex} in main \\(.*"
+	} else {
+	    gdb_test "scope all bt" \
+		"Thread 4 .* ${hex} in thread_function .*Thread 3 .* ${hex} in thread_function .*Thread 2 .*#0  main \\(.*Thread 1 .*#0  end \\(\\) .*  ${hex} in main \\(.*"
+	}
+    }
+}
+
+test_itset
+
+test_target_set
-- 
1.7.7.6



More information about the Gdb-patches mailing list