From ddd347c2b4091bb5f7479db452d0a6418897a258 Mon Sep 17 00:00:00 2001 From: Gurucharan Shetty Date: Wed, 11 Feb 2015 08:04:34 -0800 Subject: [PATCH] tests: Enable running parallel unit tests for Windows. 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 Acked-by: Eitan Eliahu Acked-by: Ben Pfaff --- INSTALL.md | 2 ++ tests/automake.mk | 7 ++-- tests/testsuite.patch | 76 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 tests/testsuite.patch diff --git a/INSTALL.md b/INSTALL.md index 94c25f718fc..273093baf50 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -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 diff --git a/tests/automake.mk b/tests/automake.mk index 2e8d213dc80..50d8ad20520 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -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 index 00000000000..e0c6bb35ac3 --- /dev/null +++ b/tests/testsuite.patch @@ -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