- major rewrite of sysreg

- refactor code to abstract os differences more cleaner
- code needs still be tested

svn path=/trunk/; revision=27569
This commit is contained in:
Johannes Anderwald 2007-07-10 18:23:07 +00:00
parent 06641a82b7
commit c0caac9484
10 changed files with 279 additions and 297 deletions

View file

@ -13,7 +13,7 @@
namespace System_
{
//---------------------------------------------------------------------------------------
FileReader::FileReader() : m_File(NULL)
FileReader::FileReader() : DataSource(), m_File(NULL)
{
}
//---------------------------------------------------------------------------------------
@ -21,12 +21,12 @@ namespace System_
{
}
//---------------------------------------------------------------------------------------
bool FileReader::openFile(TCHAR const * filename)
bool FileReader::open(const string & filename)
{
#ifdef UNICODE
m_File = _tfopen(filename, _T("rb,ccs=UNICODE"));
m_File = _tfopen(filename.c_str(), _T("rb,ccs=UNICODE"));
#else
m_File = _tfopen(filename, _T("rb"));
m_File = _tfopen(filename.c_str(), _T("rb"));
#endif
if (m_File)
@ -39,7 +39,7 @@ namespace System_
}
}
//---------------------------------------------------------------------------------------
bool FileReader::closeFile()
bool FileReader::close()
{
if (!m_File)
{
@ -55,7 +55,7 @@ namespace System_
return false;
}
//---------------------------------------------------------------------------------------
bool FileReader::readFile(vector<string> & lines)
bool FileReader::read(vector<string> & lines)
{
if (!m_File)
{

View file

@ -12,6 +12,7 @@
#include "user_types.h"
#include "data_source.h"
#include <vector>
namespace System_
@ -23,7 +24,7 @@ namespace System_
///
/// Description: this class implements reading from a file
class FileReader
class FileReader : public DataSource
{
public:
//---------------------------------------------------------------------------------------
@ -51,7 +52,7 @@ namespace System_
/// @param filename name of the file to open
/// @return bool
bool openFile(TCHAR const * filename);
virtual bool open(const string & filename);
//---------------------------------------------------------------------------------------
///
@ -61,7 +62,7 @@ namespace System_
///
/// @return bool
bool closeFile();
virtual bool close();
//---------------------------------------------------------------------------------------
///
@ -72,7 +73,7 @@ namespace System_
/// Note: returns true on success
///
bool readFile(vector<string> & lines);
virtual bool read(vector<string> & lines);

View file

@ -20,7 +20,7 @@ namespace System_
using std::vector;
//---------------------------------------------------------------------------------------
NamedPipeReader::NamedPipeReader() : h_Pipe(NULLVAL)
NamedPipeReader::NamedPipeReader() : DataSource(), h_Pipe(NULLVAL)
{
}
@ -33,7 +33,7 @@ namespace System_
//---------------------------------------------------------------------------------------
bool NamedPipeReader::openPipe(string const & PipeCmd)
bool NamedPipeReader::open(const string & PipeCmd)
{
if (h_Pipe != NULLVAL)
{
@ -41,7 +41,6 @@ namespace System_
return false;
}
#ifdef WIN32
h_Pipe = CreateFile(PipeCmd.c_str(),
GENERIC_WRITE | GENERIC_READ,
0,
@ -65,40 +64,19 @@ namespace System_
ConnectNamedPipe(
h_Pipe,
0);
#else
h_Pipe = open("PipeCmd.c_str()", O_RDONLY);
if(INVALID_HANDLE_VALUE == h_Pipe) {
cerr << "NamedPipeReader::openPipe> failed to open pipe " << PipeCmd << endl;
h_Pipe = NULLVAL;
return false;
}
else
{
cout << "NamedPipeReader::openPipe> successfully opened pipe" << endl;
return true;
}
#endif
}
//---------------------------------------------------------------------------------------
bool NamedPipeReader::closePipe()
bool NamedPipeReader::close()
{
if (!h_Pipe)
{
cerr << "NamedPipeReader::closePipe> pipe is not open" << endl;
return false;
}
#ifndef WIN32
close(h_Pipe);
#else
DisconnectNamedPipe(h_Pipe);
CloseHandle(h_Pipe);
#endif
h_Pipe = NULLVAL;
return true;
@ -193,13 +171,12 @@ namespace System_
//---------------------------------------------------------------------------------------
size_t NamedPipeReader::readPipe(vector<string> & vect)
bool NamedPipeReader::read(vector<string> & vect)
{
char * localbuf;
DWORD localsize = 100;
size_t lines = vect.size ();
#ifdef WIN32
BOOL fSuccess;
localbuf = (char*) HeapAlloc(GetProcessHeap(), 0, localsize * sizeof(char));
#ifdef UNICODE
@ -253,46 +230,6 @@ namespace System_
return 0;
}
#else /* WIN32 */
localbuf = (char*) malloc(localsize * sizeof(char));
if (localbuf != NULL)
{
DWORD cbRead;
bool append_line = false;
do
{
do
{
memset(localbuf, 0, localsize * sizeof(char));
cbRead = read(h_Pipe,
localbuf,
(localsize-1) * sizeof(char));
if (cbRead > 0)
{
extractLines(localbuf, vect, append_line, cbRead);
}
} while (!cbRead); // repeat loop as long as there is data to read
} while (append_line);
if (cbRead < 0)
return 0;
free(localbuf);
}
else
{
return 0;
}
#endif /* WIN32 */
return (vect.size () - lines);
}

View file

@ -14,6 +14,7 @@
#include "user_types.h"
#include "data_source.h"
#include <vector>
#include <stdio.h>
#include <stdlib.h>
@ -42,7 +43,7 @@ namespace System_
///
/// Description: this class implements a named pipe reader.
class NamedPipeReader
class NamedPipeReader : public DataSource
{
public:
@ -64,7 +65,7 @@ namespace System_
//---------------------------------------------------------------------------------------
///
/// openPipe
/// open
///
/// Description: this function attempts to open a pipe. If an pipe is already open or
/// it fails to open a pipe, the function returns false
@ -73,17 +74,17 @@ namespace System_
///
/// @return bool
bool openPipe(const string & PipeCmd);
virtual bool open(const string & PipeCmd);
//---------------------------------------------------------------------------------------
///
/// closePipe
/// close
///
/// Description: closes a pipe. Returns true on success
///
/// @return bool
bool closePipe();
virtual bool close();
//---------------------------------------------------------------------------------------
///
@ -95,7 +96,7 @@ namespace System_
/// @param Buffer to be written to
/// @return size_t
size_t readPipe(std::vector<string> & vect);
virtual bool read(std::vector<string> & vect);
//---------------------------------------------------------------------------------------
///

View file

@ -57,6 +57,10 @@ namespace System_
free(command);
return pid;
}
void OsSupport::sleep(long value)
{
_sleep(value);
}
#else
/********************************************************************************************************************/
OsSupport::ProcessID OsSupport::createProcess(TCHAR *procname, int procargsnum, TCHAR **procargs)
@ -83,6 +87,11 @@ namespace System_
return true;
}
void OsSupport::sleep(long value)
{
sleep(value);
}
#endif

View file

@ -10,7 +10,7 @@
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#if 0
#if 1
#include <windows.h>
#else
#include <unistd.h>
@ -39,7 +39,7 @@ namespace System_
#else
typedef pid_t ProcessID;
#endif
#endif
//---------------------------------------------------------------------------------------
///
@ -76,6 +76,8 @@ namespace System_
static bool terminateProcess(ProcessID pid);
static void sleep(long value);
protected:
//---------------------------------------------------------------------------------------
///

View file

@ -13,6 +13,7 @@
#include "user_types.h"
#include "data_source.h"
#include <stdio.h>
#include <stdlib.h>
@ -25,7 +26,7 @@ namespace System_
/// Description: this class implements a pipe reader. It uses _popen to perform opening of
/// pipe / _pclose
class PipeReader
class PipeReader : public DataSource
{
public:

View file

@ -65,31 +65,143 @@ namespace Sysreg_
{
}
//---------------------------------------------------------------------------------------
void RosBootTest::getPidFromFile()
{
FileReader file;
if (file.open(m_PidFile.c_str ()))
{
vector<string> lines;
file.read(lines);
if (lines.size() == 1)
{
string line = lines[0];
m_Pid = _ttoi(line.c_str ());
}
file.close();
}
}
//---------------------------------------------------------------------------------------
bool RosBootTest::executeBootCmd()
{
m_Pid = OsSupport::createProcess ((TCHAR*)m_BootCmd.c_str(), 0, NULL);
if (!m_Pid)
{
cerr << "Error: failed to launch boot cmd" << m_BootCmd << endl;
return false;
}
return true;
}
//---------------------------------------------------------------------------------------
void RosBootTest::delayRead()
{
if (m_Delayread)
{
///
/// delay reading until emulator is ready
///
OsSupport::sleep(m_Delayread * CLOCKS_PER_SEC );
}
}
//---------------------------------------------------------------------------------------
bool RosBootTest::execute(ConfigParser &conf_parser)
{
string boot_cmd;
string debug_port;
string timeout;
string delayread;
bool ret;
bool RosBootTest::configurePipe()
{
if (!_tcscmp(m_DebugPort.c_str(), _T("qemupipe")))
{
string::size_type pipe_pos = m_BootCmd.find(_T("-serial pipe:"));
if (pipe_pos != string::npos)
{
pipe_pos += 12;
string::size_type pipe_pos_end = m_BootCmd.find (_T(" "), pipe_pos);
if (pipe_pos != string::npos && pipe_pos_end != string::npos)
{
m_Pipe = _T("\\\\.\\pipe\\") + m_BootCmd.substr (pipe_pos, pipe_pos_end - pipe_pos);
#ifdef __LINUX__
m_DataSource = new PipeReader();
#else
m_DataSource = new NamedPipeReader();
#endif
return true;
}
}
}
else if (!_tcscmp(m_DebugPort.c_str(), _T("vmwarepipe")))
{
cerr << "VmWare debug pipe is currently fixed to \\\\.\\pipe\\vmwaredebug" << endl;
m_Pipe = _T("\\\\.\\pipe\\vmwaredebug");
#ifdef __LINUX__
m_DataSource = new PipeReader();
#else
m_DataSource = new NamedPipeReader();
#endif
return true;
}
//
// FIXME
// support other emulators
return false;
}
//---------------------------------------------------------------------------------------
bool RosBootTest::configureFile()
{
if (!_tcscmp(m_DebugPort.c_str(), _T("qemufile")))
{
string::size_type file_pos = m_BootCmd.find(_T("-serial file:"));
if (file_pos != string::npos)
{
file_pos += 12;
string::size_type file_pos_end = m_BootCmd.find (_T(" "), file_pos);
if (file_pos != string::npos && file_pos_end != string::npos)
{
m_File = m_BootCmd.substr (file_pos, file_pos_end - file_pos);
m_DataSource = new FileReader();
return true;
}
cerr << "Error: missing space at end of option" << endl;
}
}
else if (!_tcscmp(m_DebugPort.c_str(), _T("vmwarefile")))
{
cerr << "VmWare debug file is currently fixed to debug.log" << endl;
m_File = "debug.log";
m_DataSource = new FileReader();
return true;
}
//
// FIXME
// support other emulators
return false;
}
//---------------------------------------------------------------------------------------
bool RosBootTest::readConfigurationValues(ConfigParser &conf_parser)
{
///
/// read required configuration arguments
///
if (!conf_parser.getStringValue (RosBootTest::DEBUG_PORT, debug_port))
if (!conf_parser.getStringValue (RosBootTest::DEBUG_PORT, m_DebugPort))
{
cerr << "Error: ROSBOOT_DEBUG_TYPE is not set in configuration file" << endl;
return false;
}
if (!conf_parser.getStringValue(RosBootTest::VARIABLE_NAME, boot_cmd))
if (!conf_parser.getStringValue(RosBootTest::VARIABLE_NAME, m_BootCmd))
{
cerr << "Error: ROSBOOT_CMD is not set in configuration file" << endl;
return false;
}
string timeout;
if (conf_parser.getStringValue(RosBootTest::TIME_OUT, timeout))
{
TCHAR * stop;
@ -101,6 +213,19 @@ namespace Sysreg_
m_Timeout = 60.0;
}
}
if (m_DebugPort.find(_T("pipe")) != string::npos)
{
#ifdef __LINUX__
if (!conf_parser.getStringValue (RosBootTest::PID_FILE, m_PidFile))
{
cerr << "Error: linux hosts must provide pid file option" << endl;
return false;
}
_tremove(m_PidFile.c_str ());
#endif
}
string delayread;
if (conf_parser.getStringValue(RosBootTest::DELAY_READ, delayread))
{
@ -121,30 +246,66 @@ namespace Sysreg_
conf_parser.getStringValue (RosBootTest::CRITICAL_APP, m_CriticalApp);
conf_parser.getStringValue (RosBootTest::DEBUG_FILE, m_DebugFile);
if (conf_parser.getStringValue (RosBootTest::PID_FILE, m_PidFile))
{
_tremove(m_PidFile.c_str ());
}
if (!_tcscmp(debug_port.c_str(), _T("pipe")))
{
ret = fetchDebugByPipe(boot_cmd);
}
else if (!_tcscmp(debug_port.c_str(), _T("file")))
{
if (!m_DebugFile.length())
{
cerr << "Error: ROSBOOT_DEBUG_FILE is not set in configuration file" << endl;
return false;
}
ret = fetchDebugByFile(boot_cmd);
}
else
{
cerr <<"Error: unknown debug port " << debug_port <<endl
<<" Currently only file|pipe is supported" <<endl;
return false;
}
return true;
}
//---------------------------------------------------------------------------------------
bool RosBootTest::execute(ConfigParser &conf_parser)
{
if (!readConfigurationValues(conf_parser))
{
return false;
}
string src;
if (m_DebugPort.find(_T("pipe")) != string::npos)
{
if (!configurePipe())
{
cerr << "Error: failed to configure pipe" << endl;
return false;
}
#ifndef __LINUX__
if (!executeBootCmd())
{
cerr << "Error: failed to launch emulator" << endl;
return false;
}
#endif
src = m_Pipe;
}
else if (m_DebugPort.find(_T("file")) != string::npos)
{
if (!configureFile())
{
cerr << "Error: failed to configure pipe" << endl;
return false;
}
if (!executeBootCmd())
{
cerr << "Error: failed to launch emulator" << endl;
return false;
}
src = m_File;
}
if (!m_DataSource->open(src))
{
cerr << "Error: failed to open data source with " << src << endl;
return false;
}
bool ret = analyzeDebugData();
m_DataSource->close();
OsSupport::sleep(3 * CLOCKS_PER_SEC);
if (m_Pid)
{
OsSupport::terminateProcess (m_Pid);
}
return ret;
}
@ -338,65 +499,21 @@ namespace Sysreg_
}
//---------------------------------------------------------------------------------------
bool RosBootTest::fetchDebugByPipe(string boot_cmd)
bool RosBootTest::analyzeDebugData()
{
string pipecmd = _T("");
bool ret = true;
///
/// FIXME
/// split up arguments
OsSupport::ProcessID pid = OsSupport::createProcess ((TCHAR*)boot_cmd.c_str (), 0, NULL);
string::size_type pipe_pos = boot_cmd.find (_T("serial pipe:"));
NamedPipeReader namedpipe_reader;
if (pipe_pos != string::npos)
{
pipe_pos += 12;
string::size_type pipe_pos_end = boot_cmd.find (_T(" "), pipe_pos);
if (pipe_pos != string::npos && pipe_pos > 0 && pipe_pos < boot_cmd.size())
{
pipecmd = _T("\\\\.\\pipe\\") + boot_cmd.substr (pipe_pos, pipe_pos_end - pipe_pos);
}
}
if (!pipecmd.length ())
{
//FIXME
pipecmd = _T("\\\\.\\pipe\\vmwaredebug");
}
if (m_Delayread)
{
///
/// delay reading until emulator is ready
///
sleep( (clock_t)m_Delayread * CLOCKS_PER_SEC );
}
if (!namedpipe_reader.openPipe(pipecmd))
{
cerr << "Error: failed to open pipe with cmd: " << boot_cmd <<endl;
return false;
}
string Buffer;
Buffer.reserve (500);
vector<string> vect;
size_t lines = 0;
bool write_log;
ofstream file;
if (m_DebugFile.length ())
bool ret = true;
if (m_DebugFile.length ())
{
_tremove(m_DebugFile.c_str ());
file.open (m_DebugFile.c_str ());
}
write_log = file.is_open ();
while(1)
{
if (isTimeout(m_Timeout))
@ -404,8 +521,8 @@ namespace Sysreg_
break;
}
size_t prev_count = vect.size ();
size_t line_count = namedpipe_reader.readPipe (vect);
if (!line_count)
if (!m_DataSource->read (vect))
{
cerr << "No data read" << endl;
continue;
@ -429,109 +546,14 @@ namespace Sysreg_
{
break;
}
lines += line_count;
}
namedpipe_reader.closePipe ();
lines += (vect.size() -prev_count); //WTF?
}
m_DataSource->close();
if (write_log)
{
file.close();
}
_sleep(3* CLOCKS_PER_SEC);
OsSupport::terminateProcess (pid);
return ret;
return ret;
}
//---------------------------------------------------------------------------------------
bool RosBootTest::fetchDebugByFile(string boot_cmd)
{
PipeReader pipe_reader;
_tremove(m_DebugFile.c_str ());
if (!pipe_reader.openPipe(boot_cmd, string(_T("rt"))))
{
cerr << "Error: failed to open pipe with cmd: " << boot_cmd << endl;
return false;
}
if (m_Delayread)
{
///
/// delay reading until emulator is ready
///
sleep( (clock_t)m_Delayread * CLOCKS_PER_SEC );
}
OsSupport::ProcessID pid = 0;
if (m_PidFile != _T(""))
{
FileReader file;
if (file.openFile(m_PidFile.c_str ()))
{
vector<string> lines;
file.readFile(lines);
if (lines.size())
{
string line = lines[0];
pid = _ttoi(line.c_str ());
}
file.closeFile();
}
}
FileReader file;
if (!file.openFile (m_DebugFile.c_str ()))
{
cerr << "Error: failed to open debug log " << m_DebugFile<< endl;
pipe_reader.closePipe ();
return false;
}
vector<string> lines;
bool ret = true;
while(!pipe_reader.isEof ())
{
if (file.readFile (lines))
{
DebugState state = checkDebugData(lines);
if (state == DebugStateBSODDetected || state == DebugStateUMEDetected)
{
ret = false;
break;
}
else if (state == DebugStateCPReached)
{
break;
}
}
if (isTimeout(m_Timeout))
{
///
/// timeout has been reached
///
if (m_Checkpoint != _T(""))
{
///
/// timeout was reached but
/// the checkpoint was not reached
/// we see this as a "hang"
///
ret = false;
}
break;
}
}
file.closeFile ();
if (pid)
{
OsSupport::terminateProcess (pid);
}
pipe_reader.closePipe ();
return ret;
}
} // end of namespace Sysreg_

View file

@ -12,16 +12,16 @@
#include "reg_test.h"
#include "data_source.h"
#include <vector>
#ifndef WIN32
#include <unistd.h>
#define _sleep sleep
#endif
namespace Sysreg_
{
using std::vector;
using System_::DataSource;
//---------------------------------------------------------------------------------------
///
/// class RosBootTest
@ -74,31 +74,15 @@ namespace Sysreg_
virtual bool execute(ConfigParser & conf_parser);
protected:
//---------------------------------------------------------------------------------------
///
/// fetchDebugByPipe
///
/// Description: this functions debugs ReactOS by PipeReader class
///
/// Note: if an error occurs, this function returns false
///
/// @param BootCmd the command which is passed to PipeReader class
/// @return bool
bool fetchDebugByPipe(string BootCmd);
void getPidFromFile();
bool executeBootCmd();
void delayRead();
bool configurePipe();
bool configureFile();
bool analyzeDebugData();
bool readConfigurationValues(ConfigParser & conf_parser);
//---------------------------------------------------------------------------------------
///
/// fetchDebugByFile
///
/// Description: this functions fetches debug info by reading a debug log
///
/// Note: if an error occurs, this function returns false
///
/// @param BootCmd the command which is passed to PipeReader class
/// @return bool
bool fetchDebugByFile(string BootCmd);
//---------------------------------------------------------------------------------------
///
@ -144,8 +128,15 @@ protected:
string m_Checkpoint;
string m_CriticalApp;
string m_DebugFile;
string m_BootCmd;
string m_DebugPort;
string m_Pipe;
string m_File;
DataSource * m_DataSource;
vector <string> m_Checkpoints;
unsigned long m_Delayread;
long m_Pid;
long m_DelayRead;
}; // end of class RosBootTest

View file

@ -18,11 +18,11 @@ endif
SYSREGBUILD_TARGET = \
$(EXEPREFIX)$(SYSREGBUILD_OUT_)sysreg$(EXEPOSTFIX)
ifeq ($(HOST),mingw32-linux)
SYSREGBUILD_SOURCES = $(addprefix $(SYSREGBUILD_BASE_),\
conf_parser.cpp \
env_var.cpp \
pipe_reader.cpp \
namedpipe_reader.cpp \
rosboot_test.cpp \
sysreg.cpp \
file_reader.cpp \
@ -30,10 +30,28 @@ SYSREGBUILD_SOURCES = $(addprefix $(SYSREGBUILD_BASE_),\
unicode.cpp \
)
else
SYSREGBUILD_SOURCES = $(addprefix $(SYSREGBUILD_BASE_),\
conf_parser.cpp \
env_var.cpp \
rosboot_test.cpp \
namedpipe_reader.cpp \
sysreg.cpp \
file_reader.cpp \
os_support.cpp \
unicode.cpp \
)
endif
SYSREGBUILD_OBJECTS = \
$(addprefix $(INTERMEDIATE_), $(SYSREGBUILD_SOURCES:.cpp=.o))
SYSREGBUILD_HOST_CFLAGS = $(TOOLS_CPPFLAGS) -D__USE_W32API -Iinclude -Iinclude/reactos -Iinclude/psdk
ifeq ($(HOST),mingw32-linux)
SYSREGBUILD_HOST_CFLAGS = $(TOOLS_CPPFLAGS) -D__USE_W32API -D__LINUX__ -Iinclude -Iinclude/reactos -Iinclude/psdk -Iinclude/reactos/libs
else
SYSREGBUILD_HOST_CFLAGS = $(TOOLS_CPPFLAGS) -D__USE_W32API -Iinclude -Iinclude/reactos -Iinclude/psdk -Iinclude/reactos/libs
endif
SYSREGBUILD_HOST_LFLAGS = $(TOOLS_LFLAGS)
@ -56,11 +74,11 @@ $(SYSREGBUILD_INT_)env_var.o: $(SYSREGBUILD_BASE_)env_var.cpp | $(SYSREGBUILD_IN
$(SYSREGBUILD_INT_)pipe_reader.o: $(SYSREGBUILD_BASE_)pipe_reader.cpp | $(SYSREGBUILD_INT)
$(ECHO_CC)
${host_gpp} $(SYSREGBUILD_HOST_CFLAGS) -c $< -o $@
ifneq ($(HOST),mingw32-linux)
$(SYSREGBUILD_INT_)namedpipe_reader.o: $(SYSREGBUILD_BASE_)namedpipe_reader.cpp | $(SYSREGBUILD_INT)
$(ECHO_CC)
${host_gpp} $(SYSREGBUILD_HOST_CFLAGS) -c $< -o $@
endif
$(SYSREGBUILD_INT_)rosboot_test.o: $(SYSREGBUILD_BASE_)rosboot_test.cpp | $(SYSREGBUILD_INT)
$(ECHO_CC)
${host_gpp} $(SYSREGBUILD_HOST_CFLAGS) -c $< -o $@