]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-journal-interleaving: extend tests to clarify the issue in sd_journal_next(...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 21 May 2023 16:56:08 +0000 (01:56 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 21 May 2023 17:49:25 +0000 (02:49 +0900)
This illustrates bug in sd_journal_next() or friends;
calling sd_jounral_next() followed by sd_journal_seek_tail() makes the
location saved in sd-journal something corrupted, and subsequent
sd_journal_previous() or friends may fail or provides unexpected result.

src/journal/test-journal-interleaving.c

index 7fec6d9eea25ae7842c53dbcfa491a894ae3d31c..08b793c6182fd6827aad1313906403f00c0ddb80 100644 (file)
@@ -78,9 +78,9 @@ static void test_check_number(sd_journal *j, int n) {
 
         assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l));
         assert_se(k = strndup(d, l));
-        printf("%s\n", k);
+        printf("%s (expected=%i)\n", k, n);
 
-        assert_se(safe_atoi(k + 7, &x) >= 0);
+        assert_se(safe_atoi(k + STRLEN("NUMBER="), &x) >= 0);
         assert_se(n == x);
 }
 
@@ -113,27 +113,43 @@ static void test_check_numbers_up(sd_journal *j, int count) {
 }
 
 static void setup_sequential(void) {
-        ManagedJournalFile *one, *two;
-        one = test_open("one.journal");
-        two = test_open("two.journal");
-        append_number(one, 1, NULL);
-        append_number(one, 2, NULL);
-        append_number(two, 3, NULL);
-        append_number(two, 4, NULL);
-        test_close(one);
-        test_close(two);
+        ManagedJournalFile *f1, *f2, *f3;
+
+        f1 = test_open("one.journal");
+        f2 = test_open("two.journal");
+        f3 = test_open("three.journal");
+        append_number(f1, 1, NULL);
+        append_number(f1, 2, NULL);
+        append_number(f1, 3, NULL);
+        append_number(f2, 4, NULL);
+        append_number(f2, 5, NULL);
+        append_number(f2, 6, NULL);
+        append_number(f3, 7, NULL);
+        append_number(f3, 8, NULL);
+        append_number(f3, 9, NULL);
+        test_close(f1);
+        test_close(f2);
+        test_close(f3);
 }
 
 static void setup_interleaved(void) {
-        ManagedJournalFile *one, *two;
-        one = test_open("one.journal");
-        two = test_open("two.journal");
-        append_number(one, 1, NULL);
-        append_number(two, 2, NULL);
-        append_number(one, 3, NULL);
-        append_number(two, 4, NULL);
-        test_close(one);
-        test_close(two);
+        ManagedJournalFile *f1, *f2, *f3;
+
+        f1 = test_open("one.journal");
+        f2 = test_open("two.journal");
+        f3 = test_open("three.journal");
+        append_number(f1, 1, NULL);
+        append_number(f2, 2, NULL);
+        append_number(f3, 3, NULL);
+        append_number(f1, 4, NULL);
+        append_number(f2, 5, NULL);
+        append_number(f3, 6, NULL);
+        append_number(f1, 7, NULL);
+        append_number(f2, 8, NULL);
+        append_number(f3, 9, NULL);
+        test_close(f1);
+        test_close(f2);
+        test_close(f3);
 }
 
 static void mkdtemp_chdir_chattr(char *path) {
@@ -154,38 +170,140 @@ static void test_skip_one(void (*setup)(void)) {
 
         setup();
 
-        /* Seek to head, iterate down.
-         */
+        /* 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);
+        assert_ret(sd_journal_next(j));     /* pointing the first entry */
+        test_check_numbers_down(j, 9);
+        sd_journal_close(j);
+
+        /* 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));     /* pointing the first entry */
+        assert_ret(sd_journal_previous(j)); /* no-op */
+        test_check_numbers_down(j, 9);
+        sd_journal_close(j);
+
+        /* Seek to head, move to previous, then iterate down. */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_head(j));
+        /* FIXME: calling sd_journal_previous() thrice (or >= number of journal files) here works as
+         * mostly equivalent to calling sd_journal_next(). */
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_previous(j)); /* pointing the first entry */
+        test_check_numbers_down(j, 9);
+        sd_journal_close(j);
+
+        /* Seek to head, walk several steps, then iterate down. */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_head(j));
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_previous(j)); /* pointing the first entry */
+        assert_ret(sd_journal_next(j));     /* pointing the second entry */
+        /* FIXME: as calling sd_journal_previous() thrice works equivalent to sd_journal_next(),
+         * we need to call sd_journal_previous() here. */
+        assert_ret(sd_journal_previous(j)); /* pointing the first entry */
+        assert_ret(sd_journal_previous(j)); /* no-op */
+        test_check_numbers_down(j, 9);
         sd_journal_close(j);
 
