[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 16/18] libxl: events: timedereg internal unit test



Test timeout deregistration idempotency.  In the current tree this
test fails because ev->func is not cleared, meaning that a timeout
can be removed from the list more than once, corrupting the list.

It is necessary to use multiple timeouts to demonstrate this bug,
because removing the very same entry twice from a list in quick
succession, without modifying the list in other ways in between,
doesn't actually corrupt the list.  (Since removing an entry from a
doubly-linked list just copies next and back from the disappearing
entry into its neighbours.)

Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
Cc: Jim Fehlig <jfehlig@xxxxxxxx>
Cc: Ian Campbell <Ian.Campbell@xxxxxxxxxx>
---
 .gitignore                         |    1 +
 tools/libxl/Makefile               |    2 +-
 tools/libxl/libxl_test_timedereg.c |   97 ++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_test_timedereg.h |    9 ++++
 tools/libxl/test_timedereg.c       |   11 ++++
 5 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 tools/libxl/libxl_test_timedereg.c
 create mode 100644 tools/libxl/libxl_test_timedereg.h
 create mode 100644 tools/libxl/test_timedereg.c

diff --git a/.gitignore b/.gitignore
index 3504584..db3b083 100644
--- a/.gitignore
+++ b/.gitignore
@@ -361,6 +361,7 @@ tools/libxl/testidl
 tools/libxl/testidl.c
 tools/libxl/*.pyc
 tools/libxl/libxl-save-helper
+tools/libxl/test_timedereg
 tools/blktap2/control/tap-ctl
 tools/firmware/etherboot/eb-roms.h
 tools/firmware/etherboot/gpxe-git-snapshot.tar.gz
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index f04cba7..1dccbf0 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -79,7 +79,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o 
libxl_pci.o \
                        libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y)
 LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
 
-LIBXL_TESTS +=
+LIBXL_TESTS += timedereg
 # Each entry FOO in LIBXL_TESTS has two main .c files:
 #   libxl_test_FOO.c  "inside libxl" code to support the test case
 #   test_FOO.c        "outside libxl" code to exercise the test case
diff --git a/tools/libxl/libxl_test_timedereg.c 
b/tools/libxl/libxl_test_timedereg.c
new file mode 100644
index 0000000..a44639f
--- /dev/null
+++ b/tools/libxl/libxl_test_timedereg.c
@@ -0,0 +1,97 @@
+/*
+ * timedereg test case for the libxl event system
+ *
+ * To run this test:
+ *    ./test_timedereg
+ * Success:
+ *    program takes a few seconds, prints some debugging output and exits 0
+ * Failure:
+ *    crash
+ *
+ * set up [0]-group timeouts 0 1 2
+ * wait for timeout 1 to occur
+ * deregister 0 and 2.  1 is supposed to be deregistered already
+ * register [1]-group 0 1 2
+ * deregister 1 (should be a no-op)
+ * wait for [1]-group 0 1 2 in turn
+ * on final callback assert that all have been deregistered
+ */
+
+#include "libxl_internal.h"
+
+#include "libxl_test_timedereg.h"
+
+#define NTIMES 3
+static const int ms[2][NTIMES] = { { 2000,1000,2000 }, { 1000,2000,3000 } };
+static libxl__ev_time et[2][NTIMES];
+static libxl__ao *tao;
+static int seq;
+
+static void occurs(libxl__egc *egc, libxl__ev_time *ev,
+                   const struct timeval *requested_abs);
+
+static void regs(libxl__gc *gc, int j)
+{
+    int rc, i;
+    LOG(DEBUG,"regs(%d)", j);
+    for (i=0; i<NTIMES; i++) {
+        rc = libxl__ev_time_register_rel(gc, &et[j][i], occurs, ms[j][i]);
+        assert(!rc);
+    }    
+}
+
+int libxl_test_timedereg(libxl_ctx *ctx, libxl_asyncop_how *ao_how)
+{
+    int i;
+    AO_CREATE(ctx, 0, ao_how);
+
+    tao = ao;
+
+    for (i=0; i<NTIMES; i++) {
+        libxl__ev_time_init(&et[0][i]);
+        libxl__ev_time_init(&et[1][i]);
+    }
+
+    regs(gc, 0);
+
+    return AO_INPROGRESS;
+}
+
+static void occurs(libxl__egc *egc, libxl__ev_time *ev,
+                   const struct timeval *requested_abs)
+{
+    EGC_GC;
+    int i;
+
+    int off = ev - &et[0][0];
+    LOG(DEBUG,"occurs[%d][%d] seq=%d", off/NTIMES, off%NTIMES, seq);
+
+    switch (seq) {
+    case 0:
+        assert(ev == &et[0][1]);
+        libxl__ev_time_deregister(gc, &et[0][0]);
+        libxl__ev_time_deregister(gc, &et[0][2]);
+        regs(gc, 1);
+        libxl__ev_time_deregister(gc, &et[0][1]);
+        break;
+
+    case 1:
+    case 2:
+        assert(ev == &et[1][seq-1]);
+        break;
+        
+    case 3:
+        assert(ev == &et[1][2]);
+        for (i=0; i<NTIMES; i++) {
+            assert(!libxl__ev_time_isregistered(&et[0][i]));
+            assert(!libxl__ev_time_isregistered(&et[1][i]));
+        }
+        libxl__ao_complete(egc, tao, 0);
+        return;
+
+    default:
+        abort();
+    }
+
+    seq++;
+}
diff --git a/tools/libxl/libxl_test_timedereg.h 
b/tools/libxl/libxl_test_timedereg.h
new file mode 100644
index 0000000..9547dba
--- /dev/null
+++ b/tools/libxl/libxl_test_timedereg.h
@@ -0,0 +1,9 @@
+#ifndef TEST_TIMEDEREG_H
+#define TEST_TIMEDEREG_H
+
+#include <pthread.h>
+
+int libxl_test_timedereg(libxl_ctx *ctx, libxl_asyncop_how *ao_how)
+    LIBXL_EXTERNAL_CALLERS_ONLY;
+
+#endif /*TEST_TIMEDEREG_H*/
diff --git a/tools/libxl/test_timedereg.c b/tools/libxl/test_timedereg.c
new file mode 100644
index 0000000..0081ce3
--- /dev/null
+++ b/tools/libxl/test_timedereg.c
@@ -0,0 +1,11 @@
+#include "test_common.h"
+#include "libxl_test_timedereg.h"
+
+int main(int argc, char **argv) {
+    int rc;
+
+    test_common_setup(XTL_DEBUG);
+
+    rc = libxl_test_timedereg(ctx, 0);
+    assert(!rc);
+}
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.