< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.ReceiveContext
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/ReceiveContext.cs
Line coverage
77%
Covered lines: 93
Uncovered lines: 27
Coverable lines: 120
Total lines: 341
Line coverage: 77.5%
Branch coverage
54%
Covered branches: 23
Total branches: 42
Branch coverage: 54.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%11100%
.ctor()100%11100%
TryGet(...)50%2275%
TryGet(...)50%4471.42%
AbandonAsync(...)100%11100%
AbandonAsync()62.5%8884.21%
CompleteAsync()75%4494.73%
Fault()50%6685.71%
OnAbandonAsync(...)100%110%
OnFaulted()33.33%6650%
PreAbandon()50%4488.88%
PreComplete()100%11100%
ReleaseStateLock()100%11100%
ThrowIfFaulted()50%2250%
ThrowIfNotAbandoning()50%2250%
ThrowIfNotCompleting()50%2250%
ThrowIfNotReceived()50%2250%
WaitForStateLockAsync()100%1160%
WrapStateException(...)100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/ReceiveContext.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.Threading;
 6using System.Threading.Tasks;
 7using CoreWCF.Runtime;
 8
 9namespace CoreWCF.Channels
 10{
 11    public abstract class ReceiveContext
 12    {
 813        public static readonly string Name = "ReceiveContext";
 14        private readonly SemaphoreSlim _stateLock; // protects state that may be reverted
 15        private bool _contextFaulted;
 16
 17        //EventTraceActivity eventTraceActivity;
 18
 171919        protected ReceiveContext()
 20        {
 171921            ThisLock = new object();
 171922            State = ReceiveContextState.Received;
 171923            _stateLock = new SemaphoreSlim(1);
 171924        }
 25
 26        public ReceiveContextState State
 27        {
 701328            get;
 515729            protected set;
 30        }
 31
 343932        protected object ThisLock { get; }
 33
 34        public event EventHandler Faulted;
 35
 36        public static bool TryGet(Message message, out ReceiveContext property)
 37        {
 253838            if (message == null)
 39            {
 040                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(message));
 41            }
 42
 253843            bool result = TryGet(message.Properties, out property);
 44            //if (result && FxTrace.Trace.IsEnd2EndActivityTracingEnabled && property.eventTraceActivity == null)
 45            //{
 46            //    property.eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
 47            //}
 48
 253849            return result;
 50        }
 51
 52        public static bool TryGet(MessageProperties properties, out ReceiveContext property)
 53        {
 253854            if (properties == null)
 55            {
 056                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(properties));
 57            }
 58
 253859            property = null;
 253860            if (properties.TryGetValue(Name, out object foundProperty))
 61            {
 170362                property = (ReceiveContext)foundProperty;
 170363                return true;
 64            }
 83565            return false;
 66        }
 67
 68        public virtual Task AbandonAsync(CancellationToken token)
 69        {
 6870            return AbandonAsync(null, token);
 71        }
 72
 73        public virtual async Task AbandonAsync(Exception exception, CancellationToken token)
 74        {
 6875            await WaitForStateLockAsync(token);
 76
 77            try
 78            {
 6879                if (PreAbandon())
 80                {
 081                    return;
 82                }
 6883            }
 84            finally
 85            {
 86                // Abandon can never be reverted, release the state lock.
 6887                ReleaseStateLock();
 88            }
 89
 6890            bool success = false;
 91            try
 92            {
 6893                if (exception == null)
 94                {
 6895                    await OnAbandonAsync(token);
 96                }
 97                else
 98                {
 99                    //if (TD.ReceiveContextAbandonWithExceptionIsEnabled())
 100                    //{
 101                    //    TD.ReceiveContextAbandonWithException(this.eventTraceActivity, this.GetType().ToString(), exce
 102                    //}
 0103                    await OnAbandonAsync(exception, token);
 104                }
 68105                lock (ThisLock)
 106                {
 68107                    ThrowIfFaulted();
 68108                    ThrowIfNotAbandoning();
 68109                    State = ReceiveContextState.Abandoned;
 68110                }
 68111                success = true;
 68112            }
 113            finally
 114            {
 68115                if (!success)
 116                {
 117                    //if (TD.ReceiveContextAbandonFailedIsEnabled())
 118                    //{
 119                    //    TD.ReceiveContextAbandonFailed(this.eventTraceActivity, this.GetType().ToString());
 120                    //}
 0121                    Fault();
 122                }
 123            }
 68124        }
 125
 126        public virtual async Task CompleteAsync(CancellationToken token)
 127        {
 1651128            await WaitForStateLockAsync(token);
 1651129            bool success = false;
 130
 131            try
 132            {
 1651133                PreComplete();
 1651134                success = true;
 1651135            }
 136            finally
 137            {
 138                // Case 1: State validation fails, release the lock.
 139                // Case 2: No transaction, the state can never be reverted, release the lock.
 140                // Case 3: Transaction, keep the lock until we know the transaction outcome (OnTransactionStatusNotifica
 1651141                if (!success /*|| Transaction.Current == null*/)
 142                {
 0143                    ReleaseStateLock();
 144                }
 145            }
 146
 1651147            success = false;
 148            try
 149            {
 1651150                await OnCompleteAsync(token);
 1650151                lock (ThisLock)
 152                {
 1650153                    ThrowIfFaulted();
 1650154                    ThrowIfNotCompleting();
 1650155                    State = ReceiveContextState.Completed;
 1650156                }
 1650157                success = true;
 1650158            }
 159            finally
 160            {
 1651161                if (!success)
 162                {
 163                    //if (TD.ReceiveContextCompleteFailedIsEnabled())
 164                    //{
 165                    //    TD.ReceiveContextCompleteFailed(this.eventTraceActivity, this.GetType().ToString());
 166                    //}
 1167                    Fault();
 168                }
 169            }
 1650170        }
 171
 172        protected internal virtual void Fault()
 173        {
 1174            lock (ThisLock)
 175            {
 1176                if (State == ReceiveContextState.Completed || State == ReceiveContextState.Abandoned || State == Receive
 177                {
 0178                    return;
 179                }
 1180                State = ReceiveContextState.Faulted;
 1181            }
 1182            OnFaulted();
 1183        }
 184
 185        protected abstract Task OnAbandonAsync(CancellationToken token);
 186
 187        protected virtual Task OnAbandonAsync(Exception exception, CancellationToken token)
 188        {
 189            // default implementation: delegate to non-exception overload, ignoring reason
 0190            return OnAbandonAsync(token);
 191        }
 192
 193        protected abstract Task OnCompleteAsync(CancellationToken token);
 194
 195        protected virtual void OnFaulted()
 196        {
 1197            lock (ThisLock)
 198            {
 1199                if (_contextFaulted)
 200                {
 0201                    return;
 202                }
 1203                _contextFaulted = true;
 1204            }
 205
 206            //if (TD.ReceiveContextFaultedIsEnabled())
 207            //{
 208            //    TD.ReceiveContextFaulted(this.eventTraceActivity, this);
 209            //}
 210
 1211            EventHandler handler = Faulted;
 212
 1213            if (handler != null)
 214            {
 215                try
 216                {
 0217                    handler(this, EventArgs.Empty);
 0218                }
 0219                catch (Exception exception)
 220                {
 0221                    if (Fx.IsFatal(exception))
 222                    {
 0223                        throw;
 224                    }
 225
 0226                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(exception);
 227                }
 228            }
 1229        }
 230
 231        //void OnTransactionStatusNotification(TransactionStatus status)
 232        //{
 233        //    lock (ThisLock)
 234        //    {
 235        //        if (status == TransactionStatus.Aborted)
 236        //        {
 237        //            if (this.State == ReceiveContextState.Completing || this.State == ReceiveContextState.Completed)
 238        //            {
 239        //                this.State = ReceiveContextState.Received;
 240        //            }
 241        //        }
 242        //    }
 243
 244        //    if (status != TransactionStatus.Active)
 245        //    {
 246        //        this.ReleaseStateLock();
 247        //    }
 248        //}
 249
 250        private bool PreAbandon()
 251        {
 68252            bool alreadyAbandoned = false;
 68253            lock (ThisLock)
 254            {
 68255                if (State == ReceiveContextState.Abandoning || State == ReceiveContextState.Abandoned)
 256                {
 0257                    alreadyAbandoned = true;
 258                }
 259                else
 260                {
 68261                    ThrowIfFaulted();
 68262                    ThrowIfNotReceived();
 68263                    State = ReceiveContextState.Abandoning;
 264                }
 68265            }
 68266            return alreadyAbandoned;
 267        }
 268
 269        private void PreComplete()
 270        {
 1651271            lock (ThisLock)
 272            {
 1651273                ThrowIfFaulted();
 1651274                ThrowIfNotReceived();
 275                //if (Transaction.Current != null)
 276                //{
 277                //    Transaction.Current.EnlistVolatile(new EnlistmentNotifications(this), EnlistmentOptions.None);
 278                //}
 1651279                State = ReceiveContextState.Completing;
 1651280            }
 1651281        }
 282
 283        private void ReleaseStateLock()
 284        {
 68285            _stateLock.Release();
 68286        }
 287
 288        private void ThrowIfFaulted()
 289        {
 3437290            if (State == ReceiveContextState.Faulted)
 291            {
 0292                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0293                    new CommunicationException(SR.Format(SR.ReceiveContextFaulted, GetType().ToString())));
 294            }
 3437295        }
 296
 297        private void ThrowIfNotAbandoning()
 298        {
 68299            if (State != ReceiveContextState.Abandoning)
 300            {
 0301                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0302                    new InvalidOperationException(SR.Format(SR.ReceiveContextInInvalidState, GetType().ToString(), State
 303            }
 68304        }
 305
 306        private void ThrowIfNotCompleting()
 307        {
 1650308            if (State != ReceiveContextState.Completing)
 309            {
 0310                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0311                    new InvalidOperationException(SR.Format(SR.ReceiveContextInInvalidState, GetType().ToString(), State
 312            }
 1650313        }
 314
 315        private void ThrowIfNotReceived()
 316        {
 1719317            if (State != ReceiveContextState.Received)
 318            {
 0319                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0320                    new InvalidOperationException(SR.Format(SR.ReceiveContextCannotBeUsed, GetType().ToString(), State.T
 321            }
 1719322        }
 323
 324        private async Task WaitForStateLockAsync(CancellationToken token)
 325        {
 326            try
 327            {
 1719328                await _stateLock.WaitAsync(token);
 1719329            }
 0330            catch (TaskCanceledException exception)
 331            {
 0332                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WrapStateException(exception));
 333            }
 1719334        }
 335
 336        private Exception WrapStateException(Exception exception)
 337        {
 0338            return new InvalidOperationException(SR.Format(SR.ReceiveContextInInvalidState, GetType().ToString(), State.
 339        }
 340    }
 341}