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/>.
21 #include "testutils.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
{
34 testClientNew(virNetServerClientPtr client ATTRIBUTE_UNUSED
,
35 void *opaque ATTRIBUTE_UNUSED
)
37 struct testClientPriv
*priv
;
39 if (VIR_ALLOC(priv
) < 0)
48 static virJSONValuePtr
49 testClientPreExec(virNetServerClientPtr client ATTRIBUTE_UNUSED
,
52 struct testClientPriv
*priv
= data
;
54 return virJSONValueNewNumberInt(priv
->magic
);
59 testClientNewPostExec(virNetServerClientPtr client
,
60 virJSONValuePtr object
,
65 if (virJSONValueGetNumberInt(object
, &magic
) < 0)
71 return testClientNew(client
, opaque
);
76 testClientFree(void *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
;
91 if (socketpair(PF_UNIX
, SOCK_STREAM
, 0, fdclient
) < 0) {
92 virReportSystemError(errno
, "%s",
93 "Cannot create socket pair");
97 if (!(srv
= virNetServerNew(server_name
, 1,
106 if (!(svc1
= virNetServerServiceNewTCP(host
,
109 VIR_NET_SERVER_SERVICE_AUTH_NONE
,
116 if (!(svc2
= virNetServerServiceNewTCP(host
,
119 VIR_NET_SERVER_SERVICE_AUTH_POLKIT
,
126 if (virNetServerAddService(srv
, svc1
) < 0)
128 if (virNetServerAddService(srv
, svc2
) < 0)
131 if (virNetSocketNewConnectSockFD(fdclient
[0], &sk1
) < 0)
133 if (virNetSocketNewConnectSockFD(fdclient
[1], &sk2
) < 0)
136 if (!(cln1
= virNetServerClientNew(virNetServerNextClientID(srv
),
138 VIR_NET_SERVER_SERVICE_AUTH_SASL
,
148 if (!(cln2
= virNetServerClientNew(virNetServerNextClientID(srv
),
150 VIR_NET_SERVER_SERVICE_AUTH_POLKIT
,
160 if (virNetServerAddClient(srv
, cln1
) < 0)
163 if (virNetServerAddClient(srv
, cln2
) < 0)
168 virDispatchError(NULL
);
169 virObjectUnref(cln1
);
170 virObjectUnref(cln2
);
171 virObjectUnref(svc1
);
172 virObjectUnref(svc2
);
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
,
200 if (!has_ipv4
&& !has_ipv6
)
203 if (!(srv
= testCreateServer(server_name
,
204 has_ipv4
? "127.0.0.1" : "::1",
205 has_ipv4
? AF_INET
: AF_INET6
)))
208 if (!(dmn
= virNetDaemonNew()))
211 if (virNetDaemonAddServer(dmn
, srv
) < 0)
214 if (!(json
= virNetDaemonPreExecRestart(dmn
)))
217 if (!(jsonstr
= virJSONValueToString(json
, true)))
220 fprintf(stderr
, "%s\n", jsonstr
);
222 virNetServerClose(srv
);
225 virJSONValueFree(json
);
227 virDispatchError(NULL
);
232 struct testExecRestartData
{
233 const char *jsonfile
;
234 const char **serverNames
;
239 static virNetServerPtr
240 testNewServerPostExecRestart(virNetDaemonPtr dmn ATTRIBUTE_UNUSED
,
242 virJSONValuePtr object
,
245 struct testExecRestartData
*data
= opaque
;
247 for (i
= 0; i
< data
->nservers
; i
++) {
248 if (STREQ(data
->serverNames
[i
], name
)) {
249 return virNetServerNewPostExecRestart(object
,
252 testClientNewPostExec
,
259 virReportError(VIR_ERR_INTERNAL_ERROR
, "Unexpected server name '%s'", name
);
263 static int testExecRestart(const void *opaque
)
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");
280 if (socketpair(PF_UNIX
, SOCK_STREAM
, 0, fdserver
) < 0) {
281 virReportSystemError(errno
, "%s",
282 "Cannot create socket pair");
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");
298 if (virAsprintf(&infile
, "%s/virnetdaemondata/input-data-%s.json",
299 abs_srcdir
, data
->jsonfile
) < 0)
302 if (virAsprintf(&outfile
, "%s/virnetdaemondata/output-data-%s.json",
303 abs_srcdir
, data
->jsonfile
) < 0)
306 if (virFileReadAll(infile
, 8192, &injsonstr
) < 0)
309 if (!(injson
= virJSONValueFromString(injsonstr
)))
312 if (!(dmn
= virNetDaemonNewPostExecRestart(injson
,
315 testNewServerPostExecRestart
,
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
]);
328 if (!(outjson
= virNetDaemonPreExecRestart(dmn
)))
331 if (!(outjsonstr
= virJSONValueToString(outjson
, true)))
334 if (virTestCompareToFile(outjsonstr
, outfile
) < 0)
341 VIR_TEST_DEBUG("Got expected error: %s\n",
342 virGetLastErrorMessage());
346 } else if (!data
->pass
) {
347 VIR_TEST_DEBUG("Test should have failed\n");
353 VIR_FREE(outjsonstr
);
354 virJSONValueFree(injson
);
355 virJSONValueFree(outjson
);
357 VIR_FORCE_CLOSE(fdserver
[0]);
358 VIR_FORCE_CLOSE(fdserver
[1]);
359 VIR_FORCE_CLOSE(fdclient
[0]);
360 VIR_FORCE_CLOSE(fdclient
[1]);
369 const char *server_names
[] = { "testServer0", "testServer1" };
371 if (virInitialize() < 0 ||
372 virEventRegisterDefaultImpl() < 0) {
373 virDispatchError(NULL
);
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]);
387 fprintf(stdout
, "%s\n", json
);
392 # define EXEC_RESTART_TEST_FULL(file, nservers, pass) \
394 struct testExecRestartData data = { \
395 file, server_names, nservers, pass \
397 if (virTestRun("ExecRestart " file, \
398 testExecRestart, &data) < 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")
426 VIR_TEST_MAIN(mymain
);