[Tarantool-patches] [PATCH 07/10] test: rename fake libev methods to fakeev

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Tue Dec 1 02:56:16 MSK 2020


SWIM unit tests contain a special library for emulating the event
loop: swim_test_ev. It provides API similar to libev, but
implemented entirely in user-space, including clock functions.

The latter is the most important point, as the original libev
does not allow to define your own timing functions - internally it
relies on select/kqueue/epoll/poll/select/... with true clock.

Because of that it is impossible to perform long tests with the
original libev, which could last for minutes or even tens of
seconds if their count is big. swim_test_ev uses virtual time,
where hours can be played in milliseconds.

The fake libev is going to be re-used for Raft unit tests. But for
that it is necessary to detach it from all SWIM dependencies.

--

This commit makes all swim_test_ev functions have 'fakeev' prefix
instead of 'swim'. The functions, implementing swim_ev.h API, are
kept as one-line proxies to the fakeev functions.

Part of #5303
---
 test/unit/swim.c            |   4 +-
 test/unit/swim_errinj.c     |   4 +-
 test/unit/swim_test_ev.c    | 185 +++++++++++++++++++++---------------
 test/unit/swim_test_ev.h    |  27 ++++--
 test/unit/swim_test_utils.c |  10 +-
 test/unit/swim_test_utils.h |   2 +-
 6 files changed, 134 insertions(+), 98 deletions(-)

diff --git a/test/unit/swim.c b/test/unit/swim.c
index 1787745bc..a506d04e9 100644
--- a/test/unit/swim.c
+++ b/test/unit/swim.c
@@ -1077,7 +1077,7 @@ main_f(va_list ap)
 	swim_start_test(22);
 
 	(void) ap;
-	swim_test_ev_init();
+	fakeev_init();
 	fakenet_init();
 
 	swim_test_one_link();
@@ -1104,7 +1104,7 @@ main_f(va_list ap)
 	swim_test_suspect_new_members();
 
 	fakenet_free();
-	swim_test_ev_free();
+	fakeev_free();
 
 	test_result = check_plan();
 	footer();
diff --git a/test/unit/swim_errinj.c b/test/unit/swim_errinj.c
index 005be380d..00b59f63c 100644
--- a/test/unit/swim_errinj.c
+++ b/test/unit/swim_errinj.c
@@ -216,14 +216,14 @@ main_f(va_list ap)
 	swim_start_test(2);
 
 	(void) ap;
-	swim_test_ev_init();
+	fakeev_init();
 	fakenet_init();
 
 	swim_test_payload_refutation();
 	swim_test_indirect_ping();
 
 	fakenet_free();
-	swim_test_ev_free();
+	fakeev_free();
 
 	test_result = check_plan();
 	footer();
diff --git a/test/unit/swim_test_ev.c b/test/unit/swim_test_ev.c
index 625b697d9..6847836e3 100644
--- a/test/unit/swim_test_ev.c
+++ b/test/unit/swim_test_ev.c
@@ -48,18 +48,18 @@ static double watch = 0;
 static int event_id = 0;
 
 /**
- * SWIM testing event loop has two event types - natural libev
- * events like timer, and artificial like fake socket blocking.
+ * Fake event loop has two event types - natural libev events like timer, and
+ * artificial like fake socket blocking.
  */
