⛏️ index : haiku.git

/*
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */


#include "TestSuite.h"

#include <new>

#include <string.h>

#include "TestVisitor.h"


TestSuite::TestSuite(const char* name)
	:
	Test(name),
	fTests(NULL),
	fTestCount(0)
{
}


TestSuite::~TestSuite()
{
	for (int32 i = 0; i < fTestCount; i++)
		delete fTests[i];
	delete[] fTests;
}


int32
TestSuite::CountTests() const
{
	return fTestCount;
}


Test*
TestSuite::TestAt(int32 index) const
{
	return index >= 0 && index < fTestCount ? fTests[index] : NULL;
}


Test*
TestSuite::FindTest(const char* name, int32 nameLength) const
{
	if (nameLength < 0)
		nameLength = strlen(name);

	for (int32 i = 0; Test* test = TestAt(i); i++) {
		if (strlen(test->Name()) == (size_t)nameLength
			&& strncmp(test->Name(), name, nameLength) == 0) {
			return test;
		}
	}

	return NULL;
}


bool
TestSuite::AddTest(Test* test)
{
	if (test == NULL)
		return test;

	Test** tests = new(std::nothrow) Test*[fTestCount + 1];
	if (tests == NULL) {
		delete test;
		return false;
	}

	if (fTestCount > 0)
		memcpy(tests, fTests, sizeof(Test*) * fTestCount);

	delete[] fTests;

	fTests = tests;
	fTests[fTestCount++] = test;

	test->SetSuite(this);

	return true;
}


bool
TestSuite::IsLeafTest() const
{
	return false;
}


bool
TestSuite::Run(TestContext& context)
{
	for (int32 i = 0; Test* test = TestAt(i); i++) {
		bool result = _Run(context, test, NULL);
		if (!result && context.Options().quitAfterFailure)
			return false;
	}

	return true;
}


bool
TestSuite::Run(TestContext& context, const char* name)
{
	const char* separator = strstr(name, "::");
	Test* test = FindTest(name, separator != NULL ? separator - name : -1);
	if (test == NULL) {
		context.Print("No such test: \"%.*s\"\n",
			int(separator != NULL ? separator - name : strlen(name)), name);
		return !context.Options().quitAfterFailure;
	}

	return _Run(context, test, separator != NULL ? separator + 2 : NULL)
		|| !context.Options().quitAfterFailure;
}


Test*
TestSuite::Visit(TestVisitor& visitor)
{
	if (visitor.VisitTestSuitePre(this))
		return this;

	for (int32 i = 0; Test* test = TestAt(i); i++) {
		if (Test* foundTest = test->Visit(visitor))
			return foundTest;
	}

	return visitor.VisitTestSuitePost(this) ? this : NULL;
}


bool
TestSuite::_Run(TestContext& context, Test* test, const char* name)
{
	TestContext subContext(context, test);

	status_t error = test->Setup(subContext);
	if (error != B_OK) {
		subContext.Error("setup failed\n");
		test->Cleanup(subContext, false);
		subContext.TestDone(false);
		return false;
	}

	bool result = name != NULL
		? test->Run(subContext, name) : test->Run(subContext);
	test->Cleanup(subContext, true);

	subContext.TestDone(result);

	return result;
}