tests: Enable running parallel unit tests for Windows.
authorGurucharan Shetty <gshetty@nicira.com>
Wed, 11 Feb 2015 16:04:34 +0000 (08:04 -0800)
committerGurucharan Shetty <gshetty@nicira.com>
Fri, 13 Feb 2015 18:41:43 +0000 (10:41 -0800)
testsuite uses mkfifo in its job dispatcher that manages
parallel unit tests. MinGW does not have a mkfifo. This
results in unit tests running serially on Windows. Right
now it takes up to approximately 40 minutes to run all the
unit tests on Windows.

This commit provides a job dispatcher for MinGW that uses
temporary files instead of mkfifo to manage parallel jobs.
With this commit, on a Windows machine with 4 cores and with
8 parallel unit test sessions, it takes approximately 8
minutes to finish a unit test run.

Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
Acked-by: Eitan Eliahu <eliahue@vmware.com>
Acked-by: Ben Pfaff <blp@nicira.com>
INSTALL.md
tests/automake.mk
tests/testsuite.patch [new file with mode: 0644]

index 94c25f7..273093b 100644 (file)
@@ -41,6 +41,8 @@ you will need the following software:
 
   - Python 2.x, for x >= 4.
 
+  - patch (The utility that is used to patch files).
+
 On Linux, you may choose to compile the kernel module that comes with
 the Open vSwitch distribution or to use the kernel module built into
 the Linux kernel (version 3.3 or later).  See the [FAQ.md] question
index 2e8d213..50d8ad2 100644 (file)
@@ -6,7 +6,8 @@ EXTRA_DIST += \
        $(KMOD_TESTSUITE) \
        tests/atlocal.in \
        $(srcdir)/package.m4 \
-       $(srcdir)/tests/testsuite
+       $(srcdir)/tests/testsuite \
+       $(srcdir)/tests/testsuite.patch
 
 COMMON_MACROS_AT = \
        tests/ovsdb-macros.at \
@@ -87,6 +88,7 @@ KMOD_TESTSUITE_AT = \
        tests/kmod-traffic.at
 
 TESTSUITE = $(srcdir)/tests/testsuite
+TESTSUITE_PATCH = $(srcdir)/tests/testsuite.patch
 KMOD_TESTSUITE = $(srcdir)/tests/kmod-testsuite
 DISTCLEANFILES += tests/atconfig tests/atlocal
 
@@ -196,8 +198,9 @@ clean-local:
        test ! -f '$(TESTSUITE)' || $(SHELL) '$(TESTSUITE)' -C tests --clean
 
 AUTOTEST = $(AUTOM4TE) --language=autotest
-$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(COMMON_MACROS_AT)
+$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(COMMON_MACROS_AT) $(TESTSUITE_PATCH)
        $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at
+       patch -p0 $@.tmp $(TESTSUITE_PATCH)
        $(AM_V_at)mv $@.tmp $@
 
 $(KMOD_TESTSUITE): package.m4 $(KMOD_TESTSUITE_AT) $(COMMON_MACROS_AT)
diff --git a/tests/testsuite.patch b/tests/testsuite.patch
new file mode 100644 (file)
index 0000000..e0c6bb3
--- /dev/null
@@ -0,0 +1,76 @@
+--- testsuite  2015-02-11 17:19:21.654646439 -0800
++++ testsuite  2015-02-11 17:15:03.810653032 -0800
+@@ -4669,6 +4669,73 @@
+   fi
+   exec 6<&-
+   wait
++elif test $at_jobs -ne 1 &&
++     test "$IS_WIN32" = "yes"; then
++  # FIFO job dispatcher.
++  trap 'at_pids=
++      for at_pid in `jobs -p`; do
++        at_pids="$at_pids $at_job_group$at_pid"
++      done
++      if test -n "$at_pids"; then
++        at_sig=TSTP
++        test "${TMOUT+set}" = set && at_sig=STOP
++        kill -$at_sig $at_pids 2>/dev/null
++      fi
++      kill -STOP $$
++      test -z "$at_pids" || kill -CONT $at_pids 2>/dev/null' TSTP
++
++  echo
++  # Turn jobs into a list of numbers, starting from 1.
++  running_jobs="`pwd`/tests/jobdispatcher"
++  mkdir -p $running_jobs
++  at_joblist=`$as_echo "$at_groups" | sed -n 1,${at_jobs}p`
++
++  set X $at_joblist
++  shift
++  for at_group in $at_groups; do
++    $at_job_control_on 2>/dev/null
++    (
++      # Start one test group.
++      $at_job_control_off
++      touch $running_jobs/$at_group
++      trap 'set +x; set +e
++          trap "" PIPE
++          echo stop > "$at_stop_file"
++          rm -f $running_jobs/$at_group
++          as_fn_exit 141' PIPE
++      at_fn_group_prepare
++      if cd "$at_group_dir" &&
++       at_fn_test $at_group &&
++       . "$at_test_source"
++      then :; else
++      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unable to parse test group: $at_group" >&5
++$as_echo "$as_me: WARNING: unable to parse test group: $at_group" >&2;}
++      at_failed=:
++      fi
++      rm -f $running_jobs/$at_group
++      at_fn_group_postprocess
++    ) &
++    $at_job_control_off
++    shift # Consume one token.
++    if test $# -gt 0; then :; else
++      while [ "`ls -l $running_jobs 2>/dev/null | wc -l`" -gt "$at_jobs" ]; do
++        sleep 0.1
++      done
++      set x $*
++    fi
++    test -f "$at_stop_file" && break
++  done
++  # Read back the remaining ($at_jobs - 1) tokens.
++  set X $at_joblist
++  shift
++  if test $# -gt 0; then
++    shift
++    while [ "`ls -l $running_jobs | wc -l`" -gt 1 ]; do
++      sleep 0.1
++    done
++  fi
++  rmdir $running_jobs
++  wait
+ else
+   # Run serially, avoid forks and other potential surprises.
+   for at_group in $at_groups; do