void CTextNode::addChild(const CSerializationID& keyID, const ISerializableNode* child) { const CTextNode* textChild = static_cast<const CTextNode*>(child); XmlNodeRef cloneNode = textChild->m_constXmlNode->clone(); cloneNode->setTag(keyID.GetString()); m_xmlNode->addChild(cloneNode); RebuildChildrenList(); }
// create the xmlnode before passing it in void CAutoTester::CreateTestCase(XmlNodeRef &testCase, const char *testName, bool passed, const char *failedType, const char *failedMessage) { assert(testName); testCase->setTag("testcase"); testCase->setAttr("name", testName ? testName : "NULL"); testCase->setAttr("time", 0); if (!passed) { assert(failedType); assert(failedMessage); XmlNodeRef failedCase = GetISystem()->CreateXmlNode(); failedCase->setTag("failure"); failedCase->setAttr("type", failedType ? failedType : "NULL"); failedCase->setAttr("message", failedMessage ? failedMessage : "NULL"); testCase->addChild(failedCase); } }
/// Runs all registered tests (if they meet their dependencies) void CFeatureTestMgr::RunAll() { // Writing the list of the active registered tests. // This can be useful to later check, when a crash occurs, // which tests were executed and which are skipped // (We will have no valid results for them) { if(m_pAutoTester && !m_testManifestWritten) { XmlNodeRef testManifest = GetISystem()->CreateXmlNode("testManifest"); testManifest->setTag("testmanifest"); CryLogAlways("About to dump out the testmanifest xml..."); for (TFeatureTestVec::iterator iter(m_featureTests.begin()); iter != m_featureTests.end(); ++iter) { FeatureTestState& fTest = *iter; XmlNodeRef testDescrNode = fTest.m_pTest->XmlDescription(); if(testDescrNode) { testManifest->addChild(testDescrNode); } } m_pAutoTester->WriteTestManifest(testManifest); m_testManifestWritten = true; } } if (!IsRunning()) { // Ensure all tests are cleaned up and scheduled to run ResetAllTests(eFTS_Scheduled); if (StartNextTest() || WaitingForScheduledTests()) { CryLog("Running all map feature tests..."); } else { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "No tests available to run!"); } } else { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Tests are already running, can't start more until tests are complete."); } }
void CAutoTester::AddSimpleTestCase(const char * groupName, const char * testName, float duration, const char * failureReason, const char * owners) { bool passed = true; XmlNodeRef testCase = GetISystem()->CreateXmlNode(); testCase->setTag("testcase"); testCase->setAttr("name", testName); if (owners) { testCase->setAttr("owners", owners); } if (duration >= 0.f) { testCase->setAttr("time", duration); } // Set whatever other attributes are useful here! if (failureReason == NULL || failureReason[0] == '\0') { CryLogAlways ("CAutoTester::AddSimpleTestCase() Group '%s' test '%s' passed!", groupName, testName); testCase->setAttr("status", "run"); } else { CryLogAlways ("CAutoTester::AddSimpleTestCase() Group '%s' test '%s' failed: %s", groupName, testName, failureReason); XmlNodeRef failedCase = GetISystem()->CreateXmlNode(); failedCase->setTag("failure"); failedCase->setAttr("type", "TestCaseFailed"); failedCase->setAttr("message", failureReason); testCase->addChild(failedCase); passed = false; } AddTestCaseResult(string().Format("%s: %s", m_includeThisInFileName, groupName ? groupName : "No group name specified"), testCase, passed); }
bool CEditorGame::BuildEntitySerializationList(XmlNodeRef output) { if(!output) return false; typedef std::vector<IFlowGraph*> TFGVector; TSerializationData entityData; // all entities TFGVector flowGraphs; // all flowgraphs // build the all-entity list, and keep a record of those entities // which have a flowgraph attached IEntityIt* pIt = gEnv->pEntitySystem->GetEntityIterator(); while(IEntity* pEntity = pIt->Next()) { IEntityFlowGraphProxy* pFGProxy = static_cast<IEntityFlowGraphProxy*>(pEntity->GetProxy(ENTITY_PROXY_FLOWGRAPH)); if(pFGProxy) { flowGraphs.push_back(pFGProxy->GetFlowGraph()); MarkEntityForSerialize(entityData, pEntity, eST_FlowGraphContainer); } if (!stricmp(pEntity->GetClass()->GetName(), "Constraint")) { MarkEntityForSerialize(entityData, pEntity, eST_Class); float constraintRadius = -FLT_MAX; if (IScriptTable* entityTable = pEntity->GetScriptTable()) { SmartScriptTable props; if (entityTable->GetValue("Properties", props)) props->GetValue("radius", constraintRadius); } if (constraintRadius > 0.0f) { const Vec3 boxMin = pEntity->GetWorldPos() - Vec3(constraintRadius + 0.05f); const Vec3 boxMax = pEntity->GetWorldPos() + Vec3(constraintRadius + 0.05f); IPhysicalEntity** nearbyEntities = 0; if (size_t entityCount = gEnv->pPhysicalWorld->GetEntitiesInBox(boxMin, boxMax, nearbyEntities, ent_all)) { for (size_t i = 0; i < entityCount; ++i) { if (IEntity* nearbyEntity = gEnv->pEntitySystem->GetEntityFromPhysics(nearbyEntities[i])) MarkEntityForSerialize(entityData, nearbyEntity, eST_ConstraintNeighbour); } } } else { CryLogAlways("Failed to find a value radius property for constraint '%s'. " "Serialization for this constraint might not work.", pEntity->GetName()); } } else if(ShouldSaveEntityClass(pEntity)) // some classes should always be saved MarkEntityForSerialize(entityData, pEntity, eST_Class); } // for each FG, mark all entities referenced as needing saving for(TFGVector::const_iterator it = flowGraphs.begin(); it != flowGraphs.end(); ++it) { if(!*it) continue; IFlowNodeIteratorPtr nodeIt = (*it)->CreateNodeIterator(); TFlowNodeId nodeId = 0; while(IFlowNodeData* pNode = nodeIt->Next(nodeId)) { EntityId nodeEntity = (*it)->GetEntityId(nodeId); if(nodeEntity != 0) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(nodeEntity); MarkEntityForSerialize(entityData, pEntity, eST_FlowGraph); } } } // now do the same for entities moved by trackview for(int i=0; i<gEnv->pMovieSystem->GetNumSequences(); ++i) { IAnimSequence* pSeq = gEnv->pMovieSystem->GetSequence(i); int nodeCount = pSeq->GetNodeCount(); for(int j=0; j<nodeCount; ++j) { IAnimNode* pNode = pSeq->GetNode(j); if(pNode) { IEntity* pEntity = pNode->GetEntity(); if(pEntity && ShouldSaveTrackViewEntityClass(pEntity)) { MarkEntityForSerialize(entityData, pEntity, eST_TrackView); } if(EntityGUID* guid = pNode->GetEntityGuid()) { EntityId id = gEnv->pEntitySystem->FindEntityByGuid(*guid); if(id != 0) { IEntity* pEntity2 = gEnv->pEntitySystem->GetEntity(id); MarkEntityForSerialize(entityData, pEntity2, eST_TrackView); } } } } } // now check entity links: any entity linked to or from a serialized // entity must also be serialized for(TSerializationData::iterator it = entityData.begin(), end = entityData.end(); it != end; ++it) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(it->first); assert(pEntity); IEntityLink* pLink = pEntity->GetEntityLinks(); while(pLink) { IEntity* pLinkedEntity = gEnv->pEntitySystem->GetEntity(pLink->entityId); assert(pLinkedEntity); MarkEntityForSerialize(entityData, pLinkedEntity, eST_Linked); pLink = pLink->next; } } // output the final file, plus debug info #if SERIALIZATION_EXPORT_DEBUG int saveCount = 0; int totalCount = 0; int fgCount = 0; int fgRefCount = 0; int classCount = 0; int tvCount = 0; int childCount = 0; int parentCount = 0; int linkCount = 0; int fgUnique = 0; int fgRefUnique = 0; int classUnique = 0; int tvUnique = 0; int linkUnique = 0; typedef std::map<string, int> TClassSaveInfo; TClassSaveInfo classesNotSaved; TClassSaveInfo classesSaved; #endif output->setTag("EntitySerialization"); for(TSerializationData::const_iterator it = entityData.begin(); it != entityData.end(); ++it) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(it->first); #if SERIALIZATION_EXPORT_DEBUG ++totalCount; string reasons = "Saving: "; #endif if(it->second != eST_NotSerialized) { XmlNodeRef child = output->createNode("Entity"); child->setAttr("id", it->first); //child->setAttr("class", pEntity->GetClass()->GetName()); // debug check //child->setAttr("name", pEntity->GetName()); // debug check output->addChild(child); #if SERIALIZATION_EXPORT_DEBUG classesSaved[pEntity->GetClass()->GetName()]++; ++saveCount; if(it->second & eST_FlowGraphContainer) { reasons += "FG Container; "; ++fgCount; } if(it->second & eST_FlowGraph) { reasons += "FG reference; "; ++fgRefCount; } if(it->second & eST_Class) { reasons += "Class; "; ++classCount; } if(it->second & eST_TrackView) { reasons += "Trackview; "; ++tvCount; } if(it->second & eST_Child) { reasons += "Child; "; ++childCount; } if(it->second & eST_Parent) { reasons += "Parent; "; ++parentCount; } if(it->second & eST_Linked) { reasons += "Linked; "; ++linkCount; } // unique counts (things added as a result of only one condition) switch(it->second) { case eST_FlowGraph: ++fgRefUnique; break; case eST_FlowGraphContainer: ++fgUnique; break; case eST_Class: ++classUnique; break; case eST_TrackView: ++tvUnique; break; case eST_Linked: ++linkUnique; break; default: break; } } else { reasons = "Not saving"; classesNotSaved[pEntity->GetClass()->GetName()]++; } CryLogAlways("Entity %s (%d, class %s) : %s", pEntity->GetName(), it->first, pEntity->GetClass()->GetName(), reasons.c_str()); #endif } }
void CAutoTester::UpdateTestNumClientsLevelRotate() { if(gEnv->bServer) { IGameFramework *pFramework = gEnv->pGame->GetIGameFramework(); int numChannels = 1; //local channel if(pFramework) { INetNub *pNub = pFramework->GetServerNetNub(); if(pNub) { numChannels = pNub->GetNumChannels(); } } if (numChannels > m_stateData.testNumClientsRotate.m_maxNumClientsConnected) { m_stateData.testNumClientsRotate.m_maxNumClientsConnected=numChannels; } float timeSeconds=gEnv->pTimer->GetFrameStartTime().GetSeconds(); CryWatch("time=%f; nextTimeOut=%f; numClients=%d; maxNumClients=%d; numClientsExpected=%d", timeSeconds, m_stateData.testNumClientsRotate.m_nextTimeOut, numChannels, m_stateData.testNumClientsRotate.m_maxNumClientsConnected, m_stateData.testNumClientsRotate.m_numClientsExpected); if (timeSeconds > m_stateData.testNumClientsRotate.m_debugTimer) { m_stateData.testNumClientsRotate.m_debugTimer = timeSeconds+2.0f; CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() updating time=%f; nextTimeOut=%f; numClients=%d; maxNumClients=%d; numClientsExpected=%d", timeSeconds, m_stateData.testNumClientsRotate.m_nextTimeOut, numChannels, m_stateData.testNumClientsRotate.m_maxNumClientsConnected, m_stateData.testNumClientsRotate.m_numClientsExpected); } if (timeSeconds > m_stateData.testNumClientsRotate.m_nextTimeOut) { CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() testing num clients and time has expired. numClients=%d; maxNumClients=%d; numClientsExpected=%d", numChannels, m_stateData.testNumClientsRotate.m_maxNumClientsConnected, m_stateData.testNumClientsRotate.m_numClientsExpected); bool passed=false; ILevelRotation *pLevelRotation = g_pGame->GetIGameFramework()->GetILevelSystem()->GetLevelRotation(); string mapName = g_pGame->GetIGameFramework()->GetILevelSystem()->GetCurrentLevel()->GetLevelInfo()->GetName(); string gameRulesName; gameRulesName = g_pGame->GetGameRules()->GetEntity()->GetClass()->GetName(); XmlNodeRef testCase = GetISystem()->CreateXmlNode(); string nameStr; if (m_stateData.testNumClientsRotate.m_levelIndex == 0) { nameStr.Format("%02d/%d) Level: %s; gameRules: %s; numClients=%d; timeTested=%.1f seconds", m_stateData.testNumClientsRotate.m_levelIndex+1, pLevelRotation->GetLength(), mapName.c_str(), gameRulesName.c_str(), numChannels, m_stateData.testNumClientsRotate.m_firstLevelTimeOut); } else { nameStr.Format("%02d/%d) Level: %s; gameRules: %s; numClients=%d; timeTested=%.1f seconds", m_stateData.testNumClientsRotate.m_levelIndex+1, pLevelRotation->GetLength(), mapName.c_str(), gameRulesName.c_str(), numChannels, m_stateData.testNumClientsRotate.m_levelTimeOut); } CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() outputting a test result with these details [%s]", nameStr.c_str()); testCase->setTag("testcase"); testCase->setAttr("name", nameStr.c_str()); testCase->setAttr("time", 0); testCase->setAttr("numClients", numChannels); testCase->setAttr("maxNumClientsConnected",m_stateData.testNumClientsRotate.m_maxNumClientsConnected); testCase->setAttr("numClientsExpected", m_stateData.testNumClientsRotate.m_numClientsExpected); if (numChannels == m_stateData.testNumClientsRotate.m_maxNumClientsConnected) { CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() testing num clients and time has expired. We have the same number of clients are our maxNumClients %d", numChannels); if (numChannels == m_stateData.testNumClientsRotate.m_numClientsExpected) // may want to remove this check as keeping the number that joined should be sufficient { CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() testing num clients and time has expired. We have the same number of clients as we expected to have %d", numChannels); testCase->setAttr("status", "run"); passed=true; } else { CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() testing num clients and time has expired. We DON'T have the same number of clients %d as we expected to have %d", numChannels, m_stateData.testNumClientsRotate.m_numClientsExpected); //testCase->setAttr("status", "failed"); XmlNodeRef failedCase = GetISystem()->CreateXmlNode(); failedCase->setTag("failure"); failedCase->setAttr("type", "NotEnoughClients"); failedCase->setAttr("message", string().Format("testing num clients and time has expired. We DON'T have the same number of clients %d as we expected to have %d", numChannels, m_stateData.testNumClientsRotate.m_numClientsExpected)); testCase->addChild(failedCase); } } else { //testCase->setAttr("status", "failed"); XmlNodeRef failedCase = GetISystem()->CreateXmlNode(); failedCase->setTag("failure"); failedCase->setAttr("type", "NotEnoughClients"); failedCase->setAttr("message", string().Format("testing num clients and time has expired. We DON'T have the same number of clients %d as we peaked at %d", numChannels, m_stateData.testNumClientsRotate.m_maxNumClientsConnected)); testCase->addChild(failedCase); } AddTestCaseResult("Test Clients In Level Rotation", testCase, passed); Stop(); if (pLevelRotation->GetNext() != 0) { CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() has found we're not at the end of the level rotation moving on to the next level - levelIndex=%d; rotation->GetNext()=%d\n", m_stateData.testNumClientsRotate.m_levelIndex+1, pLevelRotation->GetNext()); Restart(); gEnv->pConsole->ExecuteString("g_nextlevel"); // has to be a better way of doing this m_stateData.testNumClientsRotate.m_nextTimeOut = timeSeconds + m_stateData.testNumClientsRotate.m_levelTimeOut; m_stateData.testNumClientsRotate.m_levelIndex++; } else { CryLogAlways("CAutoTester::UpdateTestNumClientsLevelRotate() has found we ARE at the end of the level rotation. Not doing anymore tests\n"); } } } }
// TODO parameterise and refactor this now its mainly duplicated between the two runs void CAutoTester::UpdateTestNumClients() { if(gEnv->bServer) { IGameFramework *pFramework = gEnv->pGame->GetIGameFramework(); int numChannels = 1; //local channel if(pFramework) { INetNub *pNub = pFramework->GetServerNetNub(); if(pNub) { numChannels = pNub->GetNumChannels(); } } if (numChannels > m_stateData.testNumClients.m_maxNumClientsConnected) { m_stateData.testNumClients.m_maxNumClientsConnected=numChannels; } float timeSeconds=gEnv->pTimer->GetFrameStartTime().GetSeconds(); CryWatch("time=%f; numClients=%d; maxNumClients=%d; numClientsExpected=%d", timeSeconds, numChannels, m_stateData.testNumClients.m_maxNumClientsConnected, m_stateData.testNumClients.m_numClientsExpected); if (timeSeconds > m_stateData.testNumClients.m_debugTimer) { m_stateData.testNumClients.m_debugTimer = timeSeconds+2.0f; CryLogAlways("CAutoTester::UpdateTestNumClients() updating time=%f; numClients=%d; maxNumClients=%d; numClientsExpected=%d", timeSeconds, numChannels, m_stateData.testNumClients.m_maxNumClientsConnected, m_stateData.testNumClients.m_numClientsExpected); } if (timeSeconds > m_stateData.testNumClients.m_timeOut) { CryLogAlways("CAutoTester::UpdateTestNumClients() testing num clients and time has expired. numClients=%d; maxNumClients=%d; numClientsExpected=%d", numChannels, m_stateData.testNumClients.m_maxNumClientsConnected, m_stateData.testNumClients.m_numClientsExpected); bool passed=false; string mapName = g_pGame->GetIGameFramework()->GetILevelSystem()->GetCurrentLevel()->GetLevelInfo()->GetName(); string gameRulesName; gameRulesName = g_pGame->GetGameRules()->GetEntity()->GetClass()->GetName(); XmlNodeRef testCase = GetISystem()->CreateXmlNode(); string nameStr; nameStr.Format("Level: %s; gameRules: %s; numClients=%d; timeTested=%.1f seconds", mapName.c_str(), gameRulesName.c_str(), numChannels, m_stateData.testNumClients.m_timeOut); testCase->setTag("testcase"); testCase->setAttr("name", nameStr.c_str()); testCase->setAttr("time", 0); testCase->setAttr("numClients", numChannels); testCase->setAttr("maxNumClientsConnected",m_stateData.testNumClients.m_maxNumClientsConnected); testCase->setAttr("numClientsExpected", m_stateData.testNumClients.m_numClientsExpected); if (numChannels == m_stateData.testNumClients.m_maxNumClientsConnected) { CryLogAlways("CAutoTester::UpdateTestNumClients() testing num clients and time has expired. We have the same number of clients are our maxNumClients %d", numChannels); if (numChannels == m_stateData.testNumClients.m_numClientsExpected) // may want to remove this check as keeping the number that joined should be sufficient { CryLogAlways("CAutoTester::UpdateTestNumClients() testing num clients and time has expired. We have the same number of clients as we expected to have %d", numChannels); testCase->setAttr("status", "run"); passed=true; } else { CryLogAlways("CAutoTester::UpdateTestNumClients() testing num clients and time has expired. We DON'T have the same number of clients %d as we expected to have %d", numChannels, m_stateData.testNumClients.m_numClientsExpected); //testCase->setAttr("status", "failed"); XmlNodeRef failedCase = GetISystem()->CreateXmlNode(); failedCase->setTag("failure"); failedCase->setAttr("type", "NotEnoughClients"); failedCase->setAttr("message", string().Format("testing num clients and time has expired. We DON'T have the same number of clients %d as we expected to have %d", numChannels, m_stateData.testNumClients.m_numClientsExpected)); testCase->addChild(failedCase); } } else { //testCase->setAttr("status", "failed"); XmlNodeRef failedCase = GetISystem()->CreateXmlNode(); failedCase->setTag("failure"); failedCase->setAttr("type", "NotEnoughClients"); failedCase->setAttr("message", string().Format("testing num clients and time has expired. We DON'T have the same number of clients %d as we peaked at %d", numChannels, m_stateData.testNumClients.m_maxNumClientsConnected)); testCase->addChild(failedCase); } AddTestCaseResult("Test Clients In Levels", testCase, passed); Stop(); } } }
void CAutoTester::WriteResults(TBitfield flags, const string * additionalTestSuiteName, const XmlNodeRef * additionalTestCase) { const int& autotest_enabled = g_pGameCVars->autotest_enabled; if (!autotest_enabled) { return; } //If result generation is skipped, exit early if (autotest_enabled == 2) { if (m_quitWhenDone) { gEnv->pConsole->ExecuteString("quit"); } return; } // test workaround //DesignerWarning(0, "test warning"); // test workaround const char * mapName; string gameRulesName; const char * serverText = ""; const char * dedicatedText = gEnv->IsDedicated() ? "_Dedicated" : ""; CGameRules * rules = g_pGame ? g_pGame->GetGameRules() : NULL; if (rules) { gameRulesName = rules->GetEntity()->GetClass()->GetName(); serverText = gEnv->bServer ? "_Server" : "_Client"; } else { gameRulesName = "FrontEnd"; } if (g_pGame && g_pGame->GetIGameFramework()->GetILevelSystem()->GetCurrentLevel()) { mapName = g_pGame->GetIGameFramework()->GetILevelSystem()->GetCurrentLevel()->GetLevelInfo()->GetName(); } else { mapName = "NoMapLoaded"; } #ifndef _RELEASE CryLogAlways ("CAutoTester::WriteResults(%s): map is '%s', game mode is '%s'", AutoEnum_GetStringFromBitfield(flags, s_writeResultsFlagNames, WriteResultsFlagList_numBits).c_str(), mapName, gameRulesName.c_str()); #endif XmlNodeRef testSuites = GetISystem()->CreateXmlNode("testSuites"); testSuites->setTag("testsuites"); for (TTestSuites::const_iterator it=m_testSuites.begin(); it!=m_testSuites.end(); ++it) { const STestSuite &testSuiteStruct = it->second; int numTests = testSuiteStruct.m_testCases.size(); int numFails = testSuiteStruct.m_numTestCasesFailed; XmlNodeRef testSuite = GetISystem()->CreateXmlNode("AutoTest"); testSuite->setTag("testsuite"); testSuite->setAttr("name", it->first); testSuite->setAttr("LevelName", mapName); testSuite->setAttr("GameRulesName", gameRulesName); if (additionalTestSuiteName && it->first == *additionalTestSuiteName) { CryLog ("Writing additional test case to existing '%s' suite", additionalTestSuiteName->c_str()); ++ numFails; // Assumption here that any additional test data provided is a failure... [TF] ++ numTests; testSuite->addChild(*additionalTestCase); additionalTestSuiteName = NULL; } testSuite->setAttr("tests", numTests); testSuite->setAttr("failures", numFails); testSuite->setAttr("errors", 0); testSuite->setAttr("time", 0); for (size_t i = 0; i < testSuiteStruct.m_testCases.size(); i++) { testSuite->addChild(testSuiteStruct.m_testCases[i]); } testSuites->addChild(testSuite); } if (additionalTestSuiteName) // Still haven't written our additional test case because the suite name didn't match any existing suite... { CryLog ("CAutoTester writing additional test case to unique '%s' suite", additionalTestSuiteName->c_str()); XmlNodeRef testSuite = GetISystem()->CreateXmlNode("AutoTest"); testSuite->setTag("testsuite"); testSuite->setAttr("name", *additionalTestSuiteName); testSuite->setAttr("LevelName", mapName); testSuite->setAttr("GameRulesName", gameRulesName); testSuite->setAttr("tests", 1); testSuite->setAttr("failures", 1); testSuite->setAttr("errors", 0); testSuite->setAttr("time", 0); testSuite->addChild(*additionalTestCase); testSuites->addChild(testSuite); } char mapNameChrs[256]; char gameRulesNameChrs[256]; cry_strncpy(mapNameChrs, mapName, sizeof(mapNameChrs)); cry_strncpy(gameRulesNameChrs, gameRulesName, sizeof(gameRulesNameChrs)); for (int i=0; mapNameChrs[i]; i++) { if (mapNameChrs[i] == '/' || mapNameChrs[i] == ' ') { mapNameChrs[i] = '_'; } } for (int i=0; gameRulesNameChrs[i]; i++) { if (gameRulesNameChrs[i] == '/' || gameRulesNameChrs[i] == ' ') { gameRulesNameChrs[i] = '_'; } } const char * resultsCompleteFailMessage = NULL; if (flags & kWriteResultsFlag_unfinished) { resultsCompleteFailMessage = "Didn't finish all tests!"; } else if (m_testSuites.size() == 0) { resultsCompleteFailMessage = "Ran zero tests!"; } if (resultsCompleteFailMessage || m_writeResultsCompleteTestCasePass) { int numFailures = 0; XmlNodeRef testSuite = GetISystem()->CreateXmlNode("testsuite"); testSuite->setAttr("name", "Are results complete?"); XmlNodeRef unfinishedFailure = GetISystem()->CreateXmlNode("testcase"); if (m_createVerboseFilename) { unfinishedFailure->setAttr("name", string().Format("%s_%s_%s%s%s", m_includeThisInFileName, mapNameChrs, gameRulesNameChrs, dedicatedText, serverText)); } else { unfinishedFailure->setAttr("name", string().Format("%s%s", m_includeThisInFileName, dedicatedText)); } if (resultsCompleteFailMessage) { XmlNodeRef failedCase = GetISystem()->CreateXmlNode("failure"); failedCase->setAttr("type", "Unfinished"); failedCase->setAttr("message", resultsCompleteFailMessage); unfinishedFailure->addChild(failedCase); ++ numFailures; } else { unfinishedFailure->setAttr("status", "run"); } testSuite->setAttr("tests", 1); testSuite->setAttr("errors", 0); testSuite->setAttr("time", 0); testSuite->setAttr("failures", numFailures); testSuite->addChild(unfinishedFailure); testSuites->addChild(testSuite); } string justTheFilename; if (m_createVerboseFilename) { justTheFilename.Format("autotest_%s_%s_%s%s%s.xml", m_includeThisInFileName, mapNameChrs, gameRulesNameChrs, dedicatedText, serverText); // TODO add datestamp if needed } else { // If m_createVerboseFilename is false, then only include things in the filename which WON'T CHANGE between the test starting and ending [TF] justTheFilename.Format("autotest_%s%s.xml", m_includeThisInFileName, dedicatedText); } m_outputPath.Format("../Xml-Reports/%s", justTheFilename.c_str()); #ifndef _RELEASE CryLogAlways ("Outputting test to %s", m_outputPath.c_str()); #endif SaveToValidXmlFile(testSuites, m_outputPath.c_str()); if (flags & kWriteResultsFlag_writeDoneMarkerFile) { XmlNodeRef finished = GetISystem()->CreateXmlNode("Finished"); SaveToValidXmlFile(finished, m_outputPath + ".done"); if (m_quitWhenDone) { gEnv->pConsole->ExecuteString("unload"); gEnv->pConsole->ExecuteString("quit"); } } }