| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
#include <iprt/initterm.h> |
|---|
| 27 |
#include <iprt/dir.h> |
|---|
| 28 |
#include <iprt/param.h> |
|---|
| 29 |
#include <iprt/path.h> |
|---|
| 30 |
#include <iprt/process.h> |
|---|
| 31 |
#include <iprt/string.h> |
|---|
| 32 |
#include <iprt/stream.h> |
|---|
| 33 |
#include <iprt/thread.h> |
|---|
| 34 |
#include <iprt/err.h> |
|---|
| 35 |
#include <iprt/env.h> |
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
static unsigned g_cPasses = 0; |
|---|
| 43 |
|
|---|
| 44 |
static unsigned g_cFailures = 0; |
|---|
| 45 |
|
|---|
| 46 |
static unsigned g_cSkipped = 0; |
|---|
| 47 |
|
|---|
| 48 |
static const char *g_apszExclude[] = |
|---|
| 49 |
{ |
|---|
| 50 |
#if 1 // slow stuff |
|---|
| 51 |
"testcase/tstFile", |
|---|
| 52 |
"testcase/tstAvl", |
|---|
| 53 |
"testcase/tstSemMutex", |
|---|
| 54 |
"testcase/tstVD", |
|---|
| 55 |
#endif |
|---|
| 56 |
"testcase/tstFileLock", |
|---|
| 57 |
"testcase/tstCritSect", |
|---|
| 58 |
"testcase/tstCritSectW32", |
|---|
| 59 |
"testcase/tstDeadlock", |
|---|
| 60 |
"testcase/tstDisasm-2", |
|---|
| 61 |
"testcase/tstFileAppendWin-1", |
|---|
| 62 |
"testcase/tstDir", |
|---|
| 63 |
"testcase/tstDir-2", |
|---|
| 64 |
"testcase/tstGlobalConfig", |
|---|
| 65 |
"testcase/tstLdr-2", |
|---|
| 66 |
"testcase/tstLdr-3", |
|---|
| 67 |
"testcase/tstLdr", |
|---|
| 68 |
"testcase/tstLdrLoad", |
|---|
| 69 |
"testcase/tstLdrObj", |
|---|
| 70 |
"testcase/tstLdrObjR0", |
|---|
| 71 |
"testcase/tstMove", |
|---|
| 72 |
"testcase/tstRunTestcases", |
|---|
| 73 |
"testcase/tstSDL", |
|---|
| 74 |
"testcase/tstTime-3", |
|---|
| 75 |
"testcase/tstSeamlessX11", |
|---|
| 76 |
"testcase/tstVBoxControl", |
|---|
| 77 |
"./tstRunTestcases", |
|---|
| 78 |
"./tstAnimate", |
|---|
| 79 |
"./tstAPI", |
|---|
| 80 |
"./tstHeadless", |
|---|
| 81 |
"./tstHeadless2", |
|---|
| 82 |
"./tstMicro", |
|---|
| 83 |
"./tstMicroGC", |
|---|
| 84 |
"./tstVBoxDbg", |
|---|
| 85 |
"./tstVMM-2", |
|---|
| 86 |
"./tstTestServMgr", |
|---|
| 87 |
"./tstXptDump", |
|---|
| 88 |
"./tstnsIFileEnumerator", |
|---|
| 89 |
"./tstSimpleTypeLib", |
|---|
| 90 |
"./tstTestAtoms", |
|---|
| 91 |
"./tstXptLink", |
|---|
| 92 |
"./tstTestCallTemplates", |
|---|
| 93 |
#if 1 // later |
|---|
| 94 |
"testcase/tstIntNetR0", |
|---|
| 95 |
"./tstVMM", |
|---|
| 96 |
"./tstVMReq", |
|---|
| 97 |
"./tstVMREQ", |
|---|
| 98 |
#endif |
|---|
| 99 |
|
|---|
| 100 |
"" |
|---|
| 101 |
}; |
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 |
|
|---|
| 108 |
|
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| 111 |
|
|---|
| 112 |
static bool IsTestcaseIncluded(const char *pszTestcase) |
|---|
| 113 |
{ |
|---|
| 114 |
char *pszDup = RTStrDup(pszTestcase); |
|---|
| 115 |
if (pszDup) |
|---|
| 116 |
{ |
|---|
| 117 |
RTPathStripExt(pszDup); |
|---|
| 118 |
for (unsigned i = 0; i < RT_ELEMENTS(g_apszExclude); i++) |
|---|
| 119 |
{ |
|---|
| 120 |
if (!strcmp(g_apszExclude[i], pszDup)) |
|---|
| 121 |
{ |
|---|
| 122 |
RTStrFree(pszDup); |
|---|
| 123 |
return false; |
|---|
| 124 |
} |
|---|
| 125 |
} |
|---|
| 126 |
RTStrFree(pszDup); |
|---|
| 127 |
return true; |
|---|
| 128 |
} |
|---|
| 129 |
|
|---|
| 130 |
RTPrintf("tstRunTestcases: Out of memory!\n"); |
|---|
| 131 |
return false; |
|---|
| 132 |
} |
|---|
| 133 |
|
|---|
| 134 |
|
|---|
| 135 |
|
|---|
| 136 |
|
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 |
|
|---|
| 140 |
|
|---|
| 141 |
|
|---|
| 142 |
static void Process(const char *pszFilter, const char *pszDir) |
|---|
| 143 |
{ |
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 |
|
|---|
| 147 |
PRTDIR pDir; |
|---|
| 148 |
int rc = RTDirOpenFiltered(&pDir, pszFilter, RTDIRFILTER_WINNT); |
|---|
| 149 |
if (RT_SUCCESS(rc)) |
|---|
| 150 |
{ |
|---|
| 151 |
for (;;) |
|---|
| 152 |
{ |
|---|
| 153 |
RTDIRENTRY DirEntry; |
|---|
| 154 |
rc = RTDirRead(pDir, &DirEntry, NULL); |
|---|
| 155 |
if (RT_FAILURE(rc)) |
|---|
| 156 |
{ |
|---|
| 157 |
if (rc == VERR_NO_MORE_FILES) |
|---|
| 158 |
rc = VINF_SUCCESS; |
|---|
| 159 |
else |
|---|
| 160 |
RTPrintf("tstRunTestcases: reading '%s' -> %Rrc\n", pszFilter, rc); |
|---|
| 161 |
break; |
|---|
| 162 |
} |
|---|
| 163 |
|
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
|
|---|
| 167 |
char *pszTestcase; |
|---|
| 168 |
RTStrAPrintf(&pszTestcase, "%s/%s", pszDir, DirEntry.szName); |
|---|
| 169 |
if (!pszTestcase) |
|---|
| 170 |
{ |
|---|
| 171 |
RTPrintf("tstRunTestcases: out of memory!\n"); |
|---|
| 172 |
rc = VERR_NO_MEMORY; |
|---|
| 173 |
break; |
|---|
| 174 |
} |
|---|
| 175 |
if (IsTestcaseIncluded(pszTestcase)) |
|---|
| 176 |
{ |
|---|
| 177 |
|
|---|
| 178 |
|
|---|
| 179 |
|
|---|
| 180 |
RTPrintf("*** %s: Executing...\n", pszTestcase); RTStrmFlush(g_pStdOut); |
|---|
| 181 |
const char *papszArgs[2]; |
|---|
| 182 |
papszArgs[0] = pszTestcase; |
|---|
| 183 |
papszArgs[1] = NULL; |
|---|
| 184 |
RTPROCESS Process; |
|---|
| 185 |
rc = RTProcCreate(pszTestcase, papszArgs, RTENV_DEFAULT, 0, &Process); |
|---|
| 186 |
if (RT_SUCCESS(rc)) |
|---|
| 187 |
{ |
|---|
| 188 |
|
|---|
| 189 |
|
|---|
| 190 |
|
|---|
| 191 |
|
|---|
| 192 |
RTTIMESPEC Start; |
|---|
| 193 |
RTTimeNow(&Start); |
|---|
| 194 |
RTPROCSTATUS ProcStatus; |
|---|
| 195 |
for (;;) |
|---|
| 196 |
{ |
|---|
| 197 |
rc = RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus); |
|---|
| 198 |
if (rc != VERR_PROCESS_RUNNING) |
|---|
| 199 |
break; |
|---|
| 200 |
RTTIMESPEC Now; |
|---|
| 201 |
if (RTTimeSpecGetMilli(RTTimeSpecSub(RTTimeNow(&Now), &Start)) > 60*1000 ) |
|---|
| 202 |
{ |
|---|
| 203 |
RTPrintf("*** %s: FAILED - timed out. killing it.\n", pszTestcase); |
|---|
| 204 |
RTProcTerminate(Process); |
|---|
| 205 |
RTThreadSleep(100); |
|---|
| 206 |
RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus); |
|---|
| 207 |
g_cFailures++; |
|---|
| 208 |
break; |
|---|
| 209 |
} |
|---|
| 210 |
RTThreadSleep(100); |
|---|
| 211 |
} |
|---|
| 212 |
|
|---|
| 213 |
|
|---|
| 214 |
|
|---|
| 215 |
|
|---|
| 216 |
if (RT_SUCCESS(rc)) |
|---|
| 217 |
{ |
|---|
| 218 |
if ( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL |
|---|
| 219 |
&& ProcStatus.iStatus == 0) |
|---|
| 220 |
{ |
|---|
| 221 |
RTPrintf("*** %s: PASSED\n", pszTestcase); |
|---|
| 222 |
g_cPasses++; |
|---|
| 223 |
} |
|---|
| 224 |
else |
|---|
| 225 |
{ |
|---|
| 226 |
RTPrintf("*** %s: FAILED\n", pszTestcase); |
|---|
| 227 |
g_cFailures++; |
|---|
| 228 |
} |
|---|
| 229 |
} |
|---|
| 230 |
else if (rc != VERR_PROCESS_RUNNING) |
|---|
| 231 |
{ |
|---|
| 232 |
RTPrintf("tstRunTestcases: %s: RTProcWait failed -> %Rrc\n", pszTestcase, rc); |
|---|
| 233 |
g_cFailures++; |
|---|
| 234 |
} |
|---|
| 235 |
} |
|---|
| 236 |
else |
|---|
| 237 |
{ |
|---|
| 238 |
RTPrintf("tstRunTestcases: %s: failed to start -> %Rrc\n", pszTestcase, rc); |
|---|
| 239 |
g_cFailures++; |
|---|
| 240 |
} |
|---|
| 241 |
|
|---|
| 242 |
} |
|---|
| 243 |
else |
|---|
| 244 |
{ |
|---|
| 245 |
RTPrintf("tstRunTestcases: %s: SKIPPED\n", pszTestcase); |
|---|
| 246 |
g_cSkipped++; |
|---|
| 247 |
} |
|---|
| 248 |
RTStrFree(pszTestcase); |
|---|
| 249 |
} |
|---|
| 250 |
|
|---|
| 251 |
RTDirClose(pDir); |
|---|
| 252 |
} |
|---|
| 253 |
else |
|---|
| 254 |
RTPrintf("tstRunTestcases: opening '%s' -> %Rrc\n", pszDir, rc); |
|---|
| 255 |
} |
|---|
| 256 |
|
|---|
| 257 |
|
|---|
| 258 |
|
|---|
| 259 |
int main(int argc, char **argv) |
|---|
| 260 |
{ |
|---|
| 261 |
RTR3Init(); |
|---|
| 262 |
|
|---|
| 263 |
if (argc == 1) |
|---|
| 264 |
{ |
|---|
| 265 |
char szPath[RTPATH_MAX]; |
|---|
| 266 |
int rc = RTPathProgram(szPath, sizeof(szPath) - sizeof("/..")); |
|---|
| 267 |
if (RT_FAILURE(rc)) |
|---|
| 268 |
{ |
|---|
| 269 |
RTPrintf("fatal error: RTPathProgram -> %Rrc\n", rc); |
|---|
| 270 |
return 1; |
|---|
| 271 |
} |
|---|
| 272 |
rc = RTPathSetCurrent(strcat(szPath, "/..")); |
|---|
| 273 |
if (RT_FAILURE(rc)) |
|---|
| 274 |
{ |
|---|
| 275 |
RTPrintf("fatal error: RTPathSetCurrent -> %Rrc\n", rc); |
|---|
| 276 |
return 1; |
|---|
| 277 |
} |
|---|
| 278 |
|
|---|
| 279 |
Process("testcase/tst*", "testcase"); |
|---|
| 280 |
Process("tst*", "."); |
|---|
| 281 |
} |
|---|
| 282 |
else |
|---|
| 283 |
{ |
|---|
| 284 |
char szDir[RTPATH_MAX]; |
|---|
| 285 |
for (int i = 1; i < argc; i++) |
|---|
| 286 |
{ |
|---|
| 287 |
if (argv[i][0] == '-') |
|---|
| 288 |
{ |
|---|
| 289 |
switch (argv[i][1]) |
|---|
| 290 |
{ |
|---|
| 291 |
|
|---|
| 292 |
|
|---|
| 293 |
default: |
|---|
| 294 |
RTPrintf("syntax error: Option '%s' is not recognized\n", argv[i]); |
|---|
| 295 |
return 1; |
|---|
| 296 |
} |
|---|
| 297 |
} |
|---|
| 298 |
else |
|---|
| 299 |
{ |
|---|
| 300 |
size_t cch = strlen(argv[i]); |
|---|
| 301 |
if (cch >= sizeof(szDir)) |
|---|
| 302 |
{ |
|---|
| 303 |
RTPrintf("syntax error: '%s' is too long!\n", argv[i]); |
|---|
| 304 |
return 1; |
|---|
| 305 |
} |
|---|
| 306 |
memcpy(szDir, argv[i], cch + 1); |
|---|
| 307 |
char *pszFilename = RTPathFilename(szDir); |
|---|
| 308 |
if (!pszFilename) |
|---|
| 309 |
{ |
|---|
| 310 |
RTPrintf("syntax error: '%s' does not include a file name or file name mask!\n", argv[i]); |
|---|
| 311 |
return 1; |
|---|
| 312 |
} |
|---|
| 313 |
RTPathStripFilename(szDir); |
|---|
| 314 |
Process(argv[i], szDir); |
|---|
| 315 |
} |
|---|
| 316 |
} |
|---|
| 317 |
} |
|---|
| 318 |
|
|---|
| 319 |
RTPrintf("\n" |
|---|
| 320 |
"********************\n" |
|---|
| 321 |
"*** PASSED: %u\n" |
|---|
| 322 |
"*** FAILED: %u\n" |
|---|
| 323 |
"*** SKIPPED: %u\n" |
|---|
| 324 |
"*** TOTAL: %u\n", |
|---|
| 325 |
g_cPasses, |
|---|
| 326 |
g_cFailures, |
|---|
| 327 |
g_cSkipped, |
|---|
| 328 |
g_cPasses + g_cFailures + g_cSkipped); |
|---|
| 329 |
return !!g_cFailures; |
|---|
| 330 |
} |
|---|
| 331 |
|
|---|