diff options
author | Vivien Kraus <vivien@planete-kraus.eu> | 2023-04-29 22:40:54 +0200 |
---|---|---|
committer | Vivien Kraus <vivien@planete-kraus.eu> | 2023-05-10 00:01:17 +0200 |
commit | 49686dd0c18bc8474f312f3e265c4467bd548628 (patch) | |
tree | b6f313afbf06932c7f5e06c45f0bed6f4379a9b2 | |
parent | 7ae97c9c9c9bab8e8406cdc5dbc61c5c4d4603a5 (diff) |
Check many concurrent updates for the append-only file.
-rw-r--r-- | guix.scm | 6 | ||||
-rw-r--r-- | include/disfluid.h | 34 | ||||
-rw-r--r-- | src/libdisfluid/disfluid-tests.h | 145 | ||||
-rw-r--r-- | src/libdisfluid/main.c | 19 | ||||
-rw-r--r-- | tests/Makefile.am | 42 | ||||
-rw-r--r-- | tests/test-append-count.c | 21 | ||||
-rw-r--r-- | tests/test-append-hello.c | 21 | ||||
-rw-r--r-- | tests/test-append-init.c | 21 | ||||
-rwxr-xr-x | tests/test-append.sh | 24 |
9 files changed, 331 insertions, 2 deletions
@@ -304,6 +304,12 @@ "test-binary-io.sh" ) (("#!/gnu/store/.*/bin/sh") + "#!/bin/sh"))) + (with-directory-excursion "tests" + (substitute* '( + "test-append.sh" + ) + (("#!/gnu/store/.*/bin/sh") "#!/bin/sh")))) (invoke "sh" "-c" "grep '/gnu/store/' -R disfluid-* && exit 1 ; true") (mkdir-p #$output) diff --git a/include/disfluid.h b/include/disfluid.h index 74b5737..6df59fe 100644 --- a/include/disfluid.h +++ b/include/disfluid.h @@ -272,6 +272,40 @@ extern "C" */ DISFLUID_API const char *disfluid_metaphor_name (void); + /** + * disfluid_test_append_init: + * @fd: (out): the opened file descriptor. + * @filename: (out): the file name. + * + * Open a temporary file for the concurrent "append" test. + * + * Returns: 0 on success, a negative value on error. + */ + DISFLUID_API int disfluid_test_append_init (int *fd, char **filename); + + /** + * disfluid_test_append_hello: + * @filename: a file name. + * @n_before: the number of hellos before this call. + * @n_after: the number of hellos after this call. + * + * Open @filename, and append "Hello!" to it. + */ + DISFLUID_API int disfluid_test_append_hello (const char *filename, + size_t *n_before, + size_t *n_after); + + /** + * disfluid_test_append_count: + * @filename: a file name. + * @n: (out): the number of occurences of "Hello!" + * + * Open @filename, check that it contains a whole sequence of + * "Hello!", and count the number of occurences. + */ + DISFLUID_API int disfluid_test_append_count (const char *filename, + size_t *n); + # ifdef __cplusplus } # endif /* __cplusplus */ diff --git a/src/libdisfluid/disfluid-tests.h b/src/libdisfluid/disfluid-tests.h index 50b5a9f..9cb41d9 100644 --- a/src/libdisfluid/disfluid-tests.h +++ b/src/libdisfluid/disfluid-tests.h @@ -5,6 +5,11 @@ struct disfluid_tests_report; static inline char *run_tests (size_t *n_tests, size_t *n_errors); +static inline int test_append_init (int *fd, char **filename); +static inline int test_append_hello (const char *filename, size_t *n_before, + size_t *n_after); +static inline int test_append_count (const char *filename, size_t *n); + # include <check.h> # include "disfluid-trie-node.h" @@ -735,4 +740,144 @@ run_tests (size_t *n_tests, size_t *n_errors) return result; } +static inline int +test_append_init (int *fd, char **filename) +{ + ensure_init (); + int error = 0; + *fd = -1; + *filename = NULL; + static const char model[] = "/tmp/disfluid-test-append-XXXXXX"; + if (ALLOC_N (*filename, strlen (model) + 1) < 0) + { + error = -2; + goto cleanup; + } + strcpy (*filename, model); + *fd = mkstemp (*filename); + if (*fd == -1) + { + error = -1; + FREE (*filename); + goto cleanup; + } + static const char *magic_data = "disfluid appendt"; + const string_desc_t magic = { + ._data = (char *) magic_data, + ._nbytes = strlen (magic_data) + }; + if (ao_file_prepare (*fd, magic) < 0) + { + error = -1; + goto cleanup; + } +cleanup: + if (error != 0) + { + FREE (*filename); + if (*fd >= 0) + { + close (*fd); + *fd = -1; + } + } + return error; +} + +static inline int +test_append_hello (const char *filename, size_t *n_before, size_t *n_after) +{ + ensure_init (); + if (test_append_count (filename, n_before) < 0) + { + return -1; + } + int file = open (filename, O_RDWR); + int error = 0; + if (file == -1) + { + return -1; + } + size_t top; + if (ao_file_lock_for_writing (file, &top) < 0) + { + error = -1; + goto cleanup; + } + static const char *hello_data = "Hello!"; + const string_desc_t hello = { + ._nbytes = strlen (hello_data), + ._data = (char *) hello_data + }; + if (ao_file_push_data (file, hello, &top) < 0) + { + error = -1; + goto cleanup; + } + if (ao_file_commit_transaction (file) < 0) + { + error = -1; + goto cleanup; + } +cleanup: + close (file); + if (error == 0) + { + if (test_append_count (filename, n_after) < 0) + { + return -1; + } + if (n_before >= n_after) + { + return -1; + } + } + return error; +} + +static inline int +test_append_count (const char *filename, size_t *n) +{ + ensure_init (); + *n = 0; + size_t top; + int error = 0; + int file = open (filename, O_RDWR); + if (file == -1) + { + return -1; + } + if (ao_file_read_top (file, &top) < 0) + { + error = -1; + goto cleanup; + } + if (top % strlen ("Hello!") != 0) + { + error = -2; + goto cleanup; + } + while (top != 0) + { + char data[6]; + assert (sizeof (data) == strlen ("Hello!")); + string_desc_t next = {._nbytes = sizeof (data),._data = data }; + if (ao_file_read (file, top, next) < 0) + { + error = -2; + goto cleanup; + } + if (memcmp (data, "Hello!", sizeof (data)) != 0) + { + error = -2; + goto cleanup; + } + top -= sizeof (data); + *n += 1; + } +cleanup: + close (file); + return error; +} + #endif /* DISFLUID_TESTS_INCLUDED */ diff --git a/src/libdisfluid/main.c b/src/libdisfluid/main.c index dbe7cfb..3a6c5e3 100644 --- a/src/libdisfluid/main.c +++ b/src/libdisfluid/main.c @@ -64,6 +64,25 @@ disfluid_run_tests (size_t *n_tests, size_t *n_errors) return run_tests (n_tests, n_errors); } +int +disfluid_test_append_init (int *fd, char **filename) +{ + return test_append_init (fd, filename); +} + +int +disfluid_test_append_hello (const char *filename, size_t *n_before, + size_t *n_after) +{ + return test_append_hello (filename, n_before, n_after); +} + +int +disfluid_test_append_count (const char *filename, size_t *n) +{ + return test_append_count (filename, n); +} + size_t disfluid_count_authors (void) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 7b5f349..c4cf4fe 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,6 @@ -TESTS += %D%/run-unit-tests -check_PROGRAMS += %D%/run-unit-tests +TESTS += %D%/run-unit-tests %D%/test-append.sh +check_PROGRAMS += %D%/run-unit-tests %D%/test-append-init %D%/test-append-hello %D%/test-append-count +dist_noinst_SCRIPTS = %D%/test-append.sh %C%_run_unit_tests_SOURCES = %D%/run-unit-tests.c %C%_run_unit_tests_CPPFLAGS = \ @@ -12,12 +13,49 @@ check_PROGRAMS += %D%/run-unit-tests %C%_run_unit_tests_LDADD = \ src/libdisfluid/libdisfluid.la +%C%_test_append_init_SOURCES = %D%/test-append-init.c +%C%_test_append_init_CPPFLAGS = \ + -I libprog -I $(srcdir)/libprog \ + -I include -I $(srcdir)/include \ + -DLOCALEDIR=\"$(localedir)\" \ + -DINSTALLDIR=\"$(bindir)\" \ + -DGETTEXT_PACKAGE=\"$(PACKAGE)\" + +%C%_test_append_init_LDADD = \ + src/libdisfluid/libdisfluid.la + +%C%_test_append_hello_SOURCES = %D%/test-append-hello.c +%C%_test_append_hello_CPPFLAGS = \ + -I libprog -I $(srcdir)/libprog \ + -I include -I $(srcdir)/include \ + -DLOCALEDIR=\"$(localedir)\" \ + -DINSTALLDIR=\"$(bindir)\" \ + -DGETTEXT_PACKAGE=\"$(PACKAGE)\" + +%C%_test_append_hello_LDADD = \ + src/libdisfluid/libdisfluid.la + +%C%_test_append_count_SOURCES = %D%/test-append-count.c +%C%_test_append_count_CPPFLAGS = \ + -I libprog -I $(srcdir)/libprog \ + -I include -I $(srcdir)/include \ + -DLOCALEDIR=\"$(localedir)\" \ + -DINSTALLDIR=\"$(bindir)\" \ + -DGETTEXT_PACKAGE=\"$(PACKAGE)\" + +%C%_test_append_count_LDADD = \ + src/libdisfluid/libdisfluid.la + EXTRA_DIST += %D%/valgrind.supp AM_VALGRINDFLAGS = --suppressions=$(srcdir)/%D%/valgrind.supp LOG_COMPILER = $(LIBTOOL) --mode=execute $(LOG_VALGRIND) +SH_LOG_COMPILER = $(LIBTOOL) --mode=execute $(SHELL) + +TEST_EXTENSIONS = .sh + AM_TESTS_ENVIRONMENT = \ >&2 echo "I don’t understand why, but the libtool script during distcheck on guix does not set up LD_LIBRARY_PATH." ; \ export "LD_LIBRARY_PATH=$(abs_top_builddir)/src/libdisfluid/.libs$(PATH_SEPARATOR)$$LD_LIBRARY_PATH" ; diff --git a/tests/test-append-count.c b/tests/test-append-count.c new file mode 100644 index 0000000..6d0ade7 --- /dev/null +++ b/tests/test-append-count.c @@ -0,0 +1,21 @@ +#include <config.h> +#include <disfluid.h> +#include <stdio.h> + +int +main (int argc, char *argv[]) +{ + /* This is just a test runner, do not call bindtextdomain () */ + if (argc != 2) + { + fprintf (stderr, "Usage: test-append-hello <test file>\n"); + return 1; + } + size_t n; + if (disfluid_test_append_count (argv[1], &n) < 0) + { + return 1; + } + printf ("%lu\n", n); + return 0; +} diff --git a/tests/test-append-hello.c b/tests/test-append-hello.c new file mode 100644 index 0000000..88d361b --- /dev/null +++ b/tests/test-append-hello.c @@ -0,0 +1,21 @@ +#include <config.h> +#include <disfluid.h> +#include <stdio.h> + +int +main (int argc, char *argv[]) +{ + /* This is just a test runner, do not call bindtextdomain () */ + if (argc != 2) + { + fprintf (stderr, "Usage: test-append-hello <test file>\n"); + return 1; + } + size_t n_before, n_after; + if (disfluid_test_append_hello (argv[1], &n_before, &n_after) < 0) + { + return 1; + } + printf ("%lu -> %lu\n", n_before, n_after); + return 0; +} diff --git a/tests/test-append-init.c b/tests/test-append-init.c new file mode 100644 index 0000000..1fbbf09 --- /dev/null +++ b/tests/test-append-init.c @@ -0,0 +1,21 @@ +#include <config.h> +#include <disfluid.h> +#include <unistd.h> +#include <stdio.h> + +int +main (int argc, char *argv[]) +{ + /* This is just a test runner, do not call bindtextdomain () */ + (void) argc; + (void) argv; + int fd; + char *filename; + if (disfluid_test_append_init (&fd, &filename) < 0) + { + return 1; + } + close (fd); + printf ("%s\n", filename); + return 0; +} diff --git a/tests/test-append.sh b/tests/test-append.sh new file mode 100755 index 0000000..f8ae93b --- /dev/null +++ b/tests/test-append.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +if TEST_FILENAME=$(./libtool --mode=execute tests/test-append-init) +then + for task in $(seq 1 32) + do + ./libtool --mode=execute tests/test-append-hello $TEST_FILENAME & + done +else + exit 1 +fi + +while true +do + if COUNT=$(./libtool --mode=execute tests/test-append-count $TEST_FILENAME) + then + if test "x$COUNT" = "x32" + then + exit 0 + fi + else + exit 1 + fi +done |