//=========================================================
double TesterManager::runTest(const std::string& strTName)
{
	double dRez = TM_EMPTY;
	if (m_MTC.empty()) {
		return dRez;
	}
	if (strTName == std::string()) {
		// run all tests
		// first resolve dependencies
		std::vector<std::string> vcStrDeps;
		if (!resolveDeps(vcStrDeps)) {
			DBG_ERR("Manager '%s', looped dependency detected, final results could seem better than actual", m_strName.c_str());
		}
		for (std::vector<std::string>::const_iterator vscit = vcStrDeps.begin(); vscit != vcStrDeps.end(); ++vscit) {
			const std::string& strDepName = *vscit;
			double dDepRez = runTest(strDepName);
			if (0.0 <= dDepRez && dDepRez <= 1.0) {
				m_DRM[strDepName] = dDepRez;
			} else {
				DBG_ERR("Manager '%s', error running dependency test, runTest returned %g", m_strName.c_str(), dDepRez);
			}
		}
		// now run all the rest
		std::size_t sztTestsRun = m_MTC.size();
		double dSum = 0.0;
		for (MapTesterClasses::iterator mtcit = m_MTC.begin(); mtcit != m_MTC.end(); ++mtcit) {
			const std::string& strCName = mtcit->first;
			if (strCName == std::string()) {
				DBG_ERR("Manager '%s', empty class name detected", m_strName.c_str());
				continue;
			}
			double dTest = runTest(strCName);
			if (0.0 <= dTest && dTest <= 1.0) {
				dSum += dTest;
			}
		}
		dRez = dSum / double(sztTestsRun);
	} else {
		// run specific test
		TesterMethod* pTM = nullptr;
		TesterClass*  pTC = nullptr;
		if (getByName(strTName, pTC, pTM)) {
			if (pTM) {
				if (m_DRM.find(strTName) != m_DRM.end()) {
					dRez = m_DRM[strTName];
				} else {
					dRez = pTM->runTest();
					if (0.0 <= dRez && dRez <= 1.0) {
						m_DRM[strTName] = dRez;
					}
				}
			} else {
				dRez = pTC->runTest();
			}
		} else {
			dRez = TM_ERROR;
		}
	}
	return dRez;
}
Exemple #2
0
int elektraSortTopology (KeySet * ks, Key ** array)
{
	if (ks == NULL || array == NULL) return -1;
	KeySet * done = ksNew (0, KS_END);
	ksRewind (ks);
	Key * cur;
	ssize_t size = ksGetSize (ks);
	Key * orderCounter = keyNew ("/#", KEY_CASCADING_NAME, KEY_END);
	elektraArrayIncName (orderCounter);
	_adjMatrix adjMatrix[size];
	int i = 0;
	int retVal = 1;
	int depCount = 0;
	Key ** localArray = elektraMalloc (size * sizeof (Key *));
	elektraKsToMemArray (ks, localArray);
	qsort (localArray, size, sizeof (Key *), topCmpOrder);
	for (long j = 0; j < size; ++j)
	{
		adjMatrix[j].key = localArray[j];
		adjMatrix[j].isResolved = 0;
		adjMatrix[j].deps = elektraCalloc (sizeof (unsigned long) * size);
	}
	kdb_octet_t hasOrder = 0;
	if (keyGetMeta (localArray[0], "order")) hasOrder = 1;
	unsigned int unresolved = 0;
	for (int j = 0; j < size; ++j)
	{
		cur = localArray[j];
		KeySet * deps = elektraMetaArrayToKS (cur, "dep");
		keyDel (ksLookupByName (deps, "dep", KDB_O_POP));
		Key * tmpDep;
		switch (ksGetSize (deps))
		{
		case -1:
		{
			// key has no dependencies, give it an order number and add it to list of resolved dependencies
			keySetMeta (cur, "order", keyBaseName (orderCounter));
			elektraArrayIncName (orderCounter);
			ksAppendKey (done, keyDup (cur));
			adjMatrix[j].isResolved = 1;
			ksDel (deps);
			break;
		}
		case 1:
		{
			// only 1 dependency:
			// test if it's reflexive
			tmpDep = ksHead (deps);
			if (!strcmp (keyName (cur), keyString (tmpDep)))
			{
				keySetMeta (cur, "order", keyBaseName (orderCounter));
				elektraArrayIncName (orderCounter);
				ksAppendKey (done, keyDup (cur));
				adjMatrix[j].isResolved = 1;
				ksDel (deps);
				break;
			}
			// if not, fallthrough to normal dependency handling
		}
		default:
		{
			int gotUnresolved = 0;
			while ((tmpDep = ksNext (deps)) != NULL)
			{
				if (!isValidKeyName (keyString (tmpDep)))
				{
					// invalid keyname -> ERROR
					retVal = -1;
					break;
				}
				i = getArrayIndex (tmpDep, adjMatrix, size);
				if (i == -1)
				{
					// key doesn't exist yet but has valid name, ignore it.
					continue;
				}
				else if (i == j)
				{
					// reflexiv depencency, do nothing
				}
				else
				{
					if (!adjMatrix[i].isResolved)
					{
						// unresolved dependency
						adjMatrix[j].deps[i] = 1;
						++gotUnresolved;
						// simple cycle detection
						if (adjMatrix[i].deps[j])
						{
							retVal = 0;
							break;
						}
					}
				}
			}
			if (gotUnresolved)
			{
				adjMatrix[j].isResolved = 0;
				++unresolved;
				// cound unresolved dependencies
				depCount += gotUnresolved;
			}
			ksDel (deps);
			break;
		}
		}
		if (retVal <= 0) break;
	}
	if (retVal <= 0)
	{
		// error or cycle: goto cleanup
		goto TopSortCleanup;
	}

	// resolve all dependencies that can be resolved immediately
	for (int j = 0; j < size; ++j)
	{
		if (adjMatrix[j].isResolved) depCount -= resolveDep (j, adjMatrix, size);
	}

	ssize_t resolved = ksGetSize (done);
	if (((depCount + resolved) >= size) && (unresolved))
	{
		// more dependencies dependencies than keys:
		//  cycle found !
		retVal = 0;
		goto TopSortCleanup;
	}

	if (unresolved)
	{
		int found = 1;
		// we have unresolved dependencies
		for (int j = 0; j < size + 1; ++j)
		{
			// loop until no dependency can be resolved anymore
			if (j == size)
			{
				if (found)
				{
					found = 0;
					j = -1;
					unresolved = 0;
					continue;
				}
				else
					break;
			}
			if (adjMatrix[j].isResolved) continue;
			++unresolved;
			if (hasOrder)
			{
				// resolve by order
				int ret = resolveDeps (j, adjMatrix, size, done, orderCounter);
				if (ret == -1) break;
				j = -1;
				found = 1;
				continue;
			}
			else
			{
				// resolve next possible dependency in keyset
				if (!hasUnresolvedDependencies (j, adjMatrix, size))
				{
					adjMatrix[j].isResolved = 1;
					resolveDep (j, adjMatrix, size);
					keySetMeta (localArray[j], "order", keyBaseName (orderCounter));
					elektraArrayIncName (orderCounter);
					ksAppendKey (done, keyDup (localArray[j]));
					found = 1;
				}
			}
		}
	}
	if (unresolved == 0)
	{
		// everything resolved
		// add dependencies in topological order to array
		elektraKsToMemArray (ks, array);
		qsort (array, size, sizeof (Key *), topCmpOrder);
		retVal = 1;
	}
	else
	{
		// still unresolved dependencies left:
		// there must be a cycle somewhere
		retVal = 0;
	}
TopSortCleanup:
	ksDel (done);
	keyDel (orderCounter);
	elektraFree (localArray);
	for (ssize_t j = 0; j < size; ++j)
	{
		elektraFree (adjMatrix[j].deps);
	}
	return retVal;
}