]>
Commit | Line | Data |
---|---|---|
faec54ad LP |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | ||
3 | #include <pthread.h> | |
4 | ||
5 | #include "fd-util.h" | |
6 | #include "pretty-print.h" | |
7 | #include "tests.h" | |
8 | #include "varlink.h" | |
9 | #include "varlink-idl.h" | |
10 | #include "varlink-io.systemd.h" | |
11 | #include "varlink-io.systemd.Journal.h" | |
12 | #include "varlink-io.systemd.ManagedOOM.h" | |
4e16d5c6 | 13 | #include "varlink-io.systemd.PCRExtend.h" |
faec54ad LP |
14 | #include "varlink-io.systemd.Resolve.Monitor.h" |
15 | #include "varlink-io.systemd.Resolve.h" | |
16 | #include "varlink-io.systemd.UserDatabase.h" | |
17 | #include "varlink-io.systemd.oom.h" | |
f5151fb4 | 18 | #include "varlink-io.systemd.sysext.h" |
faec54ad LP |
19 | #include "varlink-org.varlink.service.h" |
20 | ||
21 | static VARLINK_DEFINE_ENUM_TYPE( | |
22 | EnumTest, | |
23 | VARLINK_DEFINE_ENUM_VALUE(foo), | |
24 | VARLINK_DEFINE_ENUM_VALUE(bar), | |
25 | VARLINK_DEFINE_ENUM_VALUE(baz)); | |
26 | ||
27 | static VARLINK_DEFINE_STRUCT_TYPE( | |
28 | NestedStructTest, | |
29 | VARLINK_DEFINE_FIELD(x, VARLINK_INT, 0)); | |
30 | ||
31 | static VARLINK_DEFINE_STRUCT_TYPE( | |
32 | StructTest, | |
33 | ||
34 | VARLINK_DEFINE_FIELD(bbb, VARLINK_BOOL, 0), | |
35 | VARLINK_DEFINE_FIELD(bbbn, VARLINK_BOOL, VARLINK_NULLABLE), | |
36 | VARLINK_DEFINE_FIELD(bbba, VARLINK_BOOL, VARLINK_ARRAY), | |
37 | VARLINK_DEFINE_FIELD(bbbna, VARLINK_BOOL, VARLINK_NULLABLE|VARLINK_ARRAY), | |
38 | VARLINK_DEFINE_FIELD(bbbm, VARLINK_BOOL, VARLINK_MAP), | |
39 | VARLINK_DEFINE_FIELD(bbbnm, VARLINK_BOOL, VARLINK_NULLABLE|VARLINK_MAP), | |
40 | ||
41 | VARLINK_DEFINE_FIELD(iii, VARLINK_INT, 0), | |
42 | VARLINK_DEFINE_FIELD(iiin, VARLINK_INT, VARLINK_NULLABLE), | |
43 | VARLINK_DEFINE_FIELD(iiia, VARLINK_INT, VARLINK_ARRAY), | |
44 | VARLINK_DEFINE_FIELD(iiina, VARLINK_INT, VARLINK_NULLABLE|VARLINK_ARRAY), | |
45 | VARLINK_DEFINE_FIELD(iiim, VARLINK_INT, VARLINK_MAP), | |
46 | VARLINK_DEFINE_FIELD(iiinm, VARLINK_INT, VARLINK_NULLABLE|VARLINK_MAP), | |
47 | ||
48 | VARLINK_DEFINE_FIELD(fff, VARLINK_FLOAT, 0), | |
49 | VARLINK_DEFINE_FIELD(fffn, VARLINK_FLOAT, VARLINK_NULLABLE), | |
50 | VARLINK_DEFINE_FIELD(fffa, VARLINK_FLOAT, VARLINK_ARRAY), | |
51 | VARLINK_DEFINE_FIELD(fffna, VARLINK_FLOAT, VARLINK_NULLABLE|VARLINK_ARRAY), | |
52 | VARLINK_DEFINE_FIELD(fffm, VARLINK_FLOAT, VARLINK_MAP), | |
53 | VARLINK_DEFINE_FIELD(fffnm, VARLINK_FLOAT, VARLINK_NULLABLE|VARLINK_MAP), | |
54 | ||
55 | VARLINK_DEFINE_FIELD(sss, VARLINK_STRING, 0), | |
56 | VARLINK_DEFINE_FIELD(sssn, VARLINK_STRING, VARLINK_NULLABLE), | |
57 | VARLINK_DEFINE_FIELD(sssa, VARLINK_STRING, VARLINK_ARRAY), | |
58 | VARLINK_DEFINE_FIELD(sssna, VARLINK_STRING, VARLINK_NULLABLE|VARLINK_ARRAY), | |
59 | VARLINK_DEFINE_FIELD(sssm, VARLINK_STRING, VARLINK_MAP), | |
60 | VARLINK_DEFINE_FIELD(sssnm, VARLINK_STRING, VARLINK_NULLABLE|VARLINK_MAP), | |
61 | ||
62 | VARLINK_DEFINE_FIELD(ooo, VARLINK_OBJECT, 0), | |
63 | VARLINK_DEFINE_FIELD(ooon, VARLINK_OBJECT, VARLINK_NULLABLE), | |
64 | VARLINK_DEFINE_FIELD(oooa, VARLINK_OBJECT, VARLINK_ARRAY), | |
65 | VARLINK_DEFINE_FIELD(ooona, VARLINK_OBJECT, VARLINK_NULLABLE|VARLINK_ARRAY), | |
66 | VARLINK_DEFINE_FIELD(ooom, VARLINK_OBJECT, VARLINK_MAP), | |
67 | VARLINK_DEFINE_FIELD(ooonm, VARLINK_OBJECT, VARLINK_NULLABLE|VARLINK_MAP), | |
68 | ||
69 | VARLINK_DEFINE_FIELD_BY_TYPE(eee, EnumTest, 0), | |
70 | VARLINK_DEFINE_FIELD_BY_TYPE(eeen, EnumTest, VARLINK_NULLABLE), | |
71 | VARLINK_DEFINE_FIELD_BY_TYPE(eeea, EnumTest, VARLINK_ARRAY), | |
72 | VARLINK_DEFINE_FIELD_BY_TYPE(eeena, EnumTest, VARLINK_NULLABLE|VARLINK_ARRAY), | |
73 | VARLINK_DEFINE_FIELD_BY_TYPE(eeem, EnumTest, VARLINK_MAP), | |
74 | VARLINK_DEFINE_FIELD_BY_TYPE(eeenm, EnumTest, VARLINK_NULLABLE|VARLINK_MAP), | |
75 | ||
76 | VARLINK_DEFINE_FIELD_BY_TYPE(nnn, NestedStructTest, 0), | |
77 | VARLINK_DEFINE_FIELD_BY_TYPE(nnnn, NestedStructTest, VARLINK_NULLABLE), | |
78 | VARLINK_DEFINE_FIELD_BY_TYPE(nnna, NestedStructTest, VARLINK_ARRAY), | |
79 | VARLINK_DEFINE_FIELD_BY_TYPE(nnnna, NestedStructTest, VARLINK_NULLABLE|VARLINK_ARRAY), | |
80 | VARLINK_DEFINE_FIELD_BY_TYPE(nnnm, NestedStructTest, VARLINK_MAP), | |
81 | VARLINK_DEFINE_FIELD_BY_TYPE(nnnnm, NestedStructTest, VARLINK_NULLABLE|VARLINK_MAP)); | |
82 | ||
83 | static VARLINK_DEFINE_METHOD( | |
84 | MethodTest, | |
85 | VARLINK_DEFINE_INPUT(x, VARLINK_BOOL, 0), | |
86 | VARLINK_DEFINE_INPUT_BY_TYPE(y, EnumTest, 0), | |
87 | VARLINK_DEFINE_INPUT_BY_TYPE(z, StructTest, 0), | |
88 | VARLINK_DEFINE_OUTPUT(x, VARLINK_BOOL, 0), | |
89 | VARLINK_DEFINE_OUTPUT_BY_TYPE(y, EnumTest, 0), | |
90 | VARLINK_DEFINE_OUTPUT_BY_TYPE(z, StructTest, 0)); | |
91 | ||
92 | static VARLINK_DEFINE_ERROR( | |
93 | ErrorTest, | |
94 | VARLINK_DEFINE_FIELD(x, VARLINK_BOOL, 0), | |
95 | VARLINK_DEFINE_FIELD_BY_TYPE(y, EnumTest, 0), | |
96 | VARLINK_DEFINE_FIELD_BY_TYPE(z, StructTest, 0)); | |
97 | ||
98 | static VARLINK_DEFINE_INTERFACE( | |
99 | xyz_test, | |
100 | "xyz.test", | |
101 | &vl_type_EnumTest, | |
102 | &vl_type_NestedStructTest, | |
103 | &vl_type_StructTest, | |
104 | &vl_method_MethodTest, | |
105 | &vl_error_ErrorTest); | |
106 | ||
107 | static void test_parse_format_one(const VarlinkInterface *iface) { | |
108 | _cleanup_(varlink_interface_freep) VarlinkInterface *parsed = NULL; | |
109 | _cleanup_free_ char *text = NULL, *text2 = NULL; | |
110 | ||
111 | assert_se(iface); | |
112 | ||
113 | assert_se(varlink_idl_dump(stdout, /* use_colors=*/ true, iface) >= 0); | |
114 | assert_se(varlink_idl_consistent(iface, LOG_ERR) >= 0); | |
115 | assert_se(varlink_idl_format(iface, &text) >= 0); | |
116 | assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0); | |
117 | assert_se(varlink_idl_consistent(parsed, LOG_ERR) >= 0); | |
118 | assert_se(varlink_idl_format(parsed, &text2) >= 0); | |
119 | assert_se(streq(text, text2)); | |
120 | } | |
121 | ||
122 | TEST(parse_format) { | |
123 | test_parse_format_one(&vl_interface_org_varlink_service); | |
124 | print_separator(); | |
125 | test_parse_format_one(&vl_interface_io_systemd_UserDatabase); | |
126 | print_separator(); | |
127 | test_parse_format_one(&vl_interface_io_systemd_Journal); | |
128 | print_separator(); | |
129 | test_parse_format_one(&vl_interface_io_systemd_Resolve); | |
130 | print_separator(); | |
131 | test_parse_format_one(&vl_interface_io_systemd_Resolve_Monitor); | |
132 | print_separator(); | |
133 | test_parse_format_one(&vl_interface_io_systemd_ManagedOOM); | |
134 | print_separator(); | |
135 | test_parse_format_one(&vl_interface_io_systemd_oom); | |
136 | print_separator(); | |
137 | test_parse_format_one(&vl_interface_io_systemd); | |
138 | print_separator(); | |
4e16d5c6 LP |
139 | test_parse_format_one(&vl_interface_io_systemd_PCRExtend); |
140 | print_separator(); | |
f5151fb4 LP |
141 | test_parse_format_one(&vl_interface_io_systemd_sysext); |
142 | print_separator(); | |
faec54ad LP |
143 | test_parse_format_one(&vl_interface_xyz_test); |
144 | } | |
145 | ||
146 | TEST(parse) { | |
147 | _cleanup_(varlink_interface_freep) VarlinkInterface *parsed = NULL; | |
148 | ||
149 | /* This one has (nested) enonymous enums and structs */ | |
150 | static const char text[] = | |
151 | "interface quu.waa\n" | |
152 | "type Fooenum ( a, b, c )\n" | |
153 | "type Barstruct ( a : (x, y, z), b : (x : int), c: (f, ff, fff), d: object, e : (sub : (subsub: (subsubsub: string, subsubsub2: (iii, ooo)))))" | |
154 | ; | |
155 | ||
156 | assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0); | |
157 | test_parse_format_one(parsed); | |
5d2ea9b5 LP |
158 | |
159 | assert_se(varlink_idl_parse("interface org.freedesktop.Foo\n" | |
160 | "type Foo (b: bool, c: foo, c: int)", NULL, NULL, NULL) == -ENETUNREACH); /* unresolved type */ | |
161 | assert_se(varlink_idl_parse("interface org.freedesktop.Foo\n" | |
162 | "type Foo ()", NULL, NULL, NULL) == -EBADMSG); /* empty struct/enum */ | |
163 | ||
faec54ad LP |
164 | } |
165 | ||
166 | TEST(interface_name_is_valid) { | |
167 | assert_se(!varlink_idl_interface_name_is_valid(NULL)); | |
168 | assert_se(!varlink_idl_interface_name_is_valid("")); | |
169 | assert_se(!varlink_idl_interface_name_is_valid(",")); | |
170 | assert_se(!varlink_idl_interface_name_is_valid(".")); | |
171 | assert_se(!varlink_idl_interface_name_is_valid("-")); | |
172 | assert_se(varlink_idl_interface_name_is_valid("a")); | |
173 | assert_se(varlink_idl_interface_name_is_valid("a.a")); | |
174 | assert_se(!varlink_idl_interface_name_is_valid("-.a")); | |
175 | assert_se(!varlink_idl_interface_name_is_valid("-a.a")); | |
176 | assert_se(!varlink_idl_interface_name_is_valid("a-.a")); | |
177 | assert_se(varlink_idl_interface_name_is_valid("a-a.a")); | |
178 | assert_se(!varlink_idl_interface_name_is_valid("a-a.a-")); | |
179 | assert_se(!varlink_idl_interface_name_is_valid("a-a.-a")); | |
180 | assert_se(!varlink_idl_interface_name_is_valid("a-a.-")); | |
181 | assert_se(varlink_idl_interface_name_is_valid("a-a.a-a")); | |
182 | assert_se(varlink_idl_interface_name_is_valid("io.systemd.Foobar")); | |
183 | } | |
184 | ||
185 | TEST(symbol_name_is_valid) { | |
186 | assert_se(!varlink_idl_symbol_name_is_valid(NULL)); | |
187 | assert_se(!varlink_idl_symbol_name_is_valid("")); | |
188 | assert_se(!varlink_idl_symbol_name_is_valid("_")); | |
189 | assert_se(!varlink_idl_symbol_name_is_valid("_foo")); | |
190 | assert_se(varlink_idl_symbol_name_is_valid("Foofoo")); | |
191 | assert_se(varlink_idl_symbol_name_is_valid("Foo")); | |
192 | assert_se(varlink_idl_symbol_name_is_valid("Foo0")); | |
193 | assert_se(!varlink_idl_symbol_name_is_valid("0Foo")); | |
194 | assert_se(!varlink_idl_symbol_name_is_valid("foo")); | |
195 | assert_se(varlink_idl_symbol_name_is_valid("Foo0foo")); | |
196 | assert_se(!varlink_idl_symbol_name_is_valid("bool")); | |
197 | assert_se(!varlink_idl_symbol_name_is_valid("int")); | |
198 | assert_se(!varlink_idl_symbol_name_is_valid("float")); | |
199 | assert_se(!varlink_idl_symbol_name_is_valid("string")); | |
200 | assert_se(!varlink_idl_symbol_name_is_valid("object")); | |
201 | } | |
202 | ||
203 | TEST(field_name_is_valid) { | |
204 | assert_se(!varlink_idl_field_name_is_valid(NULL)); | |
205 | assert_se(!varlink_idl_field_name_is_valid("")); | |
206 | assert_se(!varlink_idl_field_name_is_valid("_")); | |
207 | assert_se(!varlink_idl_field_name_is_valid("_foo")); | |
208 | assert_se(!varlink_idl_field_name_is_valid("_foo_")); | |
209 | assert_se(!varlink_idl_field_name_is_valid("foo_")); | |
210 | assert_se(varlink_idl_field_name_is_valid("foo_foo")); | |
211 | assert_se(varlink_idl_field_name_is_valid("f_o_o_f_o_o")); | |
212 | assert_se(!varlink_idl_field_name_is_valid("foo__foo")); | |
213 | assert_se(varlink_idl_field_name_is_valid("Foofoo")); | |
214 | assert_se(varlink_idl_field_name_is_valid("Foo")); | |
215 | assert_se(varlink_idl_field_name_is_valid("Foo0")); | |
216 | assert_se(!varlink_idl_field_name_is_valid("0Foo")); | |
217 | assert_se(varlink_idl_field_name_is_valid("foo")); | |
218 | assert_se(varlink_idl_field_name_is_valid("Foo0foo")); | |
219 | assert_se(varlink_idl_field_name_is_valid("foo0foo")); | |
220 | } | |
221 | ||
222 | TEST(validate_json) { | |
223 | ||
224 | _cleanup_(varlink_interface_freep) VarlinkInterface *parsed = NULL; | |
225 | ||
226 | /* This one has (nested) enonymous enums and structs */ | |
227 | static const char text[] = | |
228 | "interface validate.test\n" | |
229 | "method Mymethod ( a:string, b:int, c:?bool, d:[]int, e:?[string]bool, f:?(piff, paff), g:(f:float) ) -> ()\n"; | |
230 | ||
231 | assert_se(varlink_idl_parse(text, NULL, NULL, &parsed) >= 0); | |
232 | test_parse_format_one(parsed); | |
233 | ||
234 | _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; | |
235 | ||
236 | assert_se(json_build(&v, JSON_BUILD_OBJECT( | |
237 | JSON_BUILD_PAIR("a", JSON_BUILD_STRING("x")), | |
238 | JSON_BUILD_PAIR("b", JSON_BUILD_UNSIGNED(44)), | |
239 | JSON_BUILD_PAIR("d", JSON_BUILD_ARRAY(JSON_BUILD_UNSIGNED(5), JSON_BUILD_UNSIGNED(7), JSON_BUILD_UNSIGNED(107))), | |
240 | JSON_BUILD_PAIR("g", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("f", JSON_BUILD_REAL(0.5f)))))) >= 0); | |
241 | ||
242 | json_variant_dump(v, JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO, stdout, NULL); | |
243 | ||
244 | const VarlinkSymbol* symbol = ASSERT_PTR(varlink_idl_find_symbol(parsed, VARLINK_METHOD, "Mymethod")); | |
245 | ||
246 | assert_se(varlink_idl_validate_method_call(symbol, v, NULL) >= 0); | |
247 | } | |
248 | ||
249 | static int test_method(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { | |
250 | JsonVariant *foo = json_variant_by_key(parameters, "foo"), *bar = json_variant_by_key(parameters, "bar"); | |
251 | ||
252 | return varlink_replyb(link, | |
253 | JSON_BUILD_OBJECT( | |
254 | JSON_BUILD_PAIR_UNSIGNED("waldo", json_variant_unsigned(foo) * json_variant_unsigned(bar)), | |
255 | JSON_BUILD_PAIR_UNSIGNED("quux", json_variant_unsigned(foo) + json_variant_unsigned(bar)))); | |
256 | } | |
257 | ||
258 | static int done_method(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { | |
259 | assert_se(sd_event_exit(varlink_get_event(link), 0) >= 0); | |
260 | return 0; | |
261 | } | |
262 | ||
263 | static VARLINK_DEFINE_METHOD( | |
264 | TestMethod, | |
265 | VARLINK_DEFINE_INPUT(foo, VARLINK_INT, 0), | |
266 | VARLINK_DEFINE_INPUT(bar, VARLINK_INT, 0), | |
267 | VARLINK_DEFINE_INPUT(optional, VARLINK_STRING, VARLINK_NULLABLE), | |
268 | VARLINK_DEFINE_OUTPUT(waldo, VARLINK_INT, 0), | |
269 | VARLINK_DEFINE_OUTPUT(quux, VARLINK_INT, 0)); | |
270 | ||
271 | static VARLINK_DEFINE_METHOD(Done); | |
272 | ||
273 | static VARLINK_DEFINE_INTERFACE( | |
274 | xyz, | |
275 | "xyz", | |
276 | &vl_method_TestMethod, | |
277 | &vl_method_Done); | |
278 | ||
279 | ||
280 | static void* server_thread(void *userdata) { | |
281 | _cleanup_(varlink_server_unrefp) VarlinkServer *server = NULL; | |
282 | _cleanup_(sd_event_unrefp) sd_event *event = NULL; | |
283 | ||
284 | assert_se(varlink_server_new(&server, 0) >= 0); | |
285 | assert_se(varlink_server_add_interface(server, &vl_interface_xyz) >= 0); | |
286 | assert_se(varlink_server_bind_method(server, "xyz.TestMethod", test_method) >= 0); | |
287 | assert_se(varlink_server_bind_method(server, "xyz.Done", done_method) >= 0); | |
288 | ||
289 | assert_se(sd_event_new(&event) >= 0); | |
290 | assert_se(varlink_server_attach_event(server, event, 0) >= 0); | |
291 | ||
292 | assert_se(varlink_server_add_connection(server, PTR_TO_FD(userdata), NULL) >= 0); | |
293 | ||
294 | assert_se(sd_event_loop(event) >= 0); | |
295 | return NULL; | |
296 | } | |
297 | ||
298 | TEST(validate_method_call) { | |
71136404 | 299 | _cleanup_close_pair_ int fd[2] = EBADF_PAIR; |
faec54ad LP |
300 | _cleanup_(varlink_unrefp) Varlink *v = NULL; |
301 | pthread_t t; | |
302 | ||
303 | assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, fd) >= 0); | |
304 | assert_se(pthread_create(&t, NULL, server_thread, FD_TO_PTR(TAKE_FD(fd[1]))) == 0); | |
305 | assert_se(varlink_connect_fd(&v, TAKE_FD(fd[0])) >= 0); | |
306 | ||
307 | JsonVariant *reply = NULL; | |
308 | const char *error_id = NULL; | |
309 | assert_se(varlink_callb(v, "xyz.TestMethod", &reply, &error_id, NULL, | |
310 | JSON_BUILD_OBJECT( | |
311 | JSON_BUILD_PAIR_UNSIGNED("foo", 8), | |
312 | JSON_BUILD_PAIR_UNSIGNED("bar", 9))) >= 0); | |
313 | ||
314 | _cleanup_(json_variant_unrefp) JsonVariant *expected_reply = NULL; | |
315 | assert_se(json_build(&expected_reply, | |
316 | JSON_BUILD_OBJECT( | |
317 | JSON_BUILD_PAIR_UNSIGNED("waldo", 8*9), | |
318 | JSON_BUILD_PAIR_UNSIGNED("quux", 8+9))) >= 0); | |
319 | ||
320 | assert_se(!error_id); | |
321 | ||
322 | json_variant_dump(reply, JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO, NULL, NULL); | |
323 | json_variant_dump(expected_reply, JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO, NULL, NULL); | |
324 | assert_se(json_variant_equal(reply, expected_reply)); | |
325 | ||
326 | assert_se(varlink_callb(v, "xyz.TestMethod", &reply, &error_id, NULL, | |
327 | JSON_BUILD_OBJECT( | |
328 | JSON_BUILD_PAIR_UNSIGNED("foo", 9), | |
329 | JSON_BUILD_PAIR_UNSIGNED("bar", 8), | |
330 | JSON_BUILD_PAIR_STRING("optional", "pfft"))) >= 0); | |
331 | ||
332 | assert_se(!error_id); | |
333 | assert_se(json_variant_equal(reply, expected_reply)); | |
334 | ||
335 | assert_se(varlink_callb(v, "xyz.TestMethod", &reply, &error_id, NULL, | |
336 | JSON_BUILD_OBJECT( | |
337 | JSON_BUILD_PAIR_UNSIGNED("foo", 8), | |
338 | JSON_BUILD_PAIR_UNSIGNED("bar", 9), | |
339 | JSON_BUILD_PAIR_STRING("zzz", "pfft"))) >= 0); | |
340 | assert_se(streq_ptr(error_id, VARLINK_ERROR_INVALID_PARAMETER)); | |
341 | ||
342 | assert_se(varlink_callb(v, "xyz.TestMethod", &reply, &error_id, NULL, | |
343 | JSON_BUILD_OBJECT( | |
344 | JSON_BUILD_PAIR_STRING("foo", "wuff"), | |
345 | JSON_BUILD_PAIR_UNSIGNED("bar", 9))) >= 0); | |
346 | assert_se(streq_ptr(error_id, VARLINK_ERROR_INVALID_PARAMETER)); | |
347 | ||
348 | assert_se(varlink_send(v, "xyz.Done", NULL) >= 0); | |
349 | assert_se(varlink_flush(v) >= 0); | |
350 | assert_se(pthread_join(t, NULL) == 0); | |
351 | } | |
352 | ||
353 | DEFINE_TEST_MAIN(LOG_DEBUG); |