#pragma warning(disable: 4786)
#include <exception>
#include <string>
#include <iostream>
#include "UtAsserter.h"
class myexception : public std::exception
{
public:
myexception(const std::string& s) : mMsg(s)
{
}
virtual const char* what() const throw()
{
return mMsg.c_str();
}
virtual ~myexception() throw()
{
}
const std::string mMsg;
} ;
//check for conflict with asserts
#include <assert.h>
TEST(a_test)
{
//test utassert
utassert(0, 0);
SelfTestAssert("");
utassert(1, 0);
SelfTestAssert("main.cpp(33) : a_test: FAILED: actual: 1 expected: 0");
utassert(0L, 0L);
SelfTestAssert("");
utassert(1L, 0L);
SelfTestAssert("main.cpp(37) : a_test: FAILED: actual: 1 expected: 0");
utassert("s1", "s1");
SelfTestAssert("");
utassert("s1", "s2");
SelfTestAssert("main.cpp(41) : a_test: FAILED: actual: s1 expected: s2");
}
TEST(a_nulls_in_strings)
{
utassert((char*) 0, (char*) 0);
SelfTestAssert("");
utassert("", (const char*) 0);
SelfTestAssert("main.cpp(49) : a_nulls_in_strings: FAILED: actual: expected: null");
utassert((const char*) 0, "");
SelfTestAssert("main.cpp(51) : a_nulls_in_strings: FAILED: actual: null expected: ");
utassert("", "");
SelfTestAssert("");
}
#ifdef UTASSERTER_INCLUDE_STL
TEST(stl_tests)
{
utassert(std::string("s1"), std::string("s2"));
SelfTestAssert("main.cpp(60) : stl_tests: FAILED: actual: s1 expected: s2");
}
#endif
#ifndef __GNUC__
TEST(excp_test)
{
utassert(0, 0);
int x = 0;
x = x / x;
utassert(1, 1);
}
TEST(excp_test3)
{
utassert(0, 0);
throw std::exception("std excp");
utassert(1, 1);
}
#endif
TEST(excp_test2)
{
utassert(0, 0);
throw myexception("my excp");
utassert(1, 1);
}
TEST(bool)
{
utassert(true, true);
SelfTestAssert("");
utassert(false, true);
SelfTestAssert("main.cpp(93) : bool: FAILED: actual: false expected: true");
utassert(true, false);
SelfTestAssert("main.cpp(95) : bool: FAILED: actual: true expected: false");
utassert(false, false);
SelfTestAssert("");
}
//------------------------------------------
int main ()
{
//normal example
TestSuite::Run();
//print the testcase names
//TestSuite::Run(0, true);
//print the testcase names and sort the test cases in alphabetical order
//TestSuite::Run(-1, true);
//print the testcase names and randomize the order of the test cases
//TestSuite::Run(-2, true);
//print the testcase names and randomize the order of the test cases using 500 as a seed
//TestSuite::Run(500, true);
TestSuite::CleanUp();
return 0;
}
|
#pragma warning(disable: 4786)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <time.h>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <sstream>
using namespace std;
#include "UtAsserter.h"
#if defined(__GNUC__)
#define IS_GCC 1
#elif _MSC_VER >= 1300
#define IS_VC7 1
#else
#define IS_VC6 1
#endif
//print the output
//this is the only place where cout & OutputDebugString should be mentioned!
static void PrintToOutput(const string& ss)
{
cout << ss << endl;
OutputDebugString(ss.c_str());
OutputDebugString("\n");
}
//Used for self testing only...
#if !defined(UTASSERTER_SELFTEST)
//when undefined abosorb calls.
inline void SelfTestClear() {}
inline void SelfTestSet(const string& /*ss*/) {}
#else
//Generate code to self test
static string gCurrentOutputLine;
inline void SelfTestClear()
{
gCurrentOutputLine = "";
}
inline void SelfTestSet(const string& ss)
{
gCurrentOutputLine = ss;
}
void SelfTestAssert(const char* const expected)
{
string ex = expected;
#if defined(IS_VC7)
if (ex != "") ex = string(".\\") + expected;
#elif defined(IS_VC6)
if (ex != "") ex = string("D:\\projects\\src\\jUtAsserter\\") + expected;
#else
if (ex != "") ex = string("D:/projects/src/jUtAsserter/") + expected;
#endif
if (ex == gCurrentOutputLine) return;
ostringstream msg;
msg << "SELF TEST FAILED: \n expected: '" << ex << "'\n actual : '" << gCurrentOutputLine << "'";
PrintToOutput(msg.str());
}
#endif
//save the current output line (for self test) and print it out
//Do not use this function in selftest
static void PrintIt(const string& ss)
{
SelfTestSet(ss);
PrintToOutput(ss);
}
//create the first part of the assert failure message
//the format is useful within the VC6 IDE for "next-error" (F4)
static void Prefix(ostringstream& ss, const char* const fname, long lineno, const string& casename)
{
ss << fname << "(" << lineno << ") : " << casename << ": FAILED: ";
}
//Suffix can handle most of the types correctly
template <typename T>
static void Suffix(ostringstream& ss, T actual, T expected)
{
ss << "actual: " << actual << " expected: " << expected;
}
#if !defined(IS_VC6)
template<>
#endif
static void Suffix(ostringstream& ss, bool actual, bool expected)
{
ss << "actual: " << boolalpha << actual << " expected: " << expected;
}
#if !defined(IS_VC6)
template<>
#endif
static void Suffix(ostringstream& ss, const char* actual, const char* expected)
{
if (actual == 0 && expected == 0)
ss << "actual: null expected: null";
else if (actual == 0 && expected != 0)
ss << "actual: null expected: " << expected;
else if (actual != 0 && expected == 0)
ss << "actual: " << actual << " expected: null";
else
ss << "actual: " << actual << " expected: " << expected;
}
//holds test case information
struct TestCase
{
explicit TestCase(const char* const fname, long lineno, const char* const casename, TestSuite::TESTCASEFP tc)
: mName(casename), mFile(fname), mLineno(lineno), mTest(tc)
{
}
void operator()() const
{
mTest();
}
void GetPrefix(ostringstream& ss) const
{
Prefix(ss, mFile.c_str(), mLineno, mName);
}
bool operator < (const TestCase& other) const
{
return mName < other.mName;
}
std::string mName;
std::string mFile;
long mLineno;
TestSuite::TESTCASEFP mTest;
} ;
//holds private variables
struct TestSuiteImpl
{
typedef std::vector<TestCase> TestCaseList;
TestSuiteImpl()
: mNumAsserts(0), mNumFailures(0), mNumExcps(0)
{
}
~TestSuiteImpl()
{
mSuite.clear();
}
const TestCase& Add(const TestCase& tc)
{
mSuite.push_back(tc);
return tc;
}
void BumpAsserts()
{
mNumAsserts++;
}
void BumpFailures()
{
mNumFailures++;
}
//runs the actual suite of test cases
void Run(int order, bool printtestcasenames)
{
switch(order)
{
case 0: break; //do nothing
case -1: sort(mSuite.begin(), mSuite.end()); break;
case -2:
srand((unsigned int)time(0));
random_shuffle(mSuite.begin(), mSuite.end());
break;
default:
srand(order);
random_shuffle(mSuite.begin(), mSuite.end());
break;
}
for(TestCaseList::iterator it = mSuite.begin(); it != mSuite.end(); ++it)
{
try
{
CurrentCaseName = &((*it).mName);
if (printtestcasenames)
{
ostringstream ss;
ss << "TestCase: " << *CurrentCaseName;
PrintIt(ss.str());
}
(*it)();
}
catch(const char* ex)
{
ReportException(*it, ex);
}
catch(int ex)
{
ReportException(*it, ex);
}
catch(unsigned int ex)
{
ReportException(*it, ex);
}
catch(const exception& ex)
{
ReportException(*it, ex.what());
}
catch(const exception* const ex)
{
ReportException(*it, ex->what());
}
catch(...)
{
ReportException(*it, (const char*)0);
}
}
}
template <typename T>
void ReportException(const TestCase& tc, T ex)
{
mNumExcps++;
ostringstream ss;
tc.GetPrefix(ss);
ss << "threw exception";
if (ex != 0)
ss << ": " << ex;
PrintIt(ss.str());
}
//generate a report of failures, etc.
void Report()
{
ReportStat("Num Test Cases", (unsigned int) mSuite.size());
ReportStat("Num Asserts ", mNumAsserts);
ReportStat("Num Failures ", mNumFailures);
ReportStat("Num Exceptions", mNumExcps);
}
template <typename T>
void ReportStat(const string& title, T stat)
{
ostringstream ss;
ss << title << ": " << stat;
PrintIt(ss.str());
}
TestCaseList mSuite;
string* CurrentCaseName;
int mNumAsserts;
int mNumFailures;
int mNumExcps;
} ;
//the test suite
static TestSuiteImpl* gsuite = 0;
//forward the Run request to impl
void TestSuite::Run(int order, bool printtestcasenames)
{
if (gsuite == 0) return;
gsuite->Run(order, printtestcasenames);
gsuite->Report();
}
void TestSuite::CleanUp()
{
delete gsuite;
gsuite = 0;
}
//add a test case to the suite
const TestCase& TestSuite::CreateTestCase(const char* const fname, long lineno, const char* const casename, TestSuite::TESTCASEFP tc)
{
if (gsuite == 0)
gsuite = new TestSuiteImpl();
return gsuite->Add(TestCase(fname, lineno, casename, tc));
}
//most asserts will follow this code exactly
//the only difference will be the incoming types for the expected
//and actual values... so use a template
template <class T>
static bool cmp(T lhs, T rhs)
{
return lhs == rhs;
}
#if !defined(IS_VC6)
template<>
#endif
static bool cmp(const char* lhs, const char* rhs)
{
if (lhs == 0 && rhs == 0) return true;
if (lhs == 0 && rhs != 0) return false;
if (lhs != 0 && rhs == 0) return false;
return strcmp(lhs, rhs) == 0;
}
template <class T>
static inline void AssertIt(const char* const fname, long lineno, T actual, T expected)
{
SelfTestClear();
gsuite->BumpAsserts();
if (cmp<T>(actual, expected)) return;
gsuite->BumpFailures();
ostringstream ss;
Prefix(ss, fname, lineno, *gsuite->CurrentCaseName);
Suffix<T>(ss, actual, expected);
PrintIt(ss.str());
}
//just forward to the templated function
void TestSuite::testassert(const char* const fname, long lineno, int actual, int expected)
{
AssertIt(fname, lineno, actual, expected);
}
void TestSuite::testassert(const char* const fname, long lineno, long actual, long expected)
{
AssertIt(fname, lineno, actual, expected);
}
void TestSuite::testassert(const char* const fname, long lineno, const char* const actual, const char* const expected)
{
AssertIt(fname, lineno, actual, expected);
}
void TestSuite::testassert(const char* const fname, long lineno, bool actual, bool expected)
{
AssertIt(fname, lineno, actual, expected);
}
#ifdef UTASSERTER_INCLUDE_STL
void TestSuite::testassert(const char* const fname, long lineno, const string& actual, const string& expected)
{
AssertIt(fname, lineno, actual, expected);
}
#endif
|
#pragma once
//use this define if you want to include asserts for STL types
//leave it commented out if it conflicts with other libraries
//#define UTASSERTER_INCLUDE_STL
#ifdef UTASSERTER_INCLUDE_STL
#include <string>
#endif
//--------------
struct TestCase;
class TestSuite
{
public:
//run all testcases in the suite
//if randomizeseed == 0, the test cases are run in insertion order
//if randomizeseed == -1, the test cases are run in sorted order
//if randomizeseed == -2, the test cases are run in random order using the time as a seed
//else, the test cases are run in random order using randomizeseed as a seed
static void Run(int order = 0, bool printtestcasenames = false);
static void CleanUp();
typedef void (*TESTCASEFP) ();
static const TestCase& CreateTestCase(const char* fname, long lineno, const char* casename, TESTCASEFP tc);
//define all of the assert overloads
#define DefineAssert(t) static void testassert(const char* fname, long lineno, t actual, t expected)
DefineAssert(int);
DefineAssert(long);
DefineAssert(const char*);
DefineAssert(bool);
#ifdef UTASSERTER_INCLUDE_STL
DefineAssert(const std::string&);
#endif
private:
TestSuite(); //don't allow creation or copy
~TestSuite();
} ;
//------------
//define a test
#define TEST(s) \
void Test##s(); \
const TestCase& TestCase_Test_##s = TestSuite::CreateTestCase(__FILE__, __LINE__, #s, Test##s); \
void Test##s()
//assert any failing behaviour
#define utassert(actual, expected) TestSuite::testassert(__FILE__, __LINE__, actual, expected)
//only use this for testing UtAsserter
#if defined(UTASSERTER_SELFTEST)
void SelfTestAssert(const char* const expected);
#else
#define SelfTestAssert(s)
#endif
|