using NUnit.Framework; using Encompass; using System.Collections.Generic; using Encompass.Exceptions; namespace Tests { public class WorldBuilderTest { public class EngineCycleSimple { struct AMessage : IMessage { } struct BMessage : IMessage { } [Reads(typeof(AMessage))] [Writes(typeof(BMessage))] class AEngine : Engine { public override void Update(double dt) { BMessage message; this.EmitMessage(message); } } [Reads(typeof(BMessage))] [Writes(typeof(AMessage))] class BEngine : Engine { public override void Update(double dt) { AMessage message; this.EmitMessage(message); } } [Test] public void EngineCycle() { var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new AEngine()); worldBuilder.AddEngine(new BEngine()); Assert.Throws(() => worldBuilder.Build()); } } public class EngineCycleComplex { struct AMessage : IMessage { } struct BMessage : IMessage { } struct CMessage : IMessage { } struct DMessage : IMessage { } [Reads(typeof(AMessage))] [Writes(typeof(BMessage))] class AEngine : Engine { public override void Update(double dt) { BMessage message; this.EmitMessage(message); } } [Reads(typeof(BMessage))] [Writes(typeof(CMessage))] class BEngine : Engine { public override void Update(double dt) { CMessage message; this.EmitMessage(message); } } [Reads(typeof(CMessage))] [Writes(typeof(DMessage))] class CEngine : Engine { public override void Update(double dt) { DMessage message; this.EmitMessage(message); } } [Reads(typeof(DMessage))] [Writes(typeof(AMessage))] class DEngine : Engine { public override void Update(double dt) { AMessage message; this.EmitMessage(message); } } [Test] public void EngineCycle() { var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new AEngine()); worldBuilder.AddEngine(new BEngine()); worldBuilder.AddEngine(new CEngine()); worldBuilder.AddEngine(new DEngine()); Assert.Throws(() => worldBuilder.Build()); } } public class MutationConflict { struct AComponent : IComponent { } [Writes(typeof(AComponent))] class AEngine : Engine { public override void Update(double dt) { } } [Writes(typeof(AComponent))] class BEngine : Engine { public override void Update(double dt) { } } [Test] public void MutationConflictException() { var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new AEngine()); worldBuilder.AddEngine(new BEngine()); Assert.Throws(() => worldBuilder.Build()); } } public class EngineMessageSelfCycle { struct AMessage : IMessage { } [Reads(typeof(AMessage))] [Writes(typeof(AMessage))] class AEngine : Engine { public override void Update(double dt) { } } [Test] public void ThrowsError() { var worldBuilder = new WorldBuilder(); Assert.Throws(() => worldBuilder.AddEngine(new AEngine()), "Engine both reads and writes Message AMessage"); } } public class IllegalReadType { struct ANonMessage { } [Reads(typeof(ANonMessage))] class MyEngine : Engine { public override void Update(double dt) { } } [Test] public void ThrowsError() { var worldBuilder = new WorldBuilder(); Assert.Throws(() => worldBuilder.AddEngine(new MyEngine()), "ANonMessage must be a Message or Component"); } } public class IllegalWriteType { struct ANonMessage { } [Writes(typeof(ANonMessage))] class MyEngine : Engine { public override void Update(double dt) { } } [Test] public void ThrowsError() { var worldBuilder = new WorldBuilder(); Assert.Throws(() => worldBuilder.AddEngine(new MyEngine()), "ANonMessage must be a Message or Component"); } } public class LegalEngines { static List order = new List(); struct AComponent : IComponent { } struct BComponent : IComponent { } struct AMessage : IMessage { } struct BMessage : IMessage { } struct CMessage : IMessage { } struct DMessage : IMessage { } [Writes(typeof(AMessage))] class AEngine : Engine { public override void Update(double dt) { order.Add(this); } } [Writes(typeof(BMessage))] class BEngine : Engine { public override void Update(double dt) { order.Add(this); } } [Reads(typeof(AMessage), typeof(BMessage))] [Writes(typeof(DMessage))] class CEngine : Engine { public override void Update(double dt) { order.Add(this); } } [Reads(typeof(DMessage))] class DEngine : Engine { public override void Update(double dt) { order.Add(this); } } [Test] public void EngineOrder() { var worldBuilder = new WorldBuilder(); var engineA = worldBuilder.AddEngine(new AEngine()); var engineB = worldBuilder.AddEngine(new BEngine()); var engineC = worldBuilder.AddEngine(new CEngine()); var engineD = worldBuilder.AddEngine(new DEngine()); Assert.DoesNotThrow(() => worldBuilder.Build()); var world = worldBuilder.Build(); world.Update(0.01f); Assert.That(order.IndexOf(engineA), Is.LessThan(order.IndexOf(engineC))); Assert.That(order.IndexOf(engineB), Is.LessThan(order.IndexOf(engineC))); Assert.That(order.IndexOf(engineC), Is.LessThan(order.IndexOf(engineD))); } } } }