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