VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp@ 44824

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

RTTestPassed/RTTestIPassed does not accept NULL as a parameter. Use RTTestDone/RTTestIDone if you don't want to say anything beyond that the test is complete. (You don't need to say that at all as it is implicit when RTTest[I]Sub or RTTestSummaryAndDestroy is called.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1/* $Id: tstRTProcCreateEx.cpp 44554 2013-02-05 23:37:46Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTProcCreateEx.
4 */
5
6/*
7 * Copyright (C) 2010-2012 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/process.h>
32
33#include <iprt/assert.h>
34#include <iprt/env.h>
35#include <iprt/err.h>
36#include <iprt/initterm.h>
37#include <iprt/mem.h>
38#include <iprt/message.h>
39#include <iprt/param.h>
40#include <iprt/pipe.h>
41#include <iprt/string.h>
42#include <iprt/stream.h>
43#include <iprt/test.h>
44#include <iprt/thread.h>
45
46#ifdef RT_OS_WINDOWS
47# define SECURITY_WIN32
48# include <windows.h>
49# include <Security.h>
50#endif
51
52/*******************************************************************************
53* Global Variables *
54*******************************************************************************/
55static char g_szExecName[RTPATH_MAX];
56
57
58static const char * const g_apszArgs4[] =
59{
60 /* 0 */ "non existing non executable file",
61 /* 1 */ "--testcase-child-4",
62 /* 2 */ "a b",
63 /* 3 */ " cdef",
64 /* 4 */ "ghijkl ",
65 /* 5 */ "\"",
66 /* 6 */ "\\",
67 /* 7 */ "\\\"",
68 /* 8 */ "\\\"\\",
69 /* 9 */ "\\\\\"\\",
70 /*10 */ "%TEMP%",
71 /*11 */ "%TEMP%\filename",
72 /*12 */ "%TEMP%postfix",
73 /*13 */ "Prefix%TEMP%postfix",
74 /*14 */ "%",
75 /*15 */ "%%",
76 /*16 */ "%%%",
77 /*17 */ "%X",
78 /*18 */ "%%X",
79 NULL
80};
81
82
83static int tstRTCreateProcEx5Child(int argc, char **argv)
84{
85 int rc = RTR3InitExeNoArguments(0);
86 if (RT_FAILURE(rc))
87 return RTMsgInitFailure(rc);
88
89#ifdef RT_OS_WINDOWS
90 char szUser[_1K];
91 DWORD cbLen = sizeof(szUser);
92 /** @todo Does not yet handle ERROR_MORE_DATA for user names longer than 32767. */
93 if (!GetUserName(szUser, &cbLen))
94 {
95 RTPrintf("GetUserName failed with last error=%ld\n", GetLastError());
96 return RTEXITCODE_FAILURE;
97 }
98# if 0 /* Does not work on NT4 (yet). */
99 DWORD cbSid = 0;
100 DWORD cbDomain = 0;
101 SID_NAME_USE sidUse;
102 /* First try to figure out how much space for SID + domain name we need. */
103 BOOL bRet = LookupAccountName(NULL /* current system*/,
104 szUser,
105 NULL,
106 &cbSid,
107 NULL,
108 &cbDomain,
109 &sidUse);
110 if (!bRet)
111 {
112 DWORD dwErr = GetLastError();
113 if (dwErr != ERROR_INSUFFICIENT_BUFFER)
114 {
115 RTPrintf("LookupAccountName(1) failed with last error=%ld\n", dwErr);
116 return RTEXITCODE_FAILURE;
117 }
118 }
119
120 /* Now try getting the real SID + domain name. */
121 SID *pSid = (SID *)RTMemAlloc(cbSid);
122 AssertPtr(pSid);
123 char *pszDomain = (char *)RTMemAlloc(cbDomain); /* Size in TCHAR! */
124 AssertPtr(pszDomain);
125
126 if (!LookupAccountName(NULL /* Current system */,
127 szUser,
128 pSid,
129 &cbSid,
130 pszDomain,
131 &cbDomain,
132 &sidUse))
133 {
134 RTPrintf("LookupAccountName(2) failed with last error=%ld\n", GetLastError());
135 return RTEXITCODE_FAILURE;
136 }
137 RTMemFree(pSid);
138 RTMemFree(pszDomain);
139# endif
140#else
141 /** @todo Lookup UID/effective UID, maybe GID? */
142#endif
143 return RTEXITCODE_SUCCESS;
144}
145
146static void tstRTCreateProcEx5(const char *pszUser, const char *pszPassword)
147{
148 RTTestISubF("As user \"%s\" with password \"%s\"", pszUser, pszPassword);
149
150 const char * apszArgs[3] =
151 {
152 "test", /* user name */
153 "--testcase-child-5",
154 NULL
155 };
156
157 RTPROCESS hProc;
158
159 /* Test for invalid logons. */
160 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
161 NULL, NULL, "non-existing-user", "wrong-password", &hProc), VERR_AUTHENTICATION_FAILURE);
162 /* Test for invalid application. */
163 RTTESTI_CHECK_RC_RETV(RTProcCreateEx("non-existing-app", apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
164 NULL, NULL, NULL, NULL, &hProc), VERR_FILE_NOT_FOUND);
165 /* Test a (hopefully) valid user/password logon (given by parameters of this function). */
166 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
167 NULL, NULL, pszUser, pszPassword, &hProc), VINF_SUCCESS);
168 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
169 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
170
171 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
172 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
173}
174
175
176static int tstRTCreateProcEx4Child(int argc, char **argv)
177{
178 int rc = RTR3InitExeNoArguments(0);
179 if (RT_FAILURE(rc))
180 return RTMsgInitFailure(rc);
181
182 int cErrors = 0;
183 for (int i = 0; i < argc; i++)
184 if (strcmp(argv[i], g_apszArgs4[i]))
185 {
186 RTStrmPrintf(g_pStdErr,
187 "child4: argv[%2u]='%s'\n"
188 "child4: expected='%s'\n",
189 i, argv[i], g_apszArgs4[i]);
190 cErrors++;
191 }
192
193 return cErrors == 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
194}
195
196static void tstRTCreateProcEx4(const char *pszAsUser, const char *pszPassword)
197{
198 RTTestISub("Argument with spaces and stuff");
199
200 RTPROCESS hProc;
201 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, g_apszArgs4, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
202 NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
203 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
204 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
205
206 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
207 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
208}
209
210
211static int tstRTCreateProcEx3Child(void)
212{
213 int rc = RTR3InitExeNoArguments(0);
214 if (RT_FAILURE(rc))
215 return RTMsgInitFailure(rc);
216
217 RTStrmPrintf(g_pStdOut, "w"); RTStrmFlush(g_pStdOut);
218 RTStrmPrintf(g_pStdErr, "o"); RTStrmFlush(g_pStdErr);
219 RTStrmPrintf(g_pStdOut, "r"); RTStrmFlush(g_pStdOut);
220 RTStrmPrintf(g_pStdErr, "k"); RTStrmFlush(g_pStdErr);
221 RTStrmPrintf(g_pStdOut, "s");
222
223 return RTEXITCODE_SUCCESS;
224}
225
226static void tstRTCreateProcEx3(const char *pszAsUser, const char *pszPassword)
227{
228 RTTestISub("Standard Out+Err");
229
230 RTPIPE hPipeR, hPipeW;
231 RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS);
232 const char * apszArgs[3] =
233 {
234 "non-existing-non-executable-file",
235 "--testcase-child-3",
236 NULL
237 };
238 RTHANDLE Handle;
239 Handle.enmType = RTHANDLETYPE_PIPE;
240 Handle.u.hPipe = hPipeW;
241 RTPROCESS hProc;
242 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
243 &Handle, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
244 RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
245
246 char szOutput[_4K];
247 size_t offOutput = 0;
248 for (;;)
249 {
250 size_t cbLeft = sizeof(szOutput) - 1 - offOutput;
251 RTTESTI_CHECK(cbLeft > 0);
252 if (cbLeft == 0)
253 break;
254
255 size_t cbRead;
256 int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead);
257 if (RT_FAILURE(rc))
258 {
259 RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE);
260 break;
261 }
262 offOutput += cbRead;
263 }
264 szOutput[offOutput] = '\0';
265 RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS);
266
267 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
268 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
269 RTThreadSleep(10);
270
271 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
272 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
273 else if ( offOutput != sizeof("works") - 1
274 || strcmp(szOutput, "works"))
275 RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput);
276}
277
278
279static int tstRTCreateProcEx2Child(void)
280{
281 int rc = RTR3InitExeNoArguments(0);
282 if (RT_FAILURE(rc))
283 return RTMsgInitFailure(rc);
284
285 RTStrmPrintf(g_pStdErr, "howdy");
286 RTStrmPrintf(g_pStdOut, "ignore this output\n");
287
288 return RTEXITCODE_SUCCESS;
289}
290
291static void tstRTCreateProcEx2(const char *pszAsUser, const char *pszPassword)
292{
293 RTTestISub("Standard Err");
294
295 RTPIPE hPipeR, hPipeW;
296 RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS);
297 const char * apszArgs[3] =
298 {
299 "non-existing-non-executable-file",
300 "--testcase-child-2",
301 NULL
302 };
303 RTHANDLE Handle;
304 Handle.enmType = RTHANDLETYPE_PIPE;
305 Handle.u.hPipe = hPipeW;
306 RTPROCESS hProc;
307 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
308 NULL, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
309 RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
310
311 char szOutput[_4K];
312 size_t offOutput = 0;
313 for (;;)
314 {
315 size_t cbLeft = sizeof(szOutput) - 1 - offOutput;
316 RTTESTI_CHECK(cbLeft > 0);
317 if (cbLeft == 0)
318 break;
319
320 size_t cbRead;
321 int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead);
322 if (RT_FAILURE(rc))
323 {
324 RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE);
325 break;
326 }
327 offOutput += cbRead;
328 }
329 szOutput[offOutput] = '\0';
330 RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS);
331
332 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
333 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
334 RTThreadSleep(10);
335
336 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
337 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
338 else if ( offOutput != sizeof("howdy") - 1
339 || strcmp(szOutput, "howdy"))
340 RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput);
341}
342
343
344static int tstRTCreateProcEx1Child(void)
345{
346 int rc = RTR3InitExeNoArguments(0);
347 if (RT_FAILURE(rc))
348 return RTMsgInitFailure(rc);
349
350 RTPrintf("it works");
351 RTStrmPrintf(g_pStdErr, "ignore this output\n");
352
353 return RTEXITCODE_SUCCESS;
354}
355
356
357static void tstRTCreateProcEx1(const char *pszAsUser, const char *pszPassword)
358{
359 RTTestISub("Standard Out");
360
361 RTPIPE hPipeR, hPipeW;
362 RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS);
363 const char * apszArgs[3] =
364 {
365 "non-existing-non-executable-file",
366 "--testcase-child-1",
367 NULL
368 };
369 RTHANDLE Handle;
370 Handle.enmType = RTHANDLETYPE_PIPE;
371 Handle.u.hPipe = hPipeW;
372 RTPROCESS hProc;
373 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
374 &Handle, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
375 RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
376
377 char szOutput[_4K];
378 size_t offOutput = 0;
379 for (;;)
380 {
381 size_t cbLeft = sizeof(szOutput) - 1 - offOutput;
382 RTTESTI_CHECK(cbLeft > 0);
383 if (cbLeft == 0)
384 break;
385
386 size_t cbRead;
387 int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead);
388 if (RT_FAILURE(rc))
389 {
390 RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE);
391 break;
392 }
393 offOutput += cbRead;
394 }
395 szOutput[offOutput] = '\0';
396 RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS);
397
398 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
399 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
400
401 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
402 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
403 else if ( offOutput != sizeof("it works") - 1
404 || strcmp(szOutput, "it works"))
405 RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput);
406}
407
408
409int main(int argc, char **argv)
410{
411 if (argc == 2 && !strcmp(argv[1], "--testcase-child-1"))
412 return tstRTCreateProcEx1Child();
413 if (argc == 2 && !strcmp(argv[1], "--testcase-child-2"))
414 return tstRTCreateProcEx2Child();
415 if (argc == 2 && !strcmp(argv[1], "--testcase-child-3"))
416 return tstRTCreateProcEx3Child();
417 if (argc >= 5 && !strcmp(argv[1], "--testcase-child-4"))
418 return tstRTCreateProcEx4Child(argc, argv);
419 if (argc == 2 && !strcmp(argv[1], "--testcase-child-5"))
420 return tstRTCreateProcEx5Child(argc, argv);
421 const char *pszAsUser = NULL;
422 const char *pszPassword = NULL;
423 if (argc != 1)
424 {
425 if (argc != 4 || strcmp(argv[1], "--as-user"))
426 return 99;
427 pszAsUser = argv[2];
428 pszPassword = argv[3];
429 }
430
431 RTTEST hTest;
432 int rc = RTTestInitAndCreate("tstRTProcCreateEx", &hTest);
433 if (rc)
434 return rc;
435 RTTestBanner(hTest);
436
437 if (!RTProcGetExecutablePath(g_szExecName, sizeof(g_szExecName)))
438 RTStrCopy(g_szExecName, sizeof(g_szExecName), argv[0]);
439
440 /*
441 * The tests.
442 */
443 tstRTCreateProcEx1(pszAsUser, pszPassword);
444 tstRTCreateProcEx2(pszAsUser, pszPassword);
445 tstRTCreateProcEx3(pszAsUser, pszPassword);
446 tstRTCreateProcEx4(pszAsUser, pszPassword);
447 if (pszAsUser)
448 tstRTCreateProcEx5(pszAsUser, pszPassword);
449 /** @todo Cover files, ++ */
450
451 /*
452 * Summary.
453 */
454 return RTTestSummaryAndDestroy(hTest);
455}
456
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