Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
main.cpp 4.25 KiB
#include <tclap/CmdLine.h>

#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestResult.h>
#include <cppunit/XmlOutputter.h>

#include <cppunit/Test.h>
#include <cppunit/TestFailure.h>
#include <cppunit/portability/Stream.h>
#include <cppunit/TestListener.h>
#include <cppunit/SourceLine.h>
#include <cppunit/Exception.h>

CPPUNIT_NS_BEGIN

class CPPUNIT_API TestProgressListener : public TestListener
{
public:
	TestProgressListener();

	virtual ~TestProgressListener();

	void startTest( Test *test );

	void addFailure( const TestFailure &failure );

	void endTest( Test *test );

	int getResult() const;

	void printResults() const;

private:
	TestProgressListener( const TestProgressListener &copy );

	void operator =( const TestProgressListener &copy );

private:
	int m_Failures;
	int m_Tests;
	int m_Assertions;
	bool m_lastTestFailed;
};

TestProgressListener::TestProgressListener() : m_Failures( 0 ), m_Tests(0), m_Assertions(0), m_lastTestFailed( false )
{
}

TestProgressListener::~TestProgressListener()
{
}

void TestProgressListener::startTest( Test * test )
{
	stdCOut() << test->getName() << ":" << "\n";
	stdCOut().flush();

	m_lastTestFailed = false;
	m_Tests++;
}

void TestProgressListener::addFailure( const TestFailure &failure )
{
	stdCOut() << (failure.isError() ? "error" : "assertion") << " : " << failure.failedTestName() << " : " << failure.sourceLine().lineNumber() << "\n";
	stdCOut() << "Exception " << failure.thrownException()->message().details();

	m_lastTestFailed = true;
	if(failure.isError()) m_Failures++; else m_Assertions++;
}

void TestProgressListener::endTest( Test * test)
{
	stdCOut() << "Result (" << test->getName() << ")";
	stdCOut().flush();

	if ( !m_lastTestFailed )
		stdCOut() <<	" : OK";
	else
		stdCOut() << " : Fail";
	stdCOut() << "\n\n";
}

int TestProgressListener::getResult() const {
	return m_Failures + m_Assertions;
}

void TestProgressListener::printResults() const {
	stdCOut() << "Overal result: Tests: " << m_Tests << " Assertions: " << m_Assertions << " Failures: " << m_Failures << "\n";
}

CPPUNIT_NS_END

int main(int argc, char* argv[]) {
	try {
		TCLAP::CmdLine cmd("Main test binary.", ' ', "0.01");

		TCLAP::MultiArg<std::string> testPathSegments("p", "path", "test path", false, "string" );
		cmd.add( testPathSegments );

		cmd.parse(argc, argv);

		CppUnit::TestResult controller;

		CppUnit::TestResultCollector result;
		controller.addListener( &result );

		CppUnit::TestProgressListener progressListener;
		controller.addListener( &progressListener );

		CppUnit::Test *suite = NULL;
		std::string testPath = "";
		if(testPathSegments.getValue().size() == 0) {
			// Get the top level suite from the registry
			suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
		} else if(testPathSegments.getValue().size() == 1) {
			suite = CppUnit::TestFactoryRegistry::getRegistry(testPathSegments.getValue()[0]).makeTest();
		} else {
			suite = CppUnit::TestFactoryRegistry::getRegistry(testPathSegments.getValue()[0]).makeTest();
			bool first = true;
			for(const std::string& path : testPathSegments.getValue()) {
				if(first) {
					first = false;
					continue;
				}
				testPath += path + "/";
			}
			testPath.pop_back();
		}

		// Adds the test to the list of test to run
		CppUnit::TextUi::TestRunner runner;
		runner.addTest( suite );

		// Change the default outputter to a compiler error format outputter
		runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(), std::cerr ) );
		// Run the tests.
		runner.run( controller, testPath );

		progressListener.printResults();

		std::ofstream xmlFileResults("CppUnitTestResults.xml");
		CppUnit::XmlOutputter xmlOut(&result, xmlFileResults);
		xmlOut.write();

		return progressListener.getResult();
/*	} catch(const exception::AlibException& exception) {
		std::cerr << exception.getCause() << std::endl;
		return 1;*/
	} catch(const TCLAP::ArgException& exception) {
		std::cerr << exception.error() << std::endl;
		return 2;
	} catch (const std::exception& exception) {
		std::cerr << "Exception caught: " << exception.what() << std::endl;
		return 3;
	} catch(...) {
		std::cerr << "Unknown exception caught." << std::endl;
		return 127;
	}
}