* beginning of a system regression tools

svn path=/trunk/; revision=24584
This commit is contained in:
Johannes Anderwald 2006-10-20 15:49:46 +00:00
parent 66e157c5eb
commit 4ba2129226
14 changed files with 1515 additions and 0 deletions

View file

@ -0,0 +1,204 @@
#ifndef COMPONENT_FACTORY_TEMPLATE_H_ //comp_factory.h
#define COMPONENT_FACTORY_TEMPLATE_H_
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/comp_factory.h
* PURPOSE: component management
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include <map>
#include <vector>
namespace System_
{
using std::map;
using std::vector;
using std::endl;
//----------------------------------------------------------
///
/// ComponentFactoryTemplate
///
/// This class servess as a factory class for components. In general
/// can be used for any possible class which has base class
/// and a derrived class
///
//--------------------------------------------------------------------
///
/// create
///
/// Description: this template function creates a function which returns
/// objects of type ElementType but in real are objects of DerrivedType
///
template<class ElementType, class DerrivedType>
static ElementType * create ()
{
return new DerrivedType();
}
//--------------------------------------------------------------------
template<typename ElementType, typename ElementId>
class ComponentFactoryTemplate
{
typedef ElementType * (*creation_function)();
typedef map<ElementId, creation_function> ElementMap;
typedef vector<ElementId> ElementIdVector;
public:
//--------------------------------------------------------------------
///
/// ComponentFactoryTemplate
///
/// Description: default destructor of class ComponentFactoryTemplate
///
ComponentFactoryTemplate()
{
}
//--------------------------------------------------------------------
///
/// ~ComponentFactoryTemplate
///
/// Description: default destructor of class ComponentFactoryTemplate
///
virtual ~ComponentFactoryTemplate()
{
}
//--------------------------------------------------------------------
///
/// listComponent
///
/// Description: lists all registererd components ids
void listComponentIds()
{
for(unsigned i = 0; i < ids_.size (); i++)
cout<<ids_[i]<<endl;
}
//--------------------------------------------------------------------
///
/// isComponentRegistered
///
/// Description: this function just checks if a component with a given
/// id has been registered or not. If it is it returns true else false
///
/// @return bool
/// @param element id of the component
bool isComponentRegistered(ElementId const & id)
{
typename ElementMap::const_iterator iter = elements_.find(id);
if(iter != elements_.end())
return true;
else
return false;
}
//--------------------------------------------------------------------
///
/// getNumOfComponents
///
/// Description: returns how many components have been registered
const unsigned getNumOfComponents()
{
return ids_.size ();
}
//--------------------------------------------------------------------
///
/// registerComponent
///
/// Description: this function is template function in a class template.
/// The purpose is that at compiletime for each of the derriving classes of
/// ElementType a registerComponent function is generated and then all classes
/// of that type are added at runtime to factory.
/// returns zero on success, nonzero on failure
///
/// @return bool
/// @param id the element id of the content type
template<typename ContentType>
bool registerComponent(ElementId const & id)
{
typename ElementMap::const_iterator iter = elements_.find(id);
if(iter != elements_.end())
return false;
ids_.insert(ids_.begin(),id);
elements_.insert(std::make_pair<ElementId, creation_function >(id, &create<ElementType, ContentType>));
return true;
}
//--------------------------------------------------------------------
///
/// deregisterComponent
///
/// Description: unregisters a given component indentified by param id
/// After unregistration, the specified component can no longer be
/// created
/// @return bool
/// @param id the element id of the ContentType
template<typename ContentType>
const bool deregisterComponent(ElementId const & id)
{
typename ElementMap::const_iterator iterator = elements_.find(id);
if(iterator != elements_.end())
{
elements_.erase(iterator);
return true;
}
else
return false;
}
//--------------------------------------------------------------------
///
/// createComponent
///
/// Description: creates a component according to the specified information
/// returns the component encapsulated in an std::auto_ptr
/// @param id specifies the key id, to look for
/// @return std::auto_ptr<ElementType>
ElementType * createComponent(ElementId const & id) const
{
typename ElementMap::const_iterator first_it = elements_.find(id);
if(first_it != elements_.end())
return (first_it->second)();
else
return 0;
}
//--------------------------------------------------------------------
///
/// deleteComponent
///
/// Description: deletes a component
/// @param element the element to be deleted
void deleteComponent(ElementType * element)
{
delete element;
}
protected:
ElementMap elements_;
ElementIdVector ids_;
};
} //end of namespace Sysreg_
#endif

