1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "sd-bus.h"
4 
5 #include "alloc-util.h"
6 #include "bus-common-errors.h"
7 #include "bus-error.h"
8 #include "errno-list.h"
9 #include "errno-util.h"
10 #include "string-util.h"
11 #include "tests.h"
12 
TEST(error)13 TEST(error) {
14         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
15         const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
16         const sd_bus_error temporarily_const_error = {
17                 .name = SD_BUS_ERROR_ACCESS_DENIED,
18                 .message = "oh! no",
19                 ._need_free = -1,
20         };
21 
22         assert_se(!sd_bus_error_is_set(&error));
23         assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -EOPNOTSUPP);
24         assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED));
25         assert_se(streq(error.message, "xxx"));
26         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED));
27         assert_se(sd_bus_error_has_names_sentinel(&error, SD_BUS_ERROR_NOT_SUPPORTED, NULL));
28         assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_NOT_SUPPORTED));
29         assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_NOT_SUPPORTED, SD_BUS_ERROR_FILE_NOT_FOUND));
30         assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND, SD_BUS_ERROR_NOT_SUPPORTED, NULL));
31         assert_se(!sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
32         assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP);
33         assert_se(sd_bus_error_is_set(&error));
34         sd_bus_error_free(&error);
35 
36         /* Check with no error */
37         assert_se(!sd_bus_error_is_set(&error));
38         assert_se(sd_bus_error_setf(&error, NULL, "yyy %i", -1) == 0);
39         assert_se(error.name == NULL);
40         assert_se(error.message == NULL);
41         assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
42         assert_se(!sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
43         assert_se(sd_bus_error_get_errno(&error) == 0);
44         assert_se(!sd_bus_error_is_set(&error));
45 
46         assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
47         assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
48         assert_se(streq(error.message, "yyy -1"));
49         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
50         assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
51         assert_se(sd_bus_error_get_errno(&error) == ENOENT);
52         assert_se(sd_bus_error_is_set(&error));
53 
54         assert_se(!sd_bus_error_is_set(&second));
55         assert_se(second._need_free == 0);
56         assert_se(error._need_free > 0);
57         assert_se(sd_bus_error_copy(&second, &error) == -ENOENT);
58         assert_se(second._need_free > 0);
59         assert_se(streq(error.name, second.name));
60         assert_se(streq(error.message, second.message));
61         assert_se(sd_bus_error_get_errno(&second) == ENOENT);
62         assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND));
63         assert_se(sd_bus_error_has_names(&second, SD_BUS_ERROR_FILE_NOT_FOUND));
64         assert_se(sd_bus_error_is_set(&second));
65 
66         sd_bus_error_free(&error);
67         sd_bus_error_free(&second);
68 
69         assert_se(!sd_bus_error_is_set(&second));
70         assert_se(const_error._need_free == 0);
71         assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST);
72         assert_se(second._need_free == 0);
73         assert_se(streq(const_error.name, second.name));
74         assert_se(streq(const_error.message, second.message));
75         assert_se(sd_bus_error_get_errno(&second) == EEXIST);
76         assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS));
77         assert_se(sd_bus_error_is_set(&second));
78         sd_bus_error_free(&second);
79 
80         assert_se(!sd_bus_error_is_set(&second));
81         assert_se(temporarily_const_error._need_free < 0);
82         assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES);
83         assert_se(second._need_free > 0);
84         assert_se(streq(temporarily_const_error.name, second.name));
85         assert_se(streq(temporarily_const_error.message, second.message));
86         assert_se(sd_bus_error_get_errno(&second) == EACCES);
87         assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED));
88         assert_se(sd_bus_error_is_set(&second));
89 
90         assert_se(!sd_bus_error_is_set(&error));
91         assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN);
92         assert_se(streq(error.name, "System.Error.EUCLEAN"));
93         assert_se(streq(error.message, "Hallo"));
94         assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN"));
95         assert_se(sd_bus_error_get_errno(&error) == EUCLEAN);
96         assert_se(sd_bus_error_is_set(&error));
97         sd_bus_error_free(&error);
98 
99         assert_se(!sd_bus_error_is_set(&error));
100         assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
101         assert_se(streq(error.name, "System.Error.EBUSY"));
102         assert_se(streq(error.message, strerror_safe(EBUSY)));
103         assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
104         assert_se(sd_bus_error_get_errno(&error) == EBUSY);
105         assert_se(sd_bus_error_is_set(&error));
106         sd_bus_error_free(&error);
107 
108         assert_se(!sd_bus_error_is_set(&error));
109         assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO);
110         assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR));
111         assert_se(streq(error.message, "Waldi X"));
112         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
113         assert_se(sd_bus_error_get_errno(&error) == EIO);
114         assert_se(sd_bus_error_is_set(&error));
115         sd_bus_error_free(&error);
116 
117         /* Check with no error */
118         assert_se(!sd_bus_error_is_set(&error));
119         assert_se(sd_bus_error_set_errnof(&error, 0, "Waldi %c", 'X') == 0);
120         assert_se(error.name == NULL);
121         assert_se(error.message == NULL);
122         assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
123         assert_se(sd_bus_error_get_errno(&error) == 0);
124         assert_se(!sd_bus_error_is_set(&error));
125 }
126 
127 extern const sd_bus_error_map __start_SYSTEMD_BUS_ERROR_MAP[];
128 extern const sd_bus_error_map __stop_SYSTEMD_BUS_ERROR_MAP[];
129 
dump_mapping_table(void)130 static int dump_mapping_table(void) {
131         const sd_bus_error_map *m;
132 
133         printf("----- errno mappings ------\n");
134         m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*));
135         while (m < __stop_SYSTEMD_BUS_ERROR_MAP) {
136 
137                 if (m->code == BUS_ERROR_MAP_END_MARKER) {
138                         m = ALIGN_TO_PTR(m + 1, sizeof(void*));
139                         continue;
140                 }
141 
142                 printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code)));
143                 m++;
144         }
145         printf("---------------------------\n");
146 
147         return EXIT_SUCCESS;
148 }
149 
TEST(errno_mapping_standard)150 TEST(errno_mapping_standard) {
151         assert_se(sd_bus_error_set(NULL, "System.Error.EUCLEAN", NULL) == -EUCLEAN);
152         assert_se(sd_bus_error_set(NULL, "System.Error.EBUSY", NULL) == -EBUSY);
153         assert_se(sd_bus_error_set(NULL, "System.Error.EINVAL", NULL) == -EINVAL);
154         assert_se(sd_bus_error_set(NULL, "System.Error.WHATSIT", NULL) == -EIO);
155 }
156 
157 BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors[] = {
158         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error", 5),
159         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-2", 52),
160         SD_BUS_ERROR_MAP_END
161 };
162 
163 BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors2[] = {
164         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-3", 33),
165         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-4", 44),
166         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-33", 333),
167         SD_BUS_ERROR_MAP_END
168 };
169 
170 static const sd_bus_error_map test_errors3[] = {
171         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-88", 888),
172         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-99", 999),
173         SD_BUS_ERROR_MAP_END
174 };
175 
176 static const sd_bus_error_map test_errors4[] = {
177         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-77", 777),
178         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-78", 778),
179         SD_BUS_ERROR_MAP_END
180 };
181 
182 static const sd_bus_error_map test_errors_bad1[] = {
183         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", 0),
184         SD_BUS_ERROR_MAP_END
185 };
186 
187 static const sd_bus_error_map test_errors_bad2[] = {
188         SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", -1),
189         SD_BUS_ERROR_MAP_END
190 };
191 
TEST(errno_mapping_custom)192 TEST(errno_mapping_custom) {
193         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5);
194         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
195         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-x", NULL) == -EIO);
196         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-33", NULL) == -333);
197 
198         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -EIO);
199         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -EIO);
200         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -EIO);
201 
202         assert_se(sd_bus_error_add_map(test_errors3) > 0);
203         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -888);
204         assert_se(sd_bus_error_add_map(test_errors4) > 0);
205         assert_se(sd_bus_error_add_map(test_errors4) == 0);
206         assert_se(sd_bus_error_add_map(test_errors3) == 0);
207 
208         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -999);
209         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -777);
210         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-78", NULL) == -778);
211         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
212         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-y", NULL) == -EIO);
213 
214         assert_se(sd_bus_error_set(NULL, BUS_ERROR_NO_SUCH_UNIT, NULL) == -ENOENT);
215 
216         assert_se(sd_bus_error_add_map(test_errors_bad1) == -EINVAL);
217         assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL);
218 }
219 
TEST(sd_bus_error_set_errnof)220 TEST(sd_bus_error_set_errnof) {
221         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
222         _cleanup_free_ char *str = NULL;
223 
224         assert_se(sd_bus_error_set_errnof(NULL, 0, NULL) == 0);
225         assert_se(sd_bus_error_set_errnof(NULL, ENOANO, NULL) == -ENOANO);
226 
227         assert_se(sd_bus_error_set_errnof(&error, 0, NULL) == 0);
228         assert_se(!bus_error_is_dirty(&error));
229 
230         assert_se(sd_bus_error_set_errnof(&error, EACCES, NULL) == -EACCES);
231         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED));
232         errno = EACCES;
233         assert_se(asprintf(&str, "%m") >= 0);
234         assert_se(streq(error.message, str));
235         assert_se(error._need_free == 0);
236 
237         str = mfree(str);
238         sd_bus_error_free(&error);
239 
240         assert_se(sd_bus_error_set_errnof(&error, ENOANO, NULL) == -ENOANO);
241         assert_se(sd_bus_error_has_name(&error, "System.Error.ENOANO"));
242         errno = ENOANO;
243         assert_se(asprintf(&str, "%m") >= 0);
244         assert_se(streq(error.message, str));
245         assert_se(error._need_free == 1);
246 
247         str = mfree(str);
248         sd_bus_error_free(&error);
249 
250         assert_se(sd_bus_error_set_errnof(&error, 100000, NULL) == -100000);
251         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FAILED));
252         errno = 100000;
253         assert_se(asprintf(&str, "%m") >= 0);
254         assert_se(streq(error.message, str));
255         assert_se(error._need_free == 1);
256 
257         str = mfree(str);
258         sd_bus_error_free(&error);
259 
260         assert_se(sd_bus_error_set_errnof(NULL, 0, "hoge %s: %m", "foo") == 0);
261         assert_se(sd_bus_error_set_errnof(NULL, ENOANO, "hoge %s: %m", "foo") == -ENOANO);
262 
263         assert_se(sd_bus_error_set_errnof(&error, 0, "hoge %s: %m", "foo") == 0);
264         assert_se(!bus_error_is_dirty(&error));
265 
266         assert_se(sd_bus_error_set_errnof(&error, EACCES, "hoge %s: %m", "foo") == -EACCES);
267         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED));
268         errno = EACCES;
269         assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0);
270         assert_se(streq(error.message, str));
271         assert_se(error._need_free == 1);
272 
273         str = mfree(str);
274         sd_bus_error_free(&error);
275 
276         assert_se(sd_bus_error_set_errnof(&error, ENOANO, "hoge %s: %m", "foo") == -ENOANO);
277         assert_se(sd_bus_error_has_name(&error, "System.Error.ENOANO"));
278         errno = ENOANO;
279         assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0);
280         assert_se(streq(error.message, str));
281         assert_se(error._need_free == 1);
282 
283         str = mfree(str);
284         sd_bus_error_free(&error);
285 
286         assert_se(sd_bus_error_set_errnof(&error, 100000, "hoge %s: %m", "foo") == -100000);
287         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FAILED));
288         errno = 100000;
289         assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0);
290         assert_se(streq(error.message, str));
291         assert_se(error._need_free == 1);
292 }
293 
294 DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, dump_mapping_table);
295