Add prototype serialization tests. (#18458)

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
Leon Friedrich
2023-08-06 14:47:45 +12:00
committed by GitHub
parent b97be440dd
commit 28a5e32f5e
18 changed files with 138 additions and 53 deletions

View File

@@ -40,7 +40,7 @@ public sealed class PrototypeSaveTest
[Test]
public async Task UninitializedSaveTest()
{
// Apparently SpawnTest fails to clean up properly. Due to the similarities, I'll assume this also fails.
// Apparently SpawnTest fails to clean up properly. Due to the similarities, I'll assume this also fails.
await using var pairTracker = await PoolManager.GetServerClient();
var server = pairTracker.Pair.Server;
@@ -190,14 +190,14 @@ public sealed class PrototypeSaveTest
await pairTracker.CleanReturnAsync();
}
private sealed class TestEntityUidContext : ISerializationContext,
public sealed class TestEntityUidContext : ISerializationContext,
ITypeSerializer<EntityUid, ValueDataNode>
{
public SerializationManager.SerializerProvider SerializerProvider { get; }
public bool WritingReadingPrototypes { get; set; }
public string WritingComponent = string.Empty;
public EntityPrototype Prototype = default!;
public EntityPrototype? Prototype;
public TestEntityUidContext()
{
@@ -215,7 +215,7 @@ public sealed class PrototypeSaveTest
IDependencyCollection dependencies, bool alwaysWrite = false,
ISerializationContext? context = null)
{
if (WritingComponent != "Transform" && !Prototype.NoSpawn)
if (WritingComponent != "Transform" && (Prototype?.NoSpawn == false))
{
// Maybe this will be necessary in the future, but at the moment it just indicates that there is some
// issue, like a non-nullable entityUid data-field. If a component MUST have an entity uid to work with,

View File

@@ -0,0 +1,52 @@
using Robust.Shared.Prototypes;
using Robust.UnitTesting;
namespace Content.IntegrationTests.Tests.PrototypeTests;
public sealed class PrototypeTests
{
/// <summary>
/// This test writes all known prototypes as yaml files, then validates that the result is valid yaml.
/// Can help prevent instances where prototypes have bad C# default values.
/// </summary>
[Test]
public async Task TestAllPrototypesAreSerializable()
{
await using var pairTracker = await PoolManager.GetServerClient();
var context = new PrototypeSaveTest.TestEntityUidContext();
Assert.Multiple(() =>
{
Validate(pairTracker.Pair.Server, "server", context);
// TODO fix client serialization
//Validate(pairTracker.Pair.Client, "client", context);
});
await pairTracker.CleanReturnAsync();
}
public void Validate(RobustIntegrationTest.IntegrationInstance instance, string instanceId,
PrototypeSaveTest.TestEntityUidContext ctx)
{
var protoMan = instance.ResolveDependency<IPrototypeManager>();
var errors = protoMan.ValidateAllPrototypesSerializable(ctx);
if (errors.Count == 0)
return;
Assert.Multiple(() =>
{
foreach (var (kind, ids) in errors)
{
foreach (var (id, nodes) in ids)
{
var msg = $"Error when validating {instanceId} prototype ({kind.Name}, {id}). Errors: \n";
foreach (var errorNode in nodes)
{
msg += $" - {errorNode.ErrorReason}\n";
}
Assert.Fail(msg);
}
}
});
}
}

View File

@@ -3,8 +3,6 @@ using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
// TODO: ECS.
namespace Content.Server.Arcade.SpaceVillain;
[RegisterComponent]
@@ -93,16 +91,7 @@ public sealed class SpaceVillainArcadeComponent : SharedSpaceVillainArcadeCompon
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("possibleRewards", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> PossibleRewards = new()
{
"ToyMouse", "ToyAi", "ToyNuke", "ToyAssistant", "ToyGriffin", "ToyHonk", "ToyIan",
"ToyMarauder", "ToyMauler", "ToyGygax", "ToyOdysseus", "ToyOwlman", "ToyDeathRipley",
"ToyPhazon", "ToyFireRipley", "ToyReticence", "ToyRipley", "ToySeraph", "ToyDurand", "ToySkeleton",
"FoamCrossbow", "RevolverCapGun", "PlushieHampter", "PlushieLizard", "PlushieAtmosian", "PlushieSpaceLizard",
"PlushieNuke", "PlushieCarp", "PlushieRatvar", "PlushieNar", "PlushieSnake", "Basketball", "Football",
"PlushieRouny", "PlushieBee", "PlushieSlime", "BalloonCorgi", "ToySword", "CrayonBox", "BoxDonkSoftBox", "BoxCartridgeCap",
"HarmonicaInstrument", "OcarinaInstrument", "RecorderInstrument", "GunpetInstrument", "BirdToyInstrument", "PlushieXeno", "BeachBall"
};
public List<string> PossibleRewards = new();
/// <summary>
/// The minimum number of prizes the arcade machine can have.

View File

@@ -1,12 +0,0 @@
using Content.Server.Holiday.Interfaces;
namespace Content.Server.Holiday.Celebrate
{
public sealed class DefaultHolidayCelebrate : IHolidayCelebrate
{
public void Celebrate(HolidayPrototype holiday)
{
// Nada.
}
}
}

View File

@@ -2,6 +2,7 @@ using Content.Server.Holiday.Interfaces;
namespace Content.Server.Holiday.Greet
{
[DataDefinition]
public sealed class DefaultHolidayGreet : IHolidayGreet
{
public string Greet(HolidayPrototype holiday)

View File

@@ -1,4 +1,3 @@
using Content.Server.Holiday.Celebrate;
using Content.Server.Holiday.Greet;
using Content.Server.Holiday.Interfaces;
using Content.Server.Holiday.ShouldCelebrate;
@@ -40,7 +39,7 @@ namespace Content.Server.Holiday
private readonly IHolidayGreet _greet = new DefaultHolidayGreet();
[DataField("celebrate")]
private readonly IHolidayCelebrate _celebrate = new DefaultHolidayCelebrate();
private readonly IHolidayCelebrate? _celebrate = null;
public bool ShouldCelebrate(DateTime date)
{
@@ -57,7 +56,7 @@ namespace Content.Server.Holiday
/// </summary>
public void Celebrate()
{
_celebrate.Celebrate(this);
_celebrate?.Celebrate(this);
}
}
}

View File

@@ -2,7 +2,7 @@ using Content.Server.Holiday.Interfaces;
namespace Content.Server.Holiday.ShouldCelebrate
{
[Virtual]
[Virtual, DataDefinition]
public class DefaultHolidayShouldCelebrate : IHolidayShouldCelebrate
{
public virtual bool ShouldCelebrate(DateTime date, HolidayPrototype holiday)

View File

@@ -4,6 +4,7 @@ using Content.Server.Nutrition.Components;
using Content.Shared.CCVar;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Nutrition;
using Microsoft.VisualBasic;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
@@ -102,9 +103,8 @@ public sealed class FlavorProfileSystem : EntitySystem
continue;
}
var flavor = proto.Flavor;
flavors.Add(flavor);
if (proto.Flavor != null)
flavors.Add(proto.Flavor);
}
return flavors;

View File

@@ -1,4 +1,6 @@
using Robust.Shared.Prototypes;
using System.Linq;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Alert
{
@@ -14,22 +16,25 @@ namespace Content.Shared.Alert
public string ID { get; } = default!;
[DataField("order")]
private List<(string type, string alert)> Order
private (string type, string alert)[] Order
{
// why would paul do this to me.
get
{
var res = new List<(string, string)>(_typeToIdx.Count + _categoryToIdx.Count);
var res = new (string, string)[_typeToIdx.Count + _categoryToIdx.Count];
foreach (var (type, id) in _typeToIdx)
{
res.Insert(id, ("alertType", type.ToString()));
res[id] = ("alertType", type.ToString());
}
foreach (var (category, id) in _categoryToIdx)
{
res.Insert(id, ("category", category.ToString()));
res[id] = ("category", category.ToString());
}
DebugTools.Assert(res.All(x => x != default));
return res;
}
set

View File

@@ -19,6 +19,7 @@ public sealed class BodyPrototypeSerializer : ITypeReader<BodyPrototype, Mapping
{
var nodes = new List<ValidationNode>();
var prototypes = dependencies.Resolve<IPrototypeManager>();
var factory = dependencies.Resolve<IComponentFactory>();
var connections = new List<string>();
if (slot.TryGet("connections", out SequenceDataNode? connectionsNode))
@@ -57,7 +58,7 @@ public sealed class BodyPrototypeSerializer : ITypeReader<BodyPrototype, Mapping
continue;
}
if (!organPrototype.HasComponent<OrganComponent>())
if (!organPrototype.HasComponent<OrganComponent>(factory))
{
nodes.Add(new ErrorNode(value, $"Organ {organ.Value} does not have a body component"));
}

View File

@@ -6,6 +6,7 @@ using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Database;
using Content.Shared.FixedPoint;
using Content.Shared.Nutrition;
using Robust.Shared.Audio;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
@@ -60,8 +61,8 @@ namespace Content.Shared.Chemistry.Reagent
[DataField("recognizable")]
public bool Recognizable = false;
[DataField("flavor")]
public string Flavor { get; } = default!;
[DataField("flavor", customTypeSerializer:typeof(PrototypeIdSerializer<FlavorPrototype>))]
public string? Flavor;
/// <summary>
/// There must be at least this much quantity in a solution to be tasted.

View File

@@ -1,6 +1,6 @@
using Robust.Shared.Prototypes;
namespace Content.Server.Nutrition;
namespace Content.Shared.Nutrition;
[Prototype("flavor")]
public sealed class FlavorPrototype : IPrototype

View File

@@ -261,7 +261,7 @@
- type: FlavorProfile
flavors:
- meaty
- acidic
- acid
- type: Sprite
layers:
- state: tin
@@ -277,7 +277,7 @@
- type: FlavorProfile
flavors:
- meaty
- acidic
- acid
- type: Sprite
layers:
- state: plate-small

View File

@@ -797,7 +797,7 @@
flavors:
- bun
- meaty
- acidic
- acid
- type: Sprite
state: x
- type: SolutionContainerManager

View File

@@ -489,7 +489,7 @@
- type: FlavorProfile
flavors:
- meaty
- acidic
- acid
- type: Tag
tags:
- Raw
@@ -1080,7 +1080,7 @@
- type: FlavorProfile
flavors:
- meaty
- acidic
- acid
- type: Tag
tags:
- Raw

View File

@@ -35,6 +35,54 @@
components:
- type: SpaceVillainArcade
rewardAmount: 0
possibleRewards:
- ToyMouse
- ToyAi
- ToyNuke
- ToyGriffin
- ToyHonk
- ToyIan
- ToyMarauder
- ToyMauler
- ToyGygax
- ToyOdysseus
- ToyOwlman
- ToyDeathRipley
- ToyPhazon
- ToyFireRipley
- ToyReticence
- ToyRipley
- ToySeraph
- ToyDurand
- ToySkeleton
- FoamCrossbow
- RevolverCapGun
- PlushieHampter
- PlushieLizard
- PlushieAtmosian
- PlushieSpaceLizard
- PlushieNuke
- PlushieCarp
- PlushieRatvar
- PlushieNar
- PlushieSnake
- Basketball
- Football
- PlushieRouny
- PlushieBee
- PlushieSlime
- BalloonCorgi
- ToySword
- CrayonBox
- BoxDonkSoftBox
- BoxCartridgeCap
- HarmonicaInstrument
- OcarinaInstrument
- RecorderInstrument
- GunpetInstrument
- BirdToyInstrument
- PlushieXeno
- BeachBall
- type: WiresPanel
- type: Wires
LayoutId: Arcade

View File

@@ -73,7 +73,8 @@
group: Foods
desc: reagent-desc-ketchunaise
physicalDesc: reagent-physical-desc-saucey
flavor: piquant
#I love it when people just make up fake prototypes.
#flavor: piquant
color: "#fba399"
recognizable: true

View File

@@ -100,7 +100,7 @@
group: Toxins
desc: reagent-desc-polytrinic-acid
physicalDesc: reagent-physical-desc-strong-smelling
flavor: acidic
flavor: acid
color: "#a1000b"
boilingPoint: 78.2 # This isn't a real chemical...
meltingPoint: -19.4
@@ -143,7 +143,7 @@
group: Toxins
desc: reagent-desc-fluorosulfuric-acid
physicalDesc: reagent-physical-desc-strong-smelling
flavor: acidic
flavor: acid
color: "#5050ff"
boilingPoint: 165
meltingPoint: -87
@@ -179,7 +179,7 @@
group: Toxins
desc: reagent-desc-sulfuric-acid
physicalDesc: reagent-physical-desc-oily
flavor: acidic
flavor: acid
color: "#BF8C00"
recognizable: true
boilingPoint: 337.0