< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.RequestReplyCorrelator
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/RequestReplyCorrelator.cs
Line coverage
74%
Covered lines: 60
Uncovered lines: 21
Coverable lines: 81
Total lines: 252
Line coverage: 74%
Branch coverage
55%
Covered branches: 20
Total branches: 36
Branch coverage: 55.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%11100%
CoreWCF.Channels.IRequestReplyCorrelator.Add(...)100%22100%
CoreWCF.Channels.IRequestReplyCorrelator.Find(...)100%22100%
RemoveRequest(...)0%220%
GetRelatesTo(...)50%2275%
AddressReply(...)100%11100%
AddressReply(...)50%8855.55%
ExtractReplyToInfo(...)100%11100%
PrepareRequest(...)100%22100%
PrepareReply(...)75%4483.33%
PrepareReply(...)0%440%
.ctor(...)100%22100%
IsTrivial(...)100%22100%
.ctor(...)100%11100%
Equals(...)50%4466.66%
GetHashCode()100%11100%
ToString()0%220%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/RequestReplyCorrelator.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.Collections;
 6using System.Xml;
 7using CoreWCF.Diagnostics;
 8using CoreWCF.Runtime;
 9
 10namespace CoreWCF.Channels
 11{
 12    internal class RequestReplyCorrelator : IRequestReplyCorrelator
 13    {
 14        private readonly Hashtable _states;
 15
 66016        internal RequestReplyCorrelator()
 17        {
 66018            _states = new Hashtable();
 66019        }
 20
 21        void IRequestReplyCorrelator.Add<T>(Message request, T state)
 22        {
 123            UniqueId messageId = request.Headers.MessageId;
 124            Type stateType = typeof(T);
 125            Key key = new Key(messageId, stateType);
 26
 27            // add the correlator key to the request, this will be needed for cleaning up the correlator table in case o
 28            // channel aborting or faulting while there are pending requests
 129            if (state is ICorrelatorKey value)
 30            {
 131                value.RequestCorrelatorKey = key;
 32            }
 33
 134            lock (_states)
 35            {
 136                _states.Add(key, state);
 137            }
 138        }
 39
 40        T IRequestReplyCorrelator.Find<T>(Message reply, bool remove)
 41        {
 142            UniqueId relatesTo = GetRelatesTo(reply);
 143            Type stateType = typeof(T);
 144            Key key = new Key(relatesTo, stateType);
 145            T value = (T)_states[key];
 46
 147            if (remove)
 48            {
 49                // With HashTable, only need to lock when modifying
 150                lock (_states)
 51                {
 152                    _states.Remove(key);
 153                }
 54            }
 55
 156            return value;
 57        }
 58
 59        // This method is used to remove the request from the correlator table when the
 60        // reply is lost. This will avoid leaking the correlator table in cases where the
 61        // channel faults or aborts while there are pending requests.
 62        internal void RemoveRequest(ICorrelatorKey request)
 63        {
 64            Fx.Assert(request != null, "request cannot be null");
 065            if (request.RequestCorrelatorKey != null)
 66            {
 067                lock (_states)
 68                {
 069                    _states.Remove(request.RequestCorrelatorKey);
 070                }
 71            }
 072        }
 73
 74        private UniqueId GetRelatesTo(Message reply)
 75        {
 176            UniqueId relatesTo = reply.Headers.RelatesTo;
 177            if (relatesTo == null)
 78            {
 079                throw TraceUtility.ThrowHelperError(new ArgumentException(SR.SuppliedMessageIsNotAReplyItHasNoRelatesTo0
 80            }
 81
 182            return relatesTo;
 83        }
 84
 85        internal static bool AddressReply(Message reply, Message request)
 86        {
 187            ReplyToInfo info = ExtractReplyToInfo(request);
 188            return AddressReply(reply, info);
 89        }
 90
 91        internal static bool AddressReply(Message reply, ReplyToInfo info)
 92        {
 58193            EndpointAddress destination = null;
 94
 58195            if (info.HasFaultTo && (reply.IsFault))
 96            {
 097                destination = info.FaultTo;
 98            }
 58199            else if (info.HasReplyTo)
 100            {
 0101                destination = info.ReplyTo;
 102            }
 103
 581104            if (destination != null)
 105            {
 0106                destination.ApplyTo(reply);
 0107                return !destination.IsNone;
 108            }
 109            else
 110            {
 581111                return true;
 112            }
 113        }
 114
 115        internal static ReplyToInfo ExtractReplyToInfo(Message message)
 116        {
 1117            return new ReplyToInfo(message);
 118        }
 119
 120        internal static void PrepareRequest(Message request)
 121        {
 2122            MessageHeaders requestHeaders = request.Headers;
 123
 2124            if (requestHeaders.MessageId == null)
 125            {
 1126                requestHeaders.MessageId = new UniqueId();
 127            }
 128
 2129            request.Properties.AllowOutputBatching = false;
 130            //if (TraceUtility.PropagateUserActivity || TraceUtility.ShouldPropagateActivity)
 131            //{
 132            //    TraceUtility.AddAmbientActivityToMessage(request);
 133            //}
 2134        }
 135
 136        internal static void PrepareReply(Message reply, UniqueId messageId)
 137        {
 296138            if (ReferenceEquals(messageId, null))
 139            {
 0140                throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.MissingMessageID), reply);
 141            }
 142
 296143            MessageHeaders replyHeaders = reply.Headers;
 144
 296145            if (ReferenceEquals(replyHeaders.RelatesTo, null))
 146            {
 296147                replyHeaders.RelatesTo = messageId;
 148            }
 149
 150            //if (TraceUtility.PropagateUserActivity || TraceUtility.ShouldPropagateActivity)
 151            //{
 152            //    TraceUtility.AddAmbientActivityToMessage(reply);
 153            //}
 296154        }
 155
 156        internal static void PrepareReply(Message reply, Message request)
 157        {
 0158            UniqueId messageId = request.Headers.MessageId;
 159
 0160            if (messageId != null)
 161            {
 0162                MessageHeaders replyHeaders = reply.Headers;
 163
 0164                if (ReferenceEquals(replyHeaders.RelatesTo, null))
 165                {
 0166                    replyHeaders.RelatesTo = messageId;
 167                }
 168            }
 169
 170            //if (TraceUtility.PropagateUserActivity || TraceUtility.ShouldPropagateActivity)
 171            //{
 172            //    TraceUtility.AddAmbientActivityToMessage(reply);
 173            //}
 0174        }
 175
 176        internal struct ReplyToInfo
 177        {
 178            internal ReplyToInfo(Message message)
 179            {
 684180                FaultTo = message.Headers.FaultTo;
 684181                ReplyTo = message.Headers.ReplyTo;
 684182                if (message.Version.Addressing == AddressingVersion.WSAddressingAugust2004)
 183                {
 15184                    From = message.Headers.From;
 185                }
 186                else
 187                {
 669188                    From = null;
 189                }
 669190            }
 191
 581192            internal EndpointAddress FaultTo { get; }
 193
 0194            internal EndpointAddress From { get; }
 195
 196            internal bool HasFaultTo
 197            {
 581198                get { return !IsTrivial(FaultTo); }
 199            }
 200
 201            internal bool HasFrom
 202            {
 0203                get { return !IsTrivial(From); }
 204            }
 205
 206            internal bool HasReplyTo
 207            {
 581208                get { return !IsTrivial(ReplyTo); }
 209            }
 210
 1264211            internal EndpointAddress ReplyTo { get; }
 212
 213            private bool IsTrivial(EndpointAddress address)
 214            {
 215                // Note: even if address.IsAnonymous, it may have identity, reference parameters, etc.
 1162216                return (address == null) || (address == EndpointAddress.AnonymousAddress);
 217            }
 218        }
 219
 220        internal class Key
 221        {
 222            internal UniqueId MessageId;
 223            internal Type StateType;
 224
 2225            internal Key(UniqueId messageId, Type stateType)
 226            {
 2227                MessageId = messageId;
 2228                StateType = stateType;
 2229            }
 230
 231            public override bool Equals(object obj)
 232            {
 2233                if (!(obj is Key other))
 234                {
 0235                    return false;
 236                }
 237
 2238                return other.MessageId == MessageId && other.StateType == StateType;
 239            }
 240
 241            public override int GetHashCode()
 242            {
 3243                return MessageId.GetHashCode() ^ StateType.GetHashCode();
 244            }
 245
 246            public override string ToString()
 247            {
 0248                return typeof(Key).ToString() + ": {" + MessageId + ", " + StateType.ToString() + "}";
 249            }
 250        }
 251    }
 252}