< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.RequestContextBase
Assembly: CoreWCF.UnixDomainSocket
File(s): /home/runner/work/CoreWCF/CoreWCF/src/Common/src/CoreWCF/Channels/RequestContextBase.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 91
Coverable lines: 91
Total lines: 311
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 28
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
ReInitialize(...)100%110%
SetRequestMessage(...)100%110%
SetRequestMessage(...)100%110%
Abort()0%220%
CloseAsync()100%110%
CloseAsync()0%880%
Dispose(...)0%440%
ThrowIfInvalidReply()0%880%
TryInitiateReply()0%440%
ReplyAsync(...)100%110%
ReplyAsync()100%110%
SetReplySent()100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/Common/src/CoreWCF/Channels/RequestContextBase.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Diagnostics;
 6using System.Threading;
 7using System.Threading.Tasks;
 8using CoreWCF.Runtime;
 9
 10namespace CoreWCF.Channels
 11{
 12    internal abstract class RequestContextBase : RequestContext
 13    {
 14        private TimeSpan _defaultSendTimeout;
 15        private TimeSpan _defaultCloseTimeout;
 016        private CommunicationState _state = CommunicationState.Opened;
 17        private Message _requestMessage;
 18        private Exception _requestMessageException;
 19        private bool _replySent;
 20
 021        protected RequestContextBase(Message requestMessage, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout)
 22        {
 023            _defaultSendTimeout = defaultSendTimeout;
 024            _defaultCloseTimeout = defaultCloseTimeout;
 025            _requestMessage = requestMessage;
 026        }
 27
 28        public void ReInitialize(Message requestMessage)
 29        {
 030            _state = CommunicationState.Opened;
 031            _requestMessageException = null;
 032            _replySent = false;
 033            ReplyInitiated = false;
 034            Aborted = false;
 035            _requestMessage = requestMessage;
 036        }
 37
 38        public override Message RequestMessage
 39        {
 40            get
 41            {
 042                if (_requestMessageException != null)
 43                {
 044                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(_requestMessageException);
 45                }
 46
 047                return _requestMessage;
 48            }
 49        }
 50
 51        protected void SetRequestMessage(Message requestMessage)
 52        {
 53            Fx.Assert(_requestMessageException == null, "Cannot have both a requestMessage and a requestException.");
 054            _requestMessage = requestMessage;
 055        }
 56
 57        protected void SetRequestMessage(Exception requestMessageException)
 58        {
 59            Fx.Assert(_requestMessage == null, "Cannot have both a requestMessage and a requestException.");
 060            _requestMessageException = requestMessageException;
 061        }
 62
 063        protected bool ReplyInitiated { get; private set; }
 64
 065        protected object ThisLock { get; } = new object();
 66
 067        public bool Aborted { get; private set; }
 68
 69        public TimeSpan DefaultCloseTimeout
 70        {
 071            get { return _defaultCloseTimeout; }
 72        }
 73
 74        public TimeSpan DefaultSendTimeout
 75        {
 076            get { return _defaultSendTimeout; }
 77        }
 78
 79        public override void Abort()
 80        {
 081            lock (ThisLock)
 82            {
 083                if (_state == CommunicationState.Closed)
 84                {
 085                    return;
 86                }
 87
 088                _state = CommunicationState.Closing;
 89
 090                Aborted = true;
 091            }
 92
 93            //if (DiagnosticUtility.ShouldTraceWarning)
 94            //{
 95            //    TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.RequestContextAbort,
 96            //        SRCommon.Format(SRCommon.TraceCodeRequestContextAbort), this);
 97            //}
 98
 99            try
 100            {
 0101                OnAbort();
 0102            }
 103            finally
 104            {
 0105                _state = CommunicationState.Closed;
 0106            }
 0107        }
 108
 109        public override Task CloseAsync()
 110        {
 0111            var helper = new TimeoutHelper(_defaultCloseTimeout);
 0112            return CloseAsync(helper.GetCancellationToken());
 113        }
 114
 115        public override async Task CloseAsync(CancellationToken token)
 116        {
 0117            bool sendAck = false;
 0118            lock (ThisLock)
 119            {
 0120                if (_state != CommunicationState.Opened)
 121                {
 0122                    return;
 123                }
 124
 0125                if (TryInitiateReply())
 126                {
 0127                    sendAck = true;
 128                }
 129
 0130                _state = CommunicationState.Closing;
 0131            }
 132
 0133            bool throwing = true;
 134
 135            try
 136            {
 0137                if (sendAck)
 138                {
 0139                    await OnReplyAsync(null, token);
 140                }
 141
 0142                await OnCloseAsync(token);
 0143                _state = CommunicationState.Closed;
 0144                throwing = false;
 0145            }
 146            finally
 147            {
 0148                if (throwing)
 149                {
 0150                    Abort();
 151                }
 152            }
 0153        }
 154
 155        protected override void Dispose(bool disposing)
 156        {
 0157            base.Dispose(disposing);
 158
 0159            if (!disposing)
 160            {
 0161                return;
 162            }
 163
 0164            if (_replySent)
 165            {
 0166                CloseAsync().GetAwaiter().GetResult();
 167            }
 168            else
 169            {
 0170                Abort();
 171            }
 0172        }
 173
 174        protected abstract void OnAbort();
 175        protected abstract Task OnCloseAsync(CancellationToken token);
 176        protected abstract Task OnReplyAsync(Message message, CancellationToken token);
 177
 178        protected void ThrowIfInvalidReply()
 179        {
 0180            if (_state == CommunicationState.Closed || _state == CommunicationState.Closing)
 181            {
 0182                if (Aborted)
 183                {
 0184                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationObjectAbortedException(SR
 185                }
 186                else
 187                {
 0188                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(GetType().Full
 189                }
 190            }
 191
 0192            if (ReplyInitiated)
 193            {
 0194                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRCommon.ReplyAl
 195            }
 0196        }
 197
 198        /// <summary>
 199        /// Attempts to initiate the reply. If a reply is not initiated already (and the object is opened),
 200        /// then it initiates the reply and returns true. Otherwise, it returns false.
 201        /// </summary>
 202        protected bool TryInitiateReply()
 203        {
 0204            lock (ThisLock)
 205            {
 0206                if ((_state != CommunicationState.Opened) || ReplyInitiated)
 207                {
 0208                    return false;
 209                }
 210                else
 211                {
 0212                    ReplyInitiated = true;
 0213                    return true;
 214                }
 215            }
 0216        }
 217
 218        public override Task ReplyAsync(Message message)
 219        {
 0220            var helper = new TimeoutHelper(_defaultSendTimeout);
 0221            return ReplyAsync(message, helper.GetCancellationToken());
 222        }
 223
 224        public override async Task ReplyAsync(Message message, CancellationToken token)
 225        {
 226            // "null" is a valid reply (signals a 202-style "ack"), so we don't have a null-check here
 0227            lock (ThisLock)
 228            {
 0229                ThrowIfInvalidReply();
 0230                ReplyInitiated = true;
 0231            }
 232
 0233            await OnReplyAsync(message, token);
 0234            _replySent = true;
 0235        }
 236
 237        // This method is designed for WebSocket only, and will only be used once the WebSocket response was sent.
 238        // For WebSocket, we never call HttpRequestContext.Reply to send the response back.
 239        // Instead we call AcceptWebSocket directly. So we need to set the replyInitiated and
 240        // replySent boolean to be true once the response was sent successfully. Otherwise when we
 241        // are disposing the HttpRequestContext, we will see a bunch of warnings in trace log.
 242        protected void SetReplySent()
 243        {
 0244            lock (ThisLock)
 245            {
 0246                ThrowIfInvalidReply();
 0247                ReplyInitiated = true;
 0248            }
 249
 0250            _replySent = true;
 0251        }
 252    }
 253
 254    internal class RequestContextMessageProperty : IDisposable
 255    {
 256        private RequestContext _context;
 257        private readonly object _thisLock = new object();
 258
 259        public RequestContextMessageProperty(RequestContext context)
 260        {
 261            _context = context;
 262        }
 263
 264        public static string Name
 265        {
 266            get { return "requestContext"; }
 267        }
 268
 269        void IDisposable.Dispose()
 270        {
 271            bool success = false;
 272            RequestContext thisContext;
 273
 274            lock (_thisLock)
 275            {
 276                if (_context == null)
 277                {
 278                    return;
 279                }
 280
 281                thisContext = _context;
 282                _context = null;
 283            }
 284
 285            try
 286            {
 287                thisContext.CloseAsync().GetAwaiter().GetResult();
 288                success = true;
 289            }
 290            catch (CommunicationException e)
 291            {
 292                DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 293            }
 294            catch (TimeoutException e)
 295            {
 296                //if (TD.CloseTimeoutIsEnabled())
 297                //{
 298                //    TD.CloseTimeout(e.Message);
 299                //}
 300                DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
 301            }
 302            finally
 303            {
 304                if (!success)
 305                {
 306                    thisContext.Abort();
 307                }
 308            }
 309        }
 310    }
 311}