fix silent failure when performing singular reads #11

Merged
cosmonaut merged 1 commits from SingularReadFix into main 2020-07-20 03:12:45 +00:00
5 changed files with 78 additions and 28 deletions

View File

@ -1,4 +1,5 @@
using MoonTools.FastCollections; using Encompass.Exceptions;
using MoonTools.FastCollections;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -54,11 +55,15 @@ namespace Encompass
public ref readonly TComponent Singular<TComponent>() where TComponent : struct public ref readonly TComponent Singular<TComponent>() where TComponent : struct
{ {
if (!Any<TComponent>()) { throw new NoComponentOfTypeException("No component of type {0} exists", typeof(TComponent).Name); }
return ref Lookup<TComponent>().Singular(); return ref Lookup<TComponent>().Singular();
} }
public ref readonly Entity SingularEntity<TComponent>() where TComponent : struct public ref readonly Entity SingularEntity<TComponent>() where TComponent : struct
{ {
if (!Any<TComponent>()) { throw new NoComponentOfTypeException("No component of type {0} exists", typeof(TComponent).Name); }
return ref Lookup<TComponent>().SingularEntity(); return ref Lookup<TComponent>().SingularEntity();
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Encompass.Exceptions;
namespace Encompass namespace Encompass
{ {
@ -35,6 +36,8 @@ namespace Encompass
public ref readonly TMessage First<TMessage>() where TMessage : struct, IMessage public ref readonly TMessage First<TMessage>() where TMessage : struct, IMessage
{ {
if (!Any<TMessage>()) { throw new NoMessageOfTypeException("No Message of type {0} exists", typeof(TMessage).Name); }
return ref Lookup<TMessage>().First(); return ref Lookup<TMessage>().First();
} }

View File

@ -1,25 +1,12 @@
using System; using System;
using System.Runtime.Serialization;
namespace Encompass.Exceptions namespace Encompass.Exceptions
{ {
[Serializable] public class NoComponentOfTypeException : Exception
internal class NoComponentOfTypeException : Exception
{
public NoComponentOfTypeException()
{
}
public NoComponentOfTypeException(string message) : base(message)
{
}
public NoComponentOfTypeException(string message, Exception innerException) : base(message, innerException)
{
}
protected NoComponentOfTypeException(SerializationInfo info, StreamingContext context) : base(info, context)
{ {
} public NoComponentOfTypeException(
string format,
params object[] args
) : base(string.Format(format, args)) { }
} }
} }

View File

@ -0,0 +1,12 @@
using System;
namespace Encompass.Exceptions
{
public class NoMessageOfTypeException : Exception
{
public NoMessageOfTypeException(
string format,
params object[] args
) : base(string.Format(format, args)) { }
}
}

View File

@ -17,10 +17,11 @@ namespace Tests
public class EngineTest public class EngineTest
{ {
static MockComponent[] resultComponents;
static MockComponent resultComponent; static MockComponent resultComponent;
static MockComponent[] resultComponents = new MockComponent[1];
static MockMessage[] resultMessages; static MockMessage resultMessage;
static MockMessage[] resultMessages = new MockMessage[1];
[Reads(typeof(MockComponent))] [Reads(typeof(MockComponent))]
public class ReadComponentsTestEngine : Engine public class ReadComponentsTestEngine : Engine
@ -149,6 +150,17 @@ namespace Tests
Assert.AreEqual(mockComponent, resultComponent); Assert.AreEqual(mockComponent, resultComponent);
} }
[Test]
public void ReadComponentThrowsWhenNoneExist()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ReadComponentTestEngine());
var world = worldBuilder.Build();
Assert.Throws<NoComponentOfTypeException>(() => world.Update(0.01f), "No component of type MockComponent exists");
}
[Test] [Test]
public void ReadComponentWhenMultipleComponents() public void ReadComponentWhenMultipleComponents()
{ {
@ -277,7 +289,7 @@ namespace Tests
} }
[Receives(typeof(MockMessage))] [Receives(typeof(MockMessage))]
public class MessageReadEngine : Engine public class ReadMessagesEngine : Engine
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
@ -285,18 +297,38 @@ namespace Tests
} }
} }
[Receives(typeof(MockMessage))]
public class ReadMessageEngine : Engine
{
public override void Update(double dt)
{
resultMessage = ReadMessage<MockMessage>();
}
}
[Test] [Test]
public void EmitAndReadMessage() public void EmitAndReadMessage()
{ {
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new MessageEmitEngine()); worldBuilder.AddEngine(new MessageEmitEngine());
worldBuilder.AddEngine(new MessageReadEngine()); worldBuilder.AddEngine(new ReadMessageEngine());
var world = worldBuilder.Build(); var world = worldBuilder.Build();
world.Update(0.01f); world.Update(0.01f);
Assert.AreEqual(resultMessages.First().myString, "howdy"); Assert.AreEqual(resultMessage.myString, "howdy");
}
[Test]
public void ReadMessageThrowsWhenNoneOfTypeExist()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ReadMessageEngine());
var world = worldBuilder.Build();
Assert.Throws<NoMessageOfTypeException>(() => world.Update(0.01), "No Message of type MockMessage exists");
} }
public class UndeclaredMessageEmitEngine : Engine public class UndeclaredMessageEmitEngine : Engine
@ -810,7 +842,7 @@ namespace Tests
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ActivateTimeDilationEngine()); worldBuilder.AddEngine(new ActivateTimeDilationEngine());
worldBuilder.AddEngine(new DelayedMessageEngine()); worldBuilder.AddEngine(new DelayedMessageEngine());
worldBuilder.AddEngine(new MessageReadEngine()); worldBuilder.AddEngine(new ReadMessagesEngine());
var entity = worldBuilder.CreateEntity(); var entity = worldBuilder.CreateEntity();
worldBuilder.SetComponent(entity, new MockComponent { }); worldBuilder.SetComponent(entity, new MockComponent { });
@ -857,7 +889,7 @@ namespace Tests
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ActivateTimeDilationEngine()); worldBuilder.AddEngine(new ActivateTimeDilationEngine());
worldBuilder.AddEngine(new DelayedMessageIgnoringTimeDilationEngine()); worldBuilder.AddEngine(new DelayedMessageIgnoringTimeDilationEngine());
worldBuilder.AddEngine(new MessageReadEngine()); worldBuilder.AddEngine(new ReadMessagesEngine());
var entity = worldBuilder.CreateEntity(); var entity = worldBuilder.CreateEntity();
worldBuilder.SetComponent(entity, new MockComponent { }); worldBuilder.SetComponent(entity, new MockComponent { });
@ -950,7 +982,7 @@ namespace Tests
} }
[Test] [Test]
public void GetEntityByComponentType() public void ReadEntity()
{ {
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ReadEntityByComponentTypeEngine()); worldBuilder.AddEngine(new ReadEntityByComponentTypeEngine());
@ -964,6 +996,17 @@ namespace Tests
entity.Should().BeEquivalentTo(readEntity); entity.Should().BeEquivalentTo(readEntity);
} }
[Test]
public void ReadEntityThrowsWhenNoComponentOfTypeExists()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ReadEntityByComponentTypeEngine());
var world = worldBuilder.Build();
Assert.Throws<NoComponentOfTypeException>(() => world.Update(0.01), "No component of type MockComponent exists");
}
struct MockComponentB : IComponent struct MockComponentB : IComponent
{ {
private int value; private int value;