This patch adds a basic infrastructure for developing and running
kernel module unit tests. Currently OVS contains thousands
of useful unit tests for user space programs. It is desirable to
have corresponding kernel module unit tests.

This commit adds basic framework for adding kernel module tests. Like
user space unit tests, Kmod tests are based autotest framework, thus
are similar to existing unit tests. For references, kmod-traffic.at
contains a simple ping test.

"make check-kmod" can be invoked on any build machine as a root
user. Since kernel testing can potentially crash the kernel, it is
not recommended to run those tests directly on a development machine,
but rather a testing VM, such as ones can be launched by vagrant.

Signed-off-by: Andy Zhou <az...@nicira.com>
---
 tests/automake.mk       |  18 ++++++++
 tests/kmod-macros.at    |  71 ++++++++++++++++++++++++++++
 tests/kmod-testsuite.at | 120 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/kmod-traffic.at   |  16 +++++++
 4 files changed, 225 insertions(+)
 create mode 100644 tests/kmod-macros.at
 create mode 100644 tests/kmod-testsuite.at
 create mode 100644 tests/kmod-traffic.at

diff --git a/tests/automake.mk b/tests/automake.mk
index 33502bc..1aba6a6 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -1,6 +1,8 @@
 EXTRA_DIST += \
        $(TESTSUITE_AT) \
+       $(KMOD_TESTSUITE_AT) \
        $(TESTSUITE) \
+       $(KMOD_TESTSUITE) \
        tests/atlocal.in \
        $(srcdir)/package.m4 \
        $(srcdir)/tests/testsuite
@@ -72,7 +74,14 @@ TESTSUITE_AT = \
        tests/interface-reconfigure.at \
        tests/vlog.at \
        tests/vtep-ctl.at
+
+KMOD_TESTSUITE_AT = \
+       tests/kmod-testsuite.at \
+       tests/kmod-macros.at \
+       tests/kmod-traffic.at
+
 TESTSUITE = $(srcdir)/tests/testsuite
+KMOD_TESTSUITE = $(srcdir)/tests/kmod-testsuite
 DISTCLEANFILES += tests/atconfig tests/atlocal
 
 AUTOTEST_PATH = utilities:vswitchd:ovsdb:vtep:tests
@@ -167,6 +176,11 @@ check-ryu: all
        $(AM_V_at)srcdir='$(srcdir)' $(SHELL) $(srcdir)/tests/run-ryu
 EXTRA_DIST += tests/run-ryu
 
+# Kernel module testing
+check-kmod: all tests/atconfig tests/atlocal $(KMOD_TESTSUITE)
+       $(MAKE) modules_install
+       $(SHELL) '$(KMOD_TESTSUITE)' -C tests  AUTOTEST_PATH='$(AUTOTEST_PATH)' 
-d $(TESTSUITEFLAGS)
+
 clean-local:
        test ! -f '$(TESTSUITE)' || $(SHELL) '$(TESTSUITE)' -C tests --clean
 
@@ -175,6 +189,10 @@ $(TESTSUITE): package.m4 $(TESTSUITE_AT)
        $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at
        $(AM_V_at)mv $@.tmp $@
 
