static void writeCaseListNode (std::ostream& str, const TestNode* node, const TestSet& testSet)
{
	DE_ASSERT(testSet.hasNode(node));

	TestNodeType nodeType = node->getNodeType();

	if (nodeType != TESTNODETYPE_ROOT)
		str << node->getName();

	if (nodeType == TESTNODETYPE_ROOT || nodeType == TESTNODETYPE_GROUP)
	{
		const TestGroup*	group	= static_cast<const TestGroup*>(node);
		bool				isFirst	= true;

		str << "{";

		for (int ndx = 0; ndx < group->getNumChildren(); ndx++)
		{
			const TestNode* child = group->getChild(ndx);

			if (testSet.hasNode(child))
			{
				if (!isFirst)
					str << ",";

				writeCaseListNode(str, child, testSet);
				isFirst = false;
			}
		}

		str << "}";
	}
}
static int removeExecuted (TestSet& set, const TestNode* root, const BatchResult* batchResult)
{
	TestSet					oldSet		(set);
	ConstTestNodeIterator	iter		= ConstTestNodeIterator::begin(root);
	ConstTestNodeIterator	end			= ConstTestNodeIterator::end(root);
	int						numRemoved	= 0;

	for (; iter != end; ++iter)
	{
		const TestNode* node = *iter;

		if (node->getNodeType() == TESTNODETYPE_TEST_CASE && oldSet.hasNode(node))
		{
			const TestCase* testCase = static_cast<const TestCase*>(node);

			if (isExecutedInBatch(batchResult, testCase))
			{
				set.removeCase(testCase);
				numRemoved += 1;
			}
		}
	}

	return numRemoved;
}
void BatchExecutor::launchTestSet (const TestSet& testSet)
{
	std::ostringstream caseList;
	XE_CHECK(testSet.hasNode(m_root));
	XE_CHECK(m_root->getNodeType() == TESTNODETYPE_ROOT);
	writeCaseListNode(caseList, m_root, testSet);

	m_commLink->startTestProcess(m_config.binaryName.c_str(), m_config.cmdLineArgs.c_str(), m_config.workingDir.c_str(), caseList.str().c_str());
}
static void computeBatchRequest (TestSet& requestSet, const TestSet& executeSet, const TestNode* root, int maxCasesInSet)
{
	ConstTestNodeIterator	iter		= ConstTestNodeIterator::begin(root);
	ConstTestNodeIterator	end			= ConstTestNodeIterator::end(root);
	int						numCases	= 0;

	for (; (iter != end) && (numCases < maxCasesInSet); ++iter)
	{
		const TestNode* node = *iter;

		if (node->getNodeType() == TESTNODETYPE_TEST_CASE && executeSet.hasNode(node))
		{
			const TestCase* testCase = static_cast<const TestCase*>(node);
			requestSet.addCase(testCase);
			numCases += 1;
		}
	}
}
static void computeExecuteSet (TestSet& executeSet, const TestNode* root, const TestSet& testSet, const BatchResult* batchResult)
{
	ConstTestNodeIterator	iter	= ConstTestNodeIterator::begin(root);
	ConstTestNodeIterator	end		= ConstTestNodeIterator::end(root);

	for (; iter != end; ++iter)
	{
		const TestNode* node = *iter;

		if (node->getNodeType() == TESTNODETYPE_TEST_CASE && testSet.hasNode(node))
		{
			const TestCase* testCase = static_cast<const TestCase*>(node);

			if (!isExecutedInBatch(batchResult, testCase))
				executeSet.addCase(testCase);
		}
	}
}