#include <uunit.h>

#include <ctor.h>
#include <build.h>

namespace
{
ctor::build_configurations ctorTestConfigsCyclic(const ctor::settings&)
{
	return
	{
		// No dependency
		{
			.target = "target0",
		},

		// Direct (self-depends)
		{
			.target = "target1",
			.depends = { "target1" },
		},

		// Indirect cyclic depends
		{
			.target = "target2",
			.depends = { "target3" },
		},
		{
			.target = "target3",
			.depends = { "target2" },
		},
	};
}
}

REG(ctorTestConfigsCyclic);

class CycleTest
	: public uUnit
{
public:
	CycleTest()
	{
		uTEST(CycleTest::getTargets_test);
	}

	void getTargets_test()
	{
		using namespace std::string_literals;
		ctor::settings settings{};
		const auto& tasks = getTasks(settings);
		uASSERT_EQUAL(4u, tasks.size());

		uASSERT_EQUAL("target0"s, tasks[0]->target());
		uASSERT_EQUAL("target1"s, tasks[1]->target());
		uASSERT_EQUAL("target2"s, tasks[2]->target());
		uASSERT_EQUAL("target3"s, tasks[3]->target());

		for(auto task : tasks)
		{
			if(task->registerDepTasks(tasks))
			{
				uASSERT(false);
			}
		}

		bool exc;
		exc = false;
		try { getDepTasks(tasks[0]); } catch(...) { exc = true; }
		uASSERT(!exc);

		exc = false;
		try { getDepTasks(tasks[1]); } catch(...) { exc = true; }
		uASSERT(exc);

		exc = false;
		try { getDepTasks(tasks[2]); } catch(...) { exc = true; }
		uASSERT(exc);

		exc = false;
		try { getDepTasks(tasks[3]); } catch(...) { exc = true; }
		uASSERT(exc);
	}
};

// Registers the fixture into the 'registry'
static CycleTest test;