2018-03-01 23:07:02 +08:00
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Reflection ;
using Newtonsoft.Json ;
using NUnit.Framework ;
using osu.Framework.Extensions.IEnumerableExtensions ;
using osu.Game.Beatmaps ;
using osu.Game.Beatmaps.Formats ;
using osu.Game.Rulesets.Objects ;
namespace osu.Game.Tests.Beatmaps
{
[TestFixture]
public abstract class BeatmapConversionTest < TConvertValue >
where TConvertValue : IEquatable < TConvertValue >
{
private const string resource_namespace = "Testing.Beatmaps" ;
private const string expected_conversion_suffix = "-expected-conversion" ;
protected abstract string ResourceAssembly { get ; }
2018-03-02 17:20:33 +08:00
protected void Test ( string name )
2018-03-01 23:07:02 +08:00
{
2018-03-02 17:20:33 +08:00
var ourResult = convert ( name ) ;
var expectedResult = read ( name ) ;
2018-03-01 23:07:02 +08:00
Assert . Multiple ( ( ) = >
{
int mappingCounter = 0 ;
while ( true )
{
if ( mappingCounter > = ourResult . Mappings . Count & & mappingCounter > = expectedResult . Mappings . Count )
break ;
if ( mappingCounter > = ourResult . Mappings . Count )
2018-03-02 00:40:25 +08:00
Assert . Fail ( $"A conversion did not generate any hitobjects, but should have, for hitobject at time: {expectedResult.Mappings[mappingCounter].StartTime}\n" ) ;
2018-03-01 23:07:02 +08:00
else if ( mappingCounter > = expectedResult . Mappings . Count )
2018-03-02 00:40:25 +08:00
Assert . Fail ( $"A conversion generated hitobjects, but should not have, for hitobject at time: {ourResult.Mappings[mappingCounter].StartTime}\n" ) ;
2018-03-01 23:07:02 +08:00
else
{
var counter = mappingCounter ;
Assert . Multiple ( ( ) = >
{
var ourMapping = ourResult . Mappings [ counter ] ;
var expectedMapping = expectedResult . Mappings [ counter ] ;
int objectCounter = 0 ;
while ( true )
{
if ( objectCounter > = ourMapping . Objects . Count & & objectCounter > = expectedMapping . Objects . Count )
break ;
if ( objectCounter > = ourMapping . Objects . Count )
2018-03-02 00:40:25 +08:00
Assert . Fail ( $"The conversion did not generate a hitobject, but should have, for hitobject at time: {expectedMapping.StartTime}:\n"
+ $"Expected: {JsonConvert.SerializeObject(expectedMapping.Objects[objectCounter])}\n" ) ;
2018-03-01 23:07:02 +08:00
else if ( objectCounter > = expectedMapping . Objects . Count )
2018-03-02 00:40:25 +08:00
Assert . Fail ( $"The conversion generated a hitobject, but should not have, for hitobject at time: {ourMapping.StartTime}:\n"
+ $"Received: {JsonConvert.SerializeObject(ourMapping.Objects[objectCounter])}\n" ) ;
2018-03-01 23:07:02 +08:00
else if ( ! EqualityComparer < TConvertValue > . Default . Equals ( expectedMapping . Objects [ objectCounter ] , ourMapping . Objects [ objectCounter ] ) )
{
2018-03-02 00:40:25 +08:00
Assert . Fail ( $"The conversion generated differing hitobjects for object at time: {expectedMapping.StartTime}\n"
2018-03-01 23:07:02 +08:00
+ $"Expected: {JsonConvert.SerializeObject(expectedMapping.Objects[objectCounter])}\n"
+ $"Received: {JsonConvert.SerializeObject(ourMapping.Objects[objectCounter])}\n" ) ;
}
objectCounter + + ;
}
} ) ;
}
mappingCounter + + ;
}
} ) ;
}
2018-03-02 17:20:33 +08:00
private ConvertResult convert ( string name )
2018-03-01 23:07:02 +08:00
{
2018-03-02 17:20:33 +08:00
var beatmap = getBeatmap ( name ) ;
2018-03-01 23:07:02 +08:00
var result = new ConvertResult ( ) ;
2018-03-02 00:50:54 +08:00
var converter = CreateConverter ( beatmap ) ;
2018-03-01 23:07:02 +08:00
converter . ObjectConverted + = ( orig , converted ) = >
{
converted . ForEach ( h = > h . ApplyDefaults ( beatmap . ControlPointInfo , beatmap . BeatmapInfo . BaseDifficulty ) ) ;
var mapping = new ConvertMapping { StartTime = orig . StartTime } ;
foreach ( var obj in converted )
2018-03-02 01:02:09 +08:00
mapping . Objects . AddRange ( CreateConvertValue ( obj ) ) ;
2018-03-01 23:07:02 +08:00
result . Mappings . Add ( mapping ) ;
} ;
converter . Convert ( beatmap ) ;
return result ;
}
2018-03-02 17:20:33 +08:00
private ConvertResult read ( string name )
2018-03-01 23:07:02 +08:00
{
2018-03-02 17:20:33 +08:00
using ( var resStream = openResource ( $"{resource_namespace}.{name}{expected_conversion_suffix}.json" ) )
2018-03-01 23:07:02 +08:00
using ( var reader = new StreamReader ( resStream ) )
{
var contents = reader . ReadToEnd ( ) ;
return JsonConvert . DeserializeObject < ConvertResult > ( contents ) ;
}
}
2018-03-02 17:20:33 +08:00
private Beatmap getBeatmap ( string name )
2018-03-01 23:07:02 +08:00
{
2018-03-02 17:20:33 +08:00
using ( var resStream = openResource ( $"{resource_namespace}.{name}.osu" ) )
2018-03-01 23:07:02 +08:00
using ( var stream = new StreamReader ( resStream ) )
2018-03-06 00:39:01 +08:00
{
2018-03-09 20:23:03 +08:00
var decoder = Decoder . GetDecoder < Beatmap > ( stream ) ;
2018-03-06 00:39:01 +08:00
( ( LegacyBeatmapDecoder ) decoder ) . ApplyOffsets = false ;
2018-03-09 20:23:03 +08:00
return decoder . Decode ( stream ) ;
2018-03-06 00:39:01 +08:00
}
2018-03-01 23:07:02 +08:00
}
private Stream openResource ( string name )
{
var localPath = Path . GetDirectoryName ( Uri . UnescapeDataString ( new UriBuilder ( Assembly . GetExecutingAssembly ( ) . CodeBase ) . Path ) ) ;
return Assembly . LoadFrom ( Path . Combine ( localPath , $"{ResourceAssembly}.dll" ) ) . GetManifestResourceStream ( $@"{ResourceAssembly}.Resources.{name}" ) ;
}
2018-03-02 01:02:09 +08:00
protected abstract IEnumerable < TConvertValue > CreateConvertValue ( HitObject hitObject ) ;
2018-03-02 19:19:47 +08:00
protected abstract IBeatmapConverter CreateConverter ( Beatmap beatmap ) ;
2018-03-01 23:07:02 +08:00
private class ConvertMapping
{
[JsonProperty]
public double StartTime ;
[JsonProperty]
public List < TConvertValue > Objects = new List < TConvertValue > ( ) ;
}
private class ConvertResult
{
[JsonProperty]
public List < ConvertMapping > Mappings = new List < ConvertMapping > ( ) ;
}
}
}