2019-01-24 16:43:03 +08:00
|
|
|
|
// 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.
|
2018-05-31 16:29:59 +08:00
|
|
|
|
|
2022-06-17 15:37:17 +08:00
|
|
|
|
#nullable disable
|
|
|
|
|
|
2020-03-11 12:20:31 +08:00
|
|
|
|
using System.Linq;
|
2019-03-29 13:15:57 +08:00
|
|
|
|
using System.Threading;
|
2018-05-31 16:29:59 +08:00
|
|
|
|
using NUnit.Framework;
|
2019-03-27 21:27:53 +08:00
|
|
|
|
using osu.Framework.Allocation;
|
2018-05-31 16:29:59 +08:00
|
|
|
|
using osu.Framework.Graphics;
|
|
|
|
|
using osu.Framework.Graphics.Shapes;
|
2019-01-23 19:52:00 +08:00
|
|
|
|
using osu.Framework.Screens;
|
2020-03-11 12:20:31 +08:00
|
|
|
|
using osu.Framework.Testing;
|
|
|
|
|
using osu.Game.Graphics.UserInterface;
|
2018-05-31 16:29:59 +08:00
|
|
|
|
using osu.Game.Screens;
|
|
|
|
|
using osu.Game.Screens.Menu;
|
2018-11-20 15:51:59 +08:00
|
|
|
|
using osuTK.Graphics;
|
2018-05-31 16:29:59 +08:00
|
|
|
|
|
2019-03-25 00:02:36 +08:00
|
|
|
|
namespace osu.Game.Tests.Visual.Menus
|
2018-05-31 16:29:59 +08:00
|
|
|
|
{
|
|
|
|
|
[TestFixture]
|
2022-11-24 13:32:20 +08:00
|
|
|
|
public partial class TestSceneLoader : ScreenTestScene
|
2018-05-31 16:29:59 +08:00
|
|
|
|
{
|
|
|
|
|
private TestLoader loader;
|
|
|
|
|
|
2019-03-27 21:27:53 +08:00
|
|
|
|
[Cached]
|
|
|
|
|
private OsuLogo logo;
|
|
|
|
|
|
2020-03-11 01:49:20 +08:00
|
|
|
|
public TestSceneLoader()
|
2019-03-27 21:27:53 +08:00
|
|
|
|
{
|
2019-04-19 11:44:57 +08:00
|
|
|
|
Child = logo = new OsuLogo
|
|
|
|
|
{
|
|
|
|
|
Alpha = 0,
|
|
|
|
|
Depth = float.MinValue
|
|
|
|
|
};
|
2019-03-27 21:27:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 13:15:57 +08:00
|
|
|
|
[Test]
|
|
|
|
|
public void TestInstantLoad()
|
2018-05-31 16:29:59 +08:00
|
|
|
|
{
|
2019-10-29 16:03:52 +08:00
|
|
|
|
AddStep("load immediately", () =>
|
2019-03-29 13:15:57 +08:00
|
|
|
|
{
|
|
|
|
|
loader = new TestLoader();
|
|
|
|
|
loader.AllowLoad.Set();
|
|
|
|
|
|
|
|
|
|
LoadScreen(loader);
|
|
|
|
|
});
|
2020-03-11 12:20:31 +08:00
|
|
|
|
|
Modify assert to avoid false failures
In headless tests it was possible for TestInstantLoad() to erroneously
fail. There were two scenarios in which LoadingSpinner could be null:
1. If the test runner was quick enough, the assert could end up running
even before Loader.OnEntering() had even had a chance to, meaning
that the spinner was never even actually assigned to or instantiated
at that point in time.
2. Even if Loader.OnEntering() had managed to run, there was also
a possibility that the spinner itself wasn't loaded at the point
of checking the assertion. As the spinner is accessed through
ChildrenOfType(), which only checks InternalChildren and ignores
all currently-loading drawables, it would therefore return null.
As null != 0, both of these cases would actually fail the test (this is
best seen running headless, preferably with a [Repeat] attribute
attached).
To resolve, allow the spinner to be null at the point of asserting and
duplicate the assertion step at the end. This weakens the test, as case
(1) should probably be waited for and case (2) could be solved with
exposition as protected in the base, but when attempting to wait for
the loader itself to be loaded there were also cases where the
appropriate until step would take so much time that the spinner would
actually become visible in line with the delayed display logic, so this
is a best-effort attempt to address both points without radical
changes.
2020-03-28 07:42:51 +08:00
|
|
|
|
spinnerNotPresentOrHidden();
|
2020-03-11 12:20:31 +08:00
|
|
|
|
|
|
|
|
|
AddUntilStep("loaded", () => loader.ScreenLoaded);
|
|
|
|
|
AddUntilStep("not current", () => !loader.IsCurrentScreen());
|
Modify assert to avoid false failures
In headless tests it was possible for TestInstantLoad() to erroneously
fail. There were two scenarios in which LoadingSpinner could be null:
1. If the test runner was quick enough, the assert could end up running
even before Loader.OnEntering() had even had a chance to, meaning
that the spinner was never even actually assigned to or instantiated
at that point in time.
2. Even if Loader.OnEntering() had managed to run, there was also
a possibility that the spinner itself wasn't loaded at the point
of checking the assertion. As the spinner is accessed through
ChildrenOfType(), which only checks InternalChildren and ignores
all currently-loading drawables, it would therefore return null.
As null != 0, both of these cases would actually fail the test (this is
best seen running headless, preferably with a [Repeat] attribute
attached).
To resolve, allow the spinner to be null at the point of asserting and
duplicate the assertion step at the end. This weakens the test, as case
(1) should probably be waited for and case (2) could be solved with
exposition as protected in the base, but when attempting to wait for
the loader itself to be loaded there were also cases where the
appropriate until step would take so much time that the spinner would
actually become visible in line with the delayed display logic, so this
is a best-effort attempt to address both points without radical
changes.
2020-03-28 07:42:51 +08:00
|
|
|
|
|
|
|
|
|
spinnerNotPresentOrHidden();
|
2019-03-29 13:15:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
Modify assert to avoid false failures
In headless tests it was possible for TestInstantLoad() to erroneously
fail. There were two scenarios in which LoadingSpinner could be null:
1. If the test runner was quick enough, the assert could end up running
even before Loader.OnEntering() had even had a chance to, meaning
that the spinner was never even actually assigned to or instantiated
at that point in time.
2. Even if Loader.OnEntering() had managed to run, there was also
a possibility that the spinner itself wasn't loaded at the point
of checking the assertion. As the spinner is accessed through
ChildrenOfType(), which only checks InternalChildren and ignores
all currently-loading drawables, it would therefore return null.
As null != 0, both of these cases would actually fail the test (this is
best seen running headless, preferably with a [Repeat] attribute
attached).
To resolve, allow the spinner to be null at the point of asserting and
duplicate the assertion step at the end. This weakens the test, as case
(1) should probably be waited for and case (2) could be solved with
exposition as protected in the base, but when attempting to wait for
the loader itself to be loaded there were also cases where the
appropriate until step would take so much time that the spinner would
actually become visible in line with the delayed display logic, so this
is a best-effort attempt to address both points without radical
changes.
2020-03-28 07:42:51 +08:00
|
|
|
|
private void spinnerNotPresentOrHidden() =>
|
|
|
|
|
AddAssert("spinner did not display", () => loader.LoadingSpinner == null || loader.LoadingSpinner.Alpha == 0);
|
|
|
|
|
|
2019-03-29 13:15:57 +08:00
|
|
|
|
[Test]
|
2019-05-21 13:48:14 +08:00
|
|
|
|
public void TestDelayedLoad()
|
2019-03-29 13:15:57 +08:00
|
|
|
|
{
|
|
|
|
|
AddStep("begin loading", () => LoadScreen(loader = new TestLoader()));
|
2020-03-11 12:20:31 +08:00
|
|
|
|
AddUntilStep("wait for spinner visible", () => loader.LoadingSpinner?.Alpha > 0);
|
2019-05-21 13:48:14 +08:00
|
|
|
|
AddStep("finish loading", () => loader.AllowLoad.Set());
|
2020-03-11 12:20:31 +08:00
|
|
|
|
AddUntilStep("spinner gone", () => loader.LoadingSpinner?.Alpha == 0);
|
|
|
|
|
AddUntilStep("loaded", () => loader.ScreenLoaded);
|
|
|
|
|
AddUntilStep("not current", () => !loader.IsCurrentScreen());
|
2018-05-31 16:29:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-24 13:32:20 +08:00
|
|
|
|
private partial class TestLoader : Loader
|
2018-05-31 16:29:59 +08:00
|
|
|
|
{
|
2019-03-29 13:15:57 +08:00
|
|
|
|
public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim();
|
2018-05-31 16:29:59 +08:00
|
|
|
|
|
2020-03-11 15:07:44 +08:00
|
|
|
|
public LoadingSpinner LoadingSpinner => this.ChildrenOfType<LoadingSpinner>().FirstOrDefault();
|
2018-05-31 19:07:55 +08:00
|
|
|
|
private TestScreen screen;
|
2018-05-31 16:29:59 +08:00
|
|
|
|
|
2019-01-23 19:52:00 +08:00
|
|
|
|
public bool ScreenLoaded => screen.IsCurrentScreen();
|
2018-05-31 19:07:55 +08:00
|
|
|
|
|
|
|
|
|
protected override OsuScreen CreateLoadableScreen() => screen = new TestScreen();
|
2019-03-29 13:15:57 +08:00
|
|
|
|
protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(AllowLoad);
|
2018-05-31 16:29:59 +08:00
|
|
|
|
|
2022-11-24 13:32:20 +08:00
|
|
|
|
private partial class TestShaderPrecompiler : ShaderPrecompiler
|
2018-05-31 16:29:59 +08:00
|
|
|
|
{
|
2019-03-29 13:15:57 +08:00
|
|
|
|
private readonly ManualResetEventSlim allowLoad;
|
2018-05-31 19:07:55 +08:00
|
|
|
|
|
2019-03-29 13:15:57 +08:00
|
|
|
|
public TestShaderPrecompiler(ManualResetEventSlim allowLoad)
|
2018-05-31 19:07:55 +08:00
|
|
|
|
{
|
2019-03-29 13:15:57 +08:00
|
|
|
|
this.allowLoad = allowLoad;
|
2018-05-31 19:07:55 +08:00
|
|
|
|
}
|
2018-05-31 16:29:59 +08:00
|
|
|
|
|
2019-03-29 13:15:57 +08:00
|
|
|
|
protected override bool AllLoaded => allowLoad.IsSet;
|
2018-05-31 19:07:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-24 13:32:20 +08:00
|
|
|
|
private partial class TestScreen : OsuScreen
|
2018-05-31 19:07:55 +08:00
|
|
|
|
{
|
|
|
|
|
public TestScreen()
|
|
|
|
|
{
|
2019-01-23 19:52:00 +08:00
|
|
|
|
InternalChild = new Box
|
2018-05-31 16:29:59 +08:00
|
|
|
|
{
|
|
|
|
|
RelativeSizeAxes = Axes.Both,
|
|
|
|
|
Colour = Color4.DarkSlateGray,
|
|
|
|
|
Alpha = 0,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
|
|
|
|
{
|
|
|
|
|
base.LogoArriving(logo, resuming);
|
2019-01-23 19:52:00 +08:00
|
|
|
|
InternalChild.FadeInFromZero(200);
|
2018-05-31 16:29:59 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|