public async Task LongRunningDeadline_DisposeWaitsUntilFinished()
        {
            // Arrange
            var syncPoint = new SyncPoint();

            var httpResetFeature = new TestHttpResetFeature();
            var httpContext      = new DefaultHttpContext();

            httpContext.Request.Headers[GrpcProtocolConstants.TimeoutHeader] = "200m";
            httpContext.Features.Set <IHttpResponseBodyFeature>(new TestBlockingHttpResponseCompletionFeature(syncPoint));
            httpContext.Features.Set <IHttpResetFeature>(httpResetFeature);

            var testSink   = new TestSink();
            var testLogger = new TestLogger(string.Empty, testSink, true);

            var serverCallContext = CreateServerCallContext(httpContext, testLogger);

            serverCallContext.Initialize();

            // Wait until CompleteAsync is called
            // That means we're inside the deadline method and the lock has been taken
            await syncPoint.WaitForSyncPoint();

            // Act
            var disposeTask = serverCallContext.DeadlineManager !.DisposeAsync();

            // Assert
            Assert.IsFalse(disposeTask.IsCompletedSuccessfully);

            // Allow deadline exceeded to continue
            syncPoint.Continue();

            await disposeTask;
        }
Exemple #2
0
        /// <summary>
        /// Creates a re-entrant function that waits for sync points in sequence.
        /// </summary>
        /// <param name="count">The number of sync points to expect</param>
        /// <param name="syncPoints">The <see cref="SyncPoint"/> objects that can be used to coordinate the sync point</param>
        /// <returns></returns>
        public static Func <Task> Create(int count, out SyncPoint[] syncPoints)
        {
            // Need to use a local so the closure can capture it. You can't use out vars in a closure.
            var localSyncPoints = new SyncPoint[count];

            for (var i = 0; i < count; i += 1)
            {
                localSyncPoints[i] = new SyncPoint();
            }

            syncPoints = localSyncPoints;

            var counter = 0;

            return(() =>
            {
                if (counter >= localSyncPoints.Length)
                {
                    return Task.CompletedTask;
                }
                else
                {
                    var syncPoint = localSyncPoints[counter];

                    counter += 1;
                    return syncPoint.WaitToContinue();
                }
            });
        }
Exemple #3
0
        public static Func <Task> Create(out SyncPoint syncPoint)
        {
            var handler = Create(1, out var syncPoints);

            syncPoint = syncPoints[0];
            return(handler);
        }
Exemple #4
0
        private async Task LongRunningDeadline_WaitsUntilDeadlineIsFinished(
            string methodName,
            Func <HttpContextServerCallContext, Task> method,
            string protocol,
            int expectedResetCode)
        {
            // Arrange
            var syncPoint = new SyncPoint();

            var httpResetFeature = new TestHttpResetFeature();
            var httpContext      = new DefaultHttpContext();

            httpContext.Request.Protocol = protocol;
            httpContext.Request.Headers[GrpcProtocolConstants.TimeoutHeader] = "200m";
            httpContext.Features.Set <IHttpResponseBodyFeature>(new TestBlockingHttpResponseCompletionFeature(syncPoint));
            httpContext.Features.Set <IHttpResetFeature>(httpResetFeature);

            var serverCallContext = CreateServerCallContext(httpContext);

            serverCallContext.Initialize();

            // Wait until CompleteAsync is called
            // That means we're inside the deadline method and the lock has been taken
            await syncPoint.WaitForSyncPoint().DefaultTimeout();

            // Act
            var methodTask = method(serverCallContext);

            // Assert
            if (await Task.WhenAny(methodTask, Task.Delay(TimeSpan.FromSeconds(0.2))).DefaultTimeout() == methodTask)
            {
                Assert.Fail($"{methodName} did not wait on lock taken by deadline cancellation.");
            }

            Assert.IsFalse(serverCallContext.DeadlineManager !.IsCallComplete);

            // Wait for dispose to finish
            syncPoint.Continue();
            await methodTask.DefaultTimeout();

            Assert.AreEqual(expectedResetCode, httpResetFeature.ErrorCode);

            Assert.IsTrue(serverCallContext.DeadlineManager !.IsCallComplete);
        }
Exemple #5
0
 public TestBlockingHttpResponseCompletionFeature(SyncPoint syncPoint)
 {
     _syncPoint = syncPoint;
 }
 private void ResetSyncPoint()
 {
     _awaiter = SyncPoint.Create(out _syncPoint);
 }