mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 19:26:32 +00:00
Add small testing framework.
svn path=/branches/xmlbuildsystem/; revision=12767
This commit is contained in:
@@ -4,9 +4,13 @@ TARGET = rbuild$(EXE_POSTFIX)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
OBJECTS = rbuild.o
|
||||
BASE_OBJECTS = module.o
|
||||
|
||||
CLEAN_FILES = *.o rbuild$(EXE_POSTFIX)
|
||||
OBJECTS = $(BASE_OBJECTS) rbuild.o
|
||||
|
||||
TESTS = tests/moduletest.o
|
||||
|
||||
TEST_OBJECTS = $(BASE_OBJECTS) $(TESTS) tests/alltests.o
|
||||
|
||||
HOST_CFLAGS = -g -I. -Werror -Wall
|
||||
|
||||
@@ -19,11 +23,15 @@ ifeq ($(HOST),mingw32-linux)
|
||||
clean:
|
||||
-rm -f *.o
|
||||
-rm -f rbuild$(EXE_POSTFIX)
|
||||
-rm -f tests/*.o
|
||||
-rm -f rbuild_tests$(EXE_POSTFIX)
|
||||
endif
|
||||
ifeq ($(HOST),mingw32-windows)
|
||||
clean:
|
||||
-del *.o
|
||||
-del rbuild$(EXE_POSTFIX)
|
||||
-del tests\*.o
|
||||
-del rbuild_tests$(EXE_POSTFIX)
|
||||
endif
|
||||
|
||||
.phony: clean
|
||||
@@ -32,4 +40,10 @@ endif
|
||||
$(HALFVERBOSEECHO) [CXX] $<
|
||||
$(HOST_CXX) $(HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
test: rbuild_tests$(EXE_POSTFIX)
|
||||
$(EXE_PREFIX)rbuild_tests$(EXE_POSTFIX)
|
||||
|
||||
rbuild_tests$(EXE_POSTFIX): $(TEST_OBJECTS)
|
||||
$(HOST_CXX) $(TEST_OBJECTS) $(HOST_LFLAGS) -o rbuild_tests$(EXE_POSTFIX)
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "rbuild.h"
|
||||
|
||||
Module::Module(XMLElement moduleNode)
|
||||
{
|
||||
}
|
||||
+185
-194
@@ -4,17 +4,10 @@
|
||||
#pragma warning ( disable : 4786 )
|
||||
#endif//_MSC_VER
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <assert.h>
|
||||
//#include <sys/stat.h>
|
||||
//#include <sys/types.h>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
#include "rbuild.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
unsigned __int64
|
||||
@@ -36,218 +29,216 @@ filelen ( FILE* f )
|
||||
static const char* WS = " \t\r\n";
|
||||
static const char* WSEQ = " =\t\r\n";
|
||||
|
||||
class XMLFile
|
||||
XMLFile::XMLFile()
|
||||
{
|
||||
vector<FILE*> _f;
|
||||
string _buf;
|
||||
const char *_p, *_end;
|
||||
public:
|
||||
XMLFile() {}
|
||||
void close()
|
||||
}
|
||||
|
||||
void XMLFile::close()
|
||||
{
|
||||
while ( _f.size() )
|
||||
{
|
||||
while ( _f.size() )
|
||||
fclose ( _f.back() );
|
||||
_f.pop_back();
|
||||
}
|
||||
_buf.resize(0);
|
||||
_p = _end = NULL;
|
||||
}
|
||||
|
||||
bool XMLFile::open(const char* filename)
|
||||
{
|
||||
close();
|
||||
FILE* f = fopen ( filename, "r" );
|
||||
if ( !f )
|
||||
return false;
|
||||
unsigned long len = (unsigned long)filelen(f);
|
||||
_buf.resize ( len );
|
||||
fread ( &_buf[0], 1, len, f );
|
||||
_p = _buf.c_str();
|
||||
_end = _p + len;
|
||||
_f.push_back ( f );
|
||||
next_token();
|
||||
return true;
|
||||
}
|
||||
|
||||
// next_token() moves the pointer to next token, which may be
|
||||
// an xml element or a text element, basically it's a glorified
|
||||
// skipspace, normally the user of this class won't need to call
|
||||
// this function
|
||||
void XMLFile::next_token()
|
||||
{
|
||||
_p += strspn ( _p, WS );
|
||||
}
|
||||
|
||||
bool XMLFile::next_is_text()
|
||||
{
|
||||
return *_p != '<';
|
||||
}
|
||||
|
||||
bool XMLFile::more_tokens()
|
||||
{
|
||||
return _p != _end;
|
||||
}
|
||||
|
||||
// get_token() is used to return a token, and move the pointer
|
||||
// past the token
|
||||
bool XMLFile::get_token(string& token)
|
||||
{
|
||||
const char* tokend;
|
||||
if ( *_p == '<' )
|
||||
{
|
||||
tokend = strchr ( _p, '>' );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
else
|
||||
++tokend;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokend = strchr ( _p, '<' );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
while ( tokend > _p && isspace(tokend[-1]) )
|
||||
--tokend;
|
||||
}
|
||||
if ( tokend == _p )
|
||||
return false;
|
||||
token = string ( _p, tokend-_p );
|
||||
_p = tokend;
|
||||
next_token();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool XMLFile::getc(char& c)
|
||||
{
|
||||
while ( _bufidx >= _buf.size() )
|
||||
{
|
||||
static buf[4096];
|
||||
if ( !fgets ( buf, sizeof(buf), _f.back() ) )
|
||||
{
|
||||
fclose ( _f.back() );
|
||||
_f.pop_back();
|
||||
f.pop_back();
|
||||
continue;
|
||||
}
|
||||
_buf.resize(0);
|
||||
_p = _end = NULL;
|
||||
}
|
||||
bool open ( const char* filename )
|
||||
{
|
||||
close();
|
||||
FILE* f = fopen ( filename, "r" );
|
||||
if ( !f )
|
||||
return false;
|
||||
unsigned long len = (unsigned long)filelen(f);
|
||||
_buf.resize ( len );
|
||||
fread ( &_buf[0], 1, len, f );
|
||||
_p = _buf.c_str();
|
||||
_end = _p + len;
|
||||
_f.push_back ( f );
|
||||
next_token();
|
||||
return true;
|
||||
}
|
||||
// next_token() moves the pointer to next token, which may be
|
||||
// an xml element or a text element, basically it's a glorified
|
||||
// skipspace, normally the user of this class won't need to call
|
||||
// this function
|
||||
void next_token()
|
||||
{
|
||||
_p += strspn ( _p, WS );
|
||||
}
|
||||
bool next_is_text()
|
||||
{
|
||||
return *_p != '<';
|
||||
}
|
||||
bool more_tokens()
|
||||
{
|
||||
return _p != _end;
|
||||
}
|
||||
// get_token() is used to return a token, and move the pointer
|
||||
// past the token
|
||||
bool get_token ( string& token )
|
||||
{
|
||||
const char* tokend;
|
||||
if ( *_p == '<' )
|
||||
{
|
||||
tokend = strchr ( _p, '>' );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
else
|
||||
++tokend;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokend = strchr ( _p, '<' );
|
||||
if ( !tokend )
|
||||
tokend = _end;
|
||||
while ( tokend > _p && isspace(tokend[-1]) )
|
||||
--tokend;
|
||||
}
|
||||
if ( tokend == _p )
|
||||
return false;
|
||||
token = string ( _p, tokend-_p );
|
||||
_p = tokend;
|
||||
next_token();
|
||||
return true;
|
||||
}
|
||||
#if 0
|
||||
bool getc ( char& c )
|
||||
{
|
||||
while ( _bufidx >= _buf.size() )
|
||||
{
|
||||
static buf[4096];
|
||||
if ( !fgets ( buf, sizeof(buf), _f.back() ) )
|
||||
{
|
||||
fclose ( _f.back() );
|
||||
f.pop_back();
|
||||
continue;
|
||||
}
|
||||
_buf = buf;
|
||||
_bufidx = 0;
|
||||
// REM TODO FIXME - check for and load includes here...
|
||||
/*char* p = &_buf[0];
|
||||
p += strspn ( p, " \t" );
|
||||
if ( *p++ != '#' )
|
||||
break;
|
||||
p += strspn ( p, " \t" );
|
||||
if ( strncmp ( p, "include", 7 ) )
|
||||
break;
|
||||
p += 7;
|
||||
if ( !isspace(*p++) )
|
||||
break;*/
|
||||
_buf = buf;
|
||||
_bufidx = 0;
|
||||
// REM TODO FIXME - check for and load includes here...
|
||||
/*char* p = &_buf[0];
|
||||
p += strspn ( p, " \t" );
|
||||
if ( *p++ != '#' )
|
||||
break;
|
||||
p += strspn ( p, " \t" );
|
||||
if ( strncmp ( p, "include", 7 ) )
|
||||
break;
|
||||
p += 7;
|
||||
if ( !isspace(*p++) )
|
||||
break;*/
|
||||
|
||||
}
|
||||
c = _buf[_bufidx++];
|
||||
return true;
|
||||
}
|
||||
c = _buf[_bufidx++];
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class XMLAttribute
|
||||
|
||||
XMLAttribute::XMLAttribute()
|
||||
{
|
||||
public:
|
||||
string name, value;
|
||||
}
|
||||
|
||||
XMLAttribute() {}
|
||||
|
||||
XMLAttribute ( const string& name_, const string& value_ )
|
||||
: name(name_), value(value_)
|
||||
{
|
||||
}
|
||||
|
||||
XMLAttribute ( const XMLAttribute& src )
|
||||
{
|
||||
name = src.name;
|
||||
value = src.value;
|
||||
}
|
||||
|
||||
XMLAttribute& operator = ( const XMLAttribute& src )
|
||||
{
|
||||
name = src.name;
|
||||
value = src.value;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class XMLElement
|
||||
XMLAttribute::XMLAttribute(const string& name_,
|
||||
const string& value_)
|
||||
: name(name_), value(value_)
|
||||
{
|
||||
public:
|
||||
string name;
|
||||
vector<XMLAttribute> attributes;
|
||||
vector<XMLElement*> subElements;
|
||||
string value;
|
||||
}
|
||||
|
||||
XMLElement() {}
|
||||
// Parse() returns true if you need to look for a </tag> for
|
||||
// this one...
|
||||
bool Parse ( const string& token, bool& end_tag )
|
||||
XMLAttribute::XMLAttribute(const XMLAttribute& src)
|
||||
{
|
||||
name = src.name;
|
||||
value = src.value;
|
||||
}
|
||||
|
||||
XMLAttribute& XMLAttribute::operator=(const XMLAttribute& src)
|
||||
{
|
||||
name = src.name;
|
||||
value = src.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
XMLElement::XMLElement()
|
||||
{
|
||||
}
|
||||
|
||||
// Parse() returns true if you need to look for a </tag> for
|
||||
// this one...
|
||||
bool XMLElement::Parse(const string& token,
|
||||
bool& end_tag)
|
||||
{
|
||||
const char* p = token.c_str();
|
||||
assert ( *p == '<' );
|
||||
p++;
|
||||
p += strspn ( p, WS );
|
||||
end_tag = ( *p == '/' );
|
||||
if ( end_tag )
|
||||
{
|
||||
const char* p = token.c_str();
|
||||
assert ( *p == '<' );
|
||||
p++;
|
||||
++p;
|
||||
p += strspn ( p, WS );
|
||||
end_tag = ( *p == '/' );
|
||||
if ( end_tag )
|
||||
{
|
||||
++p;
|
||||
p += strspn ( p, WS );
|
||||
}
|
||||
const char* end = strpbrk ( p, WS );
|
||||
}
|
||||
const char* end = strpbrk ( p, WS );
|
||||
if ( !end )
|
||||
{
|
||||
end = strpbrk ( p, "/>" );
|
||||
assert ( end );
|
||||
}
|
||||
name = string ( p, end-p );
|
||||
p = end;
|
||||
p += strspn ( p, WS );
|
||||
while ( *p != '>' && *p != '/' )
|
||||
{
|
||||
end = strpbrk ( p, WSEQ );
|
||||
if ( !end )
|
||||
{
|
||||
end = strpbrk ( p, "/>" );
|
||||
assert ( end );
|
||||
}
|
||||
name = string ( p, end-p );
|
||||
string attribute ( p, end-p ), value;
|
||||
p = end;
|
||||
p += strspn ( p, WS );
|
||||
while ( *p != '>' && *p != '/' )
|
||||
if ( *p == '=' )
|
||||
{
|
||||
end = strpbrk ( p, WSEQ );
|
||||
++p;
|
||||
p += strspn ( p, WS );
|
||||
char quote = 0;
|
||||
if ( strchr ( "\"'", *p ) )
|
||||
{
|
||||
quote = *p++;
|
||||
end = strchr ( p, quote );
|
||||
}
|
||||
else
|
||||
{
|
||||
end = strpbrk ( p, WS );
|
||||
}
|
||||
if ( !end )
|
||||
{
|
||||
end = strpbrk ( p, "/>" );
|
||||
assert ( end );
|
||||
end = strchr ( p, '>' );
|
||||
assert(end);
|
||||
if ( end[-1] == '/' )
|
||||
end--;
|
||||
}
|
||||
string attribute ( p, end-p ), value;
|
||||
value = string ( p, end-p );
|
||||
p = end;
|
||||
if ( quote && *p == quote )
|
||||
p++;
|
||||
p += strspn ( p, WS );
|
||||
if ( *p == '=' )
|
||||
{
|
||||
++p;
|
||||
p += strspn ( p, WS );
|
||||
char quote = 0;
|
||||
if ( strchr ( "\"'", *p ) )
|
||||
{
|
||||
quote = *p++;
|
||||
end = strchr ( p, quote );
|
||||
}
|
||||
else
|
||||
{
|
||||
end = strpbrk ( p, WS );
|
||||
}
|
||||
if ( !end )
|
||||
{
|
||||
end = strchr ( p, '>' );
|
||||
assert(end);
|
||||
if ( end[-1] == '/' )
|
||||
end--;
|
||||
}
|
||||
value = string ( p, end-p );
|
||||
p = end;
|
||||
if ( quote && *p == quote )
|
||||
p++;
|
||||
p += strspn ( p, WS );
|
||||
}
|
||||
attributes.push_back ( XMLAttribute ( attribute, value ) );
|
||||
}
|
||||
return !( *p == '/' ) && !end_tag;
|
||||
attributes.push_back ( XMLAttribute ( attribute, value ) );
|
||||
}
|
||||
};
|
||||
return !( *p == '/' ) && !end_tag;
|
||||
}
|
||||
|
||||
XMLElement* XMLParse ( XMLFile& f, bool* pend_tag = NULL )
|
||||
|
||||
XMLElement* XMLParse(XMLFile& f,
|
||||
bool* pend_tag = NULL)
|
||||
{
|
||||
string token;
|
||||
if ( !f.get_token(token) )
|
||||
@@ -310,11 +301,11 @@ int main ( int argc, char** argv )
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMLElement* head = XMLParse ( f );
|
||||
if (head)
|
||||
{
|
||||
// REM TODO FIXME actually do something with the parsed info
|
||||
}
|
||||
XMLElement* head = XMLParse(f);
|
||||
if (head)
|
||||
{
|
||||
// REM TODO FIXME actually do something with the parsed info
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef __RBUILD_H
|
||||
#define __RBUILD_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
class XMLFile
|
||||
{
|
||||
friend class XMLElement;
|
||||
public:
|
||||
XMLFile();
|
||||
void close();
|
||||
bool open(const char* filename);
|
||||
void next_token();
|
||||
bool next_is_text();
|
||||
bool more_tokens();
|
||||
bool get_token(string& token);
|
||||
|
||||
private:
|
||||
vector<FILE*> _f;
|
||||
string _buf;
|
||||
|
||||
const char *_p, *_end;
|
||||
};
|
||||
|
||||
|
||||
class XMLAttribute
|
||||
{
|
||||
public:
|
||||
string name;
|
||||
string value;
|
||||
|
||||
XMLAttribute();
|
||||
XMLAttribute ( const string& name_, const string& value_ );
|
||||
// : name(name_), value(value_);
|
||||
XMLAttribute ( const XMLAttribute& src );
|
||||
XMLAttribute& operator = ( const XMLAttribute& src );
|
||||
};
|
||||
|
||||
|
||||
class XMLElement
|
||||
{
|
||||
public:
|
||||
string name;
|
||||
vector<XMLAttribute> attributes;
|
||||
vector<XMLElement*> subElements;
|
||||
string value;
|
||||
|
||||
XMLElement();
|
||||
bool Parse(const string& token,
|
||||
bool& end_tag);
|
||||
};
|
||||
|
||||
|
||||
class Module
|
||||
{
|
||||
public:
|
||||
Module(XMLElement moduleNode);
|
||||
};
|
||||
|
||||
#endif /* __RBUILD_H */
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef __TEST_H
|
||||
#define __TEST_H
|
||||
|
||||
#include "rbuild.h"
|
||||
|
||||
class BaseTest
|
||||
{
|
||||
public:
|
||||
bool Failed;
|
||||
BaseTest();
|
||||
/*virtual void Run();*/
|
||||
protected:
|
||||
void Assert(char *message);
|
||||
void IsTrue(bool condition);
|
||||
void IsFalse(bool condition);
|
||||
void AreEqual(int expected,
|
||||
int actual);
|
||||
void AreNotEqual(int expected,
|
||||
int actual);
|
||||
private:
|
||||
void Fail();
|
||||
};
|
||||
|
||||
|
||||
class ModuleTest : public BaseTest
|
||||
{
|
||||
void Run();
|
||||
};
|
||||
|
||||
#endif /* __TEST_H */
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "rbuild.h"
|
||||
#include "test.h"
|
||||
|
||||
BaseTest::BaseTest()
|
||||
{
|
||||
Failed = true;
|
||||
}
|
||||
/*
|
||||
void BaseTest::Run()
|
||||
{
|
||||
}
|
||||
*/
|
||||
void BaseTest::Assert(char *message)
|
||||
{
|
||||
printf(message);
|
||||
Fail();
|
||||
}
|
||||
|
||||
void BaseTest::IsTrue(bool condition)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
char message[100];
|
||||
sprintf(message,
|
||||
"Condition was not true at %s:%d",
|
||||
__FILE__,
|
||||
__LINE__);
|
||||
Assert(message);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseTest::IsFalse(bool condition)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
char message[100];
|
||||
sprintf(message,
|
||||
"Condition was not false at %s:%d",
|
||||
__FILE__,
|
||||
__LINE__);
|
||||
Assert(message);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseTest::AreEqual(int expected,
|
||||
int actual)
|
||||
{
|
||||
if (actual != expected)
|
||||
{
|
||||
char message[100];
|
||||
sprintf(message,
|
||||
"Expected %d/0x%.08x was %d/0x%.08x at %s:%d",
|
||||
expected,
|
||||
expected,
|
||||
actual,
|
||||
actual,
|
||||
__FILE__,
|
||||
__LINE__);
|
||||
Assert(message);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseTest::AreNotEqual(int expected,
|
||||
int actual)
|
||||
{
|
||||
if (actual == expected)
|
||||
{
|
||||
char message[100];
|
||||
sprintf(message,
|
||||
"Actual value expected to be different from %d/0x%.08x at %s:%d",
|
||||
expected,
|
||||
expected,
|
||||
__FILE__,
|
||||
__LINE__);
|
||||
Assert(message);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseTest::Fail()
|
||||
{
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
|
||||
class TestDispatcher
|
||||
{
|
||||
public:
|
||||
void Run()
|
||||
{
|
||||
int numberOfFailedTests = 0;
|
||||
vector<BaseTest> tests = GetTests();
|
||||
for (size_t i = 0; i < tests.size(); i++)
|
||||
{
|
||||
BaseTest& test = tests[i];
|
||||
/*test.Run();*/
|
||||
if (test.Failed)
|
||||
numberOfFailedTests++;
|
||||
}
|
||||
|
||||
if (numberOfFailedTests > 0)
|
||||
printf("%d tests failed",
|
||||
numberOfFailedTests);
|
||||
else
|
||||
printf("All tests succeeded");
|
||||
}
|
||||
|
||||
private:
|
||||
vector<BaseTest> GetTests()
|
||||
{
|
||||
vector<BaseTest> tests;
|
||||
tests.push_back(ModuleTest());
|
||||
return tests;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc,
|
||||
char** argv)
|
||||
{
|
||||
TestDispatcher testDispatcher = TestDispatcher();
|
||||
testDispatcher.Run();
|
||||
return 0;
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "test.h"
|
||||
|
||||
void ModuleTest::Run()
|
||||
{
|
||||
IsTrue(false);
|
||||
}
|
||||
Reference in New Issue
Block a user