public async Task CallbackMethod_Should_InvokeAction()
        {
            var builder = new RpcServiceDefinitionsBuilder();

            builder.RegisterService <ICallbackService>();

            var(server, connection) = this.CreateServerAndConnection(builder);
            var callbackServiceImpl = new CallbackServiceImpl();

            using (var publishedService = server.PublishSingleton <ICallbackService>(callbackServiceImpl))
            {
                try
                {
                    server.Start();

                    var callbackService = connection.GetServiceSingleton <ICallbackService>();

                    int callCount = 0;

                    await callbackService.PerformActionCallbacksAsync(2, 10, v =>
                    {
                        Assert.AreEqual(2 + callCount, v.Value);
                        callCount++;
                    });


                    Assert.AreEqual(callCount, 10);
                }
                finally
                {
                    await server.ShutdownAsync();
                }
            }
        }
        public async Task CallbackWithCancellationTest()
        {
            var builder = new RpcServiceDefinitionsBuilder();

            builder.RegisterService <ICallbackService>();

            var(server, connection) = this.CreateServerAndConnection(builder);
            var callbackServiceImpl = new CallbackServiceImpl();

            using (var publishedService = server.ServicePublisher.PublishSingleton <ICallbackService>(callbackServiceImpl))
            {
                try
                {
                    server.Start();

                    var callbackService = connection.GetServiceSingleton <ICallbackService>();

                    int lastNo = 0;
                    CancellationTokenSource cts = new CancellationTokenSource();

                    Assert.CatchAsync <OperationCanceledException>(async() =>
                    {
                        await callbackService.PerformCancellableCallbacksAsync(1000, TimeSpan.FromMilliseconds(20), 10, true,
                                                                               callbackData =>
                        {
                            Assert.AreEqual(lastNo + 1, callbackData.Value);
                            lastNo = callbackData.Value;
                            if (lastNo == 3)
                            {
                                cts.Cancel();
                            }
                        }, cts.Token);
                    });

                    if (this.RoundTripCancellation)
                    {
                        Assert.Less(lastNo, 100);
                        Assert.GreaterOrEqual(lastNo, 3);
                    }
                    else
                    {
                        Assert.AreEqual(3, lastNo);
                    }

                    //
                    // Assert.IsTrue(await sequenceServiceImpl.GetIsCancelledAsync().DefaultTimeout());
                }
                finally
                {
                    await server.ShutdownAsync();
                }
            }
        }
        public async Task CallbackCall_UnpublishedInstance_ShouldThrow(bool cancellable)
        {
            var(server, connection) = this.CreateServerAndConnection();

            var serviceImpl     = new CallbackServiceImpl();
            var isCancelledTask = serviceImpl.GetIsCancelledAsync();

            var publishedInstance = server.PublishInstance <ICallbackService>(serviceImpl, true);

            server.Start();
            try
            {
                var client = connection.GetServiceInstance(publishedInstance.Value);

                TaskCompletionSource <int> firstTcs = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously);
                Task callbackTask;
                if (cancellable)
                {
                    callbackTask = client.PerformCancellableCallbacksAsync(2, TimeSpan.FromSeconds(10), 1, false, Callback, CancellationToken.None);
                }
                else
                {
                    callbackTask = client.PerformDelayedCallbacksAsync(2, TimeSpan.FromSeconds(10), 1, false, Callback);
                }

                await firstTcs.Task.DefaultTimeout();

                // Unpublish the server side service after the first data has been received
                publishedInstance.Dispose();

                Assert.ThrowsAsync <RpcServiceUnavailableException>(async() =>
                {
                    await callbackTask.TimeoutAfter(TimeSpan.FromSeconds(2));
                }
                                                                    );

                if (cancellable)
                {
                    Assert.IsTrue(await isCancelledTask.DefaultTimeout());
                }

                void Callback(CallbackData callbackData)
                {
                    firstTcs.TrySetResult(callbackData.Value);
                }
            }
            finally
            {
                await server.ShutdownAsync();
            }
        }
        public async Task CallbackTimeoutTest()
        {
            var builder = new RpcServiceDefinitionsBuilder();

            builder.RegisterService <ICallbackService>();

            var(server, connection) = this.CreateServerAndConnection(builder,
                                                                     null,
                                                                     o =>
            {
                o.StreamingCallTimeout = TimeSpan.FromSeconds(1);
            });

            var callbackServiceImpl = new CallbackServiceImpl();

            using var publishedService = server.ServicePublisher.PublishSingleton <ICallbackService>(callbackServiceImpl);
            try
            {
                server.Start();

                var callbackService = connection.GetServiceSingleton <ICallbackService>();


                var exceptionExpression = Is.InstanceOf <TimeoutException>();
                if (this.ConnectionType == RpcConnectionType.NetGrpc)
                {
                    // It seems like NetGrpc throws OperationCancelledException instead of DeadlineExceeded RpcException (but
                    // it also seems a bit timing dependent). Let's allow both exceptions.
                    exceptionExpression = exceptionExpression.Or.InstanceOf <OperationCanceledException>();
                }

                DateTime connectStart = DateTime.UtcNow;
                // Force connection
                //                sequenceService.SimpleCall();

                var connectDuration = DateTime.UtcNow - connectStart;
                Console.WriteLine("Connect duration: " + connectDuration);

                DateTime start  = DateTime.UtcNow;
                int      lastNo = 0;

                Assert.ThrowsAsync(exceptionExpression, async() =>
                {
                    await callbackService.PerformDelayedCallbacksAsync(2000, TimeSpan.FromMilliseconds(1), 1, true,
                                                                       callbackData =>
                    {
                        Assert.AreEqual(lastNo + 1, callbackData.Value);
                        lastNo = callbackData.Value;
                    }).DefaultTimeout();
                });

                TimeSpan duration = DateTime.UtcNow - start;
                Assert.GreaterOrEqual(duration, TimeSpan.FromSeconds(1));
                Assert.Less(duration, TimeSpan.FromSeconds(2));
                Assert.Greater(lastNo, 10);
            }
            finally
            {
                await server.ShutdownAsync();
            }
        }