public async Task ConnectionDoesNotResumeAfterSocketCloseIfBackpressureIsApplied() { var mockConnectionHandler = new MockConnectionHandler(); var mockLibuv = new MockLibuv(); var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler }; var transport = new LibuvTransport(mockLibuv, transportContext, null); var thread = new LibuvThread(transport); mockConnectionHandler.InputOptions = pool => new PipeOptions( bufferPool: pool, maximumSizeHigh: 3); // We don't set the output writer scheduler here since we want to run the callback inline mockConnectionHandler.OutputOptions = pool => new PipeOptions(bufferPool: pool, readerScheduler: thread); Task connectionTask = null; try { await thread.StartAsync(); // Write enough to make sure back pressure will be applied await thread.PostAsync <object>(_ => { var listenerContext = new ListenerContext(transportContext) { Thread = thread }; var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log); var connection = new LibuvConnection(listenerContext, socket); connectionTask = connection.Start(); mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out var ignored); mockLibuv.ReadCallback(socket.InternalGetHandle(), 5, ref ignored); }, null); // Now assert that we removed the callback from libuv to stop reading Assert.Null(mockLibuv.AllocCallback); Assert.Null(mockLibuv.ReadCallback); // Now complete the output writer so that the connection closes mockConnectionHandler.Output.Writer.Complete(); await connectionTask.TimeoutAfter(TimeSpan.FromSeconds(10)); // Assert that we don't try to start reading Assert.Null(mockLibuv.AllocCallback); Assert.Null(mockLibuv.ReadCallback); } finally { await thread.StopAsync(TimeSpan.FromSeconds(1)); } }
public async Task LibuvThreadDoesNotThrowIfPostingWorkAfterDispose() { var mockConnectionHandler = new MockConnectionHandler(); var mockLibuv = new MockLibuv(); var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler }; var transport = new LibuvTransport(mockLibuv, transportContext, null); var thread = new LibuvThread(transport); var ranOne = false; var ranTwo = false; var ranThree = false; var ranFour = false; await thread.StartAsync(); await thread.PostAsync <object>(_ => { ranOne = true; }, null); Assert.Equal(1, mockLibuv.PostCount); // Shutdown the libuv thread await thread.StopAsync(TimeSpan.FromSeconds(5)); Assert.Equal(2, mockLibuv.PostCount); var task = thread.PostAsync <object>(_ => { ranTwo = true; }, null); Assert.Equal(2, mockLibuv.PostCount); thread.Post <object>(_ => { ranThree = true; }, null); Assert.Equal(2, mockLibuv.PostCount); thread.Schedule(_ => { ranFour = true; }, (object)null); Assert.Equal(2, mockLibuv.PostCount); Assert.True(task.IsCompleted); Assert.True(ranOne); Assert.False(ranTwo); Assert.False(ranThree); Assert.False(ranFour); }
public void Setup() { var builder = new MockConnectionHandlerBuilder(); connectionHandler = builder.ConnectionHandler; worker = WorkerInWorld.CreateWorkerInWorldAsync(builder, "TestWorkerType", new LoggingDispatcher(), Vector3.zero).Result; receiveSystem = worker.World.GetExistingSystem <SpatialOSReceiveSystem>(); }
public virtual void Setup() { var connectionBuilder = new MockConnectionHandlerBuilder(); ConnectionHandler = connectionBuilder.ConnectionHandler; WorkerInWorld = WorkerInWorld .CreateWorkerInWorldAsync(connectionBuilder, "TestWorkerType", new LoggingDispatcher(), Vector3.zero) .Result; var world = WorkerInWorld.World; ReceiveSystem = world.GetExistingSystem <SpatialOSReceiveSystem>(); RequireLifecycleSystem = world.GetExistingSystem <RequireLifecycleSystem>(); Linker = new EntityGameObjectLinker(world); }
public void Setup() { var logDispatcher = new LoggingDispatcher(); var connectionBuilder = new MockConnectionHandlerBuilder(); connectionHandler = connectionBuilder.ConnectionHandler; workerInWorld = WorkerInWorld .CreateWorkerInWorldAsync(connectionBuilder, WorkerType, logDispatcher, Vector3.zero) .Result; receiveSystem = workerInWorld.World.GetExistingSystem <SpatialOSReceiveSystem>(); requireLifecycleSystem = workerInWorld.World.GetExistingSystem <RequireLifecycleSystem>(); var goInitSystem = workerInWorld.World .CreateSystem <GameObjectInitializationSystem>( new GameObjectCreatorFromMetadata(WorkerType, Vector3.zero, logDispatcher), null); linker = goInitSystem.Linker; }
public void Setup() { var connectionBuilder = new MockConnectionHandlerBuilder(); connectionHandler = connectionBuilder.ConnectionHandler; workerInWorld = WorkerInWorld .CreateWorkerInWorldAsync(connectionBuilder, "TestWorkerType", new LoggingDispatcher(), Vector3.zero) .Result; var world = workerInWorld.World; receiveSystem = world.GetExistingSystem <SpatialOSReceiveSystem>(); requireLifecycleSystem = world.GetExistingSystem <RequireLifecycleSystem>(); linker = new EntityGameObjectLinker(world); var template = new EntityTemplate(); template.AddComponent(new Position.Snapshot(), "worker"); connectionHandler.CreateEntity(EntityId, template); receiveSystem.Update(); }
public void Setup() { world = new World("TestWorld"); connectionHandler = new MockConnectionHandler(); world.CreateManager <WorkerSystem>(connectionHandler, null, new LoggingDispatcher(), "TestWorkerType", Vector3.zero); receiveSystem = world.CreateManager <SpatialOSReceiveSystem>(); world.GetOrCreateManager <ComponentUpdateSystem>(); world.GetOrCreateManager <ComponentConstraintsCallbackSystem>(); world.CreateManager <SubscriptionSystem>(); world.CreateManager <CommandCallbackSystem>(); world.CreateManager <ComponentCallbackSystem>(); requireLifecycleSystem = world.CreateManager <RequireLifecycleSystem>(); linker = new EntityGameObjectLinker(world); var template = new EntityTemplate(); template.AddComponent(new Position.Snapshot(), "worker"); connectionHandler.CreateEntity(EntityId, template); receiveSystem.Update(); }
public async Task DoesNotThrowIfOnReadCallbackCalledWithEOFButAllocCallbackNotCalled() { var mockConnectionHandler = new MockConnectionHandler(); var mockLibuv = new MockLibuv(); var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler }; var transport = new LibuvTransport(mockLibuv, transportContext, null); var thread = new LibuvThread(transport); try { await thread.StartAsync(); await thread.PostAsync(_ => { var listenerContext = new ListenerContext(transportContext) { Thread = thread }; var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log); var connection = new LibuvConnection(listenerContext, socket); _ = connection.Start(); var ignored = new LibuvFunctions.uv_buf_t(); mockLibuv.ReadCallback(socket.InternalGetHandle(), TestConstants.EOF, ref ignored); }, (object)null); var readAwaitable = await mockConnectionHandler.Input.Reader.ReadAsync(); Assert.True(readAwaitable.IsCompleted); } finally { await thread.StopAsync(TimeSpan.FromSeconds(5)); } }
public async Task DoesNotEndConnectionOnZeroRead() { var mockConnectionHandler = new MockConnectionHandler(); var mockLibuv = new MockLibuv(); var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler }; var transport = new LibuvTransport(mockLibuv, transportContext, null); var thread = new LibuvThread(transport); try { await thread.StartAsync(); await thread.PostAsync(_ => { var listenerContext = new ListenerContext(transportContext) { Thread = thread }; var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log); var connection = new LibuvConnection(listenerContext, socket); _ = connection.Start(); mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out var ignored); mockLibuv.ReadCallback(socket.InternalGetHandle(), 0, ref ignored); }, (object)null); var readAwaitable = mockConnectionHandler.Input.Reader.ReadAsync(); Assert.False(readAwaitable.IsCompleted); } finally { await thread.StopAsync(TimeSpan.FromSeconds(5)); } }
public async Task ConnectionDoesNotResumeAfterReadCallbackScheduledAndSocketCloseIfBackpressureIsApplied() { var mockConnectionHandler = new MockConnectionHandler(); var mockLibuv = new MockLibuv(); var transportContext = new TestLibuvTransportContext() { ConnectionHandler = mockConnectionHandler }; var transport = new LibuvTransport(mockLibuv, transportContext, null); var thread = new LibuvThread(transport); var mockScheduler = new Mock <PipeScheduler>(); Action backPressure = null; mockScheduler.Setup(m => m.Schedule(It.IsAny <Action <object> >(), It.IsAny <object>())).Callback <Action <object>, object>((a, o) => { backPressure = () => a(o); }); mockConnectionHandler.InputOptions = pool => new PipeOptions( pool: pool, pauseWriterThreshold: 3, resumeWriterThreshold: 3, writerScheduler: mockScheduler.Object, readerScheduler: PipeScheduler.Inline, useSynchronizationContext: false); mockConnectionHandler.OutputOptions = pool => new PipeOptions(pool: pool, readerScheduler: thread, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false); Task connectionTask = null; try { await thread.StartAsync(); // Write enough to make sure back pressure will be applied await thread.PostAsync <object>(_ => { var listenerContext = new ListenerContext(transportContext) { Thread = thread }; var socket = new MockSocket(mockLibuv, Thread.CurrentThread.ManagedThreadId, transportContext.Log); var connection = new LibuvConnection(listenerContext, socket); connectionTask = connection.Start(); mockLibuv.AllocCallback(socket.InternalGetHandle(), 2048, out var ignored); mockLibuv.ReadCallback(socket.InternalGetHandle(), 5, ref ignored); }, null); // Now assert that we removed the callback from libuv to stop reading Assert.Null(mockLibuv.AllocCallback); Assert.Null(mockLibuv.ReadCallback); // Now release backpressure by reading the input var result = await mockConnectionHandler.Input.Reader.ReadAsync(); // Calling advance will call into our custom scheduler that captures the back pressure // callback mockConnectionHandler.Input.Reader.AdvanceTo(result.Buffer.End); // Cancel the current pending flush mockConnectionHandler.Input.Writer.CancelPendingFlush(); // Now release the back pressure await thread.PostAsync(a => a(), backPressure); // Assert that we don't try to start reading since the write was cancelled Assert.Null(mockLibuv.AllocCallback); Assert.Null(mockLibuv.ReadCallback); // Now complete the output writer and wait for the connection to close mockConnectionHandler.Output.Writer.Complete(); await connectionTask.TimeoutAfter(TestConstants.DefaultTimeout); // Assert that we don't try to start reading Assert.Null(mockLibuv.AllocCallback); Assert.Null(mockLibuv.ReadCallback); } finally { await thread.StopAsync(TimeSpan.FromSeconds(5)); } }