View file

@ -0,0 +1,98 @@
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: configuration parser
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "conf_parser.h"
#include <iostream>
#include <sstream>
#include <fstream>
namespace Sysreg_
{
using std::cout;
using std::cerr;
using std::endl;
using std::ifstream;
//---------------------------------------------------------------------------------------
ConfigParser::ConfigParser()
{
}
//---------------------------------------------------------------------------------------
ConfigParser::~ConfigParser()
{
m_Map.clear ();
}
//---------------------------------------------------------------------------------------
bool ConfigParser::parseFile(TCHAR * FileName)
{
FILE * file;
#ifdef UNICODE
file = _tfopen(FileName, _T("rt,ccs=UNICODE"));
#else
file = _tfopen(FileName, _T("rt"));
#endif
if (!file)
{
cerr << " Error: ConfigParser::parseFile failed to open configuration file " <<endl;
return false;
}
bool ret = false;
while (!feof(file))
{
TCHAR buffer[500];
TCHAR * buf;
buf = _fgetts(buffer, sizeof(buffer) / sizeof(TCHAR), file);
if (buf)
{
if (buffer[0] != ';')
{
string s_buffer = string(buffer);
string::size_type ws_pos = s_buffer.find_first_of (_T("="));
if (ws_pos != string::npos && ws_pos > 0 && ws_pos < s_buffer.size())
{
string name = s_buffer.substr (0, ws_pos);
string value = s_buffer.substr (ws_pos + 1);
if (value[value.length () -1] == 0xA)
{
// remove newline char
value[value.length ()-1] = _T('\0');
}
m_Map[name] = value;
ret = true;
}
}
}
}
return ret;
}
//---------------------------------------------------------------------------------------
bool ConfigParser::getStringValue(string &ConfVariable, string &ConfValue)
{
ConfigMap::iterator it = m_Map.find (ConfVariable);
if (it == m_Map.end ())
{
#ifdef NDEBUG
cerr << "ConfigParser::getValue failed to find " << ConfVariable << endl;
#endif
return false;
}
ConfValue = it->second;
return true;
}
} // end of namespace Sysreg_

View file

@ -0,0 +1,92 @@
#ifndef CONF_PARSER_H__
#define CONF_PARSER_H__
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: configuration parser
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include <string>
#include <map>
#include <tchar.h>
namespace Sysreg_
{
using std::map;
//---------------------------------------------------------------------------------------
///
/// class ConfigParser
///
/// Description: this class reads configuration entries from a configuration file
/// Each entry must have the form of VALUE=XXX. The entries are stored
/// in a map which can be queried after parsing the configuration file
///
/// Note: lines beginning with an ; are ignored
///
/// Usage: First, call parseFile with param to file. Finally, call getValue with the
/// appropiate type
class ConfigParser
{
public:
typedef std::basic_string<TCHAR> string;
typedef std::basic_istringstream<TCHAR> istringstream;
typedef map<string, string> ConfigMap;
//---------------------------------------------------------------------------------------
///
/// ConfigParser
///
/// Description: constructor of class ConfigParser
ConfigParser();
//---------------------------------------------------------------------------------------
///
/// ~ConfigParser
///
/// Description: destructor of class ConfigParser
virtual ~ConfigParser();
//---------------------------------------------------------------------------------------
///
/// parseFile
///
/// Description: this function takes as param a path to file. it attempts to parse this specific
/// file with the given syntax. On success it returns true.
///
/// Note: Everytime parseFile is called, the previous stored values are cleared
///
/// @param FileName path to configuration file
/// @return bool
bool parseFile(TCHAR * FileName);
//--------------------------------------------------------------------------------------
///
/// getStringValue
///
/// Description: attempts to read a config variable from the configuration file
/// If the variable name is not found, it returns false and the param
/// ConfValue remains untouched. On success it returns the true.
///
/// @param ConfVariable name of the configuration variable to retrieve
/// @param ConfValue type of value to retrieve
bool getStringValue(string & ConfVariable, string & ConfValue);
protected:
ConfigMap m_Map;
}; // end of class ConfigParser
} // end of namspace Sysreg_
#endif /* end of CONF_PARSER_H__ */