+$(KMOD_TESTSUITE): package.m4 $(KMOD_TESTSUITE_AT)
+       $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at
+       $(AM_V_at)mv $@.tmp $@
+
 # The `:;' works around a Bash 3.2 bug when the output is not writeable.
 $(srcdir)/package.m4: $(top_srcdir)/configure.ac
        $(AM_V_GEN):;{ \
diff --git a/tests/kmod-macros.at b/tests/kmod-macros.at
new file mode 100644
index 0000000..7a6b176
--- /dev/null
+++ b/tests/kmod-macros.at
@@ -0,0 +1,71 @@
+# OVS_KMOD_VSWITCHD_START([vsctl-args], [vsctl-output], [=override])
+#
+# Creates a database and starts ovsdb-server, starts ovs-vswitchd
+# connected to that database, calls ovs-vsctl to create a bridge named
+# br0 with predictable settings, passing 'vsctl-args' as additional
+# commands to ovs-vsctl.  If 'vsctl-args' causes ovs-vsctl to provide
+# output (e.g. because it includes "create" commands) then 'vsctl-output'
+# specifies the expected output after filtering through uuidfilt.pl.
+#
+m4_define([OVS_KMOD_VSWITCHD_START],
+  [ AT_CHECK([modprobe openvswitch])
+   _OVS_VSWITCHD_START([])
+   dnl Add bridges, ports, etc.
+   AT_CHECK([ovs-vsctl -- add-br br0 -- set bridge br0 
protocols=[[OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15]] 
fail-mode=secure -- $1 m4_if([$2], [], [], [| ${PERL} $srcdir/uuidfilt.pl])], 
[0], [$2])
+])
+#
+#
+# OVS_KMOD_VSWITCHD_STOP([WHITELIST])
+#
+# Gracefully stops ovs-vswitchd and ovsdb-server, checking their log files
+# for messages with severity WARN or higher and signaling an error if any
+# is present.  The optional WHITELIST may contain shell-quoted "sed"
+# commands to delete any warnings that are actually expected, e.g.:
+#
+#   OVS_KMOD_VSWITCHD_STOP(["/expected error/d"])
+m4_define([OVS_KMOD_VSWITCHD_STOP],
+  [AT_CHECK([ovs-vsctl del-br br0])
+   OVS_SWITCHD_STOP($1)
+   AT_CHECK([modprobe -r openvswitch])
+  ])
+
+# DEL_NAMESPACES(ns [, ns ... ])
+#
+# Delete namespaces from the running OS
+m4_define([DEL_NAMESPACES],
+   [m4_foreach([ns], [$@],
+               [ip netns del ns])
+   ]
+)
+#
+# ADD_NAMESPACES(ns [, ns ... ])
+#
+# Add new namespaces, if ns exists, the old one
+# will be remove before new ones are installed.
+m4_define([ADD_NAMESPACES],
+   [m4_foreach([ns], [$@],
+               [DEL_NAMESPACES(ns)
+                AT_CHECK([ip netns add ns]) ])
+   ]
+)
+
+# ADD_VETH([port], [namespace], [ovs-br], [ip_addr], [netmask])
+#
+# Add a pair of veth ports. 'port' will be added to name space 'namespace',
+# and "ovs-'port'" will be added to ovs bridge 'ovs-br'.
+#
+# The 'port' in 'namespace' will be brought up with static IP address
+# with 'ip_addr' and 'netmask'.
+#
+# The existing 'port' or 'ovs-port' will be removed before new ones are added.
+#
+m4_define([ADD_VETH],
+    [ ovs-vsctl del-port $3 ovs-$1
+      ip netns exec $2 ip link del $1
+      AT_CHECK([ ip link add $1 type veth peer name ovs-$1 ])
+      AT_CHECK([ ip link set $1 netns $2 ])
+      AT_CHECK([ ovs-vsctl add-port $3 ovs-$1 ])
+      AT_CHECK([ ip link set dev ovs-$1 up ])
+      AT_CHECK([ ip netns exec $2 ifconfig $1 $4 netmask $5 up ])
+    ]
+)
diff --git a/tests/kmod-testsuite.at b/tests/kmod-testsuite.at
new file mode 100644
index 0000000..7f22f82
--- /dev/null
+++ b/tests/kmod-testsuite.at
@@ -0,0 +1,120 @@
+AT_INIT
+
+AT_COPYRIGHT([Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at:
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.])
+
+AT_TESTED([ovs-vswitchd])
+AT_TESTED([ovs-vsctl])
+AT_TESTED([perl])
+
+m4_include([m4/compat.at])
+
+m4_divert_push([PREPARE_TESTS])
+[
+ovs_wait () {
+    # First try a quick sleep, so that the test completes very quickly
+    # in the normal case.  POSIX doesn't require fractional times to
+    # work, so this might not work.
+    sleep 0.1
+    ovs_wait_cond && exit 0
+    # Then wait up to 10 seconds.
+    for d in 0 1 2 3 4 5 6 7 8 9; do
+        sleep 1
+        ovs_wait_cond && exit 0
+    done
+    exit 1
+}
+
+# Prints the integers from $1 to $2, increasing by $3 (default 1) on stdout.
+seq () {
+    while test $1 -le $2; do
+        echo $1
+        set `expr $1 + ${3-1}` $2 $3
+    done
+}
+
+if test "$IS_WIN32" = "yes"; then
+    pwd () {
+        command pwd -W "$@"
+    }
+
+    diff () {
+        command diff --strip-trailing-cr "$@"
+    }
+
+    kill () {
+        case "$1" in
+            -0)
+                shift
+                for i in $*; do
+                    # tasklist will always have return code 0.
+                    # If pid does exist, there will be a line with the pid.
+                    if tasklist //fi "PID eq $i" | grep $i >/dev/null; then
+                        :
+                    else
+                        return 1
+                    fi
+                done
+                return 0
+                ;;
+            -[1-9]*)
+                shift
+                for i in $*; do
+                    taskkill //F //PID $i >/dev/null
+                done
+                ;;
+            [1-9][0-9]*)
+                for i in $*; do
+                    taskkill //F //PID $i >/dev/null
+                done
+                ;;
+        esac
+    }
+fi
+]
+m4_divert_pop([PREPARE_TESTS])
+
+m4_define([OVS_WAIT],
+  [AT_CHECK(
+     [ovs_wait_cond () { $1
+}
+ovs_wait], [0], [ignore], [ignore], [$2])])
+m4_define([OVS_WAIT_UNTIL], [OVS_WAIT([$1], [$2])])
+m4_define([OVS_WAIT_WHILE],
+  [OVS_WAIT([if $1; then return 1; else return 0; fi], [$2])])
+
+dnl OVS_APP_EXIT_AND_WAIT(DAEMON)
+dnl
+dnl Ask the daemon named DAEMON to exit, via ovs-appctl, and then waits for it
+dnl to exit.
+m4_define([OVS_APP_EXIT_AND_WAIT],
+  [ovs-appctl -t $1 exit
+   OVS_WAIT_WHILE([test -e $1.pid])])
+
+dnl ON_EXIT([COMMANDS])
+dnl
+dnl Adds the shell COMMANDS to a collection executed when the current test
+dnl completes, as a cleanup action.  (The most common use is to kill a
+dnl daemon started by the test.  This is important to prevent tests that
+dnl start daemons from hanging at exit.)
+m4_define([ON_EXIT], [trap '. ./cleanup' 0; cat >>cleanup <<'EOF'
+$1
+EOF
+])
+
+m4_include([tests/ovsdb-macros.at])
+m4_include([tests/ofproto-macros.at])
+m4_include([tests/kmod-macros.at])
+
+m4_include([tests/kmod-traffic.at])
diff --git a/tests/kmod-traffic.at b/tests/kmod-traffic.at
new file mode 100644
index 0000000..cfdc25c
--- /dev/null
+++ b/tests/kmod-traffic.at
@@ -0,0 +1,16 @@
+AT_BANNER([kmod-sanity])
+
+AT_SETUP([kmod - ping between two ports])
+OVS_KMOD_VSWITCHD_START(
+   [ set-fail-mode br0 standalone -- ])
+
+ADD_NAMESPACES(_ns0, _ns1)
+
+ADD_VETH(p0, _ns0, br0, "10.1.1.1","255.255.255.0")
+ADD_VETH(p1, _ns1, br0, "10.1.1.2","255.255.255.0")
+
+AT_CHECK([ ip netns exec _ns0 bash -c "ping -q -c 3 -i 0.3 -w 2 10.1.1.2 
>/dev/null"  ])
+
+DEL_NAMESPACES(_ns0, _ns1)
+OVS_KMOD_VSWITCHD_STOP
+AT_CLEANUP
-- 
1.9.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to