summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2023-04-29 22:40:54 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2023-05-10 00:01:17 +0200
commit49686dd0c18bc8474f312f3e265c4467bd548628 (patch)
treeb6f313afbf06932c7f5e06c45f0bed6f4379a9b2
parent7ae97c9c9c9bab8e8406cdc5dbc61c5c4d4603a5 (diff)
Check many concurrent updates for the append-only file.
-rw-r--r--guix.scm6
-rw-r--r--include/disfluid.h34
-rw-r--r--src/libdisfluid/disfluid-tests.h145
-rw-r--r--src/libdisfluid/main.c19
-rw-r--r--tests/Makefile.am42
-rw-r--r--tests/test-append-count.c21
-rw-r--r--tests/test-append-hello.c21
-rw-r--r--tests/test-append-init.c21
-rwxr-xr-xtests/test-append.sh24
9 files changed, 331 insertions, 2 deletions
diff --git a/guix.scm b/guix.scm
index c381579..a23f42a 100644
--- a/guix.scm
+++ b/guix.scm
@@ -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