diff --git a/Capnp.Net.Runtime.Tests/CapabilityReflectionTests.cs b/Capnp.Net.Runtime.Tests/CapabilityReflectionTests.cs new file mode 100644 index 0000000..ccc529d --- /dev/null +++ b/Capnp.Net.Runtime.Tests/CapabilityReflectionTests.cs @@ -0,0 +1,30 @@ +using Capnp.Rpc; +using Capnproto_test.Capnp.Test; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Capnp.Net.Runtime.Tests +{ + [TestClass] + [TestCategory("Coverage")] + public class CapabilityReflectionTests + { + [TestMethod] + public void ValidateCapabilityInterface() + { + Assert.ThrowsException(() => CapabilityReflection.ValidateCapabilityInterface(null)); + CapabilityReflection.ValidateCapabilityInterface(typeof(ITestInterface)); + Assert.ThrowsException(() => CapabilityReflection.ValidateCapabilityInterface(typeof(CapabilityReflectionTests))); + } + + [TestMethod] + public void IsValidCapabilityInterface() + { + Assert.ThrowsException(() => CapabilityReflection.IsValidCapabilityInterface(null)); + Assert.IsTrue(CapabilityReflection.IsValidCapabilityInterface(typeof(ITestInterface))); + Assert.IsFalse(CapabilityReflection.IsValidCapabilityInterface(typeof(CapabilityReflectionTests))); + } + } +} diff --git a/Capnp.Net.Runtime.Tests/EdgeCaseHandling.cs b/Capnp.Net.Runtime.Tests/EdgeCaseHandling.cs index 0e61fa5..5ec303d 100644 --- a/Capnp.Net.Runtime.Tests/EdgeCaseHandling.cs +++ b/Capnp.Net.Runtime.Tests/EdgeCaseHandling.cs @@ -22,14 +22,16 @@ namespace Capnp.Net.Runtime.Tests { readonly FramePump _fromEnginePump; readonly BinaryReader _reader; + readonly FrameTracing.RpcFrameTracer _tracer; public bool Dismissed { get; private set; } public MemStreamEndpoint() { var pipe = new Pipe(); + _tracer = new FrameTracing.RpcFrameTracer(Console.Out, false); _fromEnginePump = new FramePump(pipe.Writer.AsStream()); - _fromEnginePump.AttachTracer(new FrameTracing.RpcFrameTracer(Console.Out, false)); + _fromEnginePump.AttachTracer(_tracer); _reader = new BinaryReader(pipe.Reader.AsStream()); } @@ -45,7 +47,9 @@ namespace Capnp.Net.Runtime.Tests public WireFrame ReadNextFrame() { - return _reader.ReadWireFrame(); + var frame = _reader.ReadWireFrame(); + _tracer.TraceFrame(FrameTracing.FrameDirection.Rx, frame); + return frame; } } @@ -1252,5 +1256,31 @@ namespace Capnp.Net.Runtime.Tests Assert.IsFalse(tester.IsDismissed); } + + [TestMethod] + public void ReturnToWrongSide1() + { + var tester = new RpcEngineTester(); + + var cap = tester.RealEnd.QueryMain(); + var proxy = new BareProxy(cap); + Assert.IsFalse(proxy.WhenResolved.IsCompleted); + uint id = 0; + + tester.Recv(_ => { + Assert.AreEqual(Message.WHICH.Bootstrap, _.which); + id = _.Bootstrap.QuestionId; + }); + tester.Send(_ => { + _.which = Message.WHICH.Return; + _.Return.which = Return.WHICH.ResultsSentElsewhere; + }); + tester.Recv(_ => { + Assert.AreEqual(Message.WHICH.Finish, _.which); + }); + Assert.IsTrue(proxy.WhenResolved.IsCompleted); + Assert.IsTrue(proxy.WhenResolved.IsFaulted); + tester.ExpectAbort(); + } } } diff --git a/Capnp.Net.Runtime.Tests/SerializationTests.cs b/Capnp.Net.Runtime.Tests/SerializationTests.cs index 57874ef..ad40dc2 100644 --- a/Capnp.Net.Runtime.Tests/SerializationTests.cs +++ b/Capnp.Net.Runtime.Tests/SerializationTests.cs @@ -723,7 +723,7 @@ namespace Capnp.Net.Runtime.Tests [TestMethod] public void DynamicSerializerStateSBytes() { - var expected = new sbyte[] { 1, 2, 3 }; + var expected = new List { 1, 2, 3 }; var b = MessageBuilder.Create(); var dss = b.CreateObject(); @@ -735,7 +735,7 @@ namespace Capnp.Net.Runtime.Tests [TestMethod] public void DynamicSerializerStateShorts() { - var expected = new short[] { 1, 2, 3 }; + var expected = new List { 1, 2, 3 }; var b = MessageBuilder.Create(); var dss = b.CreateObject(); @@ -759,7 +759,7 @@ namespace Capnp.Net.Runtime.Tests [TestMethod] public void DynamicSerializerStateInts() { - var expected = new int[] { 1, 2, 3 }; + var expected = new List { 1, 2, 3 }; var b = MessageBuilder.Create(); var dss = b.CreateObject(); @@ -783,7 +783,7 @@ namespace Capnp.Net.Runtime.Tests [TestMethod] public void DynamicSerializerStateLongs() { - var expected = new long[] { 1, 2, 3 }; + var expected = new List { 1, 2, 3 }; var b = MessageBuilder.Create(); var dss = b.CreateObject(); diff --git a/Capnp.Net.Runtime/Rpc/PendingQuestion.cs b/Capnp.Net.Runtime/Rpc/PendingQuestion.cs index f2e5917..97be61a 100644 --- a/Capnp.Net.Runtime/Rpc/PendingQuestion.cs +++ b/Capnp.Net.Runtime/Rpc/PendingQuestion.cs @@ -127,6 +127,7 @@ namespace Capnp.Rpc } const string ReturnDespiteTailCallMessage = "Peer sent actual results despite the question was sent as tail call. This was not expected and is a protocol error."; + const string UnexpectedTailCallReturnMessage = "Peer sent the results of this questions somewhere else. This was not expected and is a protocol error."; internal void OnReturn(DeserializerState results) { @@ -138,6 +139,7 @@ namespace Capnp.Rpc if (StateFlags.HasFlag(State.TailCall)) { _tcs.TrySetException(new RpcException(ReturnDespiteTailCallMessage)); + throw new RpcProtocolErrorException(ReturnDespiteTailCallMessage); } else { @@ -157,7 +159,8 @@ namespace Capnp.Rpc if (!StateFlags.HasFlag(State.TailCall)) { - _tcs.TrySetException(new RpcException("Peer sent the results of this questions somewhere else. This was not expected and is a protocol error.")); + _tcs.TrySetException(new RpcException(UnexpectedTailCallReturnMessage)); + throw new RpcProtocolErrorException(UnexpectedTailCallReturnMessage); } else { diff --git a/Capnp.Net.Runtime/Rpc/RpcEngine.cs b/Capnp.Net.Runtime/Rpc/RpcEngine.cs index 83ee8f7..60cc0ef 100644 --- a/Capnp.Net.Runtime/Rpc/RpcEngine.cs +++ b/Capnp.Net.Runtime/Rpc/RpcEngine.cs @@ -238,8 +238,7 @@ namespace Capnp.Rpc lock (_reentrancyBlocker) { if (!_exportTable.TryGetValue(preliminaryId, out var existing) || - existing.Cap != preliminaryCap || - existing.RefCount == 0) + existing.Cap != preliminaryCap) { // Resolved too late. Capability was already released. return; @@ -579,7 +578,7 @@ namespace Capnp.Rpc { foreach (var cap in inParams.Caps) { - cap?.Release(); + cap.Release(); } pendingAnswer = new PendingAnswer(