2019-12-10 19:44:45 +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.
2020-04-21 13:47:12 +08:00
using System ;
2020-04-21 13:49:31 +08:00
using System.Collections ;
2019-12-13 18:00:28 +08:00
using System.Collections.Generic ;
2019-12-10 19:44:45 +08:00
using System.IO ;
using System.Linq ;
2020-05-11 15:37:08 +08:00
using System.Text ;
2019-12-10 19:44:45 +08:00
using NUnit.Framework ;
2020-04-21 13:47:12 +08:00
using osu.Framework.Audio.Track ;
using osu.Framework.Graphics.Textures ;
2020-08-12 12:38:05 +08:00
using osu.Framework.IO.Stores ;
2019-12-10 19:44:45 +08:00
using osu.Game.Beatmaps ;
2020-04-21 13:49:31 +08:00
using osu.Game.Beatmaps.ControlPoints ;
2019-12-10 19:44:45 +08:00
using osu.Game.Beatmaps.Formats ;
using osu.Game.IO ;
2019-12-13 18:00:28 +08:00
using osu.Game.IO.Serialization ;
2020-04-21 13:47:12 +08:00
using osu.Game.Rulesets.Catch ;
using osu.Game.Rulesets.Mania ;
using osu.Game.Rulesets.Osu ;
using osu.Game.Rulesets.Taiko ;
2020-08-12 12:38:05 +08:00
using osu.Game.Skinning ;
2019-12-10 19:44:45 +08:00
using osu.Game.Tests.Resources ;
namespace osu.Game.Tests.Beatmaps.Formats
{
[TestFixture]
public class LegacyBeatmapEncoderTest
{
2020-08-23 21:08:02 +08:00
private static readonly DllResourceStore beatmaps_resource_store = TestResources . GetStore ( ) ;
2020-08-16 04:03:24 +08:00
2020-08-23 21:08:02 +08:00
private static IEnumerable < string > allBeatmaps = beatmaps_resource_store . GetAvailableResources ( ) . Where ( res = > res . EndsWith ( ".osu" ) ) ;
2020-08-16 04:03:24 +08:00
2019-12-13 18:00:28 +08:00
[TestCaseSource(nameof(allBeatmaps))]
2020-05-11 15:30:54 +08:00
public void TestEncodeDecodeStability ( string name )
2019-12-10 19:44:45 +08:00
{
2020-08-23 21:08:02 +08:00
var decoded = decodeFromLegacy ( TestResources . GetStore ( ) . GetStream ( name ) , name ) ;
var decodedAfterEncode = decodeFromLegacy ( encodeToLegacy ( decoded ) , name ) ;
2019-12-10 19:44:45 +08:00
2020-08-23 21:08:02 +08:00
sort ( decoded ) ;
sort ( decodedAfterEncode ) ;
2020-04-21 13:49:31 +08:00
2020-08-16 05:41:53 +08:00
Assert . That ( decodedAfterEncode . beatmap . Serialize ( ) , Is . EqualTo ( decoded . beatmap . Serialize ( ) ) ) ;
2020-08-16 06:21:26 +08:00
Assert . IsTrue ( decoded . beatmapSkin . Configuration . Equals ( decodedAfterEncode . beatmapSkin . Configuration ) ) ;
2019-12-10 19:44:45 +08:00
}
2020-08-23 21:08:02 +08:00
private void sort ( ( IBeatmap , LegacyBeatmapSkin ) bs )
2020-04-21 13:49:31 +08:00
{
2020-08-23 21:08:02 +08:00
var ( beatmap , beatmapSkin ) = bs ;
2020-04-21 13:49:31 +08:00
// Sort control points to ensure a sane ordering, as they may be parsed in different orders. This works because each group contains only uniquely-typed control points.
foreach ( var g in beatmap . ControlPointInfo . Groups )
{
ArrayList . Adapter ( ( IList ) g . ControlPoints ) . Sort (
Comparer < ControlPoint > . Create ( ( c1 , c2 ) = > string . Compare ( c1 . GetType ( ) . ToString ( ) , c2 . GetType ( ) . ToString ( ) , StringComparison . Ordinal ) ) ) ;
}
}
2020-08-23 21:08:02 +08:00
private ( IBeatmap beatmap , LegacyBeatmapSkin beatmapSkin ) decodeFromLegacy ( Stream stream , string name )
2019-12-10 19:44:45 +08:00
{
2020-05-11 15:30:54 +08:00
using ( var reader = new LineBufferedReader ( stream ) )
2020-08-16 05:41:53 +08:00
{
var beatmap = new LegacyBeatmapDecoder { ApplyOffsets = false } . Decode ( reader ) ;
2020-08-23 21:08:02 +08:00
beatmap . BeatmapInfo . BeatmapSet . Files = new List < BeatmapSetFileInfo >
{
new BeatmapSetFileInfo
{
Filename = name ,
FileInfo = new osu . Game . IO . FileInfo ( ) { Hash = name }
}
} ;
var beatmapSkin = new LegacyBeatmapSkin ( beatmap . BeatmapInfo , beatmaps_resource_store , null ) ;
2020-08-16 05:41:53 +08:00
return ( convert ( beatmap ) , beatmapSkin ) ;
}
2020-08-16 04:03:24 +08:00
}
2020-08-23 21:08:02 +08:00
private Stream encodeToLegacy ( ( IBeatmap beatmap , LegacyBeatmapSkin beatmapSkin ) fullBeatmap )
2020-05-11 15:30:54 +08:00
{
2020-08-16 05:41:53 +08:00
var ( beatmap , beatmapSkin ) = fullBeatmap ;
2020-05-11 15:30:54 +08:00
var stream = new MemoryStream ( ) ;
2019-12-10 19:44:45 +08:00
2020-05-11 16:26:11 +08:00
using ( var writer = new StreamWriter ( stream , Encoding . UTF8 , 1024 , true ) )
2020-08-16 04:06:26 +08:00
new LegacyBeatmapEncoder ( beatmap , beatmapSkin ) . Encode ( writer ) ;
2019-12-10 19:44:45 +08:00
2020-05-11 15:30:54 +08:00
stream . Position = 0 ;
2020-04-21 13:47:12 +08:00
2020-05-11 15:30:54 +08:00
return stream ;
2019-12-10 19:44:45 +08:00
}
2020-04-21 13:47:12 +08:00
private IBeatmap convert ( IBeatmap beatmap )
{
switch ( beatmap . BeatmapInfo . RulesetID )
{
case 0 :
beatmap . BeatmapInfo . Ruleset = new OsuRuleset ( ) . RulesetInfo ;
break ;
case 1 :
beatmap . BeatmapInfo . Ruleset = new TaikoRuleset ( ) . RulesetInfo ;
break ;
case 2 :
beatmap . BeatmapInfo . Ruleset = new CatchRuleset ( ) . RulesetInfo ;
break ;
case 3 :
beatmap . BeatmapInfo . Ruleset = new ManiaRuleset ( ) . RulesetInfo ;
break ;
}
return new TestWorkingBeatmap ( beatmap ) . GetPlayableBeatmap ( beatmap . BeatmapInfo . Ruleset ) ;
}
private class TestWorkingBeatmap : WorkingBeatmap
{
private readonly IBeatmap beatmap ;
public TestWorkingBeatmap ( IBeatmap beatmap )
: base ( beatmap . BeatmapInfo , null )
{
this . beatmap = beatmap ;
}
protected override IBeatmap GetBeatmap ( ) = > beatmap ;
protected override Texture GetBackground ( ) = > throw new NotImplementedException ( ) ;
protected override Track GetTrack ( ) = > throw new NotImplementedException ( ) ;
}
2019-12-10 19:44:45 +08:00
}
}