chiark / gitweb /
tests: add testcase for skipping-entries-on-direction-change-bug
authorMarius Vollmer <marius.vollmer@redhat.com>
Fri, 7 Jun 2013 04:50:21 +0000 (00:50 -0400)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 10 Jun 2013 14:10:07 +0000 (10:10 -0400)
This test case failed until a3e6f050de8.

Taken from https://bugs.freedesktop.org/show_bug.cgi?id=65255.

Makefile.am
src/journal/test-journal-interleaving.c [new file with mode: 0644]

index 70da1e4a2c315242d24d993b6230c15e97282afc..28ae7edea091f913d2f6c53cacfc26f5a740bf8d 100644 (file)
@@ -2781,6 +2781,14 @@ test_journal_verify_LDADD = \
        libsystemd-journal-internal.la \
        libsystemd-id128-internal.la
 
+test_journal_interleaving_SOURCES = \
+       src/journal/test-journal-interleaving.c
+
+test_journal_interleaving_LDADD = \
+       libsystemd-shared.la \
+       libsystemd-journal-internal.la \
+       libsystemd-id128-internal.la
+
 test_mmap_cache_SOURCES = \
        src/journal/test-mmap-cache.c
 
@@ -2956,6 +2964,7 @@ tests += \
        test-journal-match \
        test-journal-stream \
        test-journal-verify \
+       test-journal-interleaving \
        test-mmap-cache \
        test-catalog
 
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
new file mode 100644 (file)
index 0000000..c83a1ea
--- /dev/null
@@ -0,0 +1,198 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Marius Vollmer
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <systemd/sd-journal.h>
+
+#include "journal-file.h"
+#include "journal-internal.h"
+#include "util.h"
+#include "log.h"
+
+/* This program tests skipping around in a multi-file journal.
+ */
+
+static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) {
+        log_meta(LOG_CRIT, file, line, func,
+                 "'%s' failed at %s:%u (%s): %s.",
+                 text, file, line, func, strerror(eno));
+        abort();
+}
+
+#define assert_ret(expr)                                                \
+        do {                                                            \
+                int _r_ = (expr);                                       \
+                if (_unlikely_(_r_ < 0))                                \
+                        log_assert_errno(#expr, -_r_, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
+        } while (false)
+
+static JournalFile *test_open (const char *name)
+{
+        JournalFile *f;
+        assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, NULL, &f));
+        return f;
+}
+
+static void test_close (JournalFile *f)
+{
+        journal_file_close (f);
+}
+
+static void test_append_number(JournalFile *f, int n)
+{
+        char *p;
+        dual_timestamp ts;
+        struct iovec iovec[1];
+
+        dual_timestamp_get(&ts);
+
+        assert_se(asprintf(&p, "NUMBER=%d", n) >= 0);
+        iovec[0].iov_base = p;
+        iovec[0].iov_len = strlen(p);
+        assert_ret(journal_file_append_entry(f, &ts, iovec, 1, NULL, NULL, NULL));
+        free (p);
+}
+
+static void test_check_number (sd_journal *j, int n)
+{
+        const void *d;
+        char *k;
+        size_t l;
+        int x;
+
+        assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l));
+        assert_se(k = strndup(d, l));
+        printf("%s\n", k);
+
+        assert_se(safe_atoi(k + 7, &x) >= 0);
+        assert_se(n == x);
+}
+
+static void test_check_numbers_down (sd_journal *j, int count)
+{
+        for (int i = 1; i <= count; i++) {
+                int r;
+                test_check_number(j, i);
+                assert_ret(r = sd_journal_next(j));
+                if (i == count)
+                        assert_se(r == 0);
+                else
+                        assert_se(r == 1);
+        }
+
+}
+
+static void test_check_numbers_up (sd_journal *j, int count)
+{
+        for (int i = count; i >= 1; i--) {
+                int r;
+                test_check_number(j, i);
+                assert_ret(r = sd_journal_previous(j));
+                if (i == 1)
+                        assert_se(r == 0);
+                else
+                        assert_se(r == 1);
+        }
+
+}
+
+static void setup_sequential(void) {
+        JournalFile *one, *two;
+        one = test_open("one.journal");
+        two = test_open("two.journal");
+        test_append_number(one, 1);
+        test_append_number(one, 2);
+        test_append_number(two, 3);
+        test_append_number(two, 4);
+        test_close(one);
+        test_close(two);
+}
+
+static void setup_interleaved(void) {
+        JournalFile *one, *two;
+        one = test_open("one.journal");
+        two = test_open("two.journal");
+        test_append_number(one, 1);
+        test_append_number(two, 2);
+        test_append_number(one, 3);
+        test_append_number(two, 4);
+        test_close(one);
+        test_close(two);
+}
+
+static void test_skip(void (*setup)(void))
+{
+        char t[] = "/tmp/journal-skip-XXXXXX";
+        sd_journal *j;
+        int r;
+
+        log_set_max_level(LOG_DEBUG);
+
+        assert_se(mkdtemp(t));
+        assert_se(chdir(t) >= 0);
+
+        setup();
+
+        /* Seek to head, iterate down.
+         */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_head(j));
+        assert_ret(sd_journal_next(j));
+        test_check_numbers_down(j, 4);
+        sd_journal_close(j);
+
+        /* Seek to tail, iterate up.
+         */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_tail(j));
+        assert_ret(sd_journal_previous(j));
+        test_check_numbers_up(j, 4);
+        sd_journal_close(j);
+
+        /* Seek to tail, skip to head, iterate down.
+         */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_tail(j));
+        assert_ret(r = sd_journal_previous_skip(j, 4));
+        assert_se(r == 4);
+        test_check_numbers_down(j, 4);
+        sd_journal_close(j);
+
+        /* Seek to head, skip to tail, iterate up.
+         */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_head(j));
+        assert_ret(r = sd_journal_next_skip(j, 4));
+        assert_se(r == 4);
+        test_check_numbers_up(j, 4);
+        sd_journal_close(j);
+
+        assert_ret(rm_rf_dangerous(t, false, true, false));
+}
+
+int main(int argc, char *argv[]) {
+        test_skip(setup_sequential);
+        test_skip(setup_interleaved);
+
+        return 0;
+}