Ticket #4242: rejointest.patch
File rejointest.patch, 12.3 KB (added by , 8 years ago) |
---|
-
binaries/system/readme.txt
58 58 -serializationtest checks simulation state each turn for serialization errors; on test 59 59 failure, error is displayed and logs created in oos_log within the 60 60 game's log folder. NOTE: game will run much slower with this option! 61 -rejointest=N simulates a rejoin and checks simulation state each turn for serialization 62 errors; this is similar to a serialization test but much faster and 63 less complete. It should be enough for debugging most rejoin OOSes. 61 64 62 65 Windows-specific: 63 66 -wQpcTscSafe allow timing via QueryPerformanceCounter despite the fact -
source/main.cpp
471 471 { 472 472 CReplayPlayer replay; 473 473 replay.Load(replayFile); 474 replay.Replay(args.Has("serializationtest"), args.Has("ooslog")); 474 replay.Replay( 475 args.Has("serializationtest"), 476 args.Has("rejointest") ? args.Get("rejointest").ToInt() : -1, 477 args.Has("ooslog")); 475 478 } 476 479 477 480 g_VFS.reset(); -
source/ps/GameSetup/Config.cpp
169 169 170 170 if (args.Has("serializationtest")) 171 171 g_ConfigDB.SetValueString(CFG_COMMAND, "serializationtest", "true"); 172 173 if (args.Has("rejointest")) 174 g_ConfigDB.SetValueString(CFG_COMMAND, "rejointest", args.Get("rejointest")); 172 175 } 173 176 174 177 -
source/ps/Replay.cpp
114 114 ENSURE(m_Stream->good()); 115 115 } 116 116 117 void CReplayPlayer::Replay(bool serializationtest, bool ooslog)117 void CReplayPlayer::Replay(bool serializationtest, int rejointestturn, bool ooslog) 118 118 { 119 119 ENSURE(m_Stream); 120 120 … … 130 130 g_Game = new CGame(true, false); 131 131 if (serializationtest) 132 132 g_Game->GetSimulation2()->EnableSerializationTest(); 133 if (rejointestturn > 0) 134 g_Game->GetSimulation2()->EnableRejoinTest(rejointestturn); 133 135 if (ooslog) 134 136 g_Game->GetSimulation2()->EnableOOSLog(); 135 137 -
source/ps/Replay.h
1 /* Copyright (C) 201 5Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 97 97 ~CReplayPlayer(); 98 98 99 99 void Load(const std::string& path); 100 void Replay(bool serializationtest, bool ooslog);100 void Replay(bool serializationtest, int rejointestturn, bool ooslog); 101 101 102 102 private: 103 103 std::istream* m_Stream; -
source/simulation2/Simulation2.cpp
51 51 public: 52 52 CSimulation2Impl(CUnitManager* unitManager, shared_ptr<ScriptRuntime> rt, CTerrain* terrain) : 53 53 m_SimContext(), m_ComponentManager(m_SimContext, rt), 54 m_EnableOOSLog(false), m_EnableSerializationTest(false), 54 m_EnableOOSLog(false), m_EnableSerializationTest(false), m_RejoinTestTurn(-1), m_TestingRejoin(false), 55 m_SecondaryTerrain(nullptr), m_SecondaryContext(nullptr), m_SecondaryComponentManager(nullptr), m_SecondaryLoadedScripts(nullptr), 55 56 m_MapSettings(rt->m_rt), m_InitAttributes(rt->m_rt) 56 57 { 57 58 m_SimContext.m_UnitManager = unitManager; … … 65 66 { 66 67 CFG_GET_VAL("ooslog", m_EnableOOSLog); 67 68 CFG_GET_VAL("serializationtest", m_EnableSerializationTest); 69 CFG_GET_VAL("rejointest", m_RejoinTestTurn); 70 if (m_RejoinTestTurn <= 0) // Handle bogus values of the arg 71 m_RejoinTestTurn = -1; 68 72 } 69 73 70 74 if (m_EnableOOSLog) … … 76 80 77 81 ~CSimulation2Impl() 78 82 { 83 delete m_SecondaryTerrain; 84 delete m_SecondaryContext; 85 delete m_SecondaryComponentManager; 86 delete m_SecondaryLoadedScripts; 87 79 88 UnregisterFileReloadFunc(ReloadChangedFileCB, this); 80 89 } 81 90 … … 130 139 // Functions and data for the serialization test mode: (see Update() for relevant comments) 131 140 132 141 bool m_EnableSerializationTest; 142 int m_RejoinTestTurn; 143 bool m_TestingRejoin; 133 144 145 // Secondary simulation 146 CTerrain* m_SecondaryTerrain; 147 CSimContext* m_SecondaryContext; 148 CComponentManager* m_SecondaryComponentManager; 149 std::set<VfsPath>* m_SecondaryLoadedScripts; 150 134 151 struct SerializationTestState 135 152 { 136 153 std::stringstream state; … … 332 349 * Then we run the update on the secondary context, and check that its new serialized 333 350 * state matches the primary context after the update (to check that the simulation doesn't depend 334 351 * on anything that's not serialized). 352 * 353 * In rejoin test mode, the secondary simulation is initialized from serialized data at turn N, then both 354 * simulations run independantly while comparing their states each turn. This is way faster than a 355 * complete serialization test and allows us to reproduce OOSes on rejoin. 335 356 */ 336 357 337 358 const bool serializationTestDebugDump = false; // set true to save human-readable state dumps before an error is detected, for debugging (but slow) … … 340 361 SerializationTestState primaryStateBefore; 341 362 ScriptInterface& scriptInterface = m_ComponentManager.GetScriptInterface(); 342 363 343 if (m_EnableSerializationTest) 364 if (m_RejoinTestTurn == m_TurnNumber) 365 m_TestingRejoin = true; 366 367 if (m_EnableSerializationTest || m_TestingRejoin) 344 368 { 345 369 ENSURE(m_ComponentManager.SerializeState(primaryStateBefore.state)); 346 370 if (serializationTestDebugDump) … … 351 375 352 376 UpdateComponents(m_SimContext, turnLengthFixed, commands); 353 377 354 355 if (m_EnableSerializationTest) 378 if (m_EnableSerializationTest || m_RejoinTestTurn == m_TurnNumber) 356 379 { 357 // Initialise the secondary simulation 358 CTerrain secondaryTerrain; 359 CSimContext secondaryContext; 360 secondaryContext.m_Terrain = &secondaryTerrain; 361 CComponentManager secondaryComponentManager(secondaryContext, scriptInterface.GetRuntime()); 362 secondaryComponentManager.LoadComponentTypes(); 363 std::set<VfsPath> secondaryLoadedScripts; 364 ENSURE(LoadDefaultScripts(secondaryComponentManager, &secondaryLoadedScripts)); 365 ResetComponentState(secondaryComponentManager, false, false); 380 // Initialize the secondary simulation 381 delete m_SecondaryTerrain; 382 m_SecondaryTerrain = new CTerrain(); 366 383 384 delete m_SecondaryContext; 385 m_SecondaryContext = new CSimContext(); 386 m_SecondaryContext->m_Terrain = m_SecondaryTerrain; 387 388 delete m_SecondaryComponentManager; 389 m_SecondaryComponentManager = new CComponentManager(*m_SecondaryContext, scriptInterface.GetRuntime()); 390 m_SecondaryComponentManager->LoadComponentTypes(); 391 392 delete m_SecondaryLoadedScripts; 393 m_SecondaryLoadedScripts = new std::set<VfsPath>(); 394 ENSURE(LoadDefaultScripts(*m_SecondaryComponentManager, m_SecondaryLoadedScripts)); 395 ResetComponentState(*m_SecondaryComponentManager, false, false); 396 367 397 // Load the trigger scripts after we have loaded the simulation. 368 398 { 369 JSContext* cx2 = secondaryComponentManager.GetScriptInterface().GetContext();399 JSContext* cx2 = m_SecondaryComponentManager->GetScriptInterface().GetContext(); 370 400 JSAutoRequest rq2(cx2); 371 401 JS::RootedValue mapSettingsCloned(cx2, 372 secondaryComponentManager.GetScriptInterface().CloneValueFromOtherContext(402 m_SecondaryComponentManager->GetScriptInterface().CloneValueFromOtherContext( 373 403 scriptInterface, m_MapSettings)); 374 ENSURE(LoadTriggerScripts( secondaryComponentManager, mapSettingsCloned, &secondaryLoadedScripts));404 ENSURE(LoadTriggerScripts(*m_SecondaryComponentManager, mapSettingsCloned, m_SecondaryLoadedScripts)); 375 405 } 376 406 377 407 // Load the map into the secondary simulation … … 393 423 394 424 VfsPath mapfilename = VfsPath(mapFile).ChangeExtension(L".pmp"); 395 425 mapReader->LoadMap(mapfilename, scriptInterface.GetJSRuntime(), JS::UndefinedHandleValue, 396 &secondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL,397 NULL, NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure426 m_SecondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL, 427 NULL, NULL, m_SecondaryContext, INVALID_PLAYER, true); // throws exception on failure 398 428 } 399 429 400 430 LDR_EndRegistering(); 401 431 ENSURE(LDR_NonprogressiveLoad() == INFO::OK); 432 ENSURE(m_SecondaryComponentManager->DeserializeState(primaryStateBefore.state)); 433 } 402 434 403 ENSURE(secondaryComponentManager.DeserializeState(primaryStateBefore.state));404 435 if (m_EnableSerializationTest || m_TestingRejoin) 436 { 405 437 SerializationTestState secondaryStateBefore; 406 ENSURE( secondaryComponentManager.SerializeState(secondaryStateBefore.state));438 ENSURE(m_SecondaryComponentManager->SerializeState(secondaryStateBefore.state)); 407 439 if (serializationTestDebugDump) 408 ENSURE( secondaryComponentManager.DumpDebugState(secondaryStateBefore.debug, false));440 ENSURE(m_SecondaryComponentManager->DumpDebugState(secondaryStateBefore.debug, false)); 409 441 if (serializationTestHash) 410 ENSURE( secondaryComponentManager.ComputeStateHash(secondaryStateBefore.hash, false));442 ENSURE(m_SecondaryComponentManager->ComputeStateHash(secondaryStateBefore.hash, false)); 411 443 412 444 if (primaryStateBefore.state.str() != secondaryStateBefore.state.str() || 413 445 primaryStateBefore.hash != secondaryStateBefore.hash) … … 420 452 if (serializationTestHash) 421 453 ENSURE(m_ComponentManager.ComputeStateHash(primaryStateAfter.hash, false)); 422 454 423 UpdateComponents( secondaryContext, turnLengthFixed,424 CloneCommandsFromOtherContext(scriptInterface, secondaryComponentManager.GetScriptInterface(), commands));455 UpdateComponents(*m_SecondaryContext, turnLengthFixed, 456 CloneCommandsFromOtherContext(scriptInterface, m_SecondaryComponentManager->GetScriptInterface(), commands)); 425 457 SerializationTestState secondaryStateAfter; 426 ENSURE( secondaryComponentManager.SerializeState(secondaryStateAfter.state));458 ENSURE(m_SecondaryComponentManager->SerializeState(secondaryStateAfter.state)); 427 459 if (serializationTestHash) 428 ENSURE( secondaryComponentManager.ComputeStateHash(secondaryStateAfter.hash, false));460 ENSURE(m_SecondaryComponentManager->ComputeStateHash(secondaryStateAfter.hash, false)); 429 461 430 462 if (primaryStateAfter.state.str() != secondaryStateAfter.state.str() || 431 463 primaryStateAfter.hash != secondaryStateAfter.hash) … … 432 464 { 433 465 // Only do the (slow) dumping now we know we're going to need to report it 434 466 ENSURE(m_ComponentManager.DumpDebugState(primaryStateAfter.debug, false)); 435 ENSURE( secondaryComponentManager.DumpDebugState(secondaryStateAfter.debug, false));467 ENSURE(m_SecondaryComponentManager->DumpDebugState(secondaryStateAfter.debug, false)); 436 468 437 469 ReportSerializationFailure(&primaryStateBefore, &primaryStateAfter, &secondaryStateBefore, &secondaryStateAfter); 438 470 } … … 588 620 589 621 // Forward all method calls to the appropriate CSimulation2Impl/CComponentManager methods: 590 622 623 void CSimulation2::EnableSerializationTest() 624 { 625 m->m_EnableSerializationTest = true; 626 } 627 628 void CSimulation2::EnableRejoinTest(int rejoinTestTurn) 629 { 630 m->m_RejoinTestTurn = rejoinTestTurn; 631 } 632 591 633 void CSimulation2::EnableOOSLog() 592 634 { 593 635 if (m->m_EnableOOSLog) … … 599 641 debug_printf("Writing ooslogs to %s\n", m->m_OOSLogPath.string8().c_str()); 600 642 } 601 643 602 void CSimulation2::EnableSerializationTest()603 {604 m->m_EnableSerializationTest = true;605 }606 607 644 entity_id_t CSimulation2::AddEntity(const std::wstring& templateName) 608 645 { 609 646 return m->m_ComponentManager.AddEntity(templateName, m->m_ComponentManager.AllocateNewEntity()); -
source/simulation2/Simulation2.h
54 54 CSimulation2(CUnitManager* unitManager, shared_ptr<ScriptRuntime> rt, CTerrain* terrain); 55 55 ~CSimulation2(); 56 56 57 void EnableSerializationTest(); 58 void EnableRejoinTest(int rejoinTestTurn); 57 59 void EnableOOSLog(); 58 void EnableSerializationTest();59 60 60 61 /** 61 62 * Load all scripts in the specified directory (non-recursively),