using System;
using System.Reflection;
using Moq;
using NUnit.Framework;
using Robust.Shared.Exceptions;
using Robust.Shared.Log;
using Robust.Shared.Profiling;
using Robust.Shared.Timing;
namespace Robust.UnitTesting.Shared.Timing
{
[TestFixture]
[TestOf(typeof(GameLoop))]
sealed class GameLoop_Test : OurRobustUnitTest
{
///
/// With single step enabled, the game loop should run 1 tick and then pause again.
///
[Test]
public void SingleStepTest()
{
// TimeoutAttribute causes this to run on different thread on .NET Core,
// which messes up IoC if we don't run this:
BaseSetup();
// Arrange
var elapsedVal = TimeSpan.FromSeconds(Math.PI);
var newStopwatch = new Mock();
newStopwatch.SetupGet(p => p.Elapsed).Returns(elapsedVal);
var gameTiming = GameTimingFactory(newStopwatch.Object);
gameTiming.Paused = false;
var loop = new GameLoop(
gameTiming,
new RuntimeLog(),
new ProfManager(),
new LogManager().RootSawmill,
new GameLoopOptions(false));
var callCount = 0;
loop.Tick += (sender, args) => callCount++;
loop.Render += (sender, args) => loop.Running = false; // break the endless loop for testing
// Act
loop.SingleStep = true;
loop.Run();
// Assert
Assert.That(callCount, Is.EqualTo(1));
Assert.That(gameTiming.CurTick, Is.EqualTo(new GameTick(2)));
Assert.That(gameTiming.Paused, Is.True); // it will pause itself after running each tick
Assert.That(loop.SingleStep, Is.True); // still true
}
private static IGameTiming GameTimingFactory(IStopwatch stopwatch)
{
var timing = new GameTiming();
var field = typeof(GameTiming).GetField("_realTimer", BindingFlags.Instance | BindingFlags.NonPublic)!;
field.SetValue(timing, stopwatch);
return timing;
}
}
}