]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/test-journal-interleaving.c
Remove six unused variables and add annotation
[thirdparty/systemd.git] / src / journal / test-journal-interleaving.c
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
26 #include <systemd/sd-journal.h>
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
37 static bool arg_keep = false;
38
39 _noreturn_ static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) {
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
53 static JournalFile *test_open (const char *name)
54 {
55 JournalFile *f;
56 assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f));
57 return f;
58 }
59
60 static void test_close (JournalFile *f)
61 {
62 journal_file_close (f);
63 }
64
65 static void append_number(JournalFile *f, int n, uint64_t *seqnum)
66 {
67 char *p;
68 dual_timestamp ts;
69 struct iovec iovec[1];
70
71 dual_timestamp_get(&ts);
72
73 assert_se(asprintf(&p, "NUMBER=%d", n) >= 0);
74 iovec[0].iov_base = p;
75 iovec[0].iov_len = strlen(p);
76 assert_ret(journal_file_append_entry(f, &ts, iovec, 1, seqnum, NULL, NULL));
77 free (p);
78 }
79
80 static void test_check_number (sd_journal *j, int n)
81 {
82 const void *d;
83 char *k;
84 size_t l;
85 int x;
86
87 assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l));
88 assert_se(k = strndup(d, l));
89 printf("%s\n", k);
90
91 assert_se(safe_atoi(k + 7, &x) >= 0);
92 assert_se(n == x);
93 }
94
95 static void test_check_numbers_down (sd_journal *j, int count)
96 {
97 for (int i = 1; i <= count; i++) {
98 int r;
99 test_check_number(j, i);
100 assert_ret(r = sd_journal_next(j));
101 if (i == count)
102 assert_se(r == 0);
103 else
104 assert_se(r == 1);
105 }
106
107 }
108
109 static void test_check_numbers_up (sd_journal *j, int count)
110 {
111 for (int i = count; i >= 1; i--) {
112 int r;
113 test_check_number(j, i);
114 assert_ret(r = sd_journal_previous(j));
115 if (i == 1)
116 assert_se(r == 0);
117 else
118 assert_se(r == 1);
119 }
120
121 }
122
123 static void setup_sequential(void) {
124 JournalFile *one, *two;
125 one = test_open("one.journal");
126 two = test_open("two.journal");
127 append_number(one, 1, NULL);
128 append_number(one, 2, NULL);
129 append_number(two, 3, NULL);
130 append_number(two, 4, NULL);
131 test_close(one);
132 test_close(two);
133 }
134
135 static void setup_interleaved(void) {
136 JournalFile *one, *two;
137 one = test_open("one.journal");
138 two = test_open("two.journal");
139 append_number(one, 1, NULL);
140 append_number(two, 2, NULL);
141 append_number(one, 3, NULL);
142 append_number(two, 4, NULL);
143 test_close(one);
144 test_close(two);
145 }
146
147 static void test_skip(void (*setup)(void))
148 {
149 char t[] = "/tmp/journal-skip-XXXXXX";
150 sd_journal *j;
151 int r;
152
153 assert_se(mkdtemp(t));
154 assert_se(chdir(t) >= 0);
155
156 setup();
157
158 /* Seek to head, iterate down.
159 */
160 assert_ret(sd_journal_open_directory(&j, t, 0));
161 assert_ret(sd_journal_seek_head(j));
162 assert_ret(sd_journal_next(j));
163 test_check_numbers_down(j, 4);
164 sd_journal_close(j);
165
166 /* Seek to tail, iterate up.
167 */
168 assert_ret(sd_journal_open_directory(&j, t, 0));
169 assert_ret(sd_journal_seek_tail(j));
170 assert_ret(sd_journal_previous(j));
171 test_check_numbers_up(j, 4);
172 sd_journal_close(j);
173
174 /* Seek to tail, skip to head, iterate down.
175 */
176 assert_ret(sd_journal_open_directory(&j, t, 0));
177 assert_ret(sd_journal_seek_tail(j));
178 assert_ret(r = sd_journal_previous_skip(j, 4));
179 assert_se(r == 4);
180 test_check_numbers_down(j, 4);
181 sd_journal_close(j);
182
183 /* Seek to head, skip to tail, iterate up.
184 */
185 assert_ret(sd_journal_open_directory(&j, t, 0));
186 assert_ret(sd_journal_seek_head(j));
187 assert_ret(r = sd_journal_next_skip(j, 4));
188 assert_se(r == 4);
189 test_check_numbers_up(j, 4);
190 sd_journal_close(j);
191
192 log_info("Done...");
193
194 if (arg_keep)
195 log_info("Not removing %s", t);
196 else {
197 journal_directory_vacuum(".", 3000000, 0, 0, NULL);
198
199 assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
200 }
201
202 puts("------------------------------------------------------------");
203 }
204
205 static void test_sequence_numbers(void) {
206
207 char t[] = "/tmp/journal-seq-XXXXXX";
208 JournalFile *one, *two;
209 uint64_t seqnum = 0;
210 sd_id128_t seqnum_id;
211
212 assert_se(mkdtemp(t));
213 assert_se(chdir(t) >= 0);
214
215 assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644,
216 true, false, NULL, NULL, NULL, &one) == 0);
217
218 append_number(one, 1, &seqnum);
219 printf("seqnum=%"PRIu64"\n", seqnum);
220 assert(seqnum == 1);
221 append_number(one, 2, &seqnum);
222 printf("seqnum=%"PRIu64"\n", seqnum);
223 assert(seqnum == 2);
224
225 assert(one->header->state == STATE_ONLINE);
226 assert(!sd_id128_equal(one->header->file_id, one->header->machine_id));
227 assert(!sd_id128_equal(one->header->file_id, one->header->boot_id));
228 assert(sd_id128_equal(one->header->file_id, one->header->seqnum_id));
229
230 memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
231
232 assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0644,
233 true, false, NULL, NULL, one, &two) == 0);
234
235 assert(two->header->state == STATE_ONLINE);
236 assert(!sd_id128_equal(two->header->file_id, one->header->file_id));
237 assert(sd_id128_equal(one->header->machine_id, one->header->machine_id));
238 assert(sd_id128_equal(one->header->boot_id, one->header->boot_id));
239 assert(sd_id128_equal(one->header->seqnum_id, one->header->seqnum_id));
240
241 append_number(two, 3, &seqnum);
242 printf("seqnum=%"PRIu64"\n", seqnum);
243 assert(seqnum == 3);
244 append_number(two, 4, &seqnum);
245 printf("seqnum=%"PRIu64"\n", seqnum);
246 assert(seqnum == 4);
247
248 test_close(two);
249
250 append_number(one, 5, &seqnum);
251 printf("seqnum=%"PRIu64"\n", seqnum);
252 assert(seqnum == 5);
253
254 append_number(one, 6, &seqnum);
255 printf("seqnum=%"PRIu64"\n", seqnum);
256 assert(seqnum == 6);
257
258 test_close(one);
259
260 /* restart server */
261 seqnum = 0;
262
263 assert_se(journal_file_open("two.journal", O_RDWR, 0,
264 true, false, NULL, NULL, NULL, &two) == 0);
265
266 assert(sd_id128_equal(two->header->seqnum_id, seqnum_id));
267
268 append_number(two, 7, &seqnum);
269 printf("seqnum=%"PRIu64"\n", seqnum);
270 assert(seqnum == 5);
271
272 /* So..., here we have the same seqnum in two files with the
273 * same seqnum_id. */
274
275 test_close(two);
276
277 log_info("Done...");
278
279 if (arg_keep)
280 log_info("Not removing %s", t);
281 else {
282 journal_directory_vacuum(".", 3000000, 0, 0, NULL);
283
284 assert_se(rm_rf_dangerous(t, false, true, false) >= 0);
285 }
286 }
287
288 int main(int argc, char *argv[]) {
289 log_set_max_level(LOG_DEBUG);
290
291 /* journal_file_open requires a valid machine id */
292 if (access("/etc/machine-id", F_OK) != 0)
293 return EXIT_TEST_SKIP;
294
295 arg_keep = argc > 1;
296
297 test_skip(setup_sequential);
298 test_skip(setup_interleaved);
299
300 test_sequence_numbers();
301
302 return 0;
303 }