docs: Reword virDomainGetEmulatorPinInfo description
[libvirt.git] / tests / virnetdaemontest.c
blob1a5c5f32e1f9436259db510890da74a0c35c7909
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 <unistd.h>
23 #include "testutils.h"
24 #include "virerror.h"
25 #include "rpc/virnetdaemon.h"
27 #define VIR_FROM_THIS VIR_FROM_RPC
29 #if !defined(WIN32) && defined(WITH_JSON)
30 struct testClientPriv {
31 int magic;
35 static void *
36 testClientNew(virNetServerClient *client G_GNUC_UNUSED,
37 void *opaque G_GNUC_UNUSED)
39 struct testClientPriv *priv;
41 priv = g_new0(struct testClientPriv, 1);
43 priv->magic = 1729;
45 return priv;
49 static virJSONValue *
50 testClientPreExec(virNetServerClient *client G_GNUC_UNUSED,
51 void *data)
53 struct testClientPriv *priv = data;
55 return virJSONValueNewNumberInt(priv->magic);
59 static void *
60 testClientNewPostExec(virNetServerClient *client,
61 virJSONValue *object,
62 void *opaque)
64 int magic;
66 if (virJSONValueGetNumberInt(object, &magic) < 0)
67 return NULL;
69 if (magic != 1729)
70 return NULL;
72 return testClientNew(client, opaque);
76 static void
77 testClientFree(void *opaque)
79 g_free(opaque);
83 static virNetServer *
84 testCreateServer(const char *server_name, const char *host, int family)
86 virNetServer *srv = NULL;
87 virNetServerService *svc1 = NULL;
88 virNetServerService *svc2 = NULL;
89 virNetServerClient *cln1 = NULL;
90 virNetServerClient *cln2 = NULL;
91 virNetSocket *sk1 = NULL;
92 virNetSocket *sk2 = NULL;
93 int fdclient[2];
95 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdclient) < 0) {
96 virReportSystemError(errno, "%s",
97 "Cannot create socket pair");
98 goto cleanup;
101 if (!(srv = virNetServerNew(server_name, 1,
102 10, 50, 5, 100, 10,
103 120, 5,
104 testClientNew,
105 testClientPreExec,
106 testClientFree,
107 NULL)))
108 goto error;
110 if (!(svc1 = virNetServerServiceNewTCP(host,
111 NULL,
112 family,
113 VIR_NET_SERVER_SERVICE_AUTH_NONE,
114 NULL,
115 true,
117 2)))
118 goto error;
120 if (!(svc2 = virNetServerServiceNewTCP(host,
121 NULL,
122 family,
123 VIR_NET_SERVER_SERVICE_AUTH_POLKIT,
124 NULL,
125 false,
127 5)))
128 goto error;
130 virNetServerAddService(srv, svc1);
131 virNetServerAddService(srv, svc2);
133 if (virNetSocketNewConnectSockFD(fdclient[0], &sk1) < 0)
134 goto error;
135 if (virNetSocketNewConnectSockFD(fdclient[1], &sk2) < 0)
136 goto error;
138 if (!(cln1 = virNetServerClientNew(virNetServerNextClientID(srv),
139 sk1,
140 VIR_NET_SERVER_SERVICE_AUTH_SASL,
141 true,
143 NULL,
144 testClientNew,
145 testClientPreExec,
146 testClientFree,
147 NULL)))
148 goto error;
150 if (!(cln2 = virNetServerClientNew(virNetServerNextClientID(srv),
151 sk2,
152 VIR_NET_SERVER_SERVICE_AUTH_POLKIT,
153 true,
155 NULL,
156 testClientNew,
157 testClientPreExec,
158 testClientFree,
159 NULL)))
160 goto error;
162 if (virNetServerAddClient(srv, cln1) < 0)
163 goto error;
165 if (virNetServerAddClient(srv, cln2) < 0)
166 goto error;
168 cleanup:
169 if (!srv)
170 virDispatchError(NULL);
171 virObjectUnref(cln1);
172 virObjectUnref(cln2);
173 virObjectUnref(svc1);
174 virObjectUnref(svc2);
175 virObjectUnref(sk1);
176 virObjectUnref(sk2);
177 return srv;
179 error:
180 g_clear_pointer(&srv, virObjectUnref);
181 goto cleanup;
184 static char *testGenerateJSON(const char *server_name)
186 virNetDaemon *dmn = NULL;
187 virNetServer *srv = NULL;
188 g_autoptr(virJSONValue) json = NULL;
189 char *jsonstr = NULL;
190 bool has_ipv4, has_ipv6;
192 /* Our pre-saved JSON file is created so that each service
193 * only has one socket. If we let libvirt bind to IPv4 and
194 * IPv6 we might end up with two sockets, so force one or
195 * the other based on what's available on thehost
197 if (virNetSocketCheckProtocols(&has_ipv4,
198 &has_ipv6) < 0)
199 return NULL;
201 if (!has_ipv4 && !has_ipv6)
202 return NULL;
204 if (!(srv = testCreateServer(server_name,
205 has_ipv4 ? "127.0.0.1" : "::1",
206 has_ipv4 ? AF_INET : AF_INET6)))
207 goto cleanup;
209 if (!(dmn = virNetDaemonNew()))
210 goto cleanup;
212 if (virNetDaemonAddServer(dmn, srv) < 0)
213 goto cleanup;
215 if (!(json = virNetDaemonPreExecRestart(dmn)))
216 goto cleanup;
218 if (!(jsonstr = virJSONValueToString(json, true)))
219 goto cleanup;
221 fprintf(stderr, "%s\n", jsonstr);
222 cleanup:
223 virNetServerClose(srv);
224 virObjectUnref(srv);
225 virObjectUnref(dmn);
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 virNetServer *
240 testNewServerPostExecRestart(virNetDaemon *dmn G_GNUC_UNUSED,
241 const char *name,
242 virJSONValue *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 virNetDaemon *dmn = NULL;
268 const struct testExecRestartData *data = opaque;
269 g_autofree char *infile = NULL;
270 g_autofree char *outfile = NULL;
271 g_autofree char *injsonstr = NULL;
272 g_autofree char *outjsonstr = NULL;
273 g_autoptr(virJSONValue) injson = NULL;
274 g_autoptr(virJSONValue) outjson = NULL;
275 int fdclient[2] = { -1, -1 }, fdserver[2] = { -1, -1 };
277 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdclient) < 0) {
278 virReportSystemError(errno, "%s",
279 "Cannot create socket pair");
280 goto cleanup;
283 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdserver) < 0) {
284 virReportSystemError(errno, "%s",
285 "Cannot create socket pair");
286 goto cleanup;
289 /* We're blindly assuming the test case isn't using
290 * fds 100->103 for something else, which is probably
291 * fairly reasonable in general
293 if (dup2(fdserver[0], 100) < 0 ||
294 dup2(fdserver[1], 101) < 0 ||
295 dup2(fdclient[0], 102) < 0 ||
296 dup2(fdclient[1], 103) < 0) {
297 virReportSystemError(errno, "%s", "dup2() failed");
298 goto cleanup;
301 infile = g_strdup_printf("%s/virnetdaemondata/input-data-%s.json", abs_srcdir,
302 data->jsonfile);
304 outfile = g_strdup_printf("%s/virnetdaemondata/output-data-%s.%s",
305 abs_srcdir, data->jsonfile, data->pass ? "json" : "err");
307 if (virFileReadAll(infile, 8192, &injsonstr) < 0)
308 goto cleanup;
310 if (!(injson = virJSONValueFromString(injsonstr)))
311 goto cleanup;
313 if (!(dmn = virNetDaemonNewPostExecRestart(injson,
314 data->nservers,
315 data->serverNames,
316 testNewServerPostExecRestart,
317 (void *)data)))
318 goto cleanup;
320 for (i = 0; i < data->nservers; i++) {
321 if (!virNetDaemonHasServer(dmn, data->serverNames[i])) {
322 virReportError(VIR_ERR_INTERNAL_ERROR,
323 "Server %s was not created",
324 data->serverNames[i]);
325 goto cleanup;
329 if (!(outjson = virNetDaemonPreExecRestart(dmn)))
330 goto cleanup;
332 if (!data->pass)
333 goto cleanup;
335 if (!(outjsonstr = virJSONValueToString(outjson, true)))
336 goto cleanup;
338 if (virTestCompareToFile(outjsonstr, outfile) < 0)
339 goto cleanup;
341 ret = 0;
342 cleanup:
343 if (ret < 0) {
344 if (injson && !data->pass) {
345 ret = virTestCompareToFile(virGetLastErrorMessage(), outfile);
346 if (ret < 0)
347 VIR_TEST_DEBUG("Test failed with different error message");
348 virResetLastError();
350 } else if (!data->pass) {
351 VIR_TEST_DEBUG("Test should have failed");
352 ret = -1;
354 virObjectUnref(dmn);
355 VIR_FORCE_CLOSE(fdserver[0]);
356 VIR_FORCE_CLOSE(fdserver[1]);
357 VIR_FORCE_CLOSE(fdclient[0]);
358 VIR_FORCE_CLOSE(fdclient[1]);
359 return ret;
363 static int
364 mymain(void)
366 int ret = 0;
367 const char *server_names[] = { "testServer0", "testServer1" };
369 if (virInitialize() < 0 ||
370 virEventRegisterDefaultImpl() < 0) {
371 virDispatchError(NULL);
372 return EXIT_FAILURE;
375 /* Hack to make it easier to generate new JSON files when
376 * the RPC classes change. Just set this env var, save
377 * the generated JSON, and replace the file descriptor
378 * numbers with 100, 101, 102, 103.
380 if (getenv("VIR_GENERATE_JSON")) {
381 char *json = testGenerateJSON(server_names[0]);
382 if (!json)
383 return EXIT_FAILURE;
385 fprintf(stdout, "%s\n", json);
386 VIR_FREE(json);
387 return ret;
390 # define EXEC_RESTART_TEST_FULL(file, nservers, pass) \
391 do { \
392 struct testExecRestartData data = { \
393 file, server_names, nservers, pass \
394 }; \
395 if (virTestRun("ExecRestart " file, \
396 testExecRestart, &data) < 0) \
397 ret = -1; \
398 } while (0)
400 # define EXEC_RESTART_TEST(file, N) EXEC_RESTART_TEST_FULL(file, N, true)
401 # define EXEC_RESTART_TEST_FAIL(file, N) EXEC_RESTART_TEST_FULL(file, N, false)
404 EXEC_RESTART_TEST("initial", 1);
405 EXEC_RESTART_TEST("anon-clients", 1);
406 EXEC_RESTART_TEST("admin", 2);
407 EXEC_RESTART_TEST("admin-server-names", 2);
408 EXEC_RESTART_TEST("no-keepalive-required", 2);
409 EXEC_RESTART_TEST("client-ids", 1);
410 EXEC_RESTART_TEST("client-timestamp", 1);
411 EXEC_RESTART_TEST_FAIL("anon-clients", 2);
412 EXEC_RESTART_TEST("client-auth-pending", 1);
413 EXEC_RESTART_TEST_FAIL("client-auth-pending-failure", 1);
414 EXEC_RESTART_TEST_FAIL("invalid-max-clients-failure", 1);
416 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
418 VIR_TEST_MAIN_PRELOAD(mymain, VIR_TEST_MOCK("virnetdaemon"))
419 #else
420 static int
421 mymain(void)
423 return EXIT_AM_SKIP;
425 VIR_TEST_MAIN(mymain);
426 #endif