On Mon, 2005-08-08 at 16:59 -0400, Tom Lane wrote:
> Matt Miller <[EMAIL PROTECTED]> writes:
> > I want to write some regression tests that confirm the behavior of
> > multiple connections simultaneously going at the same tables/rows.  Is
> > there something like this already, e.g. in src/test/regress?
> 
> No. ... but surely we need one.

The attached patch allows src/test/regress/pg_regress.sh to recognize
lines that begin with "curr_test:" in the schedule file.  Tests named on
such a line are run concurrently across multiple connections.  To make
use of this facility each test in the group must begin with the line:

select * from concurrency_test where key = '<test_name>' for update;

where <test_name> is replace by the name of that test.  This will enable
pg_regress to start this test at the same time as the other tests in the
group.

Is this a reasonable starting point for a concurrent testing framework?

This does not address the issue of how to interpret the test output.
Maybe the simplest solution is to force test writers to generate output
that does not depend on the relative progress of any concurrent tests.
Or, maybe the "ignore:" directive in the schedule file could be employed
somehow.
Index: pg_regress.sh
===================================================================
RCS file: /var/local/pgcvs/pgsql/src/test/regress/pg_regress.sh,v
retrieving revision 1.59
diff -c -r1.59 pg_regress.sh
*** pg_regress.sh	17 Jul 2005 18:28:45 -0000	1.59
--- pg_regress.sh	15 Aug 2005 21:20:03 -0000
***************
*** 623,628 ****
--- 623,632 ----
  do
      # Count line numbers
      lno=`expr $lno + 1`
+ 
+     # Init concurrency flag
+     concurrent=
+ 
      [ -z "$line" ] && continue
  
      set X $line; shift
***************
*** 631,636 ****
--- 635,647 ----
          shift
          ignore_list="$ignore_list $@"
          continue
+     elif [ x"$1" = x"curr_test:" ]; then
+         # init support for concurrent test group
+         concurrent=1
+         cat /dev/null >"$inputdir/sql/concurrency_test_init.sql"
+         echo "create table concurrency_test (key varchar primary key);" >>"$inputdir/sql/concurrency_test_init.sql"
+         ( $PSQL -d "$dbname" <"$inputdir/sql/concurrency_test_init.sql" >"$outputdir/results/concurrency_test_init.out" 2>&1 )&
+         wait
      elif [ x"$1" != x"test:" ]; then
          echo "$me:$schedule:$lno: syntax error"
          (exit 2); exit
***************
*** 649,671 ****
          ( $PSQL -d "$dbname" <"$inputdir/sql/$1.sql" >"$outputdir/results/$1.out" 2>&1 )&
          wait
      else
!         # Start a parallel group
!         $ECHO_N "parallel group ($# tests): $ECHO_C"
!         if [ $maxconnections -gt 0 ] ; then
!             connnum=0
!             test $# -gt $maxconnections && $ECHO_N "(in groups of $maxconnections) $ECHO_C"
!         fi
!         for name do
!             ( 
!               $PSQL -d "$dbname" <"$inputdir/sql/$name.sql" >"$outputdir/results/$name.out" 2>&1
!               $ECHO_N " $name$ECHO_C"
!             ) &
              if [ $maxconnections -gt 0 ] ; then
!                 connnum=`expr \( $connnum + 1 \) % $maxconnections`
!                 test $connnum -eq 0 && wait
              fi
!         done
!         wait
          echo
      fi
  
--- 660,717 ----
          ( $PSQL -d "$dbname" <"$inputdir/sql/$1.sql" >"$outputdir/results/$1.out" 2>&1 )&
          wait
      else
!         # ----------
!         # If this is a concurrent test group then write the script "concurrent_test.sql"
!         # which will spawn and synchronize each test in the group.
!         #
!         # Concurrent test groups do not respect $maxconnections.
!         #
!         # If this is not a concurrent test group then just run each test directly.
!         # ----------
! 
!         if [ "$concurrent" = "1" ]; then
!             $ECHO_N "concurrent group ($# tests): $ECHO_C"
! 
!             # insert a lock record for each test
!             cat /dev/null >"$inputdir/sql/concurrency_test.sql"
!             echo "BEGIN;" >>"$inputdir/sql/concurrency_test.sql"
!             for name do
!                 echo "insert into concurrency_test values ('$name');" >>"$inputdir/sql/concurrency_test.sql"
!             done
!             echo "COMMIT;" >>"$inputdir/sql/concurrency_test.sql"
! 
!             # for each test, acquire the lock and then spawn the test
!             echo "BEGIN;" >>"$inputdir/sql/concurrency_test.sql"
!             for name do
!                 echo "select * from concurrency_test where key = '$name' for update;" >>"$inputdir/sql/concurrency_test.sql"
!                 echo "\! $PSQL -d \"$dbname\" <\"$inputdir/sql/$name.sql\" >\"$outputdir/results/$name.out\" 2>&1 &" >>"$inputdir/sql/concurrency_test.sql"
!             done
! 
!             # release all locks, concurrently launching all tests
!             echo "ROLLBACK;" >>"$inputdir/sql/concurrency_test.sql"
! 
!             # done writing the script.  fire it.
!             ( $PSQL -d "$dbname" <"$inputdir/sql/concurrency_test.sql" >"$outputdir/results/concurrency_test.out" 2>&1 )&
!             wait
!         else
!             $ECHO_N "parallel group ($# tests): $ECHO_C"
              if [ $maxconnections -gt 0 ] ; then
!                 connnum=0
!                 test $# -gt $maxconnections && $ECHO_N "(in groups of $maxconnections) $ECHO_C"
              fi
! 
!             for name do
!                 (
!                   $PSQL -d "$dbname" <"$inputdir/sql/$name.sql" >"$outputdir/results/$name.out" 2>&1
!                   $ECHO_N " $name$ECHO_C"
!                 ) &
!                 if [ $maxconnections -gt 0 ] ; then
!                     connnum=`expr \( $connnum + 1 \) % $maxconnections`
!                     test $connnum -eq 0 && wait
!                 fi
!             done
!             wait
!         fi
          echo
      fi
  
---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster

Reply via email to