Tweaks for JSON loading, minor refactor of unit tests

This commit is contained in:
Deukhoofd 2025-02-08 09:49:16 +01:00
parent 51dfc4d07e
commit 58e9f4c3d1
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
11 changed files with 63 additions and 34 deletions

View File

@ -15,17 +15,15 @@ public static class AbilityDataLoader
{ {
private static Dictionary<string, SerializedAbility> LoadAbilitiesData(Stream stream) private static Dictionary<string, SerializedAbility> LoadAbilitiesData(Stream stream)
{ {
var obj = JsonSerializer.Deserialize<JsonObject>(stream); var obj = JsonSerializer.Deserialize<JsonObject>(stream, JsonOptions.DefaultOptions);
if (obj == null) if (obj == null)
throw new InvalidDataException("Ability data is empty."); throw new InvalidDataException("Ability data is empty.");
obj.Remove("$schema"); obj.Remove("$schema");
var cleanedString = obj.ToJsonString(); var cleanedString = obj.ToJsonString();
var objects = JsonSerializer.Deserialize<Dictionary<string, SerializedAbility>>(cleanedString, var objects =
new JsonSerializerOptions() JsonSerializer.Deserialize<Dictionary<string, SerializedAbility>>(cleanedString,
{ JsonOptions.DefaultOptions);
PropertyNameCaseInsensitive = true,
});
if (objects == null) if (objects == null)
throw new InvalidDataException("Ability data is empty."); throw new InvalidDataException("Ability data is empty.");
return objects; return objects;

View File

@ -10,7 +10,7 @@ public static class GrowthRateDataLoader
{ {
public static GrowthRateLibrary LoadGrowthRates(Stream stream) public static GrowthRateLibrary LoadGrowthRates(Stream stream)
{ {
var objects = JsonSerializer.Deserialize<Dictionary<string, uint[]>>(stream)!; var objects = JsonSerializer.Deserialize<Dictionary<string, uint[]>>(stream, JsonOptions.DefaultOptions)!;
var library = new GrowthRateLibrary(); var library = new GrowthRateLibrary();
foreach (var (key, value) in objects) foreach (var (key, value) in objects)
{ {

View File

@ -17,10 +17,7 @@ public static class ItemDataLoader
public static ItemLibrary LoadItems(Stream stream) public static ItemLibrary LoadItems(Stream stream)
{ {
var library = new ItemLibrary(); var library = new ItemLibrary();
var obj = JsonSerializer.Deserialize<SerializedItem[]>(stream, new JsonSerializerOptions() var obj = JsonSerializer.Deserialize<SerializedItem[]>(stream, JsonOptions.DefaultOptions);
{
PropertyNameCaseInsensitive = true,
});
if (obj == null) if (obj == null)
throw new InvalidDataException("Item data is empty."); throw new InvalidDataException("Item data is empty.");
var items = obj.Select(DeserializeItem); var items = obj.Select(DeserializeItem);

View File

@ -0,0 +1,13 @@
using System.Text.Json;
namespace PkmnLib.Dataloader;
internal static class JsonOptions
{
public static JsonSerializerOptions DefaultOptions => new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip,
};
}

View File

@ -17,11 +17,7 @@ public static class MoveDataLoader
public static MoveLibrary LoadMoves(Stream stream, TypeLibrary typeLibrary) public static MoveLibrary LoadMoves(Stream stream, TypeLibrary typeLibrary)
{ {
var library = new MoveLibrary(); var library = new MoveLibrary();
var objects = JsonSerializer.Deserialize<SerializedMoveDataWrapper>(stream, var objects = JsonSerializer.Deserialize<SerializedMoveDataWrapper>(stream, JsonOptions.DefaultOptions);
new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
});
if (objects == null) if (objects == null)
throw new InvalidDataException("Move data is empty."); throw new InvalidDataException("Move data is empty.");
var moves = objects.Data.Select(x => DeserializeMove(x, typeLibrary)); var moves = objects.Data.Select(x => DeserializeMove(x, typeLibrary));

View File

@ -17,15 +17,11 @@ public static class SpeciesDataLoader
{ {
private static Dictionary<string, SerializedSpecies> LoadSpeciesData(Stream stream) private static Dictionary<string, SerializedSpecies> LoadSpeciesData(Stream stream)
{ {
var obj = JsonSerializer.Deserialize<JsonObject>(stream); var obj = JsonSerializer.Deserialize<JsonObject>(stream, JsonOptions.DefaultOptions);
if (obj == null) if (obj == null)
throw new InvalidDataException("Species data is empty."); throw new InvalidDataException("Species data is empty.");
var jsonConfig = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
};
return obj.Where(x => x.Key != "$schema") return obj.Where(x => x.Key != "$schema")
.ToDictionary(x => x.Key, x => x.Value.Deserialize<SerializedSpecies>(jsonConfig)); .ToDictionary(x => x.Key, x => x.Value.Deserialize<SerializedSpecies>(JsonOptions.DefaultOptions));
} }
public static SpeciesLibrary LoadSpecies(Stream[] streams, IReadOnlyTypeLibrary typeLibrary) public static SpeciesLibrary LoadSpecies(Stream[] streams, IReadOnlyTypeLibrary typeLibrary)

View File

@ -3614,6 +3614,7 @@
} }
} }
}, },
// Done up to here
{ {
"name": "fire_spin", "name": "fire_spin",
"type": "fire", "type": "fire",

View File

@ -1,12 +1,22 @@
using PkmnLib.Dynamic.Libraries;
using PkmnLib.Dynamic.ScriptHandling; using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Static.Moves;
using PkmnLib.Tests.Integration; using PkmnLib.Tests.Integration;
namespace PkmnLib.Tests.DataTests; namespace PkmnLib.Tests.DataTests;
public class MoveDataTests public class MoveDataTests
{ {
[Test] public record TestCaseData(IDynamicLibrary Library, IMoveData Move)
public async Task AllMoveEffectsHaveValidScripts() {
/// <inheritdoc />
public override string ToString()
{
return Move.Name + " has valid scripts";
}
}
public static IEnumerable<TestCaseData> AllMovesHaveValidScriptsData()
{ {
var library = LibraryHelpers.LoadLibrary(); var library = LibraryHelpers.LoadLibrary();
var moveLibrary = library.StaticLibrary.Moves; var moveLibrary = library.StaticLibrary.Moves;
@ -14,17 +24,26 @@ public class MoveDataTests
{ {
if (move.SecondaryEffect == null) if (move.SecondaryEffect == null)
continue; continue;
var scriptName = move.SecondaryEffect.Name; yield return new TestCaseData(library, move);
}
}
[Test]
[MethodDataSource(nameof(AllMovesHaveValidScriptsData))]
public async Task AllMoveEffectsHaveValidScripts(TestCaseData test)
{
if (test.Move.SecondaryEffect == null)
return;
var scriptName = test.Move.SecondaryEffect.Name;
try try
{ {
await Assert.That(library.ScriptResolver.TryResolve(ScriptCategory.Move, scriptName, await Assert.That(test.Library.ScriptResolver.TryResolve(ScriptCategory.Move, scriptName,
move.SecondaryEffect.Parameters, out var script)).IsTrue(); test.Move.SecondaryEffect.Parameters, out var script)).IsTrue();
} }
catch (Exception e) catch (Exception e)
{ {
throw new AggregateException($"Failed to resolve script for move {move.Name} with effect {scriptName}", e); throw new AggregateException($"Failed to resolve script for move {test.Move.Name} with effect {scriptName}", e);
}
} }
} }
} }

View File

@ -15,6 +15,8 @@ public class IntegrationTestRunner
var serializerOptions = new JsonSerializerOptions var serializerOptions = new JsonSerializerOptions
{ {
PropertyNameCaseInsensitive = true, PropertyNameCaseInsensitive = true,
AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip,
}; };
foreach (var file in files) foreach (var file in files)
{ {

View File

@ -6,6 +6,12 @@ public class IntegrationTestModel
public string Description { get; set; } = null!; public string Description { get; set; } = null!;
public IntegrationTestBattleSetup BattleSetup { get; set; } = null!; public IntegrationTestBattleSetup BattleSetup { get; set; } = null!;
public IntegrationTestAction[] Actions { get; set; } = null!; public IntegrationTestAction[] Actions { get; set; } = null!;
/// <inheritdoc />
public override string ToString()
{
return Name;
}
} }
public class IntegrationTestBattleSetup public class IntegrationTestBattleSetup

View File

@ -2,6 +2,7 @@ using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
namespace PkmnLib.Plugin.Gen7.Scripts.Moves; namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
[Script(ScriptCategory.Move, "fire_fang")]
public class FireFang : Script public class FireFang : Script
{ {
/// <inheritdoc /> /// <inheritdoc />