backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / virnetdaemontest.c
blob816bfe05d409cc531f7851d6232cdaece5dfc924
1 /*
2 * Copyright (C) 2015 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
19 #include <config.h>
21 #include "testutils.h"
22 #include "virerror.h"
23 #include "rpc/virnetdaemon.h"
25 #define VIR_FROM_THIS VIR_FROM_RPC
27 #if defined(HAVE_SOCKETPAIR) && defined(WITH_YAJL)
28 struct testClientPriv {
29 int magic;
33 static void *
34 testClientNew(virNetServerClientPtr client ATTRIBUTE_UNUSED,
35 void *opaque ATTRIBUTE_UNUSED)
37 struct testClientPriv *priv;
39 if (VIR_ALLOC(priv) < 0)
40 return NULL;
42 priv->magic = 1729;
44 return priv;
48 static virJSONValuePtr
49 testClientPreExec(virNetServerClientPtr client ATTRIBUTE_UNUSED,
50 void *data)
52 struct testClientPriv *priv = data;
54 return virJSONValueNewNumberInt(priv->magic);
58 static void *
59 testClientNewPostExec(virNetServerClientPtr client,
60 virJSONValuePtr object,
61 void *opaque)
63 int magic;
65 if (virJSONValueGetNumberInt(object, &magic) < 0)
66 return NULL;
68 if (magic != 1729)
69 return NULL;
71 return testClientNew(client, opaque);
75 static void
76 testClientFree(void *opaque)
78 VIR_FREE(opaque);
82 static virNetServerPtr
83 testCreateServer(const char *server_name, const char *host, int family)
85 virNetServerPtr srv = NULL;
86 virNetServerServicePtr svc1 = NULL, svc2 = NULL;
87 virNetServerClientPtr cln1 = NULL, cln2 = NULL;
88 virNetSocketPtr sk1 = NULL, sk2 = NULL;
89 int fdclient[2];
91 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdclient) < 0) {
92 virReportSystemError(errno, "%s",
93 "Cannot create socket pair");
94 goto cleanup;
97 if (!(srv = virNetServerNew(server_name, 1,
98 10, 50, 5, 100, 10,
99 120, 5,
100 testClientNew,
101 testClientPreExec,
102 testClientFree,
103 NULL)))
104 goto error;
106 if (!(svc1 = virNetServerServiceNewTCP(host,
107 NULL,
108 family,
109 VIR_NET_SERVER_SERVICE_AUTH_NONE,
110 NULL,
111 true,
113 2)))
114 goto error;
116 if (!(svc2 = virNetServerServiceNewTCP(host,
117 NULL,
118 family,
119 VIR_NET_SERVER_SERVICE_AUTH_POLKIT,
120 NULL,
121 false,
123 5)))
124 goto error;
126 if (virNetServerAddService(srv, svc1) < 0)
127 goto error;
128 if (virNetServerAddService(srv, svc2) < 0)
129 goto error;
131 if (virNetSocketNewConnectSockFD(fdclient[0], &sk1) < 0)
132 goto error;
133 if (virNetSocketNewConnectSockFD(fdclient[1], &sk2) < 0)
134 goto error;
136 if (!(cln1 = virNetServerClientNew(virNetServerNextClientID(srv),
137 sk1,
138 VIR_NET_SERVER_SERVICE_AUTH_SASL,
139 true,
141 NULL,
142 testClientNew,
143 testClientPreExec,
144 testClientFree,
145 NULL)))
146 goto error;
148 if (!(cln2 = virNetServerClientNew(virNetServerNextClientID(srv),
149 sk2,
150 VIR_NET_SERVER_SERVICE_AUTH_POLKIT,
151 true,
153 NULL,
154 testClientNew,
155 testClientPreExec,
156 testClientFree,
157 NULL)))
158 goto error;
160 if (virNetServerAddClient(srv, cln1) < 0)
161 goto error;
163 if (virNetServerAddClient(srv, cln2) < 0)
164 goto error;
166 cleanup:
167 if (!srv)
168 virDispatchError(NULL);
169 virObjectUnref(cln1);
170 virObjectUnref(cln2);
171 virObjectUnref(svc1);
172 virObjectUnref(svc2);
173 virObjectUnref(sk1);
174 virObjectUnref(sk2);
175 return srv;
177 error:
178 virObjectUnref(srv);
179 srv = NULL;
180 goto cleanup;
183 static char *testGenerateJSON(const char *server_name)
185 virNetDaemonPtr dmn = NULL;
186 virNetServerPtr srv = NULL;
187 virJSONValuePtr json = NULL;
188 char *jsonstr = NULL;
189 bool has_ipv4, has_ipv6;
191 /* Our pre-saved JSON file is created so that each service
192 * only has one socket. If we let libvirt bind to IPv4 and
193 * IPv6 we might end up with two sockets, so force one or
194 * the other based on what's available on thehost
196 if (virNetSocketCheckProtocols(&has_ipv4,
197 &has_ipv6) < 0)
198 return NULL;
200 if (!has_ipv4 && !has_ipv6)
201 return NULL;
203 if (!(srv = testCreateServer(server_name,
204 has_ipv4 ? "127.0.0.1" : "::1",
205 has_ipv4 ? AF_INET : AF_INET6)))
206 goto cleanup;
208 if (!(dmn = virNetDaemonNew()))
209 goto cleanup;
211 if (virNetDaemonAddServer(dmn, srv) < 0)
212 goto cleanup;
214 if (!(json = virNetDaemonPreExecRestart(dmn)))
215 goto cleanup;
217 if (!(jsonstr = virJSONValueToString(json, true)))
218 goto cleanup;
220 fprintf(stderr, "%s\n", jsonstr);
221 cleanup:
222 virNetServerClose(srv);
223 virObjectUnref(srv);
224 virObjectUnref(dmn);
225 virJSONValueFree(json);
226 if (!jsonstr)
227 virDispatchError(NULL);
228 return jsonstr;
232 struct testExecRestartData {
233 const char *jsonfile;
234 const char **serverNames;
235 int nservers;
236 bool pass;
239 static virNetServerPtr
240 testNewServerPostExecRestart(virNetDaemonPtr dmn ATTRIBUTE_UNUSED,
241 const char *name,
242 virJSONValuePtr object,
243 void *opaque)
245 struct testExecRestartData *data = opaque;
246 size_t i;
247 for (i = 0; i < data->nservers; i++) {
248 if (STREQ(data->serverNames[i], name)) {
249 return virNetServerNewPostExecRestart(object,
250 name,
251 testClientNew,
252 testClientNewPostExec,
253 testClientPreExec,
254 testClientFree,
255 NULL);
259 virReportError(VIR_ERR_INTERNAL_ERROR, "Unexpected server name '%s'", name);
260 return NULL;
263 static int testExecRestart(const void *opaque)
265 size_t i;
266 int ret = -1;
267 virNetDaemonPtr dmn = NULL;
268 const struct testExecRestartData *data = opaque;
269 char *infile = NULL, *outfile = NULL;
270 char *injsonstr = NULL, *outjsonstr = NULL;
271 virJSONValuePtr injson = NULL, outjson = NULL;
272 int fdclient[2] = { -1, -1 }, fdserver[2] = { -1, -1 };
274 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdclient) < 0) {
275 virReportSystemError(errno, "%s",
276 "Cannot create socket pair");
277 goto cleanup;
280 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdserver) < 0) {
281 virReportSystemError(errno, "%s",
282 "Cannot create socket pair");
283 goto cleanup;
286 /* We're blindly assuming the test case isn't using
287 * fds 100->103 for something else, which is probably
288 * fairly reasonable in general
290 if (dup2(fdserver[0], 100) < 0 ||
291 dup2(fdserver[1], 101) < 0 ||
292 dup2(fdclient[0], 102) < 0 ||
293 dup2(fdclient[1], 103) < 0) {
294 virReportSystemError(errno, "%s", "dup2() failed");
295 goto cleanup;
298 if (virAsprintf(&infile, "%s/virnetdaemondata/input-data-%s.json",
299 abs_srcdir, data->jsonfile) < 0)
300 goto cleanup;
302 if (virAsprintf(&outfile, "%s/virnetdaemondata/output-data-%s.json",
303 abs_srcdir, data->jsonfile) < 0)
304 goto cleanup;
306 if (virFileReadAll(infile, 8192, &injsonstr) < 0)
307 goto cleanup;
309 if (!(injson = virJSONValueFromString(injsonstr)))
310 goto cleanup;
312 if (!(dmn = virNetDaemonNewPostExecRestart(injson,
313 data->nservers,
314 data->serverNames,
315 testNewServerPostExecRestart,
316 (void *)data)))
317 goto cleanup;
319 for (i = 0; i < data->nservers; i++) {
320 if (!virNetDaemonHasServer(dmn, data->serverNames[i])) {
321 virReportError(VIR_ERR_INTERNAL_ERROR,
322 "Server %s was not created",
323 data->serverNames[i]);
324 goto cleanup;
328 if (!(outjson = virNetDaemonPreExecRestart(dmn)))
329 goto cleanup;
331 if (!(outjsonstr = virJSONValueToString(outjson, true)))
332 goto cleanup;
334 if (virTestCompareToFile(outjsonstr, outfile) < 0)
335 goto cleanup;
337 ret = 0;
338 cleanup:
339 if (ret < 0) {
340 if (!data->pass) {
341 VIR_TEST_DEBUG("Got expected error: %s\n",
342 virGetLastErrorMessage());
343 virResetLastError();
344 ret = 0;
346 } else if (!data->pass) {
347 VIR_TEST_DEBUG("Test should have failed\n");
348 ret = -1;
350 VIR_FREE(infile);
351 VIR_FREE(outfile);
352 VIR_FREE(injsonstr);
353 VIR_FREE(outjsonstr);
354 virJSONValueFree(injson);
355 virJSONValueFree(outjson);
356 virObjectUnref(dmn);
357 VIR_FORCE_CLOSE(fdserver[0]);
358 VIR_FORCE_CLOSE(fdserver[1]);
359 VIR_FORCE_CLOSE(fdclient[0]);
360 VIR_FORCE_CLOSE(fdclient[1]);
361 return ret;
365 static int
366 mymain(void)
368 int ret = 0;
369 const char *server_names[] = { "testServer0", "testServer1" };
371 if (virInitialize() < 0 ||
372 virEventRegisterDefaultImpl() < 0) {
373 virDispatchError(NULL);
374 return EXIT_FAILURE;
377 /* Hack to make it easier to generate new JSON files when
378 * the RPC classes change. Just set this env var, save
379 * the generated JSON, and replace the file descriptor
380 * numbers with 100, 101, 102, 103.
382 if (getenv("VIR_GENERATE_JSON")) {
383 char *json = testGenerateJSON(server_names[0]);
384 if (!json)
385 return EXIT_FAILURE;
387 fprintf(stdout, "%s\n", json);
388 VIR_FREE(json);
389 return ret;
392 # define EXEC_RESTART_TEST_FULL(file, nservers, pass) \
393 do { \
394 struct testExecRestartData data = { \
395 file, server_names, nservers, pass \
396 }; \
397 if (virTestRun("ExecRestart " file, \
398 testExecRestart, &data) < 0) \
399 ret = -1; \
400 } while (0)
402 # define EXEC_RESTART_TEST(file, N) EXEC_RESTART_TEST_FULL(file, N, true)
403 # define EXEC_RESTART_TEST_FAIL(file, N) EXEC_RESTART_TEST_FULL(file, N, false)
406 EXEC_RESTART_TEST("initial", 1);
407 EXEC_RESTART_TEST("anon-clients", 1);
408 EXEC_RESTART_TEST("admin", 2);
409 EXEC_RESTART_TEST("admin-server-names", 2);
410 EXEC_RESTART_TEST("no-keepalive-required", 2);
411 EXEC_RESTART_TEST("client-ids", 1);
412 EXEC_RESTART_TEST("client-timestamp", 1);
413 EXEC_RESTART_TEST_FAIL("anon-clients", 2);
414 EXEC_RESTART_TEST("client-auth-pending", 1);
415 EXEC_RESTART_TEST_FAIL("client-auth-pending-failure", 1);
417 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
419 VIR_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virnetdaemonmock.so")
420 #else
421 static int
422 mymain(void)
424 return EXIT_AM_SKIP;
426 VIR_TEST_MAIN(mymain);
427 #endif