]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/test-journal.c
Merge pull request #10902 from poettering/highlight-status
[thirdparty/systemd.git] / src / journal / test-journal.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <fcntl.h>
4 #include <unistd.h>
5
6 #include "io-util.h"
7 #include "journal-authenticate.h"
8 #include "journal-file.h"
9 #include "journal-vacuum.h"
10 #include "log.h"
11 #include "rm-rf.h"
12 #include "tests.h"
13
14 static bool arg_keep = false;
15
16 static void test_non_empty(void) {
17 dual_timestamp ts;
18 JournalFile *f;
19 struct iovec iovec;
20 static const char test[] = "TEST1=1", test2[] = "TEST2=2";
21 Object *o;
22 uint64_t p;
23 sd_id128_t fake_boot_id;
24 char t[] = "/tmp/journal-XXXXXX";
25
26 test_setup_logging(LOG_DEBUG);
27
28 assert_se(mkdtemp(t));
29 assert_se(chdir(t) >= 0);
30
31 assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f) == 0);
32
33 assert_se(dual_timestamp_get(&ts));
34 assert_se(sd_id128_randomize(&fake_boot_id) == 0);
35
36 iovec = IOVEC_MAKE_STRING(test);
37 assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
38
39 iovec = IOVEC_MAKE_STRING(test2);
40 assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
41
42 iovec = IOVEC_MAKE_STRING(test);
43 assert_se(journal_file_append_entry(f, &ts, &fake_boot_id, &iovec, 1, NULL, NULL, NULL) == 0);
44
45 #if HAVE_GCRYPT
46 journal_file_append_tag(f);
47 #endif
48 journal_file_dump(f);
49
50 assert_se(journal_file_next_entry(f, 0, DIRECTION_DOWN, &o, &p) == 1);
51 assert_se(le64toh(o->entry.seqnum) == 1);
52
53 assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1);
54 assert_se(le64toh(o->entry.seqnum) == 2);
55
56 assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1);
57 assert_se(le64toh(o->entry.seqnum) == 3);
58 assert_se(sd_id128_equal(o->entry.boot_id, fake_boot_id));
59
60 assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 0);
61
62 assert_se(journal_file_next_entry(f, 0, DIRECTION_DOWN, &o, &p) == 1);
63 assert_se(le64toh(o->entry.seqnum) == 1);
64
65 assert_se(journal_file_find_data_object(f, test, strlen(test), NULL, &p) == 1);
66 assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1);
67 assert_se(le64toh(o->entry.seqnum) == 1);
68
69 assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1);
70 assert_se(le64toh(o->entry.seqnum) == 3);
71
72 assert_se(journal_file_find_data_object(f, test2, strlen(test2), NULL, &p) == 1);
73 assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1);
74 assert_se(le64toh(o->entry.seqnum) == 2);
75
76 assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1);
77 assert_se(le64toh(o->entry.seqnum) == 2);
78
79 assert_se(journal_file_find_data_object(f, "quux", 4, NULL, &p) == 0);
80
81 assert_se(journal_file_move_to_entry_by_seqnum(f, 1, DIRECTION_DOWN, &o, NULL) == 1);
82 assert_se(le64toh(o->entry.seqnum) == 1);
83
84 assert_se(journal_file_move_to_entry_by_seqnum(f, 3, DIRECTION_DOWN, &o, NULL) == 1);
85 assert_se(le64toh(o->entry.seqnum) == 3);
86
87 assert_se(journal_file_move_to_entry_by_seqnum(f, 2, DIRECTION_DOWN, &o, NULL) == 1);
88 assert_se(le64toh(o->entry.seqnum) == 2);
89
90 assert_se(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0);
91
92 journal_file_rotate(&f, true, (uint64_t) -1, true, NULL);
93 journal_file_rotate(&f, true, (uint64_t) -1, true, NULL);
94
95 (void) journal_file_close(f);
96
97 log_info("Done...");
98
99 if (arg_keep)
100 log_info("Not removing %s", t);
101 else {
102 journal_directory_vacuum(".", 3000000, 0, 0, NULL, true);
103
104 assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
105 }
106
107 puts("------------------------------------------------------------");
108 }
109
110 static void test_empty(void) {
111 JournalFile *f1, *f2, *f3, *f4;
112 char t[] = "/tmp/journal-XXXXXX";
113
114 test_setup_logging(LOG_DEBUG);
115
116 assert_se(mkdtemp(t));
117 assert_se(chdir(t) >= 0);
118
119 assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, false, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f1) == 0);
120
121 assert_se(journal_file_open(-1, "test-compress.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f2) == 0);
122
123 assert_se(journal_file_open(-1, "test-seal.journal", O_RDWR|O_CREAT, 0666, false, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f3) == 0);
124
125 assert_se(journal_file_open(-1, "test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f4) == 0);
126
127 journal_file_print_header(f1);
128 puts("");
129 journal_file_print_header(f2);
130 puts("");
131 journal_file_print_header(f3);
132 puts("");
133 journal_file_print_header(f4);
134 puts("");
135
136 log_info("Done...");
137
138 if (arg_keep)
139 log_info("Not removing %s", t);
140 else {
141 journal_directory_vacuum(".", 3000000, 0, 0, NULL, true);
142
143 assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
144 }
145
146 (void) journal_file_close(f1);
147 (void) journal_file_close(f2);
148 (void) journal_file_close(f3);
149 (void) journal_file_close(f4);
150 }
151
152 #if HAVE_XZ || HAVE_LZ4
153 static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) {
154 dual_timestamp ts;
155 JournalFile *f;
156 struct iovec iovec;
157 Object *o;
158 uint64_t p;
159 char t[] = "/tmp/journal-XXXXXX";
160 char data[2048] = {0};
161 bool is_compressed;
162 int r;
163
164 assert_se(data_size <= sizeof(data));
165
166 test_setup_logging(LOG_DEBUG);
167
168 assert_se(mkdtemp(t));
169 assert_se(chdir(t) >= 0);
170
171 assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, compress_threshold, true, NULL, NULL, NULL, NULL, &f) == 0);
172
173 dual_timestamp_get(&ts);
174
175 iovec = IOVEC_MAKE(data, data_size);
176 assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0);
177
178 #if HAVE_GCRYPT
179 journal_file_append_tag(f);
180 #endif
181 journal_file_dump(f);
182
183 /* We have to partially reimplement some of the dump logic, because the normal next_entry does the
184 * decompression for us. */
185 p = le64toh(f->header->header_size);
186 for (;;) {
187 r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
188 assert_se(r == 0);
189 if (o->object.type == OBJECT_DATA)
190 break;
191
192 assert_se(p < le64toh(f->header->tail_object_offset));
193 p = p + ALIGN64(le64toh(o->object.size));
194 }
195
196 is_compressed = (o->object.flags & OBJECT_COMPRESSION_MASK) != 0;
197
198 (void) journal_file_close(f);
199
200 log_info("Done...");
201
202 if (arg_keep)
203 log_info("Not removing %s", t);
204 else {
205 journal_directory_vacuum(".", 3000000, 0, 0, NULL, true);
206
207 assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
208 }
209
210 puts("------------------------------------------------------------");
211
212 return is_compressed;
213 }
214
215 static void test_min_compress_size(void) {
216 /* Note that XZ will actually fail to compress anything under 80 bytes, so you have to choose the limits
217 * carefully */
218
219 /* DEFAULT_MIN_COMPRESS_SIZE is 512 */
220 assert_se(!check_compressed((uint64_t) -1, 255));
221 assert_se(check_compressed((uint64_t) -1, 513));
222
223 /* compress everything */
224 assert_se(check_compressed(0, 96));
225 assert_se(check_compressed(8, 96));
226
227 /* Ensure we don't try to compress less than 8 bytes */
228 assert_se(!check_compressed(0, 7));
229
230 /* check boundary conditions */
231 assert_se(check_compressed(256, 256));
232 assert_se(!check_compressed(256, 255));
233 }
234 #endif
235
236 int main(int argc, char *argv[]) {
237 arg_keep = argc > 1;
238
239 test_setup_logging(LOG_INFO);
240
241 /* journal_file_open requires a valid machine id */
242 if (access("/etc/machine-id", F_OK) != 0)
243 return log_tests_skipped("/etc/machine-id not found");
244
245 test_non_empty();
246 test_empty();
247 #if HAVE_XZ || HAVE_LZ4
248 test_min_compress_size();
249 #endif
250
251 return 0;
252 }