Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: kostja@tarantool.org
Subject: [tarantool-patches] [PATCH 2/6] test: introduce breakpoints for swim's event loop
Date: Wed, 20 Mar 2019 13:49:15 +0300	[thread overview]
Message-ID: <fb3133cd05b2b14dd7dcb16a892cd1af417699ab.1553078631.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1553078631.git.v.shpilevoy@tarantool.org>
In-Reply-To: <cover.1553078631.git.v.shpilevoy@tarantool.org>

Breakpoint as API gives a test writer more control over timing of
condition checks. Breakpoint stops the swim's event loop in a
certain moment of virtual time.

Without breakpoints it is possible, that a condition has failed
its deadline, but it can not be checked properly. For example,
assume that there is a cluster of two members, and after 1 second
they should become fullmesh. It means, that any checks in [0, 1)
time have to fail. But without breakpoints it is not so:

    // event_queue: [round_step, 1 sec]
    // time: 0
    swim_cluster_wait_fullmesh(cluster, 0.5); // Fails.

    // event_queue: []
    // time: 1
    swim_cluster_wait_fullmesh(cluster, 0.1); // Success.

The second test should fail, but it does not, because global time
is already 1 after the first test and the cluster is in fullmesh
already. It looks weird, so such checks should be done not later
than deadline.

Follow-up for 03b9a6e91baf246ee2bb9841d01ba3824b6768a6
---
 test/unit/swim.c            |  6 ++++--
 test/unit/swim.result       |  5 +++--
 test/unit/swim_test_ev.c    | 39 +++++++++++++++++++++++++++++++++++++
 test/unit/swim_test_ev.h    |  8 ++++++++
 test/unit/swim_test_utils.c | 26 ++++++++++++++++++-------
 5 files changed, 73 insertions(+), 11 deletions(-)

diff --git a/test/unit/swim.c b/test/unit/swim.c
index 921fc8f07..3a97aeb18 100644
--- a/test/unit/swim.c
+++ b/test/unit/swim.c
@@ -50,7 +50,7 @@ static int test_result;
 static void
 swim_test_one_link(void)
 {
-	swim_start_test(1);
+	swim_start_test(2);
 	/*
 	 * Run a simple cluster of two elements. One of them
 	 * learns about another explicitly. Another should add the
@@ -58,7 +58,9 @@ swim_test_one_link(void)
 	 */
 	struct swim_cluster *cluster = swim_cluster_new(2);
 	fail_if(swim_cluster_add_link(cluster, 0, 1) != 0);
-	is(swim_cluster_wait_fullmesh(cluster, 1), 0, "one link");
+	is(swim_cluster_wait_fullmesh(cluster, 0.9), -1,
+	   "no rounds - no fullmesh");
+	is(swim_cluster_wait_fullmesh(cluster, 0.1), 0, "one link");
 	swim_cluster_delete(cluster);
 
 	swim_finish_test();
diff --git a/test/unit/swim.result b/test/unit/swim.result
index e8991d8d8..b58325b73 100644
--- a/test/unit/swim.result
+++ b/test/unit/swim.result
@@ -1,8 +1,9 @@
 	*** main_f ***
 1..5
 	*** swim_test_one_link ***
-    1..1
-    ok 1 - one link
+    1..2
+    ok 1 - no rounds - no fullmesh
+    ok 2 - one link
 ok 1 - subtests
 	*** swim_test_one_link: done ***
 	*** swim_test_sequence ***
diff --git a/test/unit/swim_test_ev.c b/test/unit/swim_test_ev.c
index ee1fcdbb7..d4a0a4752 100644
--- a/test/unit/swim_test_ev.c
+++ b/test/unit/swim_test_ev.c
@@ -55,6 +55,7 @@ static int event_id = 0;
 enum swim_event_type {
 	SWIM_EVENT_TIMER,
 	SWIM_EVENT_FD_UNBLOCK,
+	SWIM_EVENT_BRK,
 };
 
 struct swim_event;
@@ -250,6 +251,44 @@ swim_test_ev_block_fd(int fd, double delay)
 	e->fd = fd;
 }
 
+/**
+ * Breakpoint event for debug. It does nothing but stops the event
+ * loop after a timeout to allow highlevel API to check some
+ * cases.
+ */
+struct swim_brk_event {
+	struct swim_event base;
+};
+
+/** Delete a breakpoint event. */
+static void
+swim_brk_event_delete(struct swim_event *e)
+{
+	assert(e->type == SWIM_EVENT_BRK);
+	swim_event_destroy(e);
+	free(e);
+}
+
+/**
+ * Breakpoint event processing is nothing but the event deletion.
+ */
+static void
+swim_brk_event_process(struct swim_event *e, struct ev_loop *loop)
+{
+	(void) loop;
+	assert(e->type == SWIM_EVENT_BRK);
+	swim_brk_event_delete(e);
+}
+
+void
+swim_ev_set_brk(double delay)
+{
+	struct swim_brk_event *e = (struct swim_brk_event *) malloc(sizeof(*e));
+	assert(e != NULL);
+	swim_event_create(&e->base, SWIM_EVENT_BRK, delay,
+			  swim_brk_event_process, swim_brk_event_delete);
+}
+
 /** Implementation of global time visible in SWIM. */
 double
 swim_time(void)