-enum swim_event_type {
-	SWIM_EVENT_TIMER,
-	SWIM_EVENT_BRK,
+enum fakeev_event_type {
+	FAKEEV_EVENT_TIMER,
+	FAKEEV_EVENT_BRK,
 };
 
-struct swim_event;
+struct fakeev_event;
 
-typedef void (*swim_event_process_f)(struct swim_event *, struct ev_loop *);
-typedef void (*swim_event_delete_f)(struct swim_event *);
+typedef void (*fakeev_event_process_f)(struct fakeev_event *, struct ev_loop *);
+typedef void (*fakeev_event_delete_f)(struct fakeev_event *);
 
 /**
  * An isolated event loop not visible to the fiber scheduler,
@@ -69,7 +69,7 @@ typedef void (*swim_event_delete_f)(struct swim_event *);
 static struct ev_loop *test_loop;
 
 struct ev_loop *
-swim_loop(void)
+fakeev_loop(void)
 {
 	return test_loop;
 }
@@ -78,9 +78,9 @@ swim_loop(void)
  * Base event. It is stored in the event heap and virtualizes
  * other events.
  */
-struct swim_event {
+struct fakeev_event {
 	/** Type, for assertions only. */
-	enum swim_event_type type;
+	enum fakeev_event_type type;
 	/**
 	 * When that event should be invoked according to the fake
 	 * watch.
@@ -94,9 +94,9 @@ struct swim_event {
 	 * Process the event. Usually the event is deleted right
 	 * after that.
 	 */
-	swim_event_process_f process;
+	fakeev_event_process_f process;
 	/** Just delete the event. Called on event heap reset. */
-	swim_event_delete_f delete;
+	fakeev_event_delete_f delete;
 };
 
 /**
@@ -104,7 +104,7 @@ struct swim_event {
  * deadline and the smallest ID in that deadline.
  */
 static inline bool
-swim_event_less(const struct swim_event *e1, const struct swim_event *e2)
+fakeev_event_less(const struct fakeev_event *e1, const struct fakeev_event *e2)
 {
 	if (e1->deadline == e2->deadline)
 		return e1->id < e2->id;
@@ -112,8 +112,8 @@ swim_event_less(const struct swim_event *e1, const struct swim_event *e2)
 }
 
 #define HEAP_NAME event_heap
-#define HEAP_LESS(h, e1, e2) swim_event_less(e1, e2)
-#define heap_value_t struct swim_event
+#define HEAP_LESS(h, e1, e2) fakeev_event_less(e1, e2)
+#define heap_value_t struct fakeev_event
 #define heap_value_attr in_event_heap
 #include "salad/heap.h"
 
@@ -125,15 +125,15 @@ static struct mh_i64ptr_t *events_hash;
 
 /**
  * Create a new event which should call @a process after @a delay
- * fake seconds. @A delete is called explicitly when the event
- * is deleted by SWIM explicitly, and when the event heap is
- * reset.
+ * fake seconds. @A delete is called to free the event when it is
+ * done, and when the event heap is reset.
  */
 static void
-swim_event_create(struct swim_event *e, enum swim_event_type type, double delay,
-		  swim_event_process_f process, swim_event_delete_f delete)
+fakeev_event_create(struct fakeev_event *e, enum fakeev_event_type type,
+		    double delay, fakeev_event_process_f process,
+		    fakeev_event_delete_f delete)
 {
-	e->deadline = swim_time() + delay;
+	e->deadline = fakeev_time() + delay;
 	e->id = event_id++;
 	e->process = process;
 	e->delete = delete;
@@ -143,34 +143,34 @@ swim_event_create(struct swim_event *e, enum swim_event_type type, double delay,
 
 /** Destroy a basic event. */
 static inline void
-swim_event_destroy(struct swim_event *e)
+fakeev_event_destroy(struct fakeev_event *e)
 {
 	event_heap_delete(&event_heap, e);
 }
 
 /** Destroy a event and free its resources. */
 static inline void
-swim_event_delete(struct swim_event *e)
+fakeev_event_delete(struct fakeev_event *e)
 {
 	e->delete(e);
 }
 
 /** Find an event by @a watcher. */
-static struct swim_event *
-swim_event_by_ev(struct ev_watcher *watcher)
+static struct fakeev_event *
+fakeev_event_by_ev(struct ev_watcher *watcher)
 {
 	mh_int_t rc = mh_i64ptr_find(events_hash, (uint64_t) watcher, NULL);
 	if (rc == mh_end(events_hash))
 		return NULL;
-	return (struct swim_event *) mh_i64ptr_node(events_hash, rc)->val;
+	return mh_i64ptr_node(events_hash, rc)->val;
 }
 
 /** Timer event generated by libev. */
-struct swim_timer_event {
-	struct swim_event base;
+struct fakeev_timer_event {
+	struct fakeev_event base;
 	/**
 	 * Libev watcher. Used to store callback and to find the
-	 * event by watcher pointer. It is necessary because SWIM
+	 * event by watcher pointer. It is necessary because real code
 	 * operates by libev watchers.
 	 */
 	struct ev_watcher *watcher;
@@ -178,45 +178,45 @@ struct swim_timer_event {
 
 /** Destroy a timer event and free its resources. */
 static void
-swim_timer_event_delete(struct swim_event *e)
+fakeev_timer_event_delete(struct fakeev_event *e)
 {
-	assert(e->type == SWIM_EVENT_TIMER);
-	struct swim_timer_event *te = (struct swim_timer_event *) e;
+	assert(e->type == FAKEEV_EVENT_TIMER);
+	struct fakeev_timer_event *te = (struct fakeev_timer_event *)e;
 	mh_int_t rc = mh_i64ptr_find(events_hash, (uint64_t) te->watcher, NULL);
 	assert(rc != mh_end(events_hash));
 	mh_i64ptr_del(events_hash, rc, NULL);
-	swim_event_destroy(e);
+	fakeev_event_destroy(e);
 	free(te);
 }
 
 /** Create a new timer event. */
 static void
-swim_timer_event_new(struct ev_watcher *watcher, double delay);
+fakeev_timer_event_new(struct ev_watcher *watcher, double delay);
 
 /** Process a timer event and delete it. */
 static void
-swim_timer_event_process(struct swim_event *e, struct ev_loop *loop)
+fakeev_timer_event_process(struct fakeev_event *e, struct ev_loop *loop)
 {
-	assert(e->type == SWIM_EVENT_TIMER);
-	struct ev_watcher *w = ((struct swim_timer_event *) e)->watcher;
+	assert(e->type == FAKEEV_EVENT_TIMER);
+	struct ev_watcher *w = ((struct fakeev_timer_event *)e)->watcher;
 	struct ev_timer *t = (struct ev_timer *) w;
-	swim_timer_event_delete(e);
+	fakeev_timer_event_delete(e);
 	t->at = 0;
 	if (t->repeat > 0)
-		swim_timer_event_new(w, t->repeat);
+		fakeev_timer_event_new(w, t->repeat);
 	ev_invoke(loop, w, EV_TIMER);
 }
 
 static void
-swim_timer_event_new(struct ev_watcher *watcher, double delay)
+fakeev_timer_event_new(struct ev_watcher *watcher, double delay)
 {
-	struct swim_timer_event *e =
-		(struct swim_timer_event *) malloc(sizeof(*e));
+	struct fakeev_timer_event *e = malloc(sizeof(*e));
 	assert(e != NULL);
-	swim_event_create(&e->base, SWIM_EVENT_TIMER, delay,
-			  swim_timer_event_process, swim_timer_event_delete);
+	fakeev_event_create(&e->base, FAKEEV_EVENT_TIMER, delay,
+			    fakeev_timer_event_process,
+			    fakeev_timer_event_delete);
 	e->watcher = watcher;
-	assert(swim_event_by_ev(watcher) == NULL);
+	assert(fakeev_event_by_ev(watcher) == NULL);
 	struct mh_i64ptr_node_t node = {(uint64_t) watcher, e};
 	mh_int_t rc = mh_i64ptr_put(events_hash, &node, NULL, NULL);
 	(void) rc;
@@ -227,19 +227,19 @@ swim_timer_event_new(struct ev_watcher *watcher, double delay)
  * Breakpoint event for debug. It does nothing but stops the event
  * loop after a timeout to allow highlevel API to check some
  * cases. The main feature is that a test can choose that timeout,
- * while natural SWIM events usually are out of control. That
+ * while natural events usually are out of control. That
  * events allows to check conditions between natural events.
  */
-struct swim_brk_event {
-	struct swim_event base;
+struct fakeev_brk_event {
+	struct fakeev_event base;
 };
 
 /** Delete a breakpoint event. */
 static void
-swim_brk_event_delete(struct swim_event *e)
+fakeev_brk_event_delete(struct fakeev_event *e)
 {
-	assert(e->type == SWIM_EVENT_BRK);
-	swim_event_destroy(e);
+	assert(e->type == FAKEEV_EVENT_BRK);
+	fakeev_event_destroy(e);
 	free(e);
 }
 
@@ -247,25 +247,24 @@ swim_brk_event_delete(struct swim_event *e)
  * Breakpoint event processing is nothing but the event deletion.
  */
 static void
-swim_brk_event_process(struct swim_event *e, struct ev_loop *loop)
+fakeev_brk_event_process(struct fakeev_event *e, struct ev_loop *loop)
 {
 	(void) loop;
-	assert(e->type == SWIM_EVENT_BRK);
-	swim_brk_event_delete(e);
+	assert(e->type == FAKEEV_EVENT_BRK);
+	fakeev_brk_event_delete(e);
 }
 
 void
-swim_ev_set_brk(double delay)
+fakeev_set_brk(double delay)
 {
-	struct swim_brk_event *e = (struct swim_brk_event *) malloc(sizeof(*e));
+	struct fakeev_brk_event *e = malloc(sizeof(*e));
 	assert(e != NULL);
-	swim_event_create(&e->base, SWIM_EVENT_BRK, delay,
-			  swim_brk_event_process, swim_brk_event_delete);
+	fakeev_event_create(&e->base, FAKEEV_EVENT_BRK, delay,
+			    fakeev_brk_event_process, fakeev_brk_event_delete);
 }
 
-/** Implementation of global time visible in SWIM. */
 double
-swim_time(void)
+fakeev_time(void)
 {
 	return watch;
 }
@@ -275,44 +274,44 @@ swim_time(void)
  * already started - nothing happens.
  */
 void
-swim_ev_timer_start(struct ev_loop *loop, struct ev_timer *base)
+fakeev_timer_start(struct ev_loop *loop, struct ev_timer *base)
 {
 	(void) loop;
-	if (swim_event_by_ev((struct ev_watcher *) base) != NULL)
+	if (fakeev_event_by_ev((struct ev_watcher *)base) != NULL)
 		return;
 	/* Create the periodic watcher and one event. */
-	swim_timer_event_new((struct ev_watcher *) base, base->at);
+	fakeev_timer_event_new((struct ev_watcher *)base, base->at);
 }
 
 void
-swim_ev_timer_again(struct ev_loop *loop, struct ev_timer *base)
+fakeev_timer_again(struct ev_loop *loop, struct ev_timer *base)
 {
 	(void) loop;
-	if (swim_event_by_ev((struct ev_watcher *) base) != NULL)
+	if (fakeev_event_by_ev((struct ev_watcher *)base) != NULL)
 		return;
 	/* Create the periodic watcher and one event. */
-	swim_timer_event_new((struct ev_watcher *) base, base->repeat);
+	fakeev_timer_event_new((struct ev_watcher *)base, base->repeat);
 }
 
 /** Time stop cancels the event if the timer is active. */
 void
-swim_ev_timer_stop(struct ev_loop *loop, struct ev_timer *base)
+fakeev_timer_stop(struct ev_loop *loop, struct ev_timer *base)
 {
 	(void) loop;
 	/*
 	 * Delete the watcher and its events. Should be only one.
 	 */
-	struct swim_event *e = swim_event_by_ev((struct ev_watcher *) base);
+	struct fakeev_event *e = fakeev_event_by_ev((struct ev_watcher *)base);
 	if (e == NULL)
 		return;
-	swim_event_delete(e);
+	fakeev_event_delete(e);
 }
 
 /** Process all the events with the next nearest deadline. */
 void
-swim_test_ev_do_loop_step(struct ev_loop *loop)
+fakeev_loop_update(struct ev_loop *loop)
 {
-	struct swim_event *e = event_heap_top(&event_heap);
+	struct fakeev_event *e = event_heap_top(&event_heap);
 	if (e != NULL) {
 		assert(e->deadline >= watch);
 		/* Multiple events can have the same deadline. */
@@ -326,18 +325,18 @@ swim_test_ev_do_loop_step(struct ev_loop *loop)
 }
 
 void
-swim_test_ev_reset(void)
+fakeev_reset(void)
 {
-	struct swim_event *e;
+	struct fakeev_event *e;
 	while ((e = event_heap_top(&event_heap)) != NULL)
-		swim_event_delete(e);
+		fakeev_event_delete(e);
 	assert(mh_size(events_hash) == 0);
 	event_id = 0;
 	watch = 0;
 }
 
 void
-swim_test_ev_init(void)
+fakeev_init(void)
 {
 	events_hash = mh_i64ptr_new();
 	assert(events_hash != NULL);
@@ -347,10 +346,40 @@ swim_test_ev_init(void)
 }
 
 void
-swim_test_ev_free(void)
+fakeev_free(void)
 {
-	swim_test_ev_reset();
+	fakeev_reset();
 	event_heap_destroy(&event_heap);
 	mh_i64ptr_delete(events_hash);
 	ev_loop_destroy(test_loop);
 }
+
+double
+swim_time(void)
+{
+	return fakeev_time();
+}
+
+void
+swim_ev_timer_start(struct ev_loop *loop, struct ev_timer *watcher)
+{
+	return fakeev_timer_start(loop, watcher);
+}
+
+void
+swim_ev_timer_again(struct ev_loop *loop, struct ev_timer *watcher)
+{
+	return fakeev_timer_again(loop, watcher);
+}
+
+void
+swim_ev_timer_stop(struct ev_loop *loop, struct ev_timer *watcher)
+{
+	return fakeev_timer_stop(loop, watcher);
+}
+
+struct ev_loop *
+swim_loop(void)
+{
+	return fakeev_loop();
+}
diff --git a/test/unit/swim_test_ev.h b/test/unit/swim_test_ev.h
index bc925a859..d93b149de 100644
--- a/test/unit/swim_test_ev.h
+++ b/test/unit/swim_test_ev.h
@@ -33,10 +33,9 @@
 struct ev_loop;
 
 /**
- * SWIM test_ev implements a 'fake' event loop with bogus clock to
- * speed up events processing while keeping SWIM unaware that it
- * works in a simulation. Libev is used a little, just to store
- * some IO events.
+ * Fakeev implements a 'fake' event loop with bogus clock to speed up events
+ * processing while keeping the real code unaware that it works in a simulation.
+ * Libev is used a little, just to store some IO events.
  *
  * The test event loop works as follows. It has a global watch and
  * a heap of events sorted by deadlines. An event is either a
@@ -46,7 +45,7 @@ struct ev_loop;
  * and equal deadline, and sets the global watch with the deadline
  * value. It simulates time flow. All the events with that
  * deadline are processed. An event processing usually means
- * calling a libev callback set by a SWIM instance beforehand.
+ * calling a libev callback set by real code beforehand.
  *
  * For example, if event deadlines and the watch are:
  *
@@ -82,11 +81,19 @@ struct ev_loop;
 
 /** Initialize test event processing system. */
 void
-swim_test_ev_init(void);
+fakeev_init(void);
 
 /** Destroy test event processing system, free resources. */
 void
-swim_test_ev_free(void);
+fakeev_free(void);
+
+/** Implementation of global time visible as real time in the tested code. */
+double
+fakeev_time(void);
+
+/** Global loop used by the fake events. */
+struct ev_loop *
+fakeev_loop(void);
 
 /**
  * Stop the event loop after @a delay fake seconds. It does not
@@ -94,14 +101,14 @@ swim_test_ev_free(void);
  * times.
  */
 void
-swim_ev_set_brk(double delay);
+fakeev_set_brk(double delay);
 
 /** Play one step of event loop, process generated events. */
 void
-swim_test_ev_do_loop_step(struct ev_loop *loop);
+fakeev_loop_update(struct ev_loop *loop);
 
 /** Destroy pending events, reset global watch. */
 void
-swim_test_ev_reset(void);
+fakeev_reset(void);
 
 #endif /* TARANTOOL_SWIM_TEST_EV_H_INCLUDED */
diff --git a/test/unit/swim_test_utils.c b/test/unit/swim_test_utils.c
index 6a3b6a685..c9d92a704 100644
--- a/test/unit/swim_test_utils.c
+++ b/test/unit/swim_test_utils.c
@@ -565,9 +565,9 @@ static int
 swim_wait_timeout(double timeout, struct swim_cluster *cluster,
 		  swim_loop_check_f check, void *data)
 {
-	swim_ev_set_brk(timeout);
-	double deadline = swim_time() + timeout;
-	struct ev_loop *loop = swim_loop();
+	fakeev_set_brk(timeout);
+	double deadline = fakeev_time() + timeout;
+	struct ev_loop *loop = fakeev_loop();
 	/*
 	 * There can be pending out of bound IO events, affecting
 	 * the result. For example, 'quit' messages, which are
@@ -578,9 +578,9 @@ swim_wait_timeout(double timeout, struct swim_cluster *cluster,
 	if (cluster != NULL)
 		swim_cluster_run_triggers(cluster);
 	while (! check(cluster, data)) {
-		if (swim_time() >= deadline)
+		if (fakeev_time() >= deadline)
 			return -1;
-		swim_test_ev_do_loop_step(loop);
+		fakeev_loop_update(loop);
 		/*
 		 * After events are processed, it is possible that
 		 * some of them generated IO events. Process them
diff --git a/test/unit/swim_test_utils.h b/test/unit/swim_test_utils.h
index 7a3a88c0b..0f0051edd 100644
--- a/test/unit/swim_test_utils.h
+++ b/test/unit/swim_test_utils.h
@@ -259,7 +259,7 @@ swim_run_test(const char *log_file, fiber_func test);
 
 #define swim_finish_test() { \
 	say_verbose("-------- SWIM end test %s --------", __func__); \
-	swim_test_ev_reset(); \
+	fakeev_reset(); \
 	check_plan(); \
 	footer(); \
 }
-- 
2.24.3 (Apple Git-128)



More information about the Tarantool-patches mailing list