View file

@ -0,0 +1,67 @@
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: environment variable lookup
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "env_var.h"
#include <iostream>
namespace System_
{
using std::cout;
using std::endl;
using std::cerr;
//---------------------------------------------------------------------------------------
EnvironmentVariable::EnvironmentVariable()
{
}
//---------------------------------------------------------------------------------------
EnvironmentVariable::~EnvironmentVariable()
{
m_Map.clear ();
}
//---------------------------------------------------------------------------------------
bool EnvironmentVariable::getValue(const System_::string &EnvName, System_::string &EnvValue)
{
EnvironmentMap::const_iterator it = m_Map.find (EnvName);
if (it != m_Map.end())
{
EnvValue = it->second;
return true;
}
TCHAR * value = _tgetenv(EnvName.c_str ());
if (!value)
{
#ifdef NDEBUG
cerr << "EnvironmentVariable::getValue found no value for " << EnvName << endl;
#endif
return false;
}
if (!_tcslen(value))
{
#ifdef NDEBUG
cerr << "EnvironmentVariable::getValue found no value for " << EnvName << endl;
#endif
return false;
}
EnvValue = value;
m_Map[EnvName] = EnvValue;
return true;
}
} // end of namespace System_

View file

@ -0,0 +1,71 @@
#ifndef ENV_VAR_H__
#define ENV_VAR_H__
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: environment variable lookup
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include <string>
#include <map>
#include <tchar.h>
namespace System_
{
using std::map;
typedef std::basic_string<TCHAR> string;
//---------------------------------------------------------------------------------------
///
/// class EnvironmentVariable
///
/// Description: this class performs looking up environment variable from the system
/// The result is also stored in its internal map to cache results
class EnvironmentVariable
{
typedef map<string, string> EnvironmentMap;
public:
//---------------------------------------------------------------------------------------
///
/// EnvironmentVariable
///
/// Description: constructor of class EnvironmentVariable
EnvironmentVariable();
//---------------------------------------------------------------------------------------
///
/// ~EnvironmentVariable
///
/// Description: destructor of class EnvironmentVariable
virtual ~EnvironmentVariable();
//---------------------------------------------------------------------------------------
///
/// getValue
///
/// Description: this function returns the value of an associated environment variable. if
/// the variable is set it returns true and the value in the parameter EnvValue. On error
/// it returns false and the param EnvValue remains untouched
///
/// @param EnvName name of environment variable to retrieve
/// @param EnvValue value of the environment variable
/// @return bool
bool getValue(const string & EnvName, string & EnvValue);
protected:
EnvironmentMap m_Map;
}; // end of class EnvironmentVariable
} // end of namespace System_
#endif /* end of ENV_VAR_H__ */

View file

