Author: cfinck Date: Thu Jul 2 03:30:15 2009 New Revision: 41734
URL: http://svn.reactos.org/svn/reactos?rev=41734&view=rev Log: - Simplify ERROR_* return values, don't make a difference between "Shutdown for some reason" and "Failed somehow". This should also fix a bug about the entire testing process being canceled when Kdbg is hit. As a consequence, the crash counter was renamed to a "retry counter" and the value for "maxretries" was increased, since the shutdowns in 1st and 2nd stage count as retries now. - Detect whether the same line appears over and over again and reboot the VM in this case to continue with the next test. This is done using a line cache and a configurable value of 50 allowed cache hits before we cancel the process. - Simplify some code by leaving out a block for the STDIN_FILENO fd. - Fix return values in case of early failures in ProcessDebugData. - Use "unsigned int" instead of "int" where appropriate. - Add missing license header after talking with Christoph.
Modified: trunk/tools/sysreg2/console.c trunk/tools/sysreg2/options.c trunk/tools/sysreg2/raddr2line.c trunk/tools/sysreg2/sysreg.h trunk/tools/sysreg2/sysreg.xml trunk/tools/sysreg2/utils.c trunk/tools/sysreg2/virt.c
Modified: trunk/tools/sysreg2/console.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/console.c?rev=41734&a... ============================================================================== --- trunk/tools/sysreg2/console.c [iso-8859-1] (original) +++ trunk/tools/sysreg2/console.c [iso-8859-1] Thu Jul 2 03:30:15 2009 @@ -1,28 +1,43 @@ +/* + * PROJECT: ReactOS System Regression Testing Utility + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Processing the incoming debugging data + * COPYRIGHT: Copyright 2008-2009 Christoph von Wittich christoph_vw@reactos.org + * Copyright 2009 Colin Finck colin@reactos.org + */ + #include "sysreg.h" +#define BUFFER_SIZE 512
int ProcessDebugData(const char* tty, int timeout, int stage ) { - char buf[512]; - char rbuf[512]; + char Buffer[BUFFER_SIZE]; + char CacheBuffer[BUFFER_SIZE]; + char Raddr2LineBuffer[BUFFER_SIZE]; char* bp; int got; - int ttyfd, i; + int Ret = EXIT_DONT_CONTINUE; + int ttyfd; struct termios ttyattr, rawattr; - int Ret = EXIT_NONCONTINUABLE_ERROR; - int KdbgHit = 0; + unsigned int CacheHits = 0; + unsigned int i; + unsigned int KdbgHit = 0; + + /* Initialize CacheBuffer with an empty string */ + *CacheBuffer = 0;
/* ttyfd is the file descriptor of the virtual COM port */ if ((ttyfd = open(tty, O_NOCTTY | O_RDWR)) < 0) { SysregPrintf("error opening tty\n"); - return false; + return Ret; }
/* We also monitor STDIN_FILENO, so a user can cancel the process with ESC */ if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) { SysregPrintf("tcgetattr failed with error %d\n", errno); - return false; + return Ret; }
rawattr = ttyattr; @@ -36,10 +51,10 @@ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) { SysregPrintf("tcsetattr failed with error %d\n", errno); - return false; - } - - while (1) + return Ret; + } + + for(;;) { struct pollfd fds[] = { { STDIN_FILENO, POLLIN, 0 }, @@ -60,7 +75,7 @@ { /* timeout */ SysregPrintf("timeout\n"); - Ret = EXIT_ERROR; + Ret = EXIT_CONTINUE; goto cleanup; }
@@ -70,10 +85,10 @@ if (!(fds[i].revents & POLLIN)) continue;
- bp = buf; + bp = Buffer;
/* Read one line or a maximum of 511 bytes into a buffer (leave space for the null character) */ - while (bp - buf < sizeof(buf) - 1) + while (bp - Buffer < (BUFFER_SIZE - 1)) { got = read(fds[i].fd, bp, 1);
@@ -87,10 +102,6 @@ /* No more data */ break; } - - /* Also break on newlines */ - if(*bp == '\n') - break;
if (fds[i].fd == STDIN_FILENO) { @@ -100,67 +111,94 @@ } else { + /* Also break on newlines */ + if(*bp == '\n') + break; + /* KDBG doesn't send a newline */ - if ((strstr(buf, "kdb:>")) || - (strstr(buf, "--- Press q"))) + if ((strstr(Buffer, "kdb:>")) || + (strstr(Buffer, "--- Press q"))) break; }
++bp; }
- if (bp == buf) - { - /* This usually means the machine shut down (like in 1st or 2nd stage) */ - Ret = EXIT_SHUTDOWN; + /* The rest of this logic is just about processing the serial output */ + if(fds[i].fd == STDIN_FILENO) + continue; + + /* Check whether the message is of zero length */ + if (bp == Buffer) + { + /* This can happen when the machine shut down (like after 1st or 2nd stage) + or after we got a Kdbg backtrace. */ + Ret = EXIT_CONTINUE; goto cleanup; }
+ /* Null-terminate the line */ *(++bp) = 0;
- /* Now check the output */ - if (fds[i].fd != STDIN_FILENO) - { - /* Check for "magic" sequences */ - if (strstr(buf, "kdb:>")) - { - ++KdbgHit; - - if (KdbgHit == 1) - { - /* We hit Kdbg for the first time, get a backtrace for the log */ - safewrite(ttyfd, "bt\r", 3); - continue; - } - else - { - /* We hit it yet another time, give up here */ - Ret = EXIT_ERROR; - goto cleanup; - } - } - else if (strstr(buf, "--- Press q")) - { - /* Send Return to get more data from Kdbg */ - safewrite(ttyfd, "\r", 1); + /* Detect whether the same line appears over and over again. + If that is the case, cancel this test after a specified number of repetitions. */ + if(!strcmp(Buffer, CacheBuffer)) + { + ++CacheHits; + + if(CacheHits > AppSettings.MaxCacheHits) + { + SysregPrintf("Test seems to be stuck in an endless loop, canceled!\n"); + Ret = EXIT_CONTINUE; + goto cleanup; + } + } + else + { + CacheHits = 0; + memcpy(CacheBuffer, Buffer, bp - Buffer); + } + + /* Output the line, raddr2line the included addresses if necessary */ + if (ResolveAddressFromFile(Raddr2LineBuffer, BUFFER_SIZE, Buffer)) + printf("%s", Raddr2LineBuffer); + else + printf("%s", Buffer); + + /* Check for "magic" sequences */ + if (strstr(Buffer, "kdb:>")) + { + ++KdbgHit; + + if (KdbgHit == 1) + { + /* We hit Kdbg for the first time, get a backtrace for the log */ + safewrite(ttyfd, "bt\r", 3); continue; } - else if (strstr(buf, "SYSREG_ROSAUTOTEST_FAILURE")) - { - /* rosautotest itself has problems, so there's no reason to continue */ + else + { + /* We hit it yet another time, give up here */ + Ret = EXIT_CONTINUE; goto cleanup; } - else if (*AppSettings.Stage[stage].Checkpoint && strstr(buf, AppSettings.Stage[stage].Checkpoint)) - { - /* We reached a checkpoint, so return success */ - Ret = EXIT_CHECKPOINT_REACHED; - goto cleanup; - } - - if (ResolveAddressFromFile(rbuf, sizeof(rbuf), buf)) - printf("%s", rbuf); - else - printf("%s", buf); + } + else if (strstr(Buffer, "--- Press q")) + { + /* Send Return to get more data from Kdbg */ + safewrite(ttyfd, "\r", 1); + continue; + } + else if (strstr(Buffer, "SYSREG_ROSAUTOTEST_FAILURE")) + { + /* rosautotest itself has problems, so there's no reason to continue */ + goto cleanup; + } + else if (*AppSettings.Stage[stage].Checkpoint && strstr(Buffer, AppSettings.Stage[stage].Checkpoint)) + { + /* We reached a checkpoint, so return success */ + Ret = EXIT_CHECKPOINT_REACHED; + goto cleanup; } } } @@ -172,4 +210,3 @@
return Ret; } -
Modified: trunk/tools/sysreg2/options.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/options.c?rev=41734&a... ============================================================================== --- trunk/tools/sysreg2/options.c [iso-8859-1] (original) +++ trunk/tools/sysreg2/options.c [iso-8859-1] Thu Jul 2 03:30:15 2009 @@ -1,3 +1,11 @@ +/* + * PROJECT: ReactOS System Regression Testing Utility + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Loading the utility settings + * COPYRIGHT: Copyright 2008-2009 Christoph von Wittich christoph_vw@reactos.org + * Copyright 2009 Colin Finck colin@reactos.org + */ + #include "sysreg.h"
bool LoadSettings(const char* XmlConfig) @@ -51,10 +59,18 @@ if (obj) xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST"number(/settings/general/maxcrashes/@value)",ctxt); + obj = xmlXPathEval(BAD_CAST"number(/settings/general/maxcachehits/@value)",ctxt); if ((obj != NULL) && (obj->type == XPATH_NUMBER)) { - AppSettings.MaxCrashes = (int)obj->floatval; + AppSettings.MaxCacheHits = (unsigned int)obj->floatval; + } + if (obj) + xmlXPathFreeObject(obj); + + obj = xmlXPathEval(BAD_CAST"number(/settings/general/maxretries/@value)",ctxt); + if ((obj != NULL) && (obj->type == XPATH_NUMBER)) + { + AppSettings.MaxRetries = (unsigned int)obj->floatval; } if (obj) xmlXPathFreeObject(obj);
Modified: trunk/tools/sysreg2/raddr2line.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/raddr2line.c?rev=4173... ============================================================================== --- trunk/tools/sysreg2/raddr2line.c [iso-8859-1] (original) +++ trunk/tools/sysreg2/raddr2line.c [iso-8859-1] Thu Jul 2 03:30:15 2009 @@ -1,3 +1,11 @@ +/* + * PROJECT: ReactOS System Regression Testing Utility + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Integrated raddr2line tool for getting source references from addresses + * COPYRIGHT: Copyright 2008-2009 Christoph von Wittich christoph_vw@reactos.org + * Copyright 2009 Colin Finck colin@reactos.org + */ + #include "sysreg.h"
bool GetPackagePath(char* Buffer, int BuffSize, char* Module)
Modified: trunk/tools/sysreg2/sysreg.h URL: http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/sysreg.h?rev=41734&am... ============================================================================== --- trunk/tools/sysreg2/sysreg.h [iso-8859-1] (original) +++ trunk/tools/sysreg2/sysreg.h [iso-8859-1] Thu Jul 2 03:30:15 2009 @@ -1,3 +1,11 @@ +/* + * PROJECT: ReactOS System Regression Testing Utility + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Shared header + * COPYRIGHT: Copyright 2008-2009 Christoph von Wittich christoph_vw@reactos.org + * Copyright 2009 Colin Finck colin@reactos.org + */ + #include <fcntl.h> #include <libvirt.h> #include <poll.h> @@ -16,9 +24,8 @@ #include <sys/sysinfo.h>
#define EXIT_CHECKPOINT_REACHED 0 -#define EXIT_SHUTDOWN 1 -#define EXIT_ERROR 2 -#define EXIT_NONCONTINUABLE_ERROR 3 +#define EXIT_CONTINUE 1 +#define EXIT_DONT_CONTINUE 2 #define NUM_STAGES 3
typedef struct { @@ -27,13 +34,14 @@ } stage;
typedef struct { - int MaxCrashes; int Timeout; char Filename[255]; char Name[80]; char HardDiskImage[255]; int ImageSize; stage Stage[3]; + unsigned int MaxCacheHits; + unsigned int MaxRetries; } Settings;
Settings AppSettings;
Modified: trunk/tools/sysreg2/sysreg.xml URL: http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/sysreg.xml?rev=41734&... ============================================================================== --- trunk/tools/sysreg2/sysreg.xml [iso-8859-1] (original) +++ trunk/tools/sysreg2/sysreg.xml [iso-8859-1] Thu Jul 2 03:30:15 2009 @@ -6,8 +6,13 @@ <!-- size of the hdd image in MB --> <hdd size="512"/>
- <!-- Maximum number of crashes allowed before we kill the VM --> - <maxcrashes value="10" /> + <!-- Maximum number of line cache hits allowed before we cancel this test and proceed with the next one. + See "console.c" code for more details. --> + <maxcachehits value="50" /> + + <!-- Maximum number of retries allowed before we cancel the entire testing process. + Note that this value needs to be at least 2, since the shutdowns after 1st and 2nd stage count as retries. --> + <maxretries value="15" /> </general> <firststage bootdevice="cdrom"> </firststage>
Modified: trunk/tools/sysreg2/utils.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/utils.c?rev=41734&... ============================================================================== --- trunk/tools/sysreg2/utils.c [iso-8859-1] (original) +++ trunk/tools/sysreg2/utils.c [iso-8859-1] Thu Jul 2 03:30:15 2009 @@ -1,3 +1,11 @@ +/* + * PROJECT: ReactOS System Regression Testing Utility + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Various auxiliary functions + * COPYRIGHT: Copyright 2008-2009 Christoph von Wittich christoph_vw@reactos.org + * Copyright 2009 Colin Finck colin@reactos.org + */ + #include "sysreg.h"
ssize_t safewrite(int fd, const void *buf, size_t count)
Modified: trunk/tools/sysreg2/virt.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/sysreg2/virt.c?rev=41734&... ============================================================================== --- trunk/tools/sysreg2/virt.c [iso-8859-1] (original) +++ trunk/tools/sysreg2/virt.c [iso-8859-1] Thu Jul 2 03:30:15 2009 @@ -1,3 +1,11 @@ +/* + * PROJECT: ReactOS System Regression Testing Utility + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Main entry point and controlling the virtual machine + * COPYRIGHT: Copyright 2008-2009 Christoph von Wittich christoph_vw@reactos.org + * Copyright 2009 Colin Finck colin@reactos.org + */ + #include "sysreg.h"
bool GetConsole(virDomainPtr vDomPtr, char* console) @@ -145,13 +153,13 @@ virConnectPtr vConn = NULL; virDomainPtr vDom; virDomainInfo info; - int Crashes; - int Stage; char qemu_img_cmdline[300]; FILE* file; char config[255]; - int Ret = EXIT_NONCONTINUABLE_ERROR; + int Ret = EXIT_DONT_CONTINUE; char console[50]; + unsigned int Retries; + unsigned int Stage;
if (argc == 2) strcpy(config, argv[1]); @@ -193,7 +201,7 @@
for(Stage = 0; Stage < NUM_STAGES; Stage++) { - for(Crashes = 0; Crashes < AppSettings.MaxCrashes; Crashes++) + for(Retries = 0; Retries < AppSettings.MaxRetries; Retries++) { vDom = LaunchVirtualMachine(vConn, AppSettings.Filename, AppSettings.Stage[Stage].BootDevice); @@ -223,19 +231,19 @@ /* If we have a checkpoint to reach for success, assume that the application used for running the tests (probably "rosautotest") continues with the next test after a VM restart. */ - if (Ret == EXIT_ERROR && *AppSettings.Stage[Stage].Checkpoint) - SysregPrintf("Crash %d encountered, resuming the testing process\n", Crashes); + if (Ret == EXIT_CONTINUE && *AppSettings.Stage[Stage].Checkpoint) + SysregPrintf("Rebooting VM (retry %d)\n", Retries + 1); else break; }
- if (Crashes == AppSettings.MaxCrashes) - { - SysregPrintf("Maximum number of allowed crashes exceeded, aborting!\n"); - break; - } - - if (Ret == EXIT_ERROR || Ret == EXIT_NONCONTINUABLE_ERROR) + if (Retries == AppSettings.MaxRetries) + { + SysregPrintf("Maximum number of allowed retries exceeded, aborting!\n"); + break; + } + + if (Ret == EXIT_CONTINUE || Ret == EXIT_DONT_CONTINUE) break; }
@@ -250,15 +258,11 @@ SysregPrintf("Status: Reached the checkpoint!\n"); break;
- case EXIT_SHUTDOWN: - SysregPrintf("Status: Machine shut down, but did not reach the checkpoint!\n"); - break; - - case EXIT_ERROR: + case EXIT_CONTINUE: SysregPrintf("Status: Failed to reach the checkpoint!\n"); break;
- case EXIT_NONCONTINUABLE_ERROR: + case EXIT_DONT_CONTINUE: SysregPrintf("Status: Testing process aborted!\n"); break; }