VirtualBox

source: vbox/trunk/src/testcase/tstRunTestcases.cpp@ 5799

Last change on this file since 5799 was 5700, checked in by vboxsync, 17 years ago

r=bird: Passing RTENV_DEFAULT to RTProcCreate should be sufficient.

  • Property svn:keywords set to Id
File size: 9.4 KB
Line 
1/* $Id: tstRunTestcases.cpp 5700 2007-11-12 10:25:54Z vboxsync $ */
2/** @file
3 * tstRunTescases - Driver program for running VBox testcase (tst* testcase/tst*).
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/runtime.h>
23#include <iprt/dir.h>
24#include <iprt/process.h>
25#include <iprt/path.h>
26#include <iprt/string.h>
27#include <iprt/stream.h>
28#include <iprt/thread.h>
29#include <iprt/err.h>
30#include <iprt/env.h>
31
32
33/*******************************************************************************
34* Global Variables *
35*******************************************************************************/
36/** The number of passed testcases. */
37static unsigned g_cPasses = 0;
38/** The number of failed testcases. */
39static unsigned g_cFailures = 0;
40/** The number of skipped testcases. */
41static unsigned g_cSkipped = 0;
42/** The exclude list. */
43static const char *g_apszExclude[] =
44{
45#if 1 // slow stuff
46 "testcase/tstFile",
47 "testcase/tstAvl",
48#endif
49 "testcase/tstFileLock",
50 "testcase/tstCritSect",
51 "testcase/tstCritSectW32",
52 "testcase/tstDeadlock",
53 "testcase/tstLdr-2",
54 "testcase/tstLdr-3",
55 "testcase/tstLdr",
56 "testcase/tstLdrLoad",
57 "testcase/tstLdrObj",
58 "testcase/tstLdrObjR0",
59 "testcase/tstMove",
60 "testcase/tstRunTestcases",
61 "testcase/tstSDL",
62 "testcase/tstTime-3",
63 "./tstRunTestcases",
64 "./tstAnimate",
65 "./tstAPI",
66 "./tstHeadless",
67 "./tstMicro",
68 "./tstMicroGC",
69 "./tstVBoxDbg",
70 "./tstVMM-2",
71 "./tstTestServMgr",
72 "./tstXptDump",
73 "./tstnsIFileEnumerator",
74 "./tstSimpleTypeLib",
75 "./tstTestAtoms",
76 "./tstXptLink",
77 "./tstTestCallTemplates",
78#if 1 // later
79 "testcase/tstIntNetR0",
80 "./tstVMM",
81 "./tstVMReq",
82 "./tstVMREQ",
83#endif
84 /* final entry*/
85 ""
86};
87
88
89/**
90 * Checks if a testcase is include or should be skipped.
91 *
92 * @param pszTestcase The testcase (filename).
93 *
94 * @return true if the testcase is included.
95 * false if the testcase should be skipped.
96 */
97static bool IsTestcaseIncluded(const char *pszTestcase)
98{
99 char *pszDup = RTStrDup(pszTestcase);
100 if (pszDup)
101 {
102 RTPathStripExt(pszDup);
103 for (unsigned i = 0; i < ELEMENTS(g_apszExclude); i++)
104 {
105 if (!strcmp(g_apszExclude[i], pszDup))
106 {
107 RTStrFree(pszDup);
108 return false;
109 }
110 }
111 RTStrFree(pszDup);
112 return true;
113 }
114
115 RTPrintf("tstRunTestcases: Out of memory!\n");
116 return false;
117}
118
119
120/**
121 * Process the testcases found in the filter.
122 *
123 * @param pszFilter The filter (winnt) to pass to RTDirOpenFiltered for
124 * selecting the testcases.
125 * @param pszDir The directory we're processing.
126 */
127static void Process(const char *pszFilter, const char *pszDir)
128{
129 /*
130 * Open and enumerate the directory.
131 */
132 PRTDIR pDir;
133 int rc = RTDirOpenFiltered(&pDir, pszFilter, RTDIRFILTER_WINNT);
134 if (RT_SUCCESS(rc))
135 {
136 for (;;)
137 {
138 RTDIRENTRY DirEntry;
139 rc = RTDirRead(pDir, &DirEntry, NULL);
140 if (RT_FAILURE(rc))
141 {
142 if (rc == VERR_NO_MORE_FILES)
143 rc = VINF_SUCCESS;
144 else
145 RTPrintf("tstRunTestcases: reading '%s' -> %Rrc\n", pszFilter, rc);
146 break;
147 }
148
149 /*
150 * Construct the testcase name.
151 */
152 char *pszTestcase;
153 RTStrAPrintf(&pszTestcase, "%s/%s", pszDir, DirEntry.szName);
154 if (!pszTestcase)
155 {
156 RTPrintf("tstRunTestcases: out of memory!\n");
157 rc = VERR_NO_MEMORY;
158 break;
159 }
160 if (IsTestcaseIncluded(pszTestcase))
161 {
162 /*
163 * Execute the testcase.
164 */
165 RTPrintf("*** %s: Executing...\n", pszTestcase); RTStrmFlush(g_pStdOut);
166 const char *papszArgs[2];
167 papszArgs[0] = pszTestcase;
168 papszArgs[1] = NULL;
169 RTPROCESS Process;
170 rc = RTProcCreate(pszTestcase, papszArgs, RTENV_DEFAULT, 0, &Process);
171 if (RT_SUCCESS(rc))
172 {
173 /*
174 * Wait for the process and collect it's return code.
175 * If it takes too long, we'll terminate it and continue.
176 */
177 RTTIMESPEC Start;
178 RTTimeNow(&Start);
179 RTPROCSTATUS ProcStatus;
180 for (;;)
181 {
182 rc = RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus);
183 if (rc != VERR_PROCESS_RUNNING)
184 break;
185 RTTIMESPEC Now;
186 if (RTTimeSpecGetMilli(RTTimeSpecSub(RTTimeNow(&Now), &Start)) > 60*1000 /* 1 min */)
187 {
188 RTPrintf("*** %s: FAILED - timed out. killing it.\n", pszTestcase);
189 RTProcTerminate(Process);
190 RTThreadSleep(100);
191 RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus);
192 g_cFailures++;
193 break;
194 }
195 RTThreadSleep(100);
196 }
197
198 /*
199 * Examin the exit status.
200 */
201 if (RT_SUCCESS(rc))
202 {
203 if ( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL
204 && ProcStatus.iStatus == 0)
205 {
206 RTPrintf("*** %s: PASSED\n", pszTestcase);
207 g_cPasses++;
208 }
209 else
210 {
211 RTPrintf("*** %s: FAILED\n", pszTestcase);
212 g_cFailures++;
213 }
214 }
215 else if (rc != VERR_PROCESS_RUNNING)
216 {
217 RTPrintf("tstRunTestcases: %s: RTProcWait failed -> %Rrc\n", pszTestcase, rc);
218 g_cFailures++;
219 }
220 }
221 else
222 {
223 RTPrintf("tstRunTestcases: %s: failed to start -> %Rrc\n", pszTestcase, rc);
224 g_cFailures++;
225 }
226
227 }
228 else
229 {
230 RTPrintf("tstRunTestcases: %s: SKIPPED\n", pszTestcase);
231 g_cSkipped++;
232 }
233 RTStrFree(pszTestcase);
234 } /* enumeration loop */
235
236 RTDirClose(pDir);
237 }
238 else
239 RTPrintf("tstRunTestcases: opening '%s' -> %Rrc\n", pszDir, rc);
240}
241
242
243
244int main(int argc, char **argv)
245{
246 RTR3Init(false, 0);
247
248 if (argc == 1)
249 {
250 Process("testcase/tst*", "testcase");
251 Process("tst*", ".");
252 }
253 else
254 {
255 char szDir[RTPATH_MAX];
256 for (int i = 1; i < argc; i++)
257 {
258 if (argv[i][0] == '-')
259 {
260 switch (argv[i][1])
261 {
262 /* case '':... */
263
264 default:
265 RTPrintf("syntax error: Option '%s' is not recognized\n", argv[i]);
266 return 1;
267 }
268 }
269 else
270 {
271 size_t cch = strlen(argv[i]);
272 if (cch >= sizeof(szDir))
273 {
274 RTPrintf("syntax error: '%s' is too long!\n", argv[i]);
275 return 1;
276 }
277 memcpy(szDir, argv[i], cch + 1);
278 char *pszFilename = RTPathFilename(szDir);
279 if (!pszFilename)
280 {
281 RTPrintf("syntax error: '%s' does not include a file name or file name mask!\n", argv[i]);
282 return 1;
283 }
284 RTPathStripFilename(szDir);
285 Process(argv[i], szDir);
286 }
287 }
288 }
289
290 RTPrintf("\n"
291 "********************\n"
292 "*** PASSED: %u\n"
293 "*** FAILED: %u\n"
294 "*** SKIPPED: %u\n"
295 "*** TOTAL: %u\n",
296 g_cPasses,
297 g_cFailures,
298 g_cSkipped,
299 g_cPasses + g_cFailures + g_cSkipped);
300 return !!g_cFailures;
301}
302
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