示例#1
0
        public async Task TestBufferBlockAsListenerSource()
        {
            int offset = 10;

            var sources = new BufferBlock <int>();
            var results = new BufferBlock <int>();

            // events are generated as we add items to 'sources'
            var listenerBlock = new ListenerSourceBlock <int>(async(token) => await sources.ReceiveAsync() + offset);

            // results are collected in a BufferBlock
            listenerBlock.LinkTo(results);
            listenerBlock.Start();

            var inputs = Enumerable.Range(1, 10).ToList();

            // generate some events sequentially
            foreach (int i in inputs)
            {
                Assert.True(await sources.SendAsync(i));
            }

            // assert all of them have been received in the same order they were generated
            foreach (int i in inputs)
            {
                Assert.Equal(i + offset, await results.ReceiveAsync());
            }

            listenerBlock.Complete();
            await listenerBlock.Completion;
        }
示例#2
0
        /// <nodoc/>
        public GenericServer([CanBeNull] string name, IServerConfig config, ListenerSourceBlock <TClient> .CancellableListener listener, bool clientFailuresAreFatal = false)
        {
            Contract.Requires(config != null);

            Config = config;
            Logger = config.Logger ?? VoidLogger.Instance;
            Name   = name ?? "GenericServer";

            m_diagnostics = new ConcurrentQueue <Exception>();

            // in an event loop, wait for clients to connect via the 'AcceptClient' method
            m_clientListenerBlock = new ListenerSourceBlock <TClient>(listener, name + ".EventLoop", Logger);

            // handle each connected client via the 'ClientHandler' method
            var clientHandlerAction = clientFailuresAreFatal
                ? (Func <TClient, Task>)ClientHandlerWithoutExceptionHandling
                : (Func <TClient, Task>)ClientHandlerWithExceptionHandling;
            var clientHandlerBlock = new ActionBlock <TClient>(
                clientHandlerAction,
                new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism = config.MaxConcurrentClients,
            });

            // link the event loop to feed the clientHandler ActionBlock
            m_clientListenerBlock.LinkTo(clientHandlerBlock, propagateCompletion: true);
        }
示例#3
0
        public void TestFault()
        {
            var listenerBlock = new ListenerSourceBlock <int>(
                listener: (t) => Task.FromResult(0),
                logger: new ConsoleLogger(logVerbose: true));
            var errorMessage = "test";

            listenerBlock.Fault(new ArgumentException(errorMessage));
            AwaitAndAssertTaskFailed <ArgumentException>(listenerBlock.Completion, errorMessage);
        }
示例#4
0
        public void TestStartAfterFaultThrows()
        {
            var listenerBlock = new ListenerSourceBlock <int>((token) => Task.FromResult(1));

            listenerBlock.Fault(new Exception());
            var ex = Assert.Throws <IpcException>(() => listenerBlock.Start());

            Assert.Equal(IpcException.IpcExceptionKind.StartAfterStop, ex.Kind);
            Assert.Throws(typeof(Exception), () => listenerBlock.Completion.GetAwaiter().GetResult());
            Assert.True(listenerBlock.Completion.IsFaulted);
        }
示例#5
0
        public async Task TestStartAfterCompleteThrows()
        {
            var listenerBlock = new ListenerSourceBlock <int>((token) => Task.FromResult(1));

            listenerBlock.Complete();
            var ex = Assert.Throws <IpcException>(() => listenerBlock.Start());

            Assert.Equal(IpcException.IpcExceptionKind.StartAfterStop, ex.Kind);
            await listenerBlock.Completion;

            Assert.False(listenerBlock.Completion.IsFaulted);
        }
示例#6
0
        public void TestListenerThrows()
        {
            var errorMessage  = "error";
            var results       = new ConcurrentBag <int>();
            var listenerBlock = new ListenerSourceBlock <int>((token) =>
            {
                throw new ArgumentException(errorMessage);
            });

            listenerBlock.LinkTo(new ActionBlock <int>(i => results.Add(i)));
            listenerBlock.Start();

            AwaitAndAssertTaskFailed <ArgumentException>(listenerBlock.Completion, errorMessage);
            AwaitAndAssertTaskFailed <ArgumentException>(listenerBlock.TargetBlock.Completion, errorMessage);
        }
示例#7
0
        public void TestBlockingListener()
        {
            var finalCount        = 100;
            var reachedFinalCount = new ManualResetEvent(false);
            var results           = new ConcurrentBag <int>();
            int counter           = 0;

            // events are generated periodically, until 'finalCount' is reached
            var listenerBlock = new ListenerSourceBlock <int>(async(token) =>
            {
                await Task.Delay(TimeSpan.FromMilliseconds(1));
                if (counter == finalCount)
                {
                    // let the main unit test method continue and request stop
                    reachedFinalCount.Set();

                    // block this listener for good
                    new ManualResetEvent(false).WaitOne();
                }

                return(counter++);
            });

            // collect results in a concurrent bag
            listenerBlock.LinkTo(new ActionBlock <int>(
                                     i => results.Add(i),
                                     new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism = 3
            }));
            listenerBlock.Start();

            // wait until final count has been reached
            reachedFinalCount.WaitOne();

            // request stop and wait for completions
            listenerBlock.Complete();
            listenerBlock.Completion.Wait();
            listenerBlock.TargetBlock.Completion.Wait();

            // assert that every integer generated in the event loop was received
            Assert.Equal(finalCount, counter);
            Assert.Equal(counter, results.Count);
            XAssert.SetEqual(Enumerable.Range(0, counter), results);
        }
示例#8
0
        public async Task TestPropagateCompletion(bool shouldStart)
        {
            var listenerBlock = new ListenerSourceBlock <int>((token) => Task.FromResult(1));
            var actionBlock   = new ActionBlock <int>(i => { });

            listenerBlock.LinkTo(actionBlock, propagateCompletion: true);

            if (shouldStart)
            {
                listenerBlock.Start();
            }

            Assert.False(listenerBlock.Completion.IsCompleted);
            Assert.False(actionBlock.Completion.IsCompleted);

            listenerBlock.Complete();
            await actionBlock.Completion;

            Assert.True(actionBlock.Completion.IsCompleted);
            Assert.False(actionBlock.Completion.IsFaulted);
        }
示例#9
0
        public void TestPropagateFault(bool shouldStart)
        {
            var listenerBlock = new ListenerSourceBlock <int>((token) => Task.FromResult(1));
            var actionBlock   = new ActionBlock <int>(i => { });

            listenerBlock.LinkTo(actionBlock, propagateCompletion: true);

            if (shouldStart)
            {
                listenerBlock.Start();
            }

            Assert.False(listenerBlock.Completion.IsCompleted);
            Assert.False(actionBlock.Completion.IsCompleted);

            var causeException = new Exception("hi");

            listenerBlock.Fault(causeException);
            var caughtException = Assert.Throws(causeException.GetType(), () => actionBlock.Completion.GetAwaiter().GetResult());

            Assert.Equal(causeException.Message, caughtException.Message);
            Assert.True(actionBlock.Completion.IsFaulted);
        }