-        /* Seek to tail, iterate up.
-         */
+        /* 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);
+        test_check_numbers_up(j, 9);
         sd_journal_close(j);
 
-        /* Seek to tail, skip to head, iterate down.
-         */
+        /* Seek to tail, move to next, then iterate up. */
         assert_ret(sd_journal_open_directory(&j, t, 0));
         assert_ret(sd_journal_seek_tail(j));
+        /* FIXME: calling sd_journal_next() thrice (or >= number of journal files) here works as mostly
+         * equivalent to calling sd_journal_previous(). */
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_next(j)); /* pointing the last entry */
+        test_check_numbers_up(j, 9);
+        sd_journal_close(j);
+
+        /* Seek to tail, walk several steps, then iterate up. */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_tail(j));
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_next(j));     /* pointing the last entry */
+        assert_ret(sd_journal_previous(j)); /* pointing the previous of the last entry. */
+        assert_ret(sd_journal_next(j));     /* pointing the last entry */
+        assert_ret(sd_journal_next(j));     /* no-op */
+        test_check_numbers_up(j, 9);
+        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, 9));
+        assert_se(r == 9);
+        test_check_numbers_down(j, 9);
+        sd_journal_close(j);
+
+        /* Seek to tail, skip to head in a more complext way, then iterate down. */
+        assert_ret(sd_journal_open_directory(&j, t, 0));
+        assert_ret(sd_journal_seek_tail(j));
+        // FIXME: sd_journal_next() cannot be called here.
+        //assert_ret(sd_journal_next(j));
         assert_ret(r = sd_journal_previous_skip(j, 4));
         assert_se(r == 4);
-        test_check_numbers_down(j, 4);
+        assert_ret(r = sd_journal_previous_skip(j, 5));
+        assert_se(r == 5);
+        assert_ret(sd_journal_previous(j)); /* no-op */
+        assert_ret(r = sd_journal_previous_skip(j, 5));
+        assert_se(r == 0);
+        assert_ret(sd_journal_next(j));
+        assert_ret(r = sd_journal_previous_skip(j, 5));
+        assert_se(r == 1);
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_next(j));
+        assert_ret(r = sd_journal_previous_skip(j, 5));
+        assert_se(r == 3);
+        test_check_numbers_down(j, 9);
+        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, 9));
+        assert_se(r == 9);
+        test_check_numbers_up(j, 9);
         sd_journal_close(j);
 
-        /* Seek to head, skip to tail, iterate up.
-         */
+        /* Seek to head, skip to tail in a more complex way, then iterate up. */
         assert_ret(sd_journal_open_directory(&j, t, 0));
         assert_ret(sd_journal_seek_head(j));
+        // FIXME: sd_journal_previous() cannot be called here.
+        //assert_ret(sd_journal_previous(j));
         assert_ret(r = sd_journal_next_skip(j, 4));
         assert_se(r == 4);
-        test_check_numbers_up(j, 4);
+        assert_ret(r = sd_journal_next_skip(j, 5));
+        assert_se(r == 5);
+        assert_ret(sd_journal_next(j));     /* no-op */
+        assert_ret(r = sd_journal_next_skip(j, 5));
+        assert_se(r == 0);
+        assert_ret(sd_journal_previous(j));
+        assert_ret(r = sd_journal_next_skip(j, 5));
+        assert_se(r == 1);
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_next(j));
+        assert_ret(sd_journal_previous(j));
+        assert_ret(sd_journal_previous(j));
+        assert_ret(r = sd_journal_next_skip(j, 5));
+        assert_se(r == 3);
+        test_check_numbers_up(j, 9);
         sd_journal_close(j);
 
         log_info("Done...");