VirtualBox

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

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

tstRTProcCreateEx: Pass %TEMP% and other % stuff to the child process.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.0 KB
Line 
1/* $Id: tstRTProcCreateEx.cpp 42973 2012-08-24 12:30:32Z 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 /*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 else
174 RTTestIPassed(NULL);
175}
176
177
178static int tstRTCreateProcEx4Child(int argc, char **argv)
179{
180 int rc = RTR3InitExeNoArguments(0);
181 if (RT_FAILURE(rc))
182 return RTMsgInitFailure(rc);
183
184 int cErrors = 0;
185 for (int i = 0; i < argc; i++)
186 if (strcmp(argv[i], g_apszArgs4[i]))
187 {
188 RTStrmPrintf(g_pStdErr,
189 "child4: argv[%2u]='%s'\n"
190 "child4: expected='%s'\n",
191 i, argv[i], g_apszArgs4[i]);
192 cErrors++;
193 }
194
195 return cErrors == 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
196}
197
198static void tstRTCreateProcEx4(const char *pszAsUser, const char *pszPassword)
199{
200 RTTestISub("Argument with spaces and stuff");
201
202 RTPROCESS hProc;
203 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, g_apszArgs4, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
204 NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
205 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
206 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
207
208 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
209 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
210 else
211 RTTestIPassed(NULL);
212}
213
214
215static int tstRTCreateProcEx3Child(void)
216{
217 int rc = RTR3InitExeNoArguments(0);
218 if (RT_FAILURE(rc))
219 return RTMsgInitFailure(rc);
220
221 RTStrmPrintf(g_pStdOut, "w"); RTStrmFlush(g_pStdOut);
222 RTStrmPrintf(g_pStdErr, "o"); RTStrmFlush(g_pStdErr);
223 RTStrmPrintf(g_pStdOut, "r"); RTStrmFlush(g_pStdOut);
224 RTStrmPrintf(g_pStdErr, "k"); RTStrmFlush(g_pStdErr);
225 RTStrmPrintf(g_pStdOut, "s");
226
227 return RTEXITCODE_SUCCESS;
228}
229
230static void tstRTCreateProcEx3(const char *pszAsUser, const char *pszPassword)
231{
232 RTTestISub("Standard Out+Err");
233
234 RTPIPE hPipeR, hPipeW;
235 RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS);
236 const char * apszArgs[3] =
237 {
238 "non-existing-non-executable-file",
239 "--testcase-child-3",
240 NULL
241 };
242 RTHANDLE Handle;
243 Handle.enmType = RTHANDLETYPE_PIPE;
244 Handle.u.hPipe = hPipeW;
245 RTPROCESS hProc;
246 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
247 &Handle, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
248 RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
249
250 char szOutput[_4K];
251 size_t offOutput = 0;
252 for (;;)
253 {
254 size_t cbLeft = sizeof(szOutput) - 1 - offOutput;
255 RTTESTI_CHECK(cbLeft > 0);
256 if (cbLeft == 0)
257 break;
258
259 size_t cbRead;
260 int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead);
261 if (RT_FAILURE(rc))
262 {
263 RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE);
264 break;
265 }
266 offOutput += cbRead;
267 }
268 szOutput[offOutput] = '\0';
269 RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS);
270
271 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
272 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
273 RTThreadSleep(10);
274
275 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
276 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
277 else if ( offOutput != sizeof("works") - 1
278 || strcmp(szOutput, "works"))
279 RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput);
280 else
281 RTTestIPassed(NULL);
282}
283
284
285static int tstRTCreateProcEx2Child(void)
286{
287 int rc = RTR3InitExeNoArguments(0);
288 if (RT_FAILURE(rc))
289 return RTMsgInitFailure(rc);
290
291 RTStrmPrintf(g_pStdErr, "howdy");
292 RTStrmPrintf(g_pStdOut, "ignore this output\n");
293
294 return RTEXITCODE_SUCCESS;
295}
296
297static void tstRTCreateProcEx2(const char *pszAsUser, const char *pszPassword)
298{
299 RTTestISub("Standard Err");
300
301 RTPIPE hPipeR, hPipeW;
302 RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS);
303 const char * apszArgs[3] =
304 {
305 "non-existing-non-executable-file",
306 "--testcase-child-2",
307 NULL
308 };
309 RTHANDLE Handle;
310 Handle.enmType = RTHANDLETYPE_PIPE;
311 Handle.u.hPipe = hPipeW;
312 RTPROCESS hProc;
313 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
314 NULL, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
315 RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
316
317 char szOutput[_4K];
318 size_t offOutput = 0;
319 for (;;)
320 {
321 size_t cbLeft = sizeof(szOutput) - 1 - offOutput;
322 RTTESTI_CHECK(cbLeft > 0);
323 if (cbLeft == 0)
324 break;
325
326 size_t cbRead;
327 int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead);
328 if (RT_FAILURE(rc))
329 {
330 RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE);
331 break;
332 }
333 offOutput += cbRead;
334 }
335 szOutput[offOutput] = '\0';
336 RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS);
337
338 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
339 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
340 RTThreadSleep(10);
341
342 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
343 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
344 else if ( offOutput != sizeof("howdy") - 1
345 || strcmp(szOutput, "howdy"))
346 RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput);
347 else
348 RTTestIPassed(NULL);
349}
350
351
352static int tstRTCreateProcEx1Child(void)
353{
354 int rc = RTR3InitExeNoArguments(0);
355 if (RT_FAILURE(rc))
356 return RTMsgInitFailure(rc);
357
358 RTPrintf("it works");
359 RTStrmPrintf(g_pStdErr, "ignore this output\n");
360
361 return RTEXITCODE_SUCCESS;
362}
363
364
365static void tstRTCreateProcEx1(const char *pszAsUser, const char *pszPassword)
366{
367 RTTestISub("Standard Out");
368
369 RTPIPE hPipeR, hPipeW;
370 RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS);
371 const char * apszArgs[3] =
372 {
373 "non-existing-non-executable-file",
374 "--testcase-child-1",
375 NULL
376 };
377 RTHANDLE Handle;
378 Handle.enmType = RTHANDLETYPE_PIPE;
379 Handle.u.hPipe = hPipeW;
380 RTPROCESS hProc;
381 RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
382 &Handle, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
383 RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS);
384
385 char szOutput[_4K];
386 size_t offOutput = 0;
387 for (;;)
388 {
389 size_t cbLeft = sizeof(szOutput) - 1 - offOutput;
390 RTTESTI_CHECK(cbLeft > 0);
391 if (cbLeft == 0)
392 break;
393
394 size_t cbRead;
395 int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead);
396 if (RT_FAILURE(rc))
397 {
398 RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE);
399 break;
400 }
401 offOutput += cbRead;
402 }
403 szOutput[offOutput] = '\0';
404 RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS);
405
406 RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND };
407 RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
408
409 if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
410 RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
411 else if ( offOutput != sizeof("it works") - 1
412 || strcmp(szOutput, "it works"))
413 RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput);
414 else
415 RTTestIPassed(NULL);
416}
417
418
419int main(int argc, char **argv)
420{
421 if (argc == 2 && !strcmp(argv[1], "--testcase-child-1"))
422 return tstRTCreateProcEx1Child();
423 if (argc == 2 && !strcmp(argv[1], "--testcase-child-2"))
424 return tstRTCreateProcEx2Child();
425 if (argc == 2 && !strcmp(argv[1], "--testcase-child-3"))
426 return tstRTCreateProcEx3Child();
427 if (argc >= 5 && !strcmp(argv[1], "--testcase-child-4"))
428 return tstRTCreateProcEx4Child(argc, argv);
429 if (argc == 2 && !strcmp(argv[1], "--testcase-child-5"))
430 return tstRTCreateProcEx5Child(argc, argv);
431 const char *pszAsUser = NULL;
432 const char *pszPassword = NULL;
433 if (argc != 1)
434 {
435 if (argc != 4 || strcmp(argv[1], "--as-user"))
436 return 99;
437 pszAsUser = argv[2];
438 pszPassword = argv[3];
439 }
440
441 RTTEST hTest;
442 int rc = RTTestInitAndCreate("tstRTProcCreateEx", &hTest);
443 if (rc)
444 return rc;
445 RTTestBanner(hTest);
446
447 if (!RTProcGetExecutablePath(g_szExecName, sizeof(g_szExecName)))
448 RTStrCopy(g_szExecName, sizeof(g_szExecName), argv[0]);
449
450 /*
451 * The tests.
452 */
453 tstRTCreateProcEx1(pszAsUser, pszPassword);
454 tstRTCreateProcEx2(pszAsUser, pszPassword);
455 tstRTCreateProcEx3(pszAsUser, pszPassword);
456 tstRTCreateProcEx4(pszAsUser, pszPassword);
457 if (pszAsUser)
458 tstRTCreateProcEx5(pszAsUser, pszPassword);
459 /** @todo Cover files, ++ */
460
461 /*
462 * Summary.
463 */
464 return RTTestSummaryAndDestroy(hTest);
465}
466
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