VirtualBox

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

Last change on this file since 30611 was 30093, checked in by vboxsync, 15 years ago

IPRT: Removed VERR_LOGON_FAILURE in favor of VERR_AUTHENTICATION_FAILURE. Cleaned up nits in process-win.cpp and adding some missing function docs. Hope it compiles...

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