added cap list serializer TC

bugfixes
This commit is contained in:
Christian Köllner 2020-02-26 22:04:59 +01:00
parent 3877e2aca3
commit fc6af91833
8 changed files with 103 additions and 111 deletions

View File

@ -34,7 +34,6 @@
<Compile Include="..\Capnp.Net.Runtime.Tests\TestBase.cs" Link="TestBase.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\TestCallContext.cs" Link="TestCallContext.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\TestCapImplementations.cs" Link="TestCapImplementations.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\TestInterfaces.cs" Link="TestInterfaces.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\WirePointerTests.cs" Link="WirePointerTests.cs" />
</ItemGroup>

View File

@ -1,4 +1,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Capnp.Net.Runtime.Tests.GenImpls;
using Capnproto_test.Capnp.Test;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
@ -32,12 +34,17 @@ namespace Capnp.Net.Runtime.Tests
var b = MessageBuilder.Create();
var list = b.CreateObject<ListOfBitsSerializer>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => list.Init(-1));
// Assert.AreEqual(0, list.Count); // Bug or feature? Uninitialized list's Count is -1
Assert.ThrowsException<InvalidOperationException>(() => { var _ = list[0]; });
Assert.ThrowsException<InvalidOperationException>(() => { list[0] = false; });
list.Init(130);
list[63] = true;
list[65] = true;
list[66] = true;
list[65] = false;
list[129] = true;
Assert.ThrowsException<IndexOutOfRangeException>(() => { var _ = list[130]; });
Assert.ThrowsException<IndexOutOfRangeException>(() => { list[130] = false; });
Assert.IsFalse(list[0]);
Assert.IsTrue(list[63]);
Assert.IsFalse(list[64]);
@ -59,5 +66,63 @@ namespace Capnp.Net.Runtime.Tests
var list3 = d.RequireList().CastBool();
CheckList(list3);
}
[TestMethod]
public void ListOfCaps()
{
var b = MessageBuilder.Create();
b.InitCapTable();
var list = b.CreateObject<ListOfCapsSerializer<ITestInterface>>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => list.Init(-1));
Assert.ThrowsException<InvalidOperationException>(() => { var _ = list[0]; });
Assert.ThrowsException<InvalidOperationException>(() => { list[0] = null; });
list.Init(5);
Assert.ThrowsException<InvalidOperationException>(() => list.Init(1));
var c1 = new Counters();
var cap1 = new TestInterfaceImpl(c1);
var c2 = new Counters();
var cap2 = new TestInterfaceImpl(c2);
list[0] = null;
list[1] = cap1;
list[2] = cap2;
list[3] = cap1;
list[4] = cap2;
list[3] = null;
Assert.IsTrue(list.All(p => p is Rpc.Proxy));
var proxies = list.Cast<Rpc.Proxy>().ToArray();
Assert.IsTrue(proxies[0].IsNull);
Assert.IsFalse(proxies[1].IsNull);
Assert.IsTrue(proxies[3].IsNull);
list[2].Foo(123u, true).Wait();
Assert.AreEqual(0, c1.CallCount);
Assert.AreEqual(1, c2.CallCount);
list[4].Foo(123u, true).Wait();
Assert.AreEqual(2, c2.CallCount);
var list2 = b.CreateObject<ListOfCapsSerializer<ITestInterface>>();
list2.Init(null);
list2.Init(list);
proxies = list2.Cast<Rpc.Proxy>().ToArray();
Assert.IsTrue(proxies[0].IsNull);
Assert.IsFalse(proxies[1].IsNull);
Assert.IsTrue(proxies[3].IsNull);
list2[2].Foo(123u, true).Wait();
Assert.AreEqual(0, c1.CallCount);
Assert.AreEqual(3, c2.CallCount);
list2[4].Foo(123u, true).Wait();
Assert.AreEqual(4, c2.CallCount);
DeserializerState d = list2;
var list3 = d.RequireList().CastCapList<ITestInterface>();
proxies = list3.Cast<Rpc.Proxy>().ToArray();
Assert.IsTrue(proxies[0].IsNull);
Assert.IsFalse(proxies[1].IsNull);
Assert.IsTrue(proxies[3].IsNull);
list3[2].Foo(123u, true).Wait();
Assert.AreEqual(0, c1.CallCount);
Assert.AreEqual(5, c2.CallCount);
list3[4].Foo(123u, true).Wait();
Assert.AreEqual(6, c2.CallCount);
}
}
}

View File

