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-04-13 17:19:50 +08:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Text ;
using NUnit.Framework ;
using osu.Framework.Allocation ;
2019-02-21 18:04:31 +08:00
using osu.Framework.Bindables ;
2018-04-13 17:19:50 +08:00
using osu.Framework.Extensions ;
using osu.Framework.MathUtils ;
2019-01-22 19:37:41 +08:00
using osu.Framework.Platform ;
2019-02-15 16:01:06 +08:00
using osu.Framework.Screens ;
2018-04-13 17:19:50 +08:00
using osu.Game.Beatmaps ;
using osu.Game.Database ;
using osu.Game.Rulesets ;
2018-08-14 13:18:46 +08:00
using osu.Game.Rulesets.Mods ;
using osu.Game.Rulesets.Osu.Mods ;
using osu.Game.Rulesets.Taiko ;
2018-04-13 17:19:50 +08:00
using osu.Game.Screens.Select ;
using osu.Game.Screens.Select.Carousel ;
using osu.Game.Screens.Select.Filter ;
namespace osu.Game.Tests.Visual
{
[TestFixture]
2019-02-15 16:01:06 +08:00
public class TestCasePlaySongSelect : ScreenTestCase
2018-04-13 17:19:50 +08:00
{
private BeatmapManager manager ;
private RulesetStore rulesets ;
private WorkingBeatmap defaultBeatmap ;
2018-07-19 13:07:55 +08:00
private DatabaseContextFactory factory ;
2018-04-13 17:19:50 +08:00
2018-08-14 13:18:46 +08:00
[Cached]
[Cached(Type = typeof(IBindable<IEnumerable<Mod>>))]
private readonly Bindable < IEnumerable < Mod > > selectedMods = new Bindable < IEnumerable < Mod > > ( new Mod [ ] { } ) ;
2018-04-13 17:19:50 +08:00
public override IReadOnlyList < Type > RequiredTypes = > new [ ]
{
typeof ( SongSelect ) ,
typeof ( BeatmapCarousel ) ,
typeof ( CarouselItem ) ,
typeof ( CarouselGroup ) ,
typeof ( CarouselGroupEagerSelect ) ,
typeof ( CarouselBeatmap ) ,
typeof ( CarouselBeatmapSet ) ,
typeof ( DrawableCarouselItem ) ,
typeof ( CarouselItemState ) ,
typeof ( DrawableCarouselBeatmap ) ,
typeof ( DrawableCarouselBeatmapSet ) ,
} ;
private class TestSongSelect : PlaySongSelect
{
2019-01-10 14:25:07 +08:00
public Action StartRequested ;
2018-08-14 13:18:46 +08:00
public new Bindable < RulesetInfo > Ruleset = > base . Ruleset ;
2018-04-13 17:19:50 +08:00
public WorkingBeatmap CurrentBeatmap = > Beatmap . Value ;
public WorkingBeatmap CurrentBeatmapDetailsBeatmap = > BeatmapDetails . Beatmap ;
public new BeatmapCarousel Carousel = > base . Carousel ;
2019-01-10 14:25:07 +08:00
protected override bool OnStart ( )
{
StartRequested ? . Invoke ( ) ;
return base . OnStart ( ) ;
}
2018-04-13 17:19:50 +08:00
}
2018-07-18 11:58:45 +08:00
private TestSongSelect songSelect ;
2018-07-23 04:47:25 +08:00
protected override void Dispose ( bool isDisposing )
{
factory . ResetDatabase ( ) ;
base . Dispose ( isDisposing ) ;
}
2018-04-13 17:19:50 +08:00
[BackgroundDependencyLoader]
2019-01-22 19:37:41 +08:00
private void load ( GameHost host )
2018-04-13 17:19:50 +08:00
{
2018-07-19 13:07:55 +08:00
factory = new DatabaseContextFactory ( LocalStorage ) ;
2018-07-18 15:43:46 +08:00
factory . ResetDatabase ( ) ;
2018-04-13 17:19:50 +08:00
2018-07-20 23:02:55 +08:00
using ( var usage = factory . Get ( ) )
usage . Migrate ( ) ;
2018-07-18 15:43:46 +08:00
factory . ResetDatabase ( ) ;
using ( var usage = factory . Get ( ) )
usage . Migrate ( ) ;
2018-04-13 17:19:50 +08:00
2018-06-06 19:25:40 +08:00
Dependencies . Cache ( rulesets = new RulesetStore ( factory ) ) ;
2019-01-22 19:37:41 +08:00
Dependencies . Cache ( manager = new BeatmapManager ( LocalStorage , factory , rulesets , null , null , host , defaultBeatmap = Beatmap . Default ) ) ;
2018-04-13 17:19:50 +08:00
2018-07-18 11:58:45 +08:00
Beatmap . SetDefault ( ) ;
}
2018-04-13 17:19:50 +08:00
2018-07-18 11:58:45 +08:00
[SetUp]
2019-02-15 20:50:40 +08:00
public virtual void SetUp ( ) = >
Schedule ( ( ) = > { manager ? . Delete ( manager . GetAllUsableBeatmapSets ( ) ) ; } ) ;
2018-04-13 17:19:50 +08:00
2018-07-20 10:32:00 +08:00
[Test]
2018-07-18 11:58:45 +08:00
public void TestDummy ( )
{
2019-02-15 20:50:40 +08:00
createSongSelect ( ) ;
2018-04-13 17:19:50 +08:00
AddAssert ( "dummy selected" , ( ) = > songSelect . CurrentBeatmap = = defaultBeatmap ) ;
2019-03-19 16:24:26 +08:00
AddUntilStep ( "dummy shown on wedge" , ( ) = > songSelect . CurrentBeatmapDetailsBeatmap = = defaultBeatmap ) ;
2018-04-13 17:19:50 +08:00
2018-07-18 11:58:45 +08:00
addManyTestMaps ( ) ;
2019-03-19 16:24:26 +08:00
AddWaitStep ( "wait for select" , 3 ) ;
2018-07-18 11:58:45 +08:00
2018-04-13 17:19:50 +08:00
AddAssert ( "random map selected" , ( ) = > songSelect . CurrentBeatmap ! = defaultBeatmap ) ;
2018-07-18 11:58:45 +08:00
}
2018-04-13 17:19:50 +08:00
2018-07-20 10:32:00 +08:00
[Test]
2018-07-18 11:58:45 +08:00
public void TestSorting ( )
{
2019-02-15 20:50:40 +08:00
createSongSelect ( ) ;
2018-07-18 11:58:45 +08:00
addManyTestMaps ( ) ;
2019-03-19 16:24:26 +08:00
AddWaitStep ( "wait for add" , 3 ) ;
2018-07-18 11:58:45 +08:00
2018-04-13 17:19:50 +08:00
AddAssert ( "random map selected" , ( ) = > songSelect . CurrentBeatmap ! = defaultBeatmap ) ;
AddStep ( @"Sort by Artist" , delegate { songSelect . FilterControl . Sort = SortMode . Artist ; } ) ;
AddStep ( @"Sort by Title" , delegate { songSelect . FilterControl . Sort = SortMode . Title ; } ) ;
AddStep ( @"Sort by Author" , delegate { songSelect . FilterControl . Sort = SortMode . Author ; } ) ;
AddStep ( @"Sort by Difficulty" , delegate { songSelect . FilterControl . Sort = SortMode . Difficulty ; } ) ;
}
2018-07-18 11:58:45 +08:00
[Test]
2018-07-25 22:45:07 +08:00
[Ignore("needs fixing")]
2018-08-14 13:19:26 +08:00
public void TestImportUnderDifferentRuleset ( )
2018-04-13 17:19:50 +08:00
{
2019-02-15 20:50:40 +08:00
createSongSelect ( ) ;
2018-07-20 10:32:00 +08:00
changeRuleset ( 2 ) ;
importForRuleset ( 0 ) ;
2019-03-19 16:24:26 +08:00
AddUntilStep ( "no selection" , ( ) = > songSelect . Carousel . SelectedBeatmap = = null ) ;
2018-07-20 10:32:00 +08:00
}
2018-07-19 17:51:08 +08:00
2018-07-20 10:32:00 +08:00
[Test]
2018-08-14 13:19:26 +08:00
public void TestImportUnderCurrentRuleset ( )
2018-07-20 10:32:00 +08:00
{
2019-02-15 20:50:40 +08:00
createSongSelect ( ) ;
2018-07-20 10:32:00 +08:00
changeRuleset ( 2 ) ;
importForRuleset ( 2 ) ;
importForRuleset ( 1 ) ;
2019-03-19 16:24:26 +08:00
AddUntilStep ( "has selection" , ( ) = > songSelect . Carousel . SelectedBeatmap . RulesetID = = 2 ) ;
2018-07-19 17:51:08 +08:00
2018-07-20 10:32:00 +08:00
changeRuleset ( 1 ) ;
2019-03-19 16:24:26 +08:00
AddUntilStep ( "has selection" , ( ) = > songSelect . Carousel . SelectedBeatmap . RulesetID = = 1 ) ;
2018-07-19 17:51:08 +08:00
2018-07-20 10:32:00 +08:00
changeRuleset ( 0 ) ;
2019-03-19 16:24:26 +08:00
AddUntilStep ( "no selection" , ( ) = > songSelect . Carousel . SelectedBeatmap = = null ) ;
2018-07-18 11:58:45 +08:00
}
2018-08-14 13:18:46 +08:00
[Test]
public void TestRulesetChangeResetsMods ( )
{
2019-02-15 20:50:40 +08:00
createSongSelect ( ) ;
2018-08-14 13:18:46 +08:00
changeRuleset ( 0 ) ;
changeMods ( new OsuModHardRock ( ) ) ;
int actionIndex = 0 ;
int modChangeIndex = 0 ;
int rulesetChangeIndex = 0 ;
AddStep ( "change ruleset" , ( ) = >
{
songSelect . CurrentBeatmap . Mods . ValueChanged + = onModChange ;
songSelect . Ruleset . ValueChanged + = onRulesetChange ;
Ruleset . Value = new TaikoRuleset ( ) . RulesetInfo ;
songSelect . CurrentBeatmap . Mods . ValueChanged - = onModChange ;
songSelect . Ruleset . ValueChanged - = onRulesetChange ;
} ) ;
AddAssert ( "mods changed before ruleset" , ( ) = > modChangeIndex < rulesetChangeIndex ) ;
AddAssert ( "empty mods" , ( ) = > ! selectedMods . Value . Any ( ) ) ;
2019-02-21 17:56:34 +08:00
void onModChange ( ValueChangedEvent < IEnumerable < Mod > > e ) = > modChangeIndex = actionIndex + + ;
void onRulesetChange ( ValueChangedEvent < RulesetInfo > e ) = > rulesetChangeIndex = actionIndex - - ;
2018-08-14 13:18:46 +08:00
}
2019-01-10 14:25:07 +08:00
[Test]
public void TestStartAfterUnMatchingFilterDoesNotStart ( )
{
2019-02-15 20:50:40 +08:00
createSongSelect ( ) ;
2019-01-10 14:25:07 +08:00
addManyTestMaps ( ) ;
2019-03-19 16:24:26 +08:00
AddUntilStep ( "has selection" , ( ) = > songSelect . Carousel . SelectedBeatmap ! = null ) ;
2019-01-10 14:25:07 +08:00
bool startRequested = false ;
AddStep ( "set filter and finalize" , ( ) = >
{
songSelect . StartRequested = ( ) = > startRequested = true ;
songSelect . Carousel . Filter ( new FilterCriteria { SearchText = "somestringthatshouldn'tbematchable" } ) ;
songSelect . FinaliseSelection ( ) ;
songSelect . StartRequested = null ;
} ) ;
AddAssert ( "start not requested" , ( ) = > ! startRequested ) ;
}
2018-07-20 10:32:00 +08:00
private void importForRuleset ( int id ) = > AddStep ( $"import test map for ruleset {id}" , ( ) = > manager . Import ( createTestBeatmapSet ( getImportId ( ) , rulesets . AvailableRulesets . Where ( r = > r . ID = = id ) . ToArray ( ) ) ) ) ;
private static int importId ;
private int getImportId ( ) = > + + importId ;
2018-11-30 16:16:00 +08:00
private void changeMods ( params Mod [ ] mods ) = > AddStep ( $"change mods to {string.Join(" , ", mods.Select(m => m.Acronym))}" , ( ) = > selectedMods . Value = mods ) ;
2018-08-14 13:18:46 +08:00
2018-07-20 10:32:00 +08:00
private void changeRuleset ( int id ) = > AddStep ( $"change ruleset to {id}" , ( ) = > Ruleset . Value = rulesets . AvailableRulesets . First ( r = > r . ID = = id ) ) ;
2019-02-15 20:50:40 +08:00
private void createSongSelect ( )
{
AddStep ( "create song select" , ( ) = > LoadScreen ( songSelect = new TestSongSelect ( ) ) ) ;
2019-03-19 16:24:26 +08:00
AddUntilStep ( "wait for present" , ( ) = > songSelect . IsCurrentScreen ( ) ) ;
2019-02-15 20:50:40 +08:00
}
2018-07-18 11:58:45 +08:00
private void addManyTestMaps ( )
{
AddStep ( "import test maps" , ( ) = >
{
var usableRulesets = rulesets . AvailableRulesets . Where ( r = > r . ID ! = 2 ) . ToArray ( ) ;
for ( int i = 0 ; i < 100 ; i + = 10 )
manager . Import ( createTestBeatmapSet ( i , usableRulesets ) ) ;
} ) ;
}
2018-07-20 10:32:00 +08:00
private BeatmapSetInfo createTestBeatmapSet ( int setId , RulesetInfo [ ] rulesets )
2018-07-18 11:58:45 +08:00
{
int j = 0 ;
RulesetInfo getRuleset ( ) = > rulesets [ j + + % rulesets . Length ] ;
var beatmaps = new List < BeatmapInfo > ( ) ;
for ( int i = 0 ; i < 6 ; i + + )
{
2018-07-20 10:32:00 +08:00
int beatmapId = setId * 10 + i ;
2018-07-18 11:58:45 +08:00
beatmaps . Add ( new BeatmapInfo
{
Ruleset = getRuleset ( ) ,
OnlineBeatmapID = beatmapId ,
Path = "normal.osu" ,
Version = $"{beatmapId}" ,
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = 3.5f ,
}
} ) ;
}
2018-04-13 17:19:50 +08:00
return new BeatmapSetInfo
{
2018-07-18 11:58:45 +08:00
OnlineBeatmapSetID = setId ,
2018-04-13 17:19:50 +08:00
Hash = new MemoryStream ( Encoding . UTF8 . GetBytes ( Guid . NewGuid ( ) . ToString ( ) ) ) . ComputeMD5Hash ( ) ,
Metadata = new BeatmapMetadata
{
// Create random metadata, then we can check if sorting works based on these
2018-07-18 11:58:45 +08:00
Artist = "Some Artist " + RNG . Next ( 0 , 9 ) ,
Title = $"Some Song (set id {setId})" ,
2018-04-13 17:19:50 +08:00
AuthorString = "Some Guy " + RNG . Next ( 0 , 9 ) ,
} ,
2018-07-18 11:58:45 +08:00
Beatmaps = beatmaps
2018-04-13 17:19:50 +08:00
} ;
}
}
}