]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
d4205751 LP |
2 | /*** |
3 | This file is part of systemd. | |
4 | ||
5 | Copyright 2012 Lennart Poettering | |
844ec79b | 6 | Copyright 2013 Zbigniew Jędrzejewski-Szmek |
d4205751 LP |
7 | |
8 | systemd is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU Lesser General Public License as published by | |
10 | the Free Software Foundation; either version 2.1 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | systemd is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | Lesser General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU Lesser General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
21 | ||
844ec79b | 22 | #include <errno.h> |
2d5bdf5b | 23 | #include <fcntl.h> |
cf0fbc49 TA |
24 | #include <locale.h> |
25 | #include <unistd.h> | |
d4205751 | 26 | |
07630cea LP |
27 | #include "sd-messages.h" |
28 | ||
b5efdb8a | 29 | #include "alloc-util.h" |
3ffd4af2 LP |
30 | #include "catalog.h" |
31 | #include "fd-util.h" | |
0d39fa9c | 32 | #include "fileio.h" |
d4205751 | 33 | #include "log.h" |
844ec79b | 34 | #include "macro.h" |
07630cea | 35 | #include "string-util.h" |
3ffd4af2 | 36 | #include "util.h" |
d4205751 | 37 | |
143bfdaf HHPF |
38 | static const char *catalog_dirs[] = { |
39 | CATALOG_DIR, | |
40 | NULL, | |
41 | }; | |
42 | ||
43 | static const char *no_catalog_dirs[] = { | |
44 | "/bin/hopefully/with/no/catalog", | |
45 | NULL | |
46 | }; | |
47 | ||
9d85882a | 48 | static Hashmap * test_import(const char* contents, ssize_t size, int code) { |
844ec79b ZJS |
49 | int r; |
50 | char name[] = "/tmp/test-catalog.XXXXXX"; | |
2d5bdf5b | 51 | _cleanup_close_ int fd; |
9d85882a SW |
52 | Hashmap *h; |
53 | ||
54 | if (size < 0) | |
55 | size = strlen(contents); | |
56 | ||
57 | assert_se(h = hashmap_new(&catalog_hash_ops)); | |
2d5bdf5b | 58 | |
646853bd | 59 | fd = mkostemp_safe(name); |
787784c4 | 60 | assert_se(fd >= 0); |
844ec79b ZJS |
61 | assert_se(write(fd, contents, size) == size); |
62 | ||
dbae138d | 63 | r = catalog_import_file(h, name); |
787784c4 | 64 | assert_se(r == code); |
844ec79b ZJS |
65 | |
66 | unlink(name); | |
844ec79b | 67 | |
9d85882a SW |
68 | return h; |
69 | } | |
844ec79b | 70 | |
9d85882a SW |
71 | static void test_catalog_import_invalid(void) { |
72 | _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; | |
844ec79b | 73 | |
9d85882a | 74 | h = test_import("xxx", -1, -EINVAL); |
787784c4 | 75 | assert_se(hashmap_isempty(h)); |
9d85882a | 76 | } |
844ec79b | 77 | |
9d85882a SW |
78 | static void test_catalog_import_badid(void) { |
79 | _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; | |
80 | const char *input = | |
844ec79b ZJS |
81 | "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededede\n" \ |
82 | "Subject: message\n" \ | |
83 | "\n" \ | |
9d85882a SW |
84 | "payload\n"; |
85 | h = test_import(input, -1, -EINVAL); | |
86 | } | |
844ec79b | 87 | |
9d85882a SW |
88 | static void test_catalog_import_one(void) { |
89 | _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; | |
90 | char *payload; | |
91 | Iterator j; | |
844ec79b | 92 | |
9d85882a | 93 | const char *input = |
844ec79b ZJS |
94 | "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ |
95 | "Subject: message\n" \ | |
96 | "\n" \ | |
9d85882a SW |
97 | "payload\n"; |
98 | const char *expect = | |
99 | "Subject: message\n" \ | |
100 | "\n" \ | |
101 | "payload\n"; | |
844ec79b | 102 | |
9d85882a | 103 | h = test_import(input, -1, 0); |
787784c4 | 104 | assert_se(hashmap_size(h) == 1); |
d4205751 | 105 | |
9d85882a | 106 | HASHMAP_FOREACH(payload, h, j) { |
06466a7f ZJS |
107 | printf("expect: %s\n", expect); |
108 | printf("actual: %s\n", payload); | |
9d85882a SW |
109 | assert_se(streq(expect, payload)); |
110 | } | |
844ec79b ZJS |
111 | } |
112 | ||
c059b62f SW |
113 | static void test_catalog_import_merge(void) { |
114 | _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; | |
115 | char *payload; | |
116 | Iterator j; | |
117 | ||
118 | const char *input = | |
119 | "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ | |
120 | "Subject: message\n" \ | |
121 | "Defined-By: me\n" \ | |
122 | "\n" \ | |
123 | "payload\n" \ | |
124 | "\n" \ | |
125 | "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ | |
126 | "Subject: override subject\n" \ | |
127 | "X-Header: hello\n" \ | |
128 | "\n" \ | |
129 | "override payload\n"; | |
130 | ||
131 | const char *combined = | |
132 | "Subject: override subject\n" \ | |
133 | "X-Header: hello\n" \ | |
134 | "Subject: message\n" \ | |
135 | "Defined-By: me\n" \ | |
136 | "\n" \ | |
137 | "override payload\n"; | |
138 | ||
139 | h = test_import(input, -1, 0); | |
140 | assert_se(hashmap_size(h) == 1); | |
141 | ||
142 | HASHMAP_FOREACH(payload, h, j) { | |
143 | assert_se(streq(combined, payload)); | |
144 | } | |
145 | } | |
146 | ||
147 | static void test_catalog_import_merge_no_body(void) { | |
148 | _cleanup_hashmap_free_free_free_ Hashmap *h = NULL; | |
149 | char *payload; | |
150 | Iterator j; | |
151 | ||
152 | const char *input = | |
153 | "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ | |
154 | "Subject: message\n" \ | |
155 | "Defined-By: me\n" \ | |
156 | "\n" \ | |
157 | "payload\n" \ | |
158 | "\n" \ | |
159 | "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ | |
160 | "Subject: override subject\n" \ | |
161 | "X-Header: hello\n" \ | |
162 | "\n"; | |
163 | ||
164 | const char *combined = | |
165 | "Subject: override subject\n" \ | |
166 | "X-Header: hello\n" \ | |
167 | "Subject: message\n" \ | |
168 | "Defined-By: me\n" \ | |
169 | "\n" \ | |
170 | "payload\n"; | |
171 | ||
172 | h = test_import(input, -1, 0); | |
173 | assert_se(hashmap_size(h) == 1); | |
174 | ||
175 | HASHMAP_FOREACH(payload, h, j) { | |
176 | assert_se(streq(combined, payload)); | |
177 | } | |
178 | } | |
179 | ||
844ec79b ZJS |
180 | static const char* database = NULL; |
181 | ||
182 | static void test_catalog_update(void) { | |
2d5bdf5b | 183 | static char name[] = "/tmp/test-catalog.XXXXXX"; |
844ec79b | 184 | int r; |
844ec79b | 185 | |
646853bd | 186 | r = mkostemp_safe(name); |
787784c4 | 187 | assert_se(r >= 0); |
844ec79b ZJS |
188 | |
189 | database = name; | |
190 | ||
191 | /* Test what happens if there are no files. */ | |
192 | r = catalog_update(database, NULL, NULL); | |
787784c4 | 193 | assert_se(r >= 0); |
844ec79b | 194 | |
143bfdaf HHPF |
195 | /* Test what happens if there are no files in the directory. */ |
196 | r = catalog_update(database, NULL, no_catalog_dirs); | |
787784c4 | 197 | assert_se(r >= 0); |
143bfdaf HHPF |
198 | |
199 | /* Make sure that we at least have some files loaded or the | |
200 | catalog_list below will fail. */ | |
201 | r = catalog_update(database, NULL, catalog_dirs); | |
787784c4 | 202 | assert_se(r >= 0); |
844ec79b ZJS |
203 | } |
204 | ||
c7332b08 | 205 | static void test_catalog_file_lang(void) { |
4b8268f8 | 206 | _cleanup_free_ char *lang = NULL, *lang2 = NULL, *lang3 = NULL, *lang4 = NULL; |
c7332b08 ZJS |
207 | |
208 | assert_se(catalog_file_lang("systemd.de_DE.catalog", &lang) == 1); | |
209 | assert_se(streq(lang, "de_DE")); | |
210 | ||
211 | assert_se(catalog_file_lang("systemd..catalog", &lang2) == 0); | |
212 | assert_se(lang2 == NULL); | |
213 | ||
214 | assert_se(catalog_file_lang("systemd.fr.catalog", &lang2) == 1); | |
215 | assert_se(streq(lang2, "fr")); | |
216 | ||
217 | assert_se(catalog_file_lang("systemd.fr.catalog.gz", &lang3) == 0); | |
218 | assert_se(lang3 == NULL); | |
219 | ||
220 | assert_se(catalog_file_lang("systemd.01234567890123456789012345678901.catalog", &lang3) == 0); | |
221 | assert_se(lang3 == NULL); | |
222 | ||
223 | assert_se(catalog_file_lang("systemd.0123456789012345678901234567890.catalog", &lang3) == 1); | |
224 | assert_se(streq(lang3, "0123456789012345678901234567890")); | |
4b8268f8 ZJS |
225 | |
226 | assert_se(catalog_file_lang("/x/y/systemd.catalog", &lang4) == 0); | |
227 | assert_se(lang4 == NULL); | |
228 | ||
229 | assert_se(catalog_file_lang("/x/y/systemd.ru_RU.catalog", &lang4) == 1); | |
230 | assert_se(streq(lang4, "ru_RU")); | |
c7332b08 ZJS |
231 | } |
232 | ||
844ec79b | 233 | int main(int argc, char *argv[]) { |
d4205751 | 234 | _cleanup_free_ char *text = NULL; |
844ec79b | 235 | int r; |
d4205751 LP |
236 | |
237 | setlocale(LC_ALL, "de_DE.UTF-8"); | |
238 | ||
e3b9d9c8 ZJS |
239 | log_parse_environment(); |
240 | log_open(); | |
d4205751 | 241 | |
4b8268f8 ZJS |
242 | test_catalog_file_lang(); |
243 | ||
9d85882a SW |
244 | test_catalog_import_invalid(); |
245 | test_catalog_import_badid(); | |
246 | test_catalog_import_one(); | |
c059b62f SW |
247 | test_catalog_import_merge(); |
248 | test_catalog_import_merge_no_body(); | |
d4205751 | 249 | |
844ec79b | 250 | test_catalog_update(); |
54b7254c | 251 | |
844ec79b ZJS |
252 | r = catalog_list(stdout, database, true); |
253 | assert_se(r >= 0); | |
d4205751 | 254 | |
844ec79b ZJS |
255 | r = catalog_list(stdout, database, false); |
256 | assert_se(r >= 0); | |
d4205751 | 257 | |
844ec79b | 258 | assert_se(catalog_get(database, SD_MESSAGE_COREDUMP, &text) >= 0); |
d4205751 LP |
259 | printf(">>>%s<<<\n", text); |
260 | ||
844ec79b ZJS |
261 | if (database) |
262 | unlink(database); | |
d4205751 LP |
263 | |
264 | return 0; | |
265 | } |