]> git.proxmox.com Git - systemd.git/blame - src/journal/test-journal-interleaving.c
Imported Upstream version 217
[systemd.git] / src / journal / test-journal-interleaving.c
CommitLineData
14228c0d
MB
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Marius Vollmer
7 Copyright 2013 Zbigniew Jędrzejewski-Szmek
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21***/
22
23#include <unistd.h>
24#include <fcntl.h>
25
5eef597e 26#include "systemd/sd-journal.h"
14228c0d
MB
27
28#include "journal-file.h"
29#include "journal-internal.h"
30#include "journal-vacuum.h"
31#include "util.h"
32#include "log.h"
33
34/* This program tests skipping around in a multi-file journal.
35 */
36
37static bool arg_keep = false;
38
60f067b4 39noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) {
14228c0d
MB
40 log_meta(LOG_CRIT, file, line, func,
41 "'%s' failed at %s:%u (%s): %s.",
42 text, file, line, func, strerror(eno));
43 abort();
44}
45
46#define assert_ret(expr) \
47 do { \
48 int _r_ = (expr); \
49 if (_unlikely_(_r_ < 0)) \
50 log_assert_errno(#expr, -_r_, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
51 } while (false)
52
60f067b4 53static JournalFile *test_open(const char *name) {
14228c0d
MB
54 JournalFile *f;
55 assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f));
56 return f;
57}
58
60f067b4 59static void test_close(JournalFile *f) {
14228c0d
MB
60 journal_file_close (f);
61}
62
60f067b4 63static void append_number(JournalFile *f, int n, uint64_t *seqnum) {
14228c0d
MB
64 char *p;
65 dual_timestamp ts;
66 struct iovec iovec[1];
67
68 dual_timestamp_get(&ts);
69
70 assert_se(asprintf(&p, "NUMBER=%d", n) >= 0);
71 iovec[0].iov_base = p;
72 iovec[0].iov_len = strlen(p);
73 assert_ret(journal_file_append_entry(f, &ts, iovec, 1, seqnum, NULL, NULL));
60f067b4 74 free(p);
14228c0d
MB
75}
76
60f067b4 77static void test_check_number (sd_journal *j, int n) {
14228c0d 78 const void *d;
60f067b4 79 _cleanup_free_ char *k;
14228c0d
MB
80 size_t l;
81 int x;
82
83 assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l));
84 assert_se(k = strndup(d, l));
85 printf("%s\n", k);
86
87 assert_se(safe_atoi(k + 7, &x) >= 0);
88 assert_se(n == x);
89}
90
60f067b4
JS
91static void test_check_numbers_down (sd_journal *j, int count) {
92 int i;
93
94 for (i = 1; i <= count; i++) {
14228c0d
MB
95 int r;
96 test_check_number(j, i);
97 assert_ret(r = sd_journal_next(j));
98 if (i == count)
99 assert_se(r == 0);
100 else
101 assert_se(r == 1);
102 }
103
104}
105
60f067b4 106static void test_check_numbers_up (sd_journal *j, int count) {
14228c0d
MB
107 for (int i = count; i >= 1; i--) {
108 int r;
109 test_check_number(j, i);
110 assert_ret(r = sd_journal_previous(j));
111 if (i == 1)
112 assert_se(r == 0);
113 else
114 assert_se(r == 1);
115 }
116
117}
118
119static void setup_sequential(void) {
120 JournalFile *one, *two;
121 one = test_open("one.journal");
122 two = test_open("two.journal");
123 append_number(one, 1, NULL);
124 append_number(one, 2, NULL);
125 append_number(two, 3, NULL);
126 append_number(two, 4, NULL);
127 test_close(one);
128 test_close(two);
129}
130
131static void setup_interleaved(void) {
132 JournalFile *one, *two;
133 one = test_open("one.journal");
134 two = test_open("two.journal");
135 append_number(one, 1, NULL);
136 append_number(two, 2, NULL);
137 append_number(one, 3, NULL);
138 append_number(two, 4, NULL);
139 test_close(one);
140 test_close(two);
141}
142
60f067b4 143static void test_skip(void (*setup)(void)) {
14228c0d
MB
144 char t[] = "/tmp/journal-skip-XXXXXX";
145 sd_journal *j;
146 int r;
147
148 assert_se(mkdtemp(t));
149 assert_se(chdir(t) >= 0);
150
151 setup();
152
153 /* Seek to head, iterate down.
154 */
155 assert_ret(sd_journal_open_directory(&j, t, 0));
156 assert_ret(sd_journal_seek_head(j));
157 assert_ret(sd_journal_next(j));
158 test_check_numbers_down(j, 4);
159 sd_journal_close(j);
160
161 /* Seek to tail, iterate up.
162 */
163 assert_ret(sd_journal_open_directory(&j, t, 0));
164 assert_ret(sd_journal_seek_tail(j));
165 assert_ret(sd_journal_previous(j));
166 test_check_numbers_up(j, 4);
167 sd_journal_close(j);
168
169 /* Seek to tail, skip to head, iterate down.
170 */
171 assert_ret(sd_journal_open_directory(&j, t, 0));
172 assert_ret(sd_journal_seek_tail(j));
173 assert_ret(r = sd_journal_previous_skip(j, 4));
174 assert_se(r == 4);
175 test_check_numbers_down(j, 4);
176 sd_journal_close(j);
177
178 /* Seek to head, skip to tail, iterate up.
179 */
180 assert_ret(sd_journal_open_directory(&j, t, 0));
181 assert_ret(sd_journal_seek_head(j));
182 assert_ret(r = sd_journal_next_skip(j, 4));
183 assert_se(r == 4);
184 test_check_numbers_up(j, 4);
185 sd_journal_close(j);
186
187 log_info("Done...");
188
189 if (arg_keep)
190 log_info("Not removing %s", t);
191 else {
60f067b4 192 journal_directory_vacuum(".", 3000000, 0, NULL);
14228c0d
MB
193
194 assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
195 }
196
197 puts("------------------------------------------------------------");
198}
199
200static void test_sequence_numbers(void) {
201
202 char t[] = "/tmp/journal-seq-XXXXXX";
203 JournalFile *one, *two;
204 uint64_t seqnum = 0;
205 sd_id128_t seqnum_id;
206
207 assert_se(mkdtemp(t));
208 assert_se(chdir(t) >= 0);
209
210 assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644,
211 true, false, NULL, NULL, NULL, &one) == 0);
212
213 append_number(one, 1, &seqnum);
214 printf("seqnum=%"PRIu64"\n", seqnum);
215 assert(seqnum == 1);
216 append_number(one, 2, &seqnum);
217 printf("seqnum=%"PRIu64"\n", seqnum);
218 assert(seqnum == 2);
219
220 assert(one->header->state == STATE_ONLINE);
221 assert(!sd_id128_equal(one->header->file_id, one->header->machine_id));
222 assert(!sd_id128_equal(one->header->file_id, one->header->boot_id));
223 assert(sd_id128_equal(one->header->file_id, one->header->seqnum_id));
224
225 memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
226
227 assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0644,
228 true, false, NULL, NULL, one, &two) == 0);
229
230 assert(two->header->state == STATE_ONLINE);
231 assert(!sd_id128_equal(two->header->file_id, one->header->file_id));
232 assert(sd_id128_equal(one->header->machine_id, one->header->machine_id));
233 assert(sd_id128_equal(one->header->boot_id, one->header->boot_id));
234 assert(sd_id128_equal(one->header->seqnum_id, one->header->seqnum_id));
235
236 append_number(two, 3, &seqnum);
237 printf("seqnum=%"PRIu64"\n", seqnum);
238 assert(seqnum == 3);
239 append_number(two, 4, &seqnum);
240 printf("seqnum=%"PRIu64"\n", seqnum);
241 assert(seqnum == 4);
242
243 test_close(two);
244
245 append_number(one, 5, &seqnum);
246 printf("seqnum=%"PRIu64"\n", seqnum);
247 assert(seqnum == 5);
248
249 append_number(one, 6, &seqnum);
250 printf("seqnum=%"PRIu64"\n", seqnum);
251 assert(seqnum == 6);
252
253 test_close(one);
254
255 /* restart server */
256 seqnum = 0;
257
258 assert_se(journal_file_open("two.journal", O_RDWR, 0,
259 true, false, NULL, NULL, NULL, &two) == 0);
260
261 assert(sd_id128_equal(two->header->seqnum_id, seqnum_id));
262
263 append_number(two, 7, &seqnum);
264 printf("seqnum=%"PRIu64"\n", seqnum);
265 assert(seqnum == 5);
266
267 /* So..., here we have the same seqnum in two files with the
268 * same seqnum_id. */
269
270 test_close(two);
271
272 log_info("Done...");
273
274 if (arg_keep)
275 log_info("Not removing %s", t);
276 else {
60f067b4 277 journal_directory_vacuum(".", 3000000, 0, NULL);
14228c0d
MB
278
279 assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
280 }
281}
282
283int main(int argc, char *argv[]) {
284 log_set_max_level(LOG_DEBUG);
285
286 /* journal_file_open requires a valid machine id */
287 if (access("/etc/machine-id", F_OK) != 0)
288 return EXIT_TEST_SKIP;
289
290 arg_keep = argc > 1;
291
292 test_skip(setup_sequential);
293 test_skip(setup_interleaved);
294
295 test_sequence_numbers();
296
297 return 0;
298}