Add small testing framework.

svn path=/branches/xmlbuildsystem/; revision=12767
This commit is contained in:
Casper Hornstrup
2005-01-03 23:04:52 +00:00
parent 5b5cae1d8f
commit 0f703e6c9b
7 changed files with 429 additions and 196 deletions
+16 -2
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
#include "rbuild.h"
Module::Module(XMLElement moduleNode)
{
}
+185 -194
View File
@@ -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;
}
+64
View File
@@ -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 */
+30
View File
@@ -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 */
+123
View File
@@ -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);
}