Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <fcntl.h>
4 : #include <unistd.h>
5 :
6 : #include "sd-journal.h"
7 :
8 : #include "alloc-util.h"
9 : #include "chattr-util.h"
10 : #include "journal-file.h"
11 : #include "journal-internal.h"
12 : #include "log.h"
13 : #include "macro.h"
14 : #include "parse-util.h"
15 : #include "rm-rf.h"
16 : #include "tests.h"
17 : #include "util.h"
18 :
19 : #define N_ENTRIES 200
20 :
21 3 : static void verify_contents(sd_journal *j, unsigned skip) {
22 : unsigned i;
23 :
24 3 : assert_se(j);
25 :
26 3 : i = 0;
27 245 : SD_JOURNAL_FOREACH(j) {
28 : const void *d;
29 : char *k, *c;
30 : size_t l;
31 242 : unsigned u = 0;
32 :
33 242 : assert_se(sd_journal_get_cursor(j, &k) >= 0);
34 242 : printf("cursor: %s\n", k);
35 242 : free(k);
36 :
37 242 : assert_se(sd_journal_get_data(j, "MAGIC", &d, &l) >= 0);
38 242 : printf("\t%.*s\n", (int) l, (const char*) d);
39 :
40 242 : assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0);
41 242 : assert_se(k = strndup(d, l));
42 242 : printf("\t%s\n", k);
43 :
44 242 : if (skip > 0) {
45 240 : assert_se(safe_atou(k + 7, &u) >= 0);
46 240 : assert_se(i == u);
47 240 : i += skip;
48 : }
49 :
50 242 : free(k);
51 :
52 242 : assert_se(sd_journal_get_cursor(j, &c) >= 0);
53 242 : assert_se(sd_journal_test_cursor(j, c) > 0);
54 242 : free(c);
55 : }
56 :
57 3 : if (skip > 0)
58 2 : assert_se(i == N_ENTRIES);
59 3 : }
60 :
61 1 : int main(int argc, char *argv[]) {
62 : JournalFile *one, *two, *three;
63 1 : char t[] = "/var/tmp/journal-stream-XXXXXX";
64 : unsigned i;
65 1 : _cleanup_(sd_journal_closep) sd_journal *j = NULL;
66 : char *z;
67 : const void *data;
68 : size_t l;
69 1 : dual_timestamp previous_ts = DUAL_TIMESTAMP_NULL;
70 :
71 : /* journal_file_open requires a valid machine id */
72 1 : if (access("/etc/machine-id", F_OK) != 0)
73 0 : return log_tests_skipped("/etc/machine-id not found");
74 :
75 1 : test_setup_logging(LOG_DEBUG);
76 :
77 1 : assert_se(mkdtemp(t));
78 1 : assert_se(chdir(t) >= 0);
79 1 : (void) chattr_path(t, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
80 :
81 1 : assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &one) == 0);
82 1 : assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &two) == 0);
83 1 : assert_se(journal_file_open(-1, "three.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &three) == 0);
84 :
85 201 : for (i = 0; i < N_ENTRIES; i++) {
86 : char *p, *q;
87 : dual_timestamp ts;
88 : struct iovec iovec[2];
89 :
90 200 : dual_timestamp_get(&ts);
91 :
92 200 : if (ts.monotonic <= previous_ts.monotonic)
93 0 : ts.monotonic = previous_ts.monotonic + 1;
94 :
95 200 : if (ts.realtime <= previous_ts.realtime)
96 0 : ts.realtime = previous_ts.realtime + 1;
97 :
98 200 : previous_ts = ts;
99 :
100 200 : assert_se(asprintf(&p, "NUMBER=%u", i) >= 0);
101 200 : iovec[0].iov_base = p;
102 200 : iovec[0].iov_len = strlen(p);
103 :
104 200 : assert_se(asprintf(&q, "MAGIC=%s", i % 5 == 0 ? "quux" : "waldo") >= 0);
105 :
106 200 : iovec[1].iov_base = q;
107 200 : iovec[1].iov_len = strlen(q);
108 :
109 200 : if (i % 10 == 0)
110 20 : assert_se(journal_file_append_entry(three, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
111 : else {
112 180 : if (i % 3 == 0)
113 60 : assert_se(journal_file_append_entry(two, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
114 :
115 180 : assert_se(journal_file_append_entry(one, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0);
116 : }
117 :
118 200 : free(p);
119 200 : free(q);
120 : }
121 :
122 1 : (void) journal_file_close(one);
123 1 : (void) journal_file_close(two);
124 1 : (void) journal_file_close(three);
125 :
126 1 : assert_se(sd_journal_open_directory(&j, t, 0) >= 0);
127 :
128 1 : assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);
129 41 : SD_JOURNAL_FOREACH_BACKWARDS(j) {
130 40 : _cleanup_free_ char *c;
131 :
132 40 : assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0);
133 40 : printf("\t%.*s\n", (int) l, (const char*) data);
134 :
135 40 : assert_se(sd_journal_get_cursor(j, &c) >= 0);
136 40 : assert_se(sd_journal_test_cursor(j, c) > 0);
137 : }
138 :
139 41 : SD_JOURNAL_FOREACH(j) {
140 40 : _cleanup_free_ char *c;
141 :
142 40 : assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0);
143 40 : printf("\t%.*s\n", (int) l, (const char*) data);
144 :
145 40 : assert_se(sd_journal_get_cursor(j, &c) >= 0);
146 40 : assert_se(sd_journal_test_cursor(j, c) > 0);
147 : }
148 :
149 1 : sd_journal_flush_matches(j);
150 :
151 1 : verify_contents(j, 1);
152 :
153 1 : printf("NEXT TEST\n");
154 1 : assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);
155 :
156 1 : assert_se(z = journal_make_match_string(j));
157 1 : printf("resulting match expression is: %s\n", z);
158 1 : free(z);
159 :
160 1 : verify_contents(j, 5);
161 :
162 1 : printf("NEXT TEST\n");
163 1 : sd_journal_flush_matches(j);
164 1 : assert_se(sd_journal_add_match(j, "MAGIC=waldo", 0) >= 0);
165 1 : assert_se(sd_journal_add_match(j, "NUMBER=10", 0) >= 0);
166 1 : assert_se(sd_journal_add_match(j, "NUMBER=11", 0) >= 0);
167 1 : assert_se(sd_journal_add_match(j, "NUMBER=12", 0) >= 0);
168 :
169 1 : assert_se(z = journal_make_match_string(j));
170 1 : printf("resulting match expression is: %s\n", z);
171 1 : free(z);
172 :
173 1 : verify_contents(j, 0);
174 :
175 1 : assert_se(sd_journal_query_unique(j, "NUMBER") >= 0);
176 201 : SD_JOURNAL_FOREACH_UNIQUE(j, data, l)
177 200 : printf("%.*s\n", (int) l, (const char*) data);
178 :
179 1 : assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
180 :
181 1 : return 0;
182 : }
|