git » libfiu » commit f672b4d

tests: Add a "parallel wildcard" test

author Alberto Bertogli
2013-10-24 23:23:03 UTC
committer Alberto Bertogli
2013-10-29 02:12:13 UTC
parent 14e80fa8753df9d4d7dfa8547bc098149bd7b37f

tests: Add a "parallel wildcard" test

This patch introduces a "parallel wildcard" test, similar to the existing
"parallel" one, which stress-tests failure points with wildcards.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>

tests/test-parallel-wildcard.c +211 -0

diff --git a/tests/test-parallel-wildcard.c b/tests/test-parallel-wildcard.c
new file mode 100644
index 0000000..3aaa136
--- /dev/null
+++ b/tests/test-parallel-wildcard.c
@@ -0,0 +1,211 @@
+
+/* Test creation and removal of wildcarded failure points while checking them
+ * on a different thread.
+ *
+ * This test will have a thread enabling and disabling failure points like
+ * point:number:1:*, point:number:2:*, ...
+ *
+ * Then it has two threads checking:
+ * point:number:1:1, point:number:1:2, ...,
+ * point:number:2:1, point:number:2:2, ...
+ *
+ * Please note this is a non-deterministic test. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <assert.h>
+
+#include <fiu.h>
+#include <fiu-control.h>
+
+/* Be careful with increasing these numbers, as the memory usage is directly
+ * related to them. */
+#define NHIGH 1000
+#define NLOW  1000
+
+/* Maximum number of a failure point's name */
+#define MAX_FPNAME 32
+
+/* How many seconds to run the test */
+#define TEST_TIME 5
+
+/* Signal for the threads to stop. */
+bool stop_threads = false;
+
+/* The name of each final point. */
+char final_point_name[NHIGH][NLOW][MAX_FPNAME];
+
+/* The name of each wildcarded point. */
+char wildcard_point_name[NHIGH][MAX_FPNAME];
+
+char *make_final_point_name(char *name, int high, int low)
+{
+	sprintf(name, "point/number/%d/%d", high, low);
+	return name;
+}
+
+char *make_wildcard_point_name(char *name, int high)
+{
+	sprintf(name, "point/number/%d/*", high);
+	return name;
+}
+
+/* Calls all the final points all the time. */
+unsigned long long no_check_caller_count = 0;
+void *no_check_caller(void *unused)
+{
+	int high, low;
+
+	for (;;) {
+		for (high = 0; high < NHIGH; high++) {
+			for (low = 0; low < NLOW; low++) {
+				fiu_fail(final_point_name[high][low]);
+				no_check_caller_count++;
+			}
+			if (stop_threads)
+				return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+bool rand_bool(void) {
+	return (rand() % 2) == 0;
+}
+
+/* Used too know if a point is enabled or not. */
+bool enabled[NHIGH];
+pthread_rwlock_t enabled_lock;
+
+
+/* Calls all the *enabled* points all the time. */
+unsigned long long checking_caller_count = 0;
+void *checking_caller(void *unused)
+{
+	int high, low;
+	int failed;
+
+	for (;;) {
+		for (high = 0; high < NHIGH; high++) {
+			pthread_rwlock_rdlock(&enabled_lock);
+			if (!enabled[high]) {
+				pthread_rwlock_unlock(&enabled_lock);
+				continue;
+			}
+
+			for (low = 0; low < NLOW; low++) {
+				failed = fiu_fail(
+					final_point_name[high][low]) != 0;
+				if (!failed) {
+					printf("ERROR: %d:%d did not fail\n",
+							high, low);
+					assert(false);
+				}
+				checking_caller_count++;
+			}
+			pthread_rwlock_unlock(&enabled_lock);
+
+			if (stop_threads)
+				return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+/* Enable and disable wildcarded points all the time. */
+unsigned long long enabler_count = 0;
+void *enabler(void *unused)
+{
+	int high;
+
+	for (;;) {
+		for (high = 0; high < NHIGH; high++) {
+			/* 50% chance of flipping this point. */
+			if (rand_bool())
+				continue;
+
+			pthread_rwlock_wrlock(&enabled_lock);
+			if (enabled[high]) {
+				assert(fiu_disable(wildcard_point_name[high])
+						== 0);
+				enabled[high] = false;
+			} else {
+				assert(
+					fiu_enable(
+						wildcard_point_name[high],
+						1, NULL, 0) == 0);
+				enabled[high] = true;
+			}
+			pthread_rwlock_unlock(&enabled_lock);
+			enabler_count++;
+
+			if (stop_threads)
+				return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+void disable_all()
+{
+	int high;
+
+	pthread_rwlock_wrlock(&enabled_lock);
+	for (high = 0; high < NHIGH; high++) {
+		/* Note this could fail as we don't check if they're active or
+		 * not, but here we don't care. */
+		fiu_disable(wildcard_point_name[high]);
+	}
+	pthread_rwlock_unlock(&enabled_lock);
+}
+
+int main(void)
+{
+	int high, low;
+
+	pthread_t t1, t2, t3;
+
+	fiu_init(0);
+
+	for (high = 0; high < NHIGH; high++) {
+		make_wildcard_point_name(wildcard_point_name[high], high);
+
+		for (low = 0; low < NLOW; low++) {
+			make_final_point_name(final_point_name[high][low],
+					high, low);
+		}
+	}
+
+	pthread_rwlock_init(&enabled_lock, NULL);
+
+	pthread_create(&t1, NULL, no_check_caller, NULL);
+	pthread_create(&t2, NULL, checking_caller, NULL);
+	pthread_create(&t3, NULL, enabler, NULL);
+
+	sleep(TEST_TIME);
+
+	stop_threads = 1;
+
+	pthread_join(t1, NULL);
+	pthread_join(t2, NULL);
+	pthread_join(t3, NULL);
+
+	disable_all();
+
+	pthread_rwlock_destroy(&enabled_lock);
+
+	printf("wildcard nc: %-8llu  c: %-8llu  e: %-8llu  t: %llu\n",
+			no_check_caller_count, checking_caller_count,
+			enabler_count,
+			no_check_caller_count + checking_caller_count
+				+ enabler_count);
+
+	return 0;
+}
+