VirtualBox

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

Last change on this file since 47084 was 47084, checked in by vboxsync, 12 years ago

SVN props.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.8 KB
Line 
1/* $Id: tstRTLocalIpc.cpp 47084 2013-07-10 15:39:44Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTLocalIpc.
4 */
5
6/*
7 * Copyright (C) 2013 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/path.h>
34#include <iprt/process.h>
35#include <iprt/string.h>
36#include <iprt/test.h>
37#include <iprt/thread.h>
38#include <iprt/time.h>
39
40
41typedef struct LOCALIPCTHREADCTX
42{
43 /** The IPC server handle. */
44 RTLOCALIPCSERVER hServer;
45 /** The test handle. */
46 RTTEST hTest;
47} LOCALIPCTHREADCTX, *PLOCALIPCTHREADCTX;
48
49static int testServerListenAndCancel2(const char *pszExecPath)
50{
51 const char *apszArgs[4] = { pszExecPath, "child", "testServerListenAndCancel", NULL };
52 RTPROCESS hProc;
53 int rc = RTProcCreate(pszExecPath, apszArgs, RTENV_DEFAULT, 0 /* fFlags*/, &hProc);
54
55 return rc;
56}
57
58static DECLCALLBACK(int) testServerListenAndCancelThread(RTTHREAD hSelf, void *pvUser)
59{
60 PRTLOCALIPCSERVER pServer = (PRTLOCALIPCSERVER)pvUser;
61 AssertPtr(pServer);
62
63 RTThreadSleep(5000); /* Wait a bit to simulate waiting in main thread. */
64
65 int rc = RTLocalIpcServerCancel(*pServer);
66 AssertRC(rc);
67
68 return 0;
69}
70
71static int testServerListenAndCancel(RTTEST hTest, const char *pszExecPath)
72{
73 RTTestISub("testServerListenAndCancel");
74
75 RTLOCALIPCSERVER ipcServer;
76 int rc = RTLocalIpcServerCreate(&ipcServer, "testServerListenAndCancel",
77 RTLOCALIPC_FLAGS_MULTI_SESSION);
78 if (RT_SUCCESS(rc))
79 {
80 /* Spawn a simple worker thread and let it listen for incoming connections.
81 * In the meanwhile we try to cancel the server and see what happens. */
82 RTTHREAD hThread;
83 rc = RTThreadCreate(&hThread, testServerListenAndCancelThread,
84 &ipcServer, 0 /* Stack */, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tstIpc1");
85 if (RT_SUCCESS(rc))
86 {
87 do
88 {
89 RTTestPrintf(hTest, RTTESTLVL_INFO, "Listening for incoming connections ...\n");
90 RTLOCALIPCSESSION ipcSession;
91 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerListen(ipcServer, &ipcSession), VERR_CANCELLED);
92 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS);
93 RTTEST_CHECK_RC_BREAK(hTest, RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS);
94
95 RTTestPrintf(hTest, RTTESTLVL_INFO, "Waiting for thread to exit ...\n");
96 RTTEST_CHECK_RC(hTest, RTThreadWait(hThread,
97 30 * 1000 /* 30s timeout */, NULL), VINF_SUCCESS);
98 } while (0);
99 }
100 else
101 RTTestIFailed("Unable to create thread for cancelling server, rc=%Rrc\n", rc);
102 }
103 else
104 RTTestIFailed("Unable to create IPC server, rc=%Rrc\n", rc);
105
106 return VINF_SUCCESS;
107}
108
109static DECLCALLBACK(int) testSessionConnectionThread(RTTHREAD hSelf, void *pvUser)
110{
111 PLOCALIPCTHREADCTX pCtx = (PLOCALIPCTHREADCTX)pvUser;
112 AssertPtr(pCtx);
113
114 int rc;
115 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Listening for incoming connections ...\n");
116 for (;;)
117 {
118 RTLOCALIPCSESSION ipcSession;
119 rc = RTLocalIpcServerListen(pCtx->hServer, &ipcSession);
120#ifdef DEBUG_andy
121 RTTestPrintf(pCtx->hTest, RTTESTLVL_INFO, "testSessionConnectionThread: Listening returned with rc=%Rrc\n", rc);
122#endif
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 RTTestISub("testSessionConnection");
154
155 RTLOCALIPCSERVER ipcServer;
156 int rc = RTLocalIpcServerCreate(&ipcServer, "tstRTLocalIpcSessionConnection",
157 RTLOCALIPC_FLAGS_MULTI_SESSION);
158 if (RT_SUCCESS(rc))
159 {
160#if 0
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, VINF_SUCCESS);
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 RTTestIFailed("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 RTTestIFailed("Error while listening, rc=%Rrc\n", rc);
208
209 } while (0);
210#endif
211 }
212 else
213 RTTestIFailed("Unable to create IPC server, rc=%Rrc\n", rc);
214
215 return VINF_SUCCESS;
216}
217
218static RTEXITCODE mainChild(int argc, char **argv)
219{
220 /* Note: We assume argv[2] always contains the actual test type to perform. */
221 RTTEST hTest;
222 RTEXITCODE rcExit = RTTestInitAndCreate(argv[2], &hTest);
223 if (rcExit)
224 return rcExit;
225 RTTestBanner(hTest);
226
227 if (!RTStrICmp(argv[2], "tstRTLocalIpcSessionConnectionFork"))
228 rcExit = testSessionConnectionChild(argc, argv, hTest);
229
230 return RTTestSummaryAndDestroy(hTest);
231}
232
233int main(int argc, char **argv)
234{
235 if ( argc > 2
236 && !RTStrICmp(argv[1], "child"))
237 return mainChild(argc, argv);
238
239 RTTEST hTest;
240 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTLocalIpc", &hTest);
241 if (rcExit)
242 return rcExit;
243 RTTestBanner(hTest);
244
245 char szExecPath[RTPATH_MAX];
246 if (!RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))
247 RTStrCopy(szExecPath, sizeof(szExecPath), argv[0]);
248
249 RTTestISub("Basics");
250
251 RTAssertSetMayPanic(false);
252#ifdef DEBUG_andy
253 RTAssertSetQuiet(true);
254#endif
255
256 /* Server-side. */
257 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(NULL, NULL, 0), VERR_INVALID_POINTER, 1);
258 RTLOCALIPCSERVER ipcServer;
259 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, NULL, 0), VERR_INVALID_POINTER, 1);
260 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "", 0), VERR_INVALID_PARAMETER, 1);
261 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", 0 /* Invalid flags */), VERR_INVALID_PARAMETER, 1);
262 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", 1234 /* Invalid flags */), VERR_INVALID_PARAMETER, 1);
263 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(NULL), VERR_INVALID_HANDLE, 1);
264 RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(NULL), VINF_SUCCESS, 1);
265 /* Basic server creation / destruction. */
266 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCreate(&ipcServer, "BasicTest", RTLOCALIPC_FLAGS_MULTI_SESSION), VINF_SUCCESS, 1);
267 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(ipcServer), VINF_SUCCESS, 1);
268 RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(ipcServer), VINF_SUCCESS, 1);
269
270 /* Client-side (per session). */
271 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(NULL, NULL, 0), VERR_INVALID_POINTER, 1);
272 RTLOCALIPCSESSION ipcSession;
273 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, NULL, 0), VERR_INVALID_POINTER, 1);
274 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "", 0), VERR_INVALID_PARAMETER, 1);
275 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "BasicTest", 1234 /* Invalid flags */), VERR_INVALID_PARAMETER, 1);
276 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionCancel(NULL), VERR_INVALID_HANDLE, 1);
277 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionClose(NULL), VINF_SUCCESS, 1);
278 /* Basic client creation / destruction. */
279 RTTESTI_CHECK_RC_RET(RTLocalIpcSessionConnect(&ipcSession, "BasicTest", 0), VERR_FILE_NOT_FOUND, 1);
280 RTTESTI_CHECK_RC_RET(RTLocalIpcServerCancel(ipcServer), VERR_INVALID_MAGIC, 1);
281 RTTESTI_CHECK_RC_RET(RTLocalIpcServerDestroy(ipcServer), VERR_INVALID_MAGIC, 1);
282
283 if (RTTestErrorCount(hTest) == 0)
284 {
285#ifndef DEBUG_andy
286 RTTESTI_CHECK_RC_RET(testServerListenAndCancel(hTest, szExecPath), VINF_SUCCESS, 1);
287#endif
288 RTTESTI_CHECK_RC_RET(testSessionConnection(hTest, szExecPath), VINF_SUCCESS, 1);
289 }
290
291 /*
292 * Summary.
293 */
294 return RTTestSummaryAndDestroy(hTest);
295}
296
Note: See TracBrowser for help on using the repository browser.

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