mirror of
https://github.com/ppy/osu.git
synced 2026-05-16 10:22:53 +08:00
82906300b4
This is still a workaround but arguably it's something we could leave in place without much loss. I think this at least feels better than the previous code. Notably, you could argue the test coverage of the fail case is lower since made it implicit that all tests will avoid the "backwards seek" detections. But we never really had tests correctly- fail on the original so I don't see any loss of value.
203 lines
5.8 KiB
C#
203 lines
5.8 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
#nullable disable
|
|
|
|
using NUnit.Framework;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Timing;
|
|
using osu.Game.Graphics.Sprites;
|
|
using osu.Game.Rulesets.UI;
|
|
|
|
namespace osu.Game.Tests.Visual.Gameplay
|
|
{
|
|
public partial class TestSceneFrameStabilityContainer : OsuTestScene
|
|
{
|
|
private readonly ManualClock manualClock;
|
|
|
|
private readonly Container mainContainer;
|
|
|
|
private ClockConsumingChild consumer;
|
|
|
|
public TestSceneFrameStabilityContainer()
|
|
{
|
|
Child = mainContainer = new Container
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Clock = new FramedClock(manualClock = new ManualClock()),
|
|
};
|
|
}
|
|
|
|
[Test]
|
|
public void TestLargeJumps()
|
|
{
|
|
seekManualTo(0);
|
|
createStabilityContainer();
|
|
seekManualTo(100000);
|
|
|
|
confirmSeek(100000);
|
|
checkFrameCount(6000);
|
|
|
|
seekManualTo(0);
|
|
|
|
confirmSeek(0);
|
|
checkFrameCount(12000);
|
|
}
|
|
|
|
[Test]
|
|
public void TestSmallJumps()
|
|
{
|
|
seekManualTo(0);
|
|
createStabilityContainer();
|
|
seekManualTo(40);
|
|
|
|
confirmSeek(40);
|
|
checkFrameCount(3);
|
|
|
|
seekManualTo(0);
|
|
|
|
confirmSeek(0);
|
|
checkFrameCount(6);
|
|
}
|
|
|
|
[Test]
|
|
public void TestSingleFrameJump()
|
|
{
|
|
seekManualTo(0);
|
|
createStabilityContainer();
|
|
seekManualTo(8);
|
|
confirmSeek(8);
|
|
checkFrameCount(1);
|
|
|
|
seekManualTo(16);
|
|
confirmSeek(16);
|
|
checkFrameCount(2);
|
|
}
|
|
|
|
[Test]
|
|
public void TestInitialSeekWithGameplayStart()
|
|
{
|
|
seekManualTo(1000);
|
|
createStabilityContainer(30000);
|
|
|
|
confirmSeek(1000);
|
|
checkFrameCount(0);
|
|
|
|
seekManualTo(10000);
|
|
confirmSeek(10000);
|
|
|
|
checkFrameCount(1);
|
|
|
|
seekManualTo(130000);
|
|
confirmSeek(130000);
|
|
|
|
checkFrameCount(6002);
|
|
}
|
|
|
|
[Test]
|
|
public void TestInitialSeek()
|
|
{
|
|
seekManualTo(100000);
|
|
createStabilityContainer();
|
|
|
|
confirmSeek(100000);
|
|
checkFrameCount(0);
|
|
}
|
|
|
|
[Test]
|
|
public void TestRatePreservedWhenTimeNotProgressing()
|
|
{
|
|
AddStep("set manual clock rate", () => manualClock.Rate = 1);
|
|
seekManualTo(5000);
|
|
createStabilityContainer();
|
|
checkRate(1);
|
|
|
|
seekManualTo(10000);
|
|
checkRate(1);
|
|
|
|
AddWaitStep("wait some", 3);
|
|
checkRate(1);
|
|
|
|
seekManualTo(5000);
|
|
checkRate(-1);
|
|
|
|
AddWaitStep("wait some", 3);
|
|
checkRate(-1);
|
|
|
|
seekManualTo(10000);
|
|
checkRate(1);
|
|
}
|
|
|
|
private void createStabilityContainer(double gameplayStartTime = double.MinValue) => AddStep("create container", () =>
|
|
{
|
|
mainContainer.Child = new FrameStabilityContainer(gameplayStartTime).WithChild(consumer = new ClockConsumingChild());
|
|
});
|
|
|
|
private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time);
|
|
|
|
private void confirmSeek(double time) => AddUntilStep($"wait for seek to {time}", () => consumer.Clock.CurrentTime, () => Is.EqualTo(time));
|
|
|
|
private void checkFrameCount(int frames) =>
|
|
AddAssert($"elapsed frames is {frames}", () => consumer.ElapsedFrames, () => Is.EqualTo(frames));
|
|
|
|
private void checkRate(double rate) =>
|
|
AddAssert($"clock rate is {rate}", () => consumer.Clock.Rate, () => Is.EqualTo(rate));
|
|
|
|
public partial class ClockConsumingChild : CompositeDrawable
|
|
{
|
|
private readonly OsuSpriteText text;
|
|
private readonly OsuSpriteText text2;
|
|
private readonly OsuSpriteText text3;
|
|
|
|
public ClockConsumingChild()
|
|
{
|
|
Anchor = Anchor.Centre;
|
|
Origin = Anchor.Centre;
|
|
|
|
InternalChildren = new Drawable[]
|
|
{
|
|
new FillFlowContainer
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Direction = FillDirection.Vertical,
|
|
Children = new Drawable[]
|
|
{
|
|
text = new OsuSpriteText
|
|
{
|
|
Anchor = Anchor.Centre,
|
|
Origin = Anchor.Centre,
|
|
},
|
|
text2 = new OsuSpriteText
|
|
{
|
|
Anchor = Anchor.Centre,
|
|
Origin = Anchor.Centre,
|
|
},
|
|
text3 = new OsuSpriteText
|
|
{
|
|
Anchor = Anchor.Centre,
|
|
Origin = Anchor.Centre,
|
|
},
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
public int ElapsedFrames;
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
|
|
if (Clock.ElapsedFrameTime != 0)
|
|
ElapsedFrames++;
|
|
|
|
text.Text = $"current time: {Clock.CurrentTime:F0}";
|
|
if (Clock.ElapsedFrameTime != 0)
|
|
text2.Text = $"last elapsed frame time: {Clock.ElapsedFrameTime:F0}";
|
|
text3.Text = $"total frames: {ElapsedFrames:F0}";
|
|
}
|
|
}
|
|
}
|
|
}
|