VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTLocalIpc.cpp@ 58106

Last change on this file since 58106 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.5 KB
Line 
1/* $Id: tstRTLocalIpc.cpp 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTLocalIpc.
4 */
5
6/*
7 * Copyright (C) 2013-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/env.h>
32#include <iprt/localipc.h>
33#include <iprt/mem.h>
34#include <iprt/path.h>
35#include <iprt/process.h>
36#include <iprt/rand.h>
37#include <iprt/string.h>
38#include <iprt/test.h>
39#include <iprt/thread.h>
40#include <iprt/time.h>
41
42
43typedef struct LOCALIPCTHREADCTX
44{
45 /** The IPC server handle. */
46 RTLOCALIPCSERVER hServer;
47 /** The test handle. */
48 RTTEST hTest;
49} LOCALIPCTHREADCTX, *PLOCALIPCTHREADCTX;
50
51static int testServerListenAndCancel2(const char *pszExecPath)
52{
53 const char *apszArgs[4] = { pszExecPath, "child", "testServerListenAndCancel", NULL };
54 RTPROCESS hProc;
55 int rc = RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc);
56
57 return rc;
58}
59
60static DECLCALLBACK(int) testServerListenAndCancelThread(RTTHREAD hSelf, void *pvUser)
61{
62 PRTLOCALIPCSERVER pServer = (PRTLOCALIPCSERVER)pvUser;
63 AssertPtr(pServer);
64
65 RTThreadSleep(5000); /* Wait a bit to simulate waiting in main thread. */
66
67 int rc = RTLocalIpcServerCancel(*pServer);
68 AssertRC(rc);
69
70 return 0;
71}
72
73static int testServerListenAndCancel(RTTEST hTest, const char *pszExecPath)
74{
75 RTTestSub(hTest, "testServerListenAndCancel");
76
77 RTLOCALIPCSERVER ipcServer;
78 int rc = RTLocalIpcServerCreate(&ipcServer, "testServerListenAndCancel",
79 RTLOCALIPC_FLAGS_MULTI_SESSION);
80 if (RT_SUCCESS(rc))
81 {
82 /* Spawn a simple worker thread and let it listen for incoming connections.
83 * In the meanwhile we try to cancel the server and see what happens. */
84 RTTHREAD hThread;
85 rc = RTThreadCreate(&hThread, testServerListenAndCancelThread,
86 &ipcServer, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc1");
87 if (RT_SUCCESS(rc))
88 {
89 do
90 {
91 RTTestPrintf(hTest, RTTESTLVL_INFO, "Listening for incoming connections ...\n");
92 RTLOCALIPCSESSION ipcSession;
93 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerListen(ipcServer, &ipcSession), VERR_CANCELLED);
94 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS);
95 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS);
96
97 RTTestPrintf(hTest, RTTESTLVL_INFO, "Waiting for thread to exit ...\n");
98 RTTEST_CHECK_RC(hTest, RTThreadWait(hThread,
99 30 * 1000 /* 30s timeout */, NULL), VINF_SUCCESS);
100 } while (0);
101 }
102 else
103 RTTestIFailed("Unable to create thread for cancelling server, rc=%Rrc\n", rc);
104 }
105 else
106 RTTestIFailed("Unable to create IPC server, rc=%Rrc\n", rc);
107
108 return VINF_SUCCESS;
109}
110
111static DECLCALLBACK(int) testSessionConnectionThread(RTTHREAD hSelf, void *pvUser)
112{
113 PLOCALIPCTHREADCTX pCtx = (PLOCALIPCTHREADCTX)pvUser;
114 AssertPtr(pCtx);
115
116 int rc;
117 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Listening for incoming connections ...\n");
118 for (;;)
119 {
120 RTLOCALIPCSESSION ipcSession;
121 rc = RTLocalIpcServerListen(pCtx->hServer, &ipcSession);
122 RTTestPrintf(pCtx->hTest, RTTESTLVL_DEBUG, "testSessionConnectionThread: Listening returned with rc=%Rrc\n", rc);
123 if (RT_SUCCESS(rc))
124 {
125 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Got new client connection\n");
126 }
127 else
128 break;
129 }
130
131 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Ended with rc=%Rrc\n", rc);
132 return rc;
133}
134
135static RTEXITCODE testSessionConnectionChild(int argc, char **argv, RTTEST hTest)
136{
137 do
138 {
139 RTThreadSleep(2000); /* Fudge */
140 RTLOCALIPCSESSION clientSession;
141 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionConnect(&clientSession, "tstRTLocalIpcSessionConnection",
142 0 /* Flags */), VINF_SUCCESS);
143 RTThreadSleep(5000); /* Fudge */
144 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionClose(clientSession), VINF_SUCCESS);
145
146 } while (0);
147
148 return !RTTestErrorCount(hTest) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
149}
150
151static int testSessionConnection(RTTEST hTest, const char *pszExecPath)
152{
153 RTTestSub(hTest, "testSessionConnection");
154
155 RTLOCALIPCSERVER ipcServer;
156 int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionConnection",
157 RTLOCALIPC_FLAGS_MULTI_SESSION);
158 if (RT_SUCCESS(rc))
159 {
160#ifndef VBOX_TESTCASES_WITH_NO_THREADING
161 LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest };
162
163 /* Spawn a simple worker thread and let it listen for incoming connections.
164 * In the meanwhile we try to cancel the server and see what happens. */
165 RTTHREAD hThread;
166 rc = RTThreadCreate(&hThread, testSessionConnectionThread,
167 &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc2");
168 if (RT_SUCCESS(rc))
169 {
170 do
171 {
172 RTPROCESS hProc;
173 const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionConnectionFork", NULL };
174 RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs,
175 RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS);
176 RTPROCSTATUS stsChild;
177 RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS);
178 RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated, waiting for server thread ...\n");
179 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS);
180 int threadRc;
181 RTTEST_CHECK_RC(hTest, RTThreadWait(hThread,
182 30 * 1000 /* 30s timeout */, &threadRc), VINF_SUCCESS);
183 RTTEST_CHECK_RC_BREAK(hTest, threadRc, VERR_CANCELLED);
184 RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n");
185 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS);
186 RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL);
187 RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0);
188 }
189 while (0);
190 }
191 else
192 RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc);
193#else
194 do
195 {
196 RTPROCESS hProc;
197 const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionConnectionFork", NULL };
198 RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs,
199 RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS);
200 RTLOCALIPCSESSION ipcSession;
201 rc = RTLocalIpcServerListen(ipcServer, &ipcSession);
202 if (RT_SUCCESS(rc))
203 {
204 RTTestPrintf(hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Got new client connection\n");
205 }
206 else
207 RTTestFailed(hTest, "Error while listening, rc=%Rrc\n", rc);
208
209 } while (0);
210#endif
211 }
212 else
213 RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc);
214
215 return VINF_SUCCESS;
216}
217
218static DECLCALLBACK(int) testSessionWaitThread(RTTHREAD hSelf, void *pvUser)
219{
220 PLOCALIPCTHREADCTX pCtx = (PLOCALIPCTHREADCTX)pvUser;
221 AssertPtr(pCtx);
222
223 int rc;
224 for (;;)
225 {
226 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Listening for incoming connections ...\n");
227 RTLOCALIPCSESSION ipcSession;
228 rc = RTLocalIpcServerListen(pCtx->hServer, &ipcSession);
229 if (RT_SUCCESS(rc))
230 {
231 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Got new client connection, waiting a bit ...\n");
232 RTThreadSleep(2000);
233 rc = RTLocalIpcSessionClose(ipcSession);
234 }
235 else
236 {
237 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Listening ended with rc=%Rrc\n", rc);
238 break;
239 }
240 }
241
242 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionWaitThread: Ended with rc=%Rrc\n", rc);
243 return rc;
244}
245
246static RTEXITCODE testSessionWaitChild(int argc, char **argv, RTTEST hTest)
247{
248 do
249 {
250 RTThreadSleep(2000); /* Fudge. */
251 RTLOCALIPCSESSION clientSession;
252 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionConnect(&clientSession, "tstRTLocalIpcSessionWait",
253 0 /* Flags */), VINF_SUCCESS);
254 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, 100 /* 100ms timeout */),
255 VERR_TIMEOUT);
256 /* Next, try 60s timeout. Should be returning way earlier because the server closed the
257 * connection after the first client connected. */
258 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, 60 * 1000),
259 VERR_BROKEN_PIPE);
260 /* Last try, also should fail because the server should be not around anymore. */
261 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(clientSession, 5 * 1000),
262 VERR_BROKEN_PIPE);
263 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionClose(clientSession), VINF_SUCCESS);
264
265 } while (0);
266
267 return !RTTestErrorCount(hTest) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
268}
269
270static int testSessionWait(RTTEST hTest, const char *pszExecPath)
271{
272 RTTestSub(hTest, "testSessionWait");
273
274 RTLOCALIPCSERVER ipcServer;
275 int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionWait",
276 RTLOCALIPC_FLAGS_MULTI_SESSION);
277 if (RT_SUCCESS(rc))
278 {
279 LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest };
280
281 /* Spawn a simple worker thread and let it listen for incoming connections.
282 * In the meanwhile we try to cancel the server and see what happens. */
283 RTTHREAD hThread;
284 rc = RTThreadCreate(&hThread, testSessionWaitThread,
285 &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc3");
286 if (RT_SUCCESS(rc))
287 {
288 do
289 {
290 RTPROCESS hProc;
291 const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionWaitFork", NULL };
292 RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs,
293 RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS);
294 RTThreadSleep(5000); /* Let the server run for some time ... */
295 RTTestPrintf(hTest, RTTESTLVL_INFO, "Cancelling server listening\n");
296 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS);
297 /* Wait for the server thread to terminate. */
298 int threadRc;
299 RTTEST_CHECK_RC(hTest, RTThreadWait(hThread,
300 30 * 1000 /* 30s timeout */, &threadRc), VINF_SUCCESS);
301 RTTEST_CHECK_RC_BREAK(hTest, threadRc, VERR_CANCELLED);
302 RTTEST_CHECK_RC(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS);
303 RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n");
304 /* Check if the child ran successfully. */
305 RTPROCSTATUS stsChild;
306 RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS);
307 RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated\n");
308 RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL);
309 RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0);
310 }
311 while (0);
312 }
313 else
314 RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc);
315 }
316 else
317 RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc);
318
319 return VINF_SUCCESS;
320}
321
322/**
323 * Simple structure holding the test IPC messages.
324 */
325typedef struct LOCALIPCTESTMSG
326{
327 /** The actual message. */
328 char szOp[255];
329} LOCALIPCTESTMSG, *PLOCALIPCTESTMSG;
330
331static int testSessionDataReadTestMsg(RTTEST hTest, RTLOCALIPCSESSION hSession,
332 void *pvBuffer, size_t cbBuffer, const char *pszMsg)
333{
334 AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
335 AssertPtrReturn(pszMsg, VERR_INVALID_POINTER);
336
337 void *pvBufCur = pvBuffer;
338 size_t cbReadTotal = 0;
339 for (;;)
340 {
341 size_t cbRead = RTRandU32Ex(1, sizeof(LOCALIPCTESTMSG) - cbReadTotal); /* Force a bit of fragmentation. */
342 RTTEST_CHECK_BREAK(hTest, cbRead);
343 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionRead(hSession, pvBufCur,
344 cbBuffer,
345 &cbRead), VINF_SUCCESS);
346 RTTEST_CHECK_BREAK(hTest, cbRead);
347 pvBufCur = (uint8_t *)pvBufCur + cbRead; /* Advance. */
348 cbReadTotal += cbRead;
349 RTTEST_CHECK_BREAK(hTest, cbReadTotal <= cbBuffer);
350 if (cbReadTotal >= sizeof(LOCALIPCTESTMSG)) /* Got a complete test message? */
351 {
352 RTTEST_CHECK_BREAK(hTest, cbReadTotal == sizeof(LOCALIPCTESTMSG));
353 PLOCALIPCTESTMSG pMsg = (PLOCALIPCTESTMSG)pvBuffer;
354 RTTEST_CHECK_BREAK(hTest, pMsg != NULL);
355 RTTEST_CHECK_BREAK(hTest, !RTStrCmp(pMsg->szOp, pszMsg));
356 break;
357 }
358 /* Try receiving next part of the message in another round. */
359 }
360
361 return !RTTestErrorCount(hTest) ? VINF_SUCCESS : VERR_GENERAL_FAILURE /* Doesn't matter */;
362}
363
364static int testSessionDataThreadWorker(PLOCALIPCTHREADCTX pCtx)
365{
366 AssertPtr(pCtx);
367
368 size_t cbScratchBuf = _1K; /** @todo Make this random in future. */
369 uint8_t *pvScratchBuf = (uint8_t*)RTMemAlloc(cbScratchBuf);
370 RTTEST_CHECK_RET(pCtx->hTest, pvScratchBuf != NULL, VERR_NO_MEMORY);
371
372 do
373 {
374 /* Note: At the moment we only support one client per run. */
375 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Listening for incoming connections ...\n");
376 RTLOCALIPCSESSION hSession;
377 RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcServerListen(pCtx->hServer, &hSession), VINF_SUCCESS);
378 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Got new client connection\n");
379 uint32_t cRounds = 256; /** @todo Use RTRand(). */
380 /* Write how many rounds we're going to send data. */
381 RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcSessionWrite(hSession, &cRounds, sizeof(cRounds)), VINF_SUCCESS);
382 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Written number of rounds\n");
383 for (uint32_t i = 0; i < cRounds; i++)
384 {
385 LOCALIPCTESTMSG msg;
386 RTTEST_CHECK_BREAK(pCtx->hTest, RTStrPrintf(msg.szOp, sizeof(msg.szOp),
387 "YayIGotRound%RU32FromTheServer", i) > 0);
388 RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcSessionWrite(hSession, &msg, sizeof(msg)), VINF_SUCCESS);
389 }
390 if (!RTTestErrorCount(pCtx->hTest))
391 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Data successfully written\n");
392 /* Try to receive the same amount of rounds from the client. */
393 for (uint32_t i = 0; i < cRounds; i++)
394 {
395 RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcSessionWaitForData(hSession, RT_INDEFINITE_WAIT),
396 VINF_SUCCESS);
397 char szMsg[32];
398 RTTEST_CHECK_BREAK(pCtx->hTest, RTStrPrintf(szMsg, sizeof(szMsg), "YayIGotRound%RU32FromTheClient", i) > 0);
399 RTTEST_CHECK_RC_BREAK(pCtx->hTest, testSessionDataReadTestMsg(pCtx->hTest, hSession,
400 pvScratchBuf, cbScratchBuf,
401 szMsg), VINF_SUCCESS);
402 if (RTTestErrorCount(pCtx->hTest))
403 break;
404 }
405 if (!RTTestErrorCount(pCtx->hTest))
406 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionDataThread: Data successfully read\n");
407 RTTEST_CHECK_RC_BREAK(pCtx->hTest, RTLocalIpcSessionClose(hSession), VINF_SUCCESS);
408
409 } while (0);
410
411 RTMemFree(pvScratchBuf);
412 return !RTTestErrorCount(pCtx->hTest) ? VINF_SUCCESS : VERR_GENERAL_FAILURE /* Doesn't matter */;
413}
414
415static DECLCALLBACK(int) testSessionDataThread(RTTHREAD hSelf, void *pvUser)
416{
417 PLOCALIPCTHREADCTX pCtx = (PLOCALIPCTHREADCTX)pvUser;
418 AssertPtr(pCtx);
419
420 return testSessionDataThreadWorker(pCtx);
421}
422
423static int testSessionDataChildWorker(RTTEST hTest)
424{
425 size_t cbScratchBuf = _1K; /** @todo Make this random in future. */
426 uint8_t *pvScratchBuf = (uint8_t*)RTMemAlloc(cbScratchBuf);
427 RTTEST_CHECK_RET(hTest, pvScratchBuf != NULL, RTEXITCODE_FAILURE);
428
429 do
430 {
431 RTThreadSleep(2000); /* Fudge. */
432 RTLOCALIPCSESSION hSession;
433 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionConnect(&hSession, "tstRTLocalIpcSessionData",
434 0 /* Flags */), VINF_SUCCESS);
435 /* Get number of rounds we want to read/write. */
436 uint32_t cRounds = 0;
437 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(hSession, RT_INDEFINITE_WAIT),
438 VINF_SUCCESS);
439 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionRead(hSession, &cRounds, sizeof(cRounds),
440 NULL /* Get exactly sizeof(cRounds) bytes */), VINF_SUCCESS);
441 RTTEST_CHECK_BREAK(hTest, cRounds == 256); /** @todo Check for != 0 when using RTRand(). */
442 /* Receive all rounds. */
443 for (uint32_t i = 0; i < cRounds; i++)
444 {
445 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWaitForData(hSession, RT_INDEFINITE_WAIT),
446 VINF_SUCCESS);
447 char szMsg[32];
448 RTTEST_CHECK_BREAK(hTest, RTStrPrintf(szMsg, sizeof(szMsg), "YayIGotRound%RU32FromTheServer", i) > 0);
449 RTTEST_CHECK_RC_BREAK(hTest, testSessionDataReadTestMsg(hTest, hSession,
450 pvScratchBuf, cbScratchBuf,
451 szMsg), VINF_SUCCESS);
452 if (RTTestErrorCount(hTest))
453 break;
454 }
455 /* Send all rounds back to the server. */
456 for (uint32_t i = 0; i < cRounds; i++)
457 {
458 LOCALIPCTESTMSG msg;
459 RTTEST_CHECK_BREAK(hTest, RTStrPrintf(msg.szOp, sizeof(msg.szOp),
460 "YayIGotRound%RU32FromTheClient", i) > 0);
461 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionWrite(hSession, &msg, sizeof(msg)), VINF_SUCCESS);
462 }
463 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcSessionClose(hSession), VINF_SUCCESS);
464
465 } while (0);
466
467 RTMemFree(pvScratchBuf);
468 return !RTTestErrorCount(hTest) ? VINF_SUCCESS : VERR_GENERAL_FAILURE /* Doesn't matter */;
469}
470
471static DECLCALLBACK(int) testSessionDataChildAsThread(RTTHREAD hSelf, void *pvUser)
472{
473 PRTTEST phTest = (PRTTEST)pvUser;
474 AssertPtr(phTest);
475 return testSessionDataChildWorker(*phTest);
476}
477
478static RTEXITCODE testSessionDataChild(int argc, char **argv, RTTEST hTest)
479{
480 return RT_SUCCESS(testSessionDataChildWorker(hTest)) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
481}
482
483static int testSessionData(RTTEST hTest, const char *pszExecPath)
484{
485 RTTestSub(hTest, "testSessionData");
486
487 RTLOCALIPCSERVER ipcServer;
488 int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionData",
489 RTLOCALIPC_FLAGS_MULTI_SESSION);
490 if (RT_SUCCESS(rc))
491 {
492 LOCALIPCTHREADCTX threadCtx = { ipcServer, hTest };
493#if 0
494 /* Run server + client in threads instead of fork'ed processes (useful for debugging). */
495 RTTHREAD hThreadServer, hThreadClient;
496 rc = RTThreadCreate(&hThreadServer, testSessionDataThread,
497 &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc4");
498 if (RT_SUCCESS(rc))
499 rc = RTThreadCreate(&hThreadClient, testSessionDataChildAsThread,
500 &hTest, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc5");
501 if (RT_SUCCESS(rc))
502 {
503 do
504 {
505 int threadRc;
506 RTTEST_CHECK_RC(hTest, RTThreadWait(hThreadServer,
507 5 * 60 * 1000 /* 5 minutes timeout */, &threadRc), VINF_SUCCESS);
508 RTTEST_CHECK_RC_BREAK(hTest, threadRc, VINF_SUCCESS);
509 RTTEST_CHECK_RC(hTest, RTThreadWait(hThreadClient,
510 5 * 60 * 1000 /* 5 minutes timeout */, &threadRc), VINF_SUCCESS);
511 RTTEST_CHECK_RC_BREAK(hTest, threadRc, VINF_SUCCESS);
512
513 } while (0);
514 }
515#else
516 /* Spawn a simple worker thread and let it listen for incoming connections.
517 * In the meanwhile we try to cancel the server and see what happens. */
518 RTTHREAD hThread;
519 rc = RTThreadCreate(&hThread, testSessionDataThread,
520 &threadCtx, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc4");
521 if (RT_SUCCESS(rc))
522 {
523 do
524 {
525 RTPROCESS hProc;
526 const char *apszArgs[4] = { pszExecPath, "child", "tstRTLocalIpcSessionDataFork", NULL };
527 RTTEST_CHECK_RC_BREAK(hTest, RTProcCreate(pszExecPath, apszArgs,
528 RTENV_DEFAULT, 0 /* fFlags*/, &hProc), VINF_SUCCESS);
529 /* Wait for the server thread to terminate. */
530 int threadRc;
531 RTTEST_CHECK_RC(hTest, RTThreadWait(hThread,
532 5 * 60 * 1000 /* 5 minutes timeout */, &threadRc), VINF_SUCCESS);
533 RTTEST_CHECK_RC_BREAK(hTest, threadRc, VINF_SUCCESS);
534 RTTEST_CHECK_RC(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS);
535 RTTestPrintf(hTest, RTTESTLVL_INFO, "Server thread terminated successfully\n");
536 /* Check if the child ran successfully. */
537 RTPROCSTATUS stsChild;
538 RTTEST_CHECK_RC_BREAK(hTest, RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &stsChild), VINF_SUCCESS);
539 RTTestPrintf(hTest, RTTESTLVL_INFO, "Child terminated\n");
540 RTTEST_CHECK_BREAK(hTest, stsChild.enmReason == RTPROCEXITREASON_NORMAL);
541 RTTEST_CHECK_BREAK(hTest, stsChild.iStatus == 0);
542 }
543 while (0);
544 }
545 else
546 RTTestFailed(hTest, "Unable to create thread for cancelling server, rc=%Rrc\n", rc);
547#endif
548 }
549 else
550 RTTestFailed(hTest, "Unable to create IPC server, rc=%Rrc\n", rc);
551
552 return !RTTestErrorCount(hTest) ? VINF_SUCCESS : VERR_GENERAL_FAILURE /* Doesn't matter */;
553}
554
555static RTEXITCODE mainChild(int argc, char **argv)
556{
557 if (argc < 3) /* Safety first. */
558 return RTEXITCODE_FAILURE;
559 /* Note: We assume argv[2] always contains the actual test type to perform. */
560 RTTEST hTest;
561 RTEXITCODE rcExit = RTTestInitAndCreate(argv[2], &hTest);
562 if (rcExit)
563 return rcExit;
564 RTTestBanner(hTest);
565
566 RTAssertSetMayPanic(false);
567#ifdef DEBUG_andy
568 RTAssertSetQuiet(false);
569#endif
570
571 if (!RTStrICmp(argv[2], "tstRTLocalIpcSessionConnectionFork"))
572 rcExit = testSessionConnectionChild(argc, argv, hTest);
573 else if (!RTStrICmp(argv[2], "tstRTLocalIpcSessionWaitFork"))
574 rcExit = testSessionWaitChild(argc, argv, hTest);
575 else if (!RTStrICmp(argv[2], "tstRTLocalIpcSessionDataFork"))
576 rcExit = testSessionDataChild(argc, argv, hTest);
577
578 return RTTestSummaryAndDestroy(hTest);
579}
580
581int main(int argc, char **argv)
582{
583 if ( argc > 2
584 && !RTStrICmp(argv[1], "child"))
585 return mainChild(argc, argv);
586
587 RTTEST hTest;
588 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTLocalIpc", &hTest);
589 if (rcExit)
590 return rcExit;
591 RTTestBanner(hTest);
592
593 char szExecPath[RTPATH_MAX];
594 if (!RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))
595 RTStrCopy(szExecPath, sizeof(szExecPath), argv[0]);
596
597 RTTestISub("Basics");
598
599 RTAssertSetMayPanic(false);
600#ifdef DEBUG_andy
601 RTAssertSetQuiet(false);
602#endif
603
604 /* Server-side. */
605 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(NULL, NULL, 0), VERR_INVALID_POINTER, 1);
606 RTLOCALIPCSERVER ipcServer;
607 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, NULL, 0), VERR_INVALID_POINTER, 1);
608 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "", 0), VERR_INVALID_PARAMETER, 1);
609 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", 0 /* Invalid flags */), VERR_INVALID_PARAMETER, 1);
610 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", 1234 /* Invalid flags */), VERR_INVALID_PARAMETER, 1);
611 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(NULL), VERR_INVALID_HANDLE, 1);
612 RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(NULL), VINF_SUCCESS, 1);
613 /* Basic server creation / destruction. */
614 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", RTLOCALIPC_FLAGS_MULTI_SESSION), VINF_SUCCESS, 1);
615 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS, 1);
616 RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS, 1);
617
618 /* Client-side (per session). */
619 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(NULL, NULL, 0), VERR_INVALID_POINTER, 1);
620 RTLOCALIPCSESSION ipcSession;
621 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, NULL, 0), VERR_INVALID_POINTER, 1);
622 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "", 0), VERR_INVALID_PARAMETER, 1);
623 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "BasicTest", 1234 /* Invalid flags */), VERR_INVALID_PARAMETER, 1);
624 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionCancel(NULL), VERR_INVALID_HANDLE, 1);
625 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionClose(NULL), VINF_SUCCESS, 1);
626 /* Basic client creation / destruction. */
627 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "BasicTest", 0), VERR_FILE_NOT_FOUND, 1);
628 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(ipcServer), VERR_INVALID_MAGIC, 1);
629 RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(ipcServer), VERR_INVALID_MAGIC, 1);
630
631 if (RTTestErrorCount(hTest) == 0)
632 {
633 RTTESTI_CHECK_RC_RET(testServerListenAndCancel(hTest, szExecPath), VINF_SUCCESS, 1);
634 RTTESTI_CHECK_RC_RET(testSessionConnection(hTest, szExecPath), VINF_SUCCESS, 1);
635 RTTESTI_CHECK_RC_RET(testSessionWait(hTest, szExecPath), VINF_SUCCESS, 1);
636 RTTESTI_CHECK_RC_RET(testSessionData(hTest, szExecPath), VINF_SUCCESS, 1);
637 }
638
639 /*
640 * Summary.
641 */
642 return RTTestSummaryAndDestroy(hTest);
643}
644
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette