330 | 330 | |
331 | 331 | fixed turnLengthFixed = fixed::FromInt(turnLength) / 1000; |
332 | 332 | |
333 | 333 | /* |
334 | 334 | * In serialization test mode, we save the original (primary) simulation state before each turn update. |
335 | 335 | * We run the update, then load the saved state into a secondary context. |
336 | 336 | * We serialize that again and compare to the original serialization (to check that |
337 | 337 | * serialize->deserialize->serialize is equivalent to serialize). |
338 | 338 | * Then we run the update on the secondary context, and check that its new serialized |
339 | 339 | * state matches the primary context after the update (to check that the simulation doesn't depend |
340 | 340 | * on anything that's not serialized). |
341 | 341 | */ |
342 | 342 | |
343 | 343 | const bool serializationTestDebugDump = false; // set true to save human-readable state dumps before an error is detected, for debugging (but slow) |
344 | 344 | const bool serializationTestHash = true; // set true to save and compare hash of state |
345 | 345 | |
346 | 346 | SerializationTestState primaryStateBefore; |
347 | 347 | ScriptInterface& scriptInterface = m_ComponentManager.GetScriptInterface(); |
348 | 348 | |
373 | 372 | // Load the trigger scripts after we have loaded the simulation. |
374 | 373 | { |
375 | 374 | JSContext* cx2 = secondaryComponentManager.GetScriptInterface().GetContext(); |
376 | 375 | JSAutoRequest rq2(cx2); |
377 | 376 | JS::RootedValue mapSettingsCloned(cx2, |
378 | 377 | secondaryComponentManager.GetScriptInterface().CloneValueFromOtherContext( |
379 | 378 | scriptInterface, m_MapSettings)); |
380 | 379 | ENSURE(LoadTriggerScripts(secondaryComponentManager, mapSettingsCloned, &secondaryLoadedScripts)); |
381 | 380 | } |
382 | 381 | |
383 | 382 | // Load the map into the secondary simulation |
384 | 383 | |
385 | 384 | LDR_BeginRegistering(); |
386 | 385 | CMapReader* mapReader = new CMapReader; // automatically deletes itself |
387 | 386 | |
388 | 387 | std::string mapType; |
389 | 388 | scriptInterface.GetProperty(m_InitAttributes, "mapType", mapType); |
390 | 389 | if (mapType == "random") |
391 | 390 | { |
392 | 391 | // TODO: support random map scripts |
393 | 392 | debug_warn(L"Serialization test mode does not support random maps"); |
394 | 393 | } |
395 | 394 | else |
396 | 395 | { |
397 | 396 | std::wstring mapFile; |
398 | 397 | scriptInterface.GetProperty(m_InitAttributes, "map", mapFile); |
399 | 398 | |
400 | 399 | VfsPath mapfilename = VfsPath(mapFile).ChangeExtension(L".pmp"); |
401 | 400 | mapReader->LoadMap(mapfilename, scriptInterface.GetJSRuntime(), JS::UndefinedHandleValue, |
402 | 401 | &secondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL, |
403 | 402 | NULL, NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure |
404 | 403 | } |
405 | 404 | |
406 | 405 | LDR_EndRegistering(); |
407 | 406 | ENSURE(LDR_NonprogressiveLoad() == INFO::OK); |
408 | 407 | |
409 | 408 | ENSURE(secondaryComponentManager.DeserializeState(primaryStateBefore.state)); |
410 | 409 | |
412 | 410 | ENSURE(secondaryComponentManager.SerializeState(secondaryStateBefore.state)); |
413 | 411 | if (serializationTestDebugDump) |
414 | 412 | ENSURE(secondaryComponentManager.DumpDebugState(secondaryStateBefore.debug, false)); |
415 | 413 | if (serializationTestHash) |
416 | 414 | ENSURE(secondaryComponentManager.ComputeStateHash(secondaryStateBefore.hash, false)); |
417 | 415 | |
418 | 416 | if (primaryStateBefore.state.str() != secondaryStateBefore.state.str() || |
419 | 417 | primaryStateBefore.hash != secondaryStateBefore.hash) |
420 | 418 | { |
421 | 419 | ReportSerializationFailure(&primaryStateBefore, NULL, &secondaryStateBefore, NULL); |
422 | 420 | } |
431 | 435 | SerializationTestState secondaryStateAfter; |
432 | 436 | ENSURE(secondaryComponentManager.SerializeState(secondaryStateAfter.state)); |
433 | 437 | if (serializationTestHash) |
434 | 438 | ENSURE(secondaryComponentManager.ComputeStateHash(secondaryStateAfter.hash, false)); |
435 | 439 | |
436 | 440 | if (primaryStateAfter.state.str() != secondaryStateAfter.state.str() || |
437 | 441 | primaryStateAfter.hash != secondaryStateAfter.hash) |
438 | 442 | { |
439 | 443 | // Only do the (slow) dumping now we know we're going to need to report it |
440 | 444 | ENSURE(m_ComponentManager.DumpDebugState(primaryStateAfter.debug, false)); |
441 | 445 | ENSURE(secondaryComponentManager.DumpDebugState(secondaryStateAfter.debug, false)); |
442 | 446 | |
443 | 447 | ReportSerializationFailure(&primaryStateBefore, &primaryStateAfter, &secondaryStateBefore, &secondaryStateAfter); |
444 | 448 | } |
445 | 449 | } |
446 | 450 | |
447 | 451 | // if (m_TurnNumber == 0) |
448 | 452 | // m_ComponentManager.GetScriptInterface().DumpHeap(); |
449 | 453 | |