< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Dispatcher.EndpointAddressProcessor
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Dispatcher/EndpointAddressProcessor.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 135
Coverable lines: 135
Total lines: 354
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 83
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
.ctor(...)100%110%
GetComparableForm(...)0%45450%
AppendString(...)100%110%
CompleteValue(...)0%220%
Clear(...)0%220%
ProcessHeaders(...)0%10100%
SetBit(...)0%660%
TestExact(...)0%440%
TestMask(...)0%660%
.ctor()100%110%
Compare(...)0%220%
Equals(...)0%220%
GetHashCode(...)100%110%
.ctor(...)100%110%
AddToMask(...)0%440%
.ctor(...)100%110%
CompareTo(...)100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Dispatcher/EndpointAddressProcessor.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.Generic;
 6using System.Globalization;
 7using System.Text;
 8using System.Xml;
 9using CoreWCF.Channels;
 10using CoreWCF.Runtime;
 11
 12namespace CoreWCF.Dispatcher
 13{
 14    internal class EndpointAddressProcessor
 15    {
 016        internal static readonly QNameKeyComparer QNameComparer = new QNameKeyComparer();
 17
 18        // QName Attributes
 19        //internal static readonly string XsiNs = XmlSchema.InstanceNamespace;
 020        internal static readonly string XsiNs = "http://www.w3.org/2001/XMLSchema-instance";
 21        internal const string SerNs = "http://schemas.microsoft.com/2003/10/Serialization/";
 22        internal const string TypeLN = "type";
 23        internal const string ItemTypeLN = "ItemType";
 24        internal const string FactoryTypeLN = "FactoryType";
 25
 26        // Pooling
 27        private readonly StringBuilder _builder;
 28        private byte[] _resultData;
 29
 030        internal EndpointAddressProcessor(int length)
 31        {
 032            _builder = new StringBuilder();
 033            _resultData = new byte[length];
 034        }
 35
 036        internal EndpointAddressProcessor Next { get; set; }
 37
 38        internal static string GetComparableForm(StringBuilder builder, XmlReader reader)
 39        {
 040            List<Attr> attrSet = new List<Attr>();
 041            int valueLength = -1;
 042            while (!reader.EOF)
 43            {
 044                XmlNodeType type = reader.MoveToContent();
 45                switch (type)
 46                {
 47                    case XmlNodeType.Element:
 048                        CompleteValue(builder, valueLength);
 049                        valueLength = -1;
 50
 051                        builder.Append("<");
 052                        AppendString(builder, reader.LocalName);
 053                        builder.Append(":");
 054                        AppendString(builder, reader.NamespaceURI);
 055                        builder.Append(" ");
 56
 57                        // Scan attributes
 058                        attrSet.Clear();
 059                        if (reader.MoveToFirstAttribute())
 60                        {
 61                            do
 62                            {
 63                                // Ignore namespaces
 064                                if (reader.Prefix == "xmlns" || reader.Name == "xmlns")
 65                                {
 66                                    continue;
 67                                }
 068                                if (reader.LocalName == AddressingStrings.IsReferenceParameter && reader.NamespaceURI ==
 69                                {
 70                                    continue;  // ignore IsReferenceParameter
 71                                }
 72
 073                                string val = reader.Value;
 074                                if ((reader.LocalName == TypeLN && reader.NamespaceURI == XsiNs) ||
 075                                    (reader.NamespaceURI == SerNs && (reader.LocalName == ItemTypeLN || reader.LocalName
 76                                {
 077                                    XmlUtil.ParseQName(reader, val, out string local, out string ns);
 078                                    val = local + "^" + local.Length.ToString(CultureInfo.InvariantCulture) + ":" + ns +
 79                                }
 080                                else if (reader.LocalName == XD.UtilityDictionary.IdAttribute.Value && reader.NamespaceU
 81                                {
 82                                    // ignore wsu:Id attributes added by security to sign the header
 83                                    continue;
 84                                }
 085                                attrSet.Add(new Attr(reader.LocalName, reader.NamespaceURI, val));
 086                            } while (reader.MoveToNextAttribute());
 87                        }
 088                        reader.MoveToElement();
 89
 090                        if (attrSet.Count > 0)
 91                        {
 092                            attrSet.Sort();
 093                            for (int i = 0; i < attrSet.Count; ++i)
 94                            {
 095                                Attr a = attrSet[i];
 96
 097                                AppendString(builder, a._local);
 098                                builder.Append(":");
 099                                AppendString(builder, a._ns);
 0100                                builder.Append("=\"");
 0101                                AppendString(builder, a._val);
 0102                                builder.Append("\" ");
 103                            }
 104                        }
 105
 0106                        if (reader.IsEmptyElement)
 107                        {
 0108                            builder.Append("></>");  // Should be the same as an empty tag.
 109                        }
 110                        else
 111                        {
 0112                            builder.Append(">");
 113                        }
 114
 0115                        break;
 116
 117                    case XmlNodeType.EndElement:
 0118                        CompleteValue(builder, valueLength);
 0119                        valueLength = -1;
 0120                        builder.Append("</>");
 0121                        break;
 122
 123                    // Need to escape CDATA values
 124                    case XmlNodeType.CDATA:
 0125                        CompleteValue(builder, valueLength);
 0126                        valueLength = -1;
 127
 0128                        builder.Append("<![CDATA[");
 0129                        AppendString(builder, reader.Value);
 0130                        builder.Append("]]>");
 0131                        break;
 132
 133                    case XmlNodeType.SignificantWhitespace:
 134                    case XmlNodeType.Text:
 0135                        if (valueLength < 0)
 136                        {
 0137                            valueLength = builder.Length;
 138                        }
 139
 0140                        builder.Append(reader.Value);
 141                        break;
 142
 143                    default:
 144                        // Do nothing
 145                        break;
 146                }
 0147                reader.Read();
 148            }
 0149            return builder.ToString();
 150        }
 151
 152        private static void AppendString(StringBuilder builder, string s)
 153        {
 0154            builder.Append(s);
 0155            builder.Append("^");
 0156            builder.Append(s.Length.ToString(CultureInfo.InvariantCulture));
 0157        }
 158
 159        private static void CompleteValue(StringBuilder builder, int startLength)
 160        {
 0161            if (startLength < 0)
 162            {
 0163                return;
 164            }
 165
 0166            int len = builder.Length - startLength;
 0167            builder.Append("^");
 0168            builder.Append(len.ToString(CultureInfo.InvariantCulture));
 0169        }
 170
 171        internal void Clear(int length)
 172        {
 0173            if (_resultData.Length == length)
 174            {
 0175                Array.Clear(_resultData, 0, _resultData.Length);
 176            }
 177            else
 178            {
 0179                _resultData = new byte[length];
 180            }
 0181        }
 182
 183        internal void ProcessHeaders(Message msg, Dictionary<QName, int> qnameLookup, Dictionary<string, HeaderBit[]> he
 184        {
 185            string key;
 186            QName qname;
 0187            MessageHeaders headers = msg.Headers;
 0188            for (int j = 0; j < headers.Count; ++j)
 189            {
 0190                qname.name = headers[j].Name;
 0191                qname.ns = headers[j].Namespace;
 0192                if (headers.MessageVersion.Addressing == AddressingVersion.WSAddressing10
 0193                    && !headers[j].IsReferenceParameter)
 194                {
 195                    continue;
 196                }
 0197                if (qnameLookup.ContainsKey(qname))
 198                {
 0199                    _builder.Remove(0, _builder.Length);
 0200                    XmlReader reader = headers.GetReaderAtHeader(j).ReadSubtree();
 0201                    reader.Read();  // Needed after call to ReadSubtree
 0202                    key = GetComparableForm(_builder, reader);
 203
 0204                    if (headerLookup.TryGetValue(key, out HeaderBit[] bits))
 205                    {
 0206                        SetBit(bits);
 207                    }
 208                }
 209            }
 0210        }
 211
 212        internal void SetBit(HeaderBit[] bits)
 213        {
 0214            if (bits.Length == 1)
 215            {
 0216                _resultData[bits[0]._index] |= bits[0]._mask;
 217            }
 218            else
 219            {
 0220                byte[] results = _resultData;
 0221                for (int i = 0; i < bits.Length; ++i)
 222                {
 0223                    if ((results[bits[i]._index] & bits[i]._mask) == 0)
 224                    {
 0225                        results[bits[i]._index] |= bits[i]._mask;
 0226                        break;
 227                    }
 228                }
 229            }
 0230        }
 231
 232        internal bool TestExact(byte[] exact)
 233        {
 234            Fx.Assert(_resultData.Length == exact.Length, "");
 235
 0236            byte[] results = _resultData;
 0237            for (int i = 0; i < exact.Length; ++i)
 238            {
 0239                if (results[i] != exact[i])
 240                {
 0241                    return false;
 242                }
 243            }
 244
 0245            return true;
 246        }
 247
 248        internal bool TestMask(byte[] mask)
 249        {
 0250            if (mask == null)
 251            {
 0252                return true;
 253            }
 254
 0255            byte[] results = _resultData;
 0256            for (int i = 0; i < mask.Length; ++i)
 257            {
 0258                if ((results[i] & mask[i]) != mask[i])
 259                {
 0260                    return false;
 261                }
 262            }
 263
 0264            return true;
 265        }
 266
 267        internal struct QName
 268        {
 269            internal string name;
 270            internal string ns;
 271        }
 272
 273        internal class QNameKeyComparer : IComparer<QName>, IEqualityComparer<QName>
 274        {
 0275            internal QNameKeyComparer()
 276            {
 0277            }
 278
 279            public int Compare(QName x, QName y)
 280            {
 0281                int i = string.CompareOrdinal(x.name, y.name);
 0282                if (i != 0)
 283                {
 0284                    return i;
 285                }
 286
 0287                return string.CompareOrdinal(x.ns, y.ns);
 288            }
 289
 290            public bool Equals(QName x, QName y)
 291            {
 0292                int i = string.CompareOrdinal(x.name, y.name);
 0293                if (i != 0)
 294                {
 0295                    return false;
 296                }
 297
 0298                return string.CompareOrdinal(x.ns, y.ns) == 0;
 299            }
 300
 301            public int GetHashCode(QName obj)
 302            {
 0303                return obj.name.GetHashCode() ^ obj.ns.GetHashCode();
 304            }
 305        }
 306
 307        internal struct HeaderBit
 308        {
 309            internal int _index;
 310            internal byte _mask;
 311
 312            internal HeaderBit(int bitNum)
 313            {
 0314                _index = bitNum / 8;
 0315                _mask = (byte)(1 << (bitNum % 8));
 0316            }
 317
 318            internal void AddToMask(ref byte[] mask)
 319            {
 0320                if (mask == null)
 321                {
 0322                    mask = new byte[_index + 1];
 323                }
 0324                else if (mask.Length <= _index)
 325                {
 0326                    Array.Resize(ref mask, _index + 1);
 327                }
 328
 0329                mask[_index] |= _mask;
 0330            }
 331        }
 332
 333        private class Attr : IComparable<Attr>
 334        {
 335            internal string _local;
 336            internal string _ns;
 337            internal string _val;
 338            private readonly string _key;
 339
 0340            internal Attr(string l, string ns, string v)
 341            {
 0342                _local = l;
 0343                _ns = ns;
 0344                _val = v;
 0345                _key = ns + ":" + l;
 0346            }
 347
 348            public int CompareTo(Attr a)
 349            {
 0350                return string.Compare(_key, a._key, StringComparison.Ordinal);
 351            }
 352        }
 353    }
 354}