@ -0,0 +1,132 @@
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: pipe reader support
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "pipe_reader.h"
#include <iostream>
#include <assert.h>
namespace System_
{
using std::cout;
using std::endl;
using std::cerr;
//---------------------------------------------------------------------------------------
PipeReader::PipeReader() : m_File(NULL)
{
}
//---------------------------------------------------------------------------------------
PipeReader::~PipeReader()
{
}
//---------------------------------------------------------------------------------------
bool PipeReader::openPipe(const System_::string &PipeCmd, System_::string AccessMode)
{
if (m_File != NULL)
{
#ifdef NDEBUG
cerr << "PipeReader::openPipe> pipe already open" << endl;
#endif
return false;
}
//
m_File = _tpopen(PipeCmd.c_str(), AccessMode.c_str());
if (m_File)
{
#ifdef NDEBUG
cerr << "PipeReader::openPipe> successfully opened pipe" << endl;
#endif
return true;
}
#ifdef NDEBUG
cerr << "PipeReader::openPipe> failed to open pipe " << PipeCmd << endl;
#endif
return false;
}
//---------------------------------------------------------------------------------------
bool PipeReader::closePipe()
{
if (!m_File)
{
#ifdef NDEBUG
cerr << "PipeReader::closePipe> pipe is not open" << endl;
#endif
return false;
}
int res = _pclose(m_File);
if (res == UINT_MAX)
{
#ifdef NDEBUG
cerr << "Error: _pclose failed " <<endl;
#endif
return false;
}
m_File = NULL;
return true;
}
//---------------------------------------------------------------------------------------
bool PipeReader::isEof() const
{
return feof(m_File);
}
//---------------------------------------------------------------------------------------
string::size_type PipeReader::readPipe(System_::string &Buffer)
{
TCHAR * buf = (TCHAR *)Buffer.c_str();
System_::string::size_type size = Buffer.capacity();
//#ifdef NDEBUG
memset(buf, 0x0, sizeof(TCHAR) * size);
//#endif
TCHAR * res = _fgetts(buf, size, m_File);
if (!res)
{
#ifdef NDEBUG
cerr << "Error: PipeReader::readPipe failed" << endl;
#endif
return 0;
}
#ifdef NDEBUG
cerr << "PipeReader::readPipe> res: " << Buffer << endl;
#endif
return _tcslen(buf);
}
//---------------------------------------------------------------------------------------
bool PipeReader::writePipe(const string & Buffer)
{
//TODO
// implement me
cerr << "PipeReader::writePipe is not yet implemented" << endl;
return false;
}
} // end of namespace System_

View file

@ -0,0 +1,117 @@
#ifndef PIPE_READER_H__
#define PIPE_READER_H__
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: pipe reader support
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include <string>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
namespace System_
{
typedef std::basic_string<TCHAR> string;
//---------------------------------------------------------------------------------------
///
/// class PipeReader
///
/// Description: this class implements a pipe reader. It uses _popen to perform opening of
/// pipe / _pclose
class PipeReader
{
public:
//---------------------------------------------------------------------------------------
///
/// PipeReader
///
/// Description: constructor of class PipeReader
PipeReader();
//---------------------------------------------------------------------------------------
///
/// virtual ~PipeReader
///
/// Description: destructor of class PipeReader
virtual ~PipeReader();
//---------------------------------------------------------------------------------------
///
/// openPipe
///
/// 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
///
/// @param PipeCmd command of the pipe to open
/// @param AccessMode on how to open the pipe
/// accepted modes are t ... text mode - not compatible with b
/// b ... binary mode - not compatible with t
/// r ... allows reading from the pipe
/// w ... allows writing to the pipe
/// @return bool
bool openPipe(const string & PipeCmd, string AccessMode = _T("rt"));
//---------------------------------------------------------------------------------------
///
/// closePipe
///
/// Description: closes a pipe. Returns true on success
///
/// @return bool
bool closePipe();
//---------------------------------------------------------------------------------------
///
/// readPipe
///
/// Description: attempts to read from the pipe. Returns true on success. If it returns
/// false, call PipeReader::isEoF() to determine if the pipe should be closed
///
/// @param Buffer to be written to
/// @return string::size_type
string::size_type readPipe(string & Buffer);
//---------------------------------------------------------------------------------------
///
/// writePipe
///
/// Description: attempts to write to the pipe. Returns true on success.
///
/// @param Buffer containing information which is written to the pipe
bool writePipe(const string & Buffer);
//---------------------------------------------------------------------------------------
///
/// isEof
///
/// Description: returns true if the pipe has reached end of file. The caller should call
/// closePipe if this function returns true
bool isEof() const;
protected:
FILE * m_File;
}; // end of class PipeReader
} // end of namespace System_
#endif /* end of PIPE_READER_H__ */