diff --git a/test/unit/swim_test_ev.h b/test/unit/swim_test_ev.h
index 808bc510e..01a1b8868 100644
--- a/test/unit/swim_test_ev.h
+++ b/test/unit/swim_test_ev.h
@@ -51,6 +51,14 @@ swim_test_ev_free(void);
 void
 swim_test_ev_block_fd(int fd, double delay);
 
+/**
+ * Stop the event loop after @a delay fake seconds. It does not
+ * affect other events, so the loop can stop earlier multiple
+ * times.
+ */
+void
+swim_ev_set_brk(double delay);
+
 /** Play one step of event loop, process generated events. */
 void
 swim_do_loop_step(struct ev_loop *loop);
diff --git a/test/unit/swim_test_utils.c b/test/unit/swim_test_utils.c
index a92e55233..0b301333b 100644
--- a/test/unit/swim_test_utils.c
+++ b/test/unit/swim_test_utils.c
@@ -129,16 +129,28 @@ swim_cluster_is_fullmesh(struct swim_cluster *cluster)
 	return true;
 }
 
+/**
+ * A common wrapper for some conditions checking after each event
+ * loop step.
+ */
+#define swim_wait_timeout(timeout, target_cond) ({			\
+	swim_ev_set_brk(timeout);					\
+	double deadline = swim_time() + timeout;			\
+	int rc = 0;							\
+	while (! (target_cond)) {					\
+		if (swim_time() >= deadline) {				\
+			rc = -1;					\
+			break;						\
+		}							\
+		swim_do_loop_step(loop());				\
+	}								\
+	rc;								\
+})
+
 int
 swim_cluster_wait_fullmesh(struct swim_cluster *cluster, double timeout)
 {
-	double deadline = swim_time() + timeout;
-	while (! swim_cluster_is_fullmesh(cluster)) {
-		if (swim_time() >= deadline)
-			return -1;
-		swim_do_loop_step(loop());
-	}
-	return 0;
+	return swim_wait_timeout(timeout, swim_cluster_is_fullmesh(cluster));
 }
 
 bool
-- 
2.17.2 (Apple Git-113)

  parent reply	other threads:[~2019-03-20 10:49 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-20 10:49 [tarantool-patches] [PATCH 0/6] SWIM failure detection draft Vladislav Shpilevoy
2019-03-20 10:49 ` [tarantool-patches] [PATCH 1/6] swim: follow-ups for SWIM anti-entropy Vladislav Shpilevoy
2019-03-29  8:27   ` [tarantool-patches] " Konstantin Osipov
2019-03-29 10:19     ` Vladislav Shpilevoy
2019-03-20 10:49 ` Vladislav Shpilevoy [this message]
2019-03-29 18:20   ` [tarantool-patches] Re: [PATCH 2/6] test: introduce breakpoints for swim's event loop Konstantin Osipov
2019-04-02 12:25     ` Vladislav Shpilevoy
2019-04-02 19:16       ` Vladislav Shpilevoy
2019-04-02 20:40         ` Konstantin Osipov
2019-04-02 21:26           ` Vladislav Shpilevoy
2019-03-20 10:49 ` [tarantool-patches] [PATCH 3/6] test: remove swim_unblock_fd event from swim test harness Vladislav Shpilevoy
2019-03-29 18:22   ` [tarantool-patches] " Konstantin Osipov
2019-04-02 21:26     ` Vladislav Shpilevoy
2019-03-20 10:49 ` [tarantool-patches] [PATCH 4/6] swim: expose enum swim_member_status to public API Vladislav Shpilevoy
2019-03-29 18:24   ` [tarantool-patches] " Konstantin Osipov
2019-04-02 12:25     ` Vladislav Shpilevoy
2019-04-02 13:17       ` Konstantin Osipov
2019-04-02 21:26         ` Vladislav Shpilevoy
2019-03-20 10:49 ` [tarantool-patches] [PATCH 5/6] test: differentiate blocked and closed swim fake fds Vladislav Shpilevoy
2019-03-29 18:25   ` [tarantool-patches] " Konstantin Osipov
2019-04-02 21:26     ` Vladislav Shpilevoy
2019-03-20 10:49 ` [tarantool-patches] [PATCH 6/6] [RAW] swim: introduce failure detection component Vladislav Shpilevoy
2019-03-29 18:59   ` [tarantool-patches] " Konstantin Osipov
2019-04-02 12:25     ` Vladislav Shpilevoy
2019-04-04 10:20       ` Vladislav Shpilevoy
2019-04-04 12:45       ` Konstantin Osipov
2019-04-04 13:57         ` Vladislav Shpilevoy
2019-04-04 16:14           ` Vladimir Davydov
2019-04-04 16:47             ` Vladislav Shpilevoy
2019-03-27 19:28 ` [tarantool-patches] [PATCH 7/6] swim: make swim_upsert_member returning two values Vladislav Shpilevoy
2019-03-28  8:52   ` [tarantool-patches] " Konstantin Osipov
2019-03-28 11:52     ` Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fb3133cd05b2b14dd7dcb16a892cd1af417699ab.1553078631.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH 2/6] test: introduce breakpoints for swim'\''s event loop' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox