VirtualBox

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

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