View file

@ -0,0 +1,87 @@
#ifndef REG_TEST_H__
#define REG_TEST_H__
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: regression test abstract class
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "conf_parser.h"
#include <string>
#include <tchar.h>
namespace Sysreg_
{
using Sysreg_::ConfigParser;
typedef std::basic_string<TCHAR> string;
//-------------------------------------------------------------------
///
/// class RegressionTest
///
/// Description: The class RegressionTest is an abstract base class. Every
/// regression test class derives from this class.
class RegressionTest
{
public:
//---------------------------------------------------------------------------------------
///
/// RegressionTest
///
/// Description: constructor of class RegressionTest
///
/// @param RegName name of derriving subclass
RegressionTest(const string RegName) : m_Name(RegName)
{}
//---------------------------------------------------------------------------------------
///
/// ~RegressionTest
///
/// Description: destructor of class RegressionTest
virtual ~RegressionTest()
{}
//---------------------------------------------------------------------------------------
///
/// getName
///
/// Description: returns the value of the member m_Name
const string & getName() const
{ return m_Name; }
//---------------------------------------------------------------------------------------
///
/// execute
///
/// Description: the execute function passes an System_::ConfigParser object to the
/// derriving RegresssionTest class. The class can then read required options from the
/// configuration file. The RegressionTest shall then perform its specific regression test.
/// @see System_::PipeReader
/// @see System_::SymbolFile
///
/// Note : if an error happens or the option cannot be found, this function
/// should return false.
virtual bool execute(ConfigParser & conf_parser) = 0;
protected:
string m_Name;
}; // end of class RegressionTest
} // end of namespace Sysreg_
#endif

View file

@ -0,0 +1,161 @@
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: ReactOS boot test
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "rosboot_test.h"
#include "pipe_reader.h"
#include <iostream>
namespace Sysreg_
{
using std::cout;
using std::endl;
using std::cerr;
using System_::PipeReader;
string RosBootTest::VARIABLE_NAME = _T("ROSBOOT_CMD");
string RosBootTest::CLASS_NAME = _T("rosboot");
string RosBootTest::DEBUG_PORT = _T("ROSBOOT_DEBUG_PORT");
string RosBootTest::DEBUG_FILE = _T("ROSBOOT_DEBUG_FILE");
//---------------------------------------------------------------------------------------
RosBootTest::RosBootTest() : RegressionTest(RosBootTest::CLASS_NAME)
{
}
//---------------------------------------------------------------------------------------
RosBootTest::~RosBootTest()
{
}
//---------------------------------------------------------------------------------------
bool RosBootTest::execute(ConfigParser &conf_parser)
{
string boot_cmd;
string debug_port;
bool ret;
if (!conf_parser.getStringValue (RosBootTest::DEBUG_PORT, debug_port))
{
cerr << "Error: ROSBOOT_DEBUG_TYPE is not set in configuration file" << endl;
return false;
}
if (!conf_parser.getStringValue(RosBootTest::VARIABLE_NAME, boot_cmd))
{
cerr << "Error: ROSBOOT_CMD is not set in configuration file" << endl;
return false;
}
if (!_tcscmp(debug_port.c_str(), _T("pipe")))
{
ret = fetchDebugByPipe(boot_cmd);
}
else if (!_tcscmp(debug_port.c_str(), _T("file")))
{
string debug_file;
if (!conf_parser.getStringValue (RosBootTest::DEBUG_FILE, debug_file))
{
cerr << "Error: ROSBOOT_DEBUG_FILE is not set in configuration file" << endl;
return false;
}
ret = fetchDebugByFile(boot_cmd, debug_file);
}
else
{
_tprintf(_T("Error: unknown debug port %s Currently only file|pipe is supported\n"), debug_port);
return false;
}
return ret;
}
//---------------------------------------------------------------------------------------
bool RosBootTest::checkDebugData(string debug_data)
{
///
/// FIXME
///
/// parse debug_data and output STOP errors, UM exception
/// as well as important stages i.e. ntoskrnl loaded
/// TBD the information needs to be written into an provided log object
/// which writes the info into HTML/log / sends etc ....
_tprintf(debug_data.c_str ());
return true;
}
//---------------------------------------------------------------------------------------
bool RosBootTest::fetchDebugByPipe(string boot_cmd)
{
struct timeval ts;
PipeReader pipe_reader;
if (!pipe_reader.openPipe(boot_cmd, string(_T("rt"))))
{
_tprintf(_T("Error: failed to open pipe with cmd: %s\n"), boot_cmd.c_str ());
return false;
}
string Buffer;
Buffer.reserve (10000);
// gettimeofday(&ts, NULL);
while(!pipe_reader.isEof ())
{
pipe_reader.readPipe (Buffer);
if (!checkDebugData(Buffer))
{
break;
}
if (hasTimeout(&ts, 60000)
}
pipe_reader.closePipe ();
return true;
}
//---------------------------------------------------------------------------------------
bool RosBootTest::fetchDebugByFile(Sysreg_::string boot_cmd, Sysreg_::string debug_log)
{
PipeReader pipe_reader;
if (!pipe_reader.openPipe(boot_cmd, string(_T("rt"))))
{
_tprintf(_T("Error: failed to open pipe with cmd: %s\n"), boot_cmd.c_str ());
return false;
}
FILE * file = _tfopen(debug_log.c_str (), _T("rt"));
if (!file)
{
_tprintf(_T("Error: failed to open debug log %s\n", debug_log.c_str ()));
pipe_reader.closePipe ();
return false;
}
TCHAR szBuffer[500];
do
{
if (_fgetts(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), file))
{
string buffer = szBuffer;
if (!checkDebugData(buffer))
{
break;
}
}
}while(!pipe_reader.isEof ());
pipe_reader.closePipe ();
}
} // end of namespace Sysreg_