@ -1,102 +0,0 @@
using Capnp.Rpc;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Net.Runtime.Tests.ManualImpls
{
// [Skeleton(typeof(TestInterfaceSkeleton))]
// [Proxy(typeof(TestInterfaceProxy))]
// interface ITestInterface: IDisposable
// {
// Task<string> Foo(uint i, bool j);
// Task Bar();
// Task<int> Baz(int s);
// }
// [Skeleton(typeof(TestExtendsSkeleton))]
// [Proxy(typeof(TestExtendsProxy))]
// interface ITestExtends: ITestInterface, IDisposable
// {
// void Qux();
// Task Corge(int x);
// Task<int> Grault();
// }
// interface ITestExtends2: ITestExtends, IDisposable
// {
// }
// struct Box
// {
// public ITestExtends Cap { get; set; }
// }
// struct AnyBox
// {
// public object Cap { get; set; }
// }
// [Skeleton(typeof(TestPipelineSkeleton))]
// [Proxy(typeof(TestPipelineProxy))]
// interface ITestPipeline: IDisposable
// {
// Task<(string, Box)> GetCap(uint n, ITestInterface inCap);
// Task TestPointers(ITestExtends cap, DeserializerState obj, IReadOnlyList<ITestExtends> list);
// Task<(string, AnyBox)> GetAnyCap(uint n, object inCap);
// }
// [Skeleton(typeof(TestCallOrderSkeleton))]
// [Proxy(typeof(TestCallOrderProxy))]
// interface ITestCallOrder : IDisposable
// {
// Task<uint> GetCallSequence(uint expected);
// }
// struct TailResult
// {
// public uint I { get; set; }
// public string T { get; set; }
// public ITestCallOrder C { get; set; }
//}
// [Skeleton(typeof(TestTailCalleeSkeleton))]
// [Proxy(typeof(TestTailCalleeProxy))]
// interface ITestTailCallee: IDisposable
// {
// Task<TailResult> Foo(int i, string t);
// }
// [Skeleton(typeof(TestTailCallerSkeleton))]
// [Proxy(typeof(TestTailCallerProxy))]
// interface ITestTailCaller: IDisposable
// {
// Task<TailResult> Foo(int i, ITestTailCallee c);
// }
// [Skeleton(typeof(TestHandleSkeleton))]
// [Proxy(typeof(TestHandleProxy))]
// interface ITestHandle: IDisposable { }
// [Skeleton(typeof(TestMoreStuffSkeleton))]
// [Proxy(typeof(TestMoreStuffProxy))]
// interface ITestMoreStuff: ITestCallOrder
// {
// Task<string> CallFoo(ITestInterface cap);
// Task<string> CallFooWhenResolved(ITestInterface cap);
// Task<ITestInterface> NeverReturn(ITestInterface cap, CancellationToken ct);
// Task Hold(ITestInterface cap);
// Task<string> CallHeld();
// Task<ITestInterface> GetHeld();
// Task<ITestCallOrder> Echo(ITestCallOrder cap);
// Task ExpectCancel(ITestInterface cap, CancellationToken ct);
// Task<(string, string)> MethodWithDefaults(string a, uint b, string c);
// void MethodWithNullDefault(string a, ITestInterface b);
// Task<ITestHandle> GetHandle();
// Task<ITestMoreStuff> GetNull();
// Task<string> GetEnormousString();
// }
}

View File

@ -89,7 +89,7 @@ namespace Capnp
/// <returns>Capability list representation</returns>
/// <exception cref="NotSupportedException">If this kind of list cannot be represented as list of capabilities (because it is a list of non-pointers)</exception>
/// <exception cref="Rpc.InvalidCapabilityInterfaceException">If <typeparamref name="T"/> does not qualify as capability interface.</exception>
public virtual IReadOnlyList<ListOfCapsDeserializer<T>> CastCapList<T>() where T: class
public virtual IReadOnlyList<T> CastCapList<T>() where T: class
{
throw new NotSupportedException("This kind of list does not contain nested lists");
}

View File

@ -51,6 +51,8 @@ namespace Capnp
{
get
{
ListSerializerHelper.EnsureAllocated(this);
if (index < 0 || index >= Count)
throw new IndexOutOfRangeException();
@ -61,6 +63,8 @@ namespace Capnp
}
set
{
ListSerializerHelper.EnsureAllocated(this);
if (index < 0 || index >= Count)
throw new IndexOutOfRangeException();

View File

@ -35,16 +35,29 @@ namespace Capnp
[AllowNull]
public T this[int index]
{
get => (Rpc.CapabilityReflection.CreateProxy<T>(DecodeCapPointer(index)) as T)!;
get
{
ListSerializerHelper.EnsureAllocated(this);
try
{
return (Rpc.CapabilityReflection.CreateProxy<T>(DecodeCapPointer(index)) as T)!;
}
catch (ArgumentOutOfRangeException)
{
throw new IndexOutOfRangeException();
}
}
set
{
if (!IsAllocated)
throw new InvalidOperationException("Call Init() first");
ListSerializerHelper.EnsureAllocated(this);
if (index < 0 || index >= RawData.Length)
throw new IndexOutOfRangeException("index out of range");
RawData[index] = ProvideCapability(value);
var p = default(WirePointer);
p.SetCapability(ProvideCapability(value));
RawData[index] = p;
}
}

View File

@ -83,9 +83,9 @@ namespace Capnp
/// </summary>
/// <typeparam name="T">Capability interface</typeparam>
/// <returns>The desired representation. Since it is evaluated lazily, type conflicts will not happen before accessing the resulting list's elements.</returns>
public override IReadOnlyList<ListOfCapsDeserializer<T>> CastCapList<T>()
public override IReadOnlyList<T> CastCapList<T>()
{
return this.LazyListSelect(d => d.RequireCapList<T>());
return State.RequireCapList<T>();
}
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace Capnp
{
static class ListSerializerHelper
{
public static void EnsureAllocated(SerializerState serializer)
{
if (!serializer.IsAllocated)
throw new InvalidOperationException("Call Init() first");
}
}
}