author | Alberto Bertogli
<albertito@blitiri.com.ar> 2013-10-11 00:48:13 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2013-10-29 02:12:00 UTC |
parent | 8e39c4e6c0d168b197f0d7fb7758758f995131df |
bindings/python/fiu.py | +7 | -0 |
tests/Makefile | +1 | -1 |
tests/test-manyfps.py | +25 | -0 |
tests/test-onetime.py | +17 | -0 |
tests/test-parallel.c | +142 | -0 |
diff --git a/bindings/python/fiu.py b/bindings/python/fiu.py index fda5639..0b0a308 100644 --- a/bindings/python/fiu.py +++ b/bindings/python/fiu.py @@ -25,6 +25,13 @@ def failinfo(name): Python.""" return _ll.failinfo() +class Flags: + """Contains the valid flag constants. + + ONETIME: This point of failure is disabled immediately after failing once. + """ + ONETIME = _ll.FIU_ONETIME + # To be sure failinfo doesn't dissapear from under our feet, we keep a # name -> failinfo table. See fiu_ll's comments for more details. diff --git a/tests/Makefile b/tests/Makefile index 41d63d3..cdc478d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -38,7 +38,7 @@ C_BINS := $(patsubst %.c,%,$(C_SRCS)) c-tests: $(patsubst %.c,c-run-%,$(C_SRCS)) test-%: test-%.o build-flags - $(NICE_CC) $(ALL_CFLAGS) $< -lfiu -o $@ + $(NICE_CC) $(ALL_CFLAGS) $< -lfiu -lpthread -o $@ c-run-%: % $(NICE_RUN) ./$< diff --git a/tests/test-manyfps.py b/tests/test-manyfps.py new file mode 100644 index 0000000..5679993 --- /dev/null +++ b/tests/test-manyfps.py @@ -0,0 +1,25 @@ + +""" +Test the creation of many failure points. +""" + +import fiu + +N = 1000 + +for i in range(N): + fiu.enable(str(i)) + +for i in range(N): + assert fiu.fail(str(i)) + +# Remove only half and check again; this will stress the shrinking of our data +# structures. +for i in range(N / 2): + fiu.disable(str(i)) + +for i in range(N / 2, N): + assert fiu.fail(str(i)) + +for i in range(N / 2, N): + fiu.disable(str(i)) diff --git a/tests/test-onetime.py b/tests/test-onetime.py new file mode 100644 index 0000000..182a4a8 --- /dev/null +++ b/tests/test-onetime.py @@ -0,0 +1,17 @@ + +""" +Test that we fail ONETIME points only one time. +""" + +import fiu + +fiu.enable('p1', flags = fiu.Flags.ONETIME) +fiu.enable('p2') + +assert fiu.fail('p1') +for i in range(100): + assert not fiu.fail('p1') + +for i in range(100): + assert fiu.fail('p2') + diff --git a/tests/test-parallel.c b/tests/test-parallel.c new file mode 100644 index 0000000..2d5a9dd --- /dev/null +++ b/tests/test-parallel.c @@ -0,0 +1,142 @@ + +/* Test creation and removal of failure points while checking them on a + * different thread. + * + * 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> + +#define NPOINTS 10000 + +/* How many seconds to run the test */ +#define TEST_TIME 5 + +/* Signal for the threads to stop. */ +bool stop_threads = false; + +char *make_point_name(char *name, int i) +{ + sprintf(name, "fp-%d", i); + return name; +} + +/* Calls all the points all the time. */ +void *no_check_caller(void *unused) +{ + int i; + char name[200]; + + while (!stop_threads) { + for (i = 0; i < NPOINTS; i++) { + fiu_fail(make_point_name(name, i)); + } + } + + return NULL; +} + +bool rand_bool(void) { + return (rand() % 2) == 0; +} + +/* Used too know if a point is enabled or not. */ +bool enabled[NPOINTS]; +pthread_mutex_t enabled_lock = PTHREAD_MUTEX_INITIALIZER; + + + +/* Calls all the *enabled* points all the time. */ +void *checking_caller(void *unused) +{ + int i = 0; + int failed; + char name[200]; + + while (!stop_threads) { + pthread_mutex_lock(&enabled_lock); + if (enabled[i]) { + failed = fiu_fail(make_point_name(name, i)) != 0; + if (!failed) { + printf("ERROR: fp %d did not fail\n", i); + assert(false); + } + } + pthread_mutex_unlock(&enabled_lock); + + i = (i + 1) % NPOINTS; + } + + return NULL; +} + +/* Enable and disable points all the time. */ +void *enabler(void *unused) +{ + int i = 0; + char name[200]; + + while (!stop_threads) { + pthread_mutex_lock(&enabled_lock); + if (rand_bool()) { + make_point_name(name, i); + if (enabled[i]) { + assert(fiu_disable(name) == 0); + enabled[i] = false; + } else { + assert(fiu_enable(name, 1, NULL, 0) == 0); + enabled[i] = true; + } + } + pthread_mutex_unlock(&enabled_lock); + + i = (i + 1) % NPOINTS; + } + + return NULL; +} + +void disable_all() +{ + int i = 0; + char name[200]; + + pthread_mutex_lock(&enabled_lock); + for (i = 0; i < NPOINTS; i++) { + /* Note this could fail as we don't check if they're active or + * not, but here we don't care. */ + fiu_disable(make_point_name(name, i)); + } + pthread_mutex_unlock(&enabled_lock); +} + +int main(void) +{ + pthread_t t1, t2, t3; + + fiu_init(0); + + 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(); + + return 0; +} +