View file

@ -0,0 +1,116 @@
#ifndef ROSBOOT_TEST_H__
#define ROSBOOT_TEST_H__
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: ReactOS boot test
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "reg_test.h"
#include <winsock2.h>
namespace Sysreg_
{
//---------------------------------------------------------------------------------------
///
/// class RosBootTest
///
/// Description: this class attempts to boot ReactOS in an emulator with console logging enabled.
/// It
class RosBootTest : public RegressionTest
{
public:
static string VARIABLE_NAME;
static string CLASS_NAME;
static string DEBUG_PORT;
static string DEBUG_FILE;
//---------------------------------------------------------------------------------------
///
/// RosBootTest
///
/// Description: constructor of class RosBootTest
///
RosBootTest();
//---------------------------------------------------------------------------------------
///
/// ~RosBootTest
///
/// Description: destructor of class RosBootTest
///
virtual ~RosBootTest();
//---------------------------------------------------------------------------------------
///
/// execute
///
/// Description: this function performs a ReactOS boot test. It reads the variable
/// ROSBOOT_CMD and executes this specific command. This command shall contain the path
/// to an emulator (i.e. qemu) and the required arguments (-serial switch, hdd img etc) to be able
/// to read from console. If an error is detected, it attempts to resolve the faulting
/// module and address.
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);
//---------------------------------------------------------------------------------------
///
/// 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
/// @param debug_log path pointing to debug log
/// @return bool
bool fetchDebugByFile(string BootCmd, string debug_log);
//---------------------------------------------------------------------------------------
///
/// checkDebugData
///
/// Description: this function parses the given debug data for BSOD, UM exception etc
/// If it detects an fatal error, it should return false
///
/// Note: the received debug information should be written to an internal log object
/// to facilate post-processing of the results
bool checkDebugData(string debug_data);
}; // end of class RosBootTest
//---------------------------------------------------------------------------------------
///
/// checkTimeOut
///
/// Description: this function checks if the the application has already hung
bool checkTimeOut(struct timeval * ts, unsigned max_timeout);
} // end of namespace Sysreg_
#endif /* end of ROSBOOT_H__ */

View file

@ -0,0 +1,144 @@
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: source symbol lookup
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "sym_file.h"
#include "env_var.h"
#include "pipe_reader.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <time.h>
namespace System_
{
using std::cout;
using std::endl;
using std::cerr;
string SymbolFile::VAR_ROS_OUTPUT = _T("ROS_OUTPUT");
//---------------------------------------------------------------------------------------
SymbolFile::SymbolFile()
{
}
//---------------------------------------------------------------------------------------
SymbolFile::~SymbolFile()
{
}
//---------------------------------------------------------------------------------------
bool SymbolFile::initialize(const System_::string &Path)
{
char szBuffer[260];
// vector<string> vect;
EnvironmentVariable envvar;
string val = _T("output-i386");
envvar.getValue(SymbolFile::VAR_ROS_OUTPUT, val);
struct _finddata_t c_file;
strcpy(szBuffer, "D:\\reactos\\output-i386\\*");
intptr_t hFile = _findfirst(szBuffer, &c_file);
if (hFile == -1L)
{
cerr << "SymbolFile::initialize> failed" <<endl;
return false;
}
do
{
if (strstr(c_file.name, ".nostrip."))
{
cerr << c_file.name << endl;
}
}while(_findnext(hFile, &c_file) == 0);
return false;
}
//---------------------------------------------------------------------------------------
bool SymbolFile::resolveAddress(const string &module_name, const string &module_address, string &Buffer)
{
SymbolMap::const_iterator it = m_Map.find (module_name);
/*
if (it == m_Map.end ())
{
#ifdef NDEBUG
cerr << "SymbolFile::resolveAddress> no symbol file found for module " << module_name << endl;
#endif
return false;
}
*/
///
/// fetch environment path
///
EnvironmentVariable envvar;
#if 1
string pipe_cmd = _T("");//D:\\reactos\\output-i386");
#else
string path = _T("output-i386");
envvar.getValue(SymbolFile::VAR_ROS_OUTPUT, path);
#endif
pipe_cmd += _T("addr2line.exe "); //FIXXME file extension
pipe_cmd += _T("--exe=");
#if 1
pipe_cmd += _T("D:\\reactos\\output-i386\\dll\\win32\\kernel32\\kernel32.nostrip.dll");
#else
path += it->second;
#endif
pipe_cmd += _T(" ");
pipe_cmd += module_address;
PipeReader pipe_reader;
if (!pipe_reader.openPipe (pipe_cmd))
{
#ifdef NDEBUG
_tprintf(_T("SymbolFile::resolveAddress> failed to open pipe %s"), pipe_cmd);
#endif
return false;
}
if (Buffer.capacity () < 100)
{
Buffer.reserve (500);
}
return pipe_reader.readPipe (Buffer);
}
//---------------------------------------------------------------------------------------
bool SymbolFile::getSymbolFilePath(const System_::string &ModuleName, System_::string &FilePath)
{
cerr << "SymbolFile::getSymbolFilePath is not yet implemented" <<endl;
return false;
}
} // end of namespace System_

View file

@ -0,0 +1,110 @@
#ifndef SYM_FILE_H__
#define SYM_FILE_H__
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: source symbol lookup
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include <string>
#include <tchar.h>
#include <map>
namespace System_
{
typedef std::basic_string<TCHAR> string;
//---------------------------------------------------------------------------------------
///
/// class SymbolFile
///
/// Description: this class performs 2 tasks: First, it locates all available module names
/// and their associated symbol files. Secondly, it performs resolving address to source addresses
/// via the function resolveAddress
///
/// Usage: call initialize(). Then call resolveAddress();
/// i.e. resolveAddress("comctl32.dll", 0xBLABLABLA, result);
class SymbolFile
{
typedef std::map<string, string> SymbolMap;
public:
static string VAR_ROS_OUTPUT;
//---------------------------------------------------------------------------------------
///
/// SymbolFile
///
/// Description: constructor of class SymbolFile
SymbolFile();
//---------------------------------------------------------------------------------------
///
/// ~SymbolFile
///
/// Description: destructor of class SymbolFile
virtual ~SymbolFile();
//---------------------------------------------------------------------------------------
///
/// initialize
///
/// Description: this function initialize the class. It searches the subdirs
/// of ROS_OUTPUT and adds all files with name *.nostrip.* to a map with module
/// name as the key.
///
/// Note: if the param Path is not empty, it adds all found modules to the internal
/// map
///
/// Note: if the path does not exist or the no symbol files were added then false is returned
///
/// Note: if a module with same module name is already in the map, then the new module is not added
///
/// @param Path path to ROS_OUTPUT containing symbol files
/// @return bool
bool initialize(const string & Path = _T("output-i386"));
//---------------------------------------------------------------------------------------
///
/// resolveAddress
///
/// Description: this function attempts to resolve an address using a given symbol file
///
/// Note: the lookup is performed with raddr2line
///
/// @param module_name name of the module to examine
/// @param module_address address of the module to resolve
/// @param buffer receives information about the resolved location
/// @return bool
bool resolveAddress(const string & module_name, const string & module_address, string & Buffer);
//---------------------------------------------------------------------------------------
///
/// getSymbolFilePath
///
/// Description: this function returns the associated FilePath to a given module name. If
/// the module name is not known, it returns false and the param FilePath remains untouched
///
/// @param ModuleName name of the module to lookup
/// @param FilePath buffer receiving the address of symbol file
bool getSymbolFilePath(const string & ModuleName, string & FilePath);
protected:
SymbolMap m_Map;
};
} // end of namespace System_
#endif /* end of SYM_FILE_H__ */

View file

@ -0,0 +1,82 @@
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: app initialization
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include "sysreg.h"
typedef std::basic_string<TCHAR> string;
using std::cout;
using std::endl;
using std::cerr;
using System_::EnvironmentVariable;
using System_::ComponentFactoryTemplate;
using Sysreg_::ConfigParser;
//regression test classes
using Sysreg_::RegressionTest;
using Sysreg_::RosBootTest;
//test include
using System_::SymbolFile;
typedef ComponentFactoryTemplate<RegressionTest, string> ComponentFactory;
static const TCHAR USAGE[] =
_T("sysreg.exe <conf_file> <testname>\n\nconf_file ... path to a configuration file\ntest_name ... name of test to execute\n");
int _tmain(int argc, TCHAR * argv[])
{
ConfigParser config;
ComponentFactory comp_factory;
if (argc != 3)
{
cerr << USAGE << endl;
return -1;
}
//---------------------------------------------------------------------------------------
/// regression tests should be registered here
comp_factory.registerComponent<RosBootTest>(RosBootTest::CLASS_NAME);
//---------------------------------------------------------------------------------------
if (!config.parseFile (argv[1]))
{
cerr << USAGE << endl;
return -1;
}
RegressionTest * regtest = comp_factory.createComponent (argv[2]);
if (!regtest)
{
_tprintf(_T("Error: the requested regression test does not exist"));
return -1;
}
if (regtest->execute (config))
{
_tprintf(_T("The regression test %s completed successfully\n"), regtest->getName ().c_str ());
}
else
{
_tprintf(_T("The regression test %s failed\n"), regtest->getName ().c_str ());
}
return 0;
}

View file

@ -0,0 +1,34 @@
#ifndef SYSREG_H__
#define SYSREG_H__
/* $Id$
*
* PROJECT: System regression tool for ReactOS
* LICENSE: GPL - See COPYING in the top level directory
* FILE: tools/sysreg/conf_parser.h
* PURPOSE: app initialization
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald at sbox tugraz at)
*/
#include <tchar.h>
#include <string>
#include <iostream>
#include "env_var.h"
#include "pipe_reader.h"
#include "comp_factory.h"
#include "conf_parser.h"
// regression test classes
#include "rosboot_test.h"
//test include
#include "sym_file.h"
#endif /* end of SYSREG_H__ */