< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.BaseUriWithWildcard
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/BaseUriWithWildcard.cs
Line coverage
17%
Covered lines: 20
Uncovered lines: 92
Coverable lines: 112
Total lines: 323
Line coverage: 17.8%
Branch coverage
11%
Covered branches: 10
Total branches: 84
Branch coverage: 11.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
.ctor(...)0%12120%
SplitBinding(...)0%22220%
CreateHostedUri(...)0%10100%
Equals(...)50%101066.66%
GetHashCode()100%11100%
IsBaseOf(...)0%16160%
OnDeserialized(...)0%220%
ParseHostAndHostNameComparisonMode(...)0%660%
SetComparisonAddressAndHashCode()66.66%6688.88%
ToString()100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Channels/BaseUriWithWildcard.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.Diagnostics;
 7using System.Globalization;
 8using System.Runtime.Serialization;
 9using CoreWCF.Runtime;
 10
 11namespace CoreWCF.Channels
 12{
 13    // TODO: Make internal again
 14    [DataContract]
 15    public sealed class BaseUriWithWildcard
 16    {
 17        [DataMember]
 18        private readonly Uri _baseAddress;
 19        private const char segmentDelimiter = '/';
 20
 21        [DataMember]
 22        private HostNameComparisonMode _hostNameComparisonMode;
 23        private const string plus = "+";
 24        private const string star = "*";
 25        private const int HttpUriDefaultPort = 80;
 26        private const int HttpsUriDefaultPort = 443;
 27
 28        // Derived from [DataMember] fields
 29        private Comparand _comparand;
 30        private int _hashCode;
 31
 29732        public BaseUriWithWildcard(Uri baseAddress, HostNameComparisonMode hostNameComparisonMode)
 33        {
 29734            _baseAddress = baseAddress;
 29735            _hostNameComparisonMode = hostNameComparisonMode;
 29736            SetComparisonAddressAndHashCode();
 37
 38            // Note the Uri may contain query string for WSDL purpose.
 39            // So do not check IsValid().
 29740        }
 41
 042        private BaseUriWithWildcard(string protocol, int defaultPort, string binding, int segmentCount, string path, str
 43        {
 044            string[] urlParameters = SplitBinding(binding);
 45
 046            if (urlParameters.Length != segmentCount)
 47            {
 048                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 049                    new UriFormatException(SR.Format(SR.Hosting_MisformattedBinding, binding, protocol, sampleBinding)))
 50            }
 51
 052            int currentIndex = segmentCount - 1;
 053            string host = ParseHostAndHostNameComparisonMode(urlParameters[currentIndex]);
 54
 055            int port = -1;
 56
 057            if (--currentIndex >= 0)
 58            {
 059                string portString = urlParameters[currentIndex].Trim();
 60
 061                if (!string.IsNullOrEmpty(portString) &&
 062                    !int.TryParse(portString, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out port))
 63                {
 064                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new UriFormatException(SR.Format(SR.Hostin
 65                }
 66
 067                if (port == defaultPort)
 68                {
 69                    // Set to -1 so that Uri does not show it in the string.
 070                    port = -1;
 71                }
 72            }
 73            try
 74            {
 75                Fx.Assert(path != null, "path should never be null here");
 076                _baseAddress = new UriBuilder(protocol, host, port, path).Uri;
 077            }
 78            catch (Exception exception)
 79            {
 080                if (Fx.IsFatal(exception))
 81                {
 082                    throw;
 83                }
 84
 085                DiagnosticUtility.TraceHandledException(exception, TraceEventType.Error);
 86
 087                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new UriFormatException(SR.Format(SR.Hosting_Mi
 088                    protocol)));
 89            }
 090            SetComparisonAddressAndHashCode();
 091        }
 92
 93        // TODO: Make internal again
 94        public Uri BaseAddress
 95        {
 26096            get { return _baseAddress; }
 97        }
 98
 99        // TODO: Make internal again
 100        public HostNameComparisonMode HostNameComparisonMode
 101        {
 739102            get { return _hostNameComparisonMode; }
 103        }
 104
 105        private static string[] SplitBinding(string binding)
 106        {
 0107            bool parsingIPv6Address = false;
 108            const char splitChar = ':', startIPv6Address = '[', endIPv6Address = ']';
 109
 0110            List<int> splitLocations = null;
 111
 0112            for (int i = 0; i < binding.Length; i++)
 113            {
 0114                if (parsingIPv6Address && binding[i] == endIPv6Address)
 115                {
 0116                    parsingIPv6Address = false;
 117                }
 0118                else if (binding[i] == startIPv6Address)
 119                {
 0120                    parsingIPv6Address = true;
 121                }
 0122                else if (!parsingIPv6Address && binding[i] == splitChar)
 123                {
 0124                    if (splitLocations == null)
 125                    {
 0126                        splitLocations = new List<int>();
 127                    }
 0128                    splitLocations.Add(i);
 129                }
 130            }
 131
 132            string[] tokens;
 0133            if (splitLocations == null)
 134            {
 0135                tokens = new[] { binding };
 136            }
 137            else
 138            {
 0139                tokens = new string[splitLocations.Count + 1];
 0140                int startIndex = 0;
 0141                for (int i = 0; i < tokens.Length; i++)
 142                {
 0143                    if (i < splitLocations.Count)
 144                    {
 0145                        int nextSplitIndex = splitLocations[i];
 0146                        tokens[i] = binding.Substring(startIndex, nextSplitIndex - startIndex);
 0147                        startIndex = nextSplitIndex + 1;
 148                    }
 149                    else //splitting the last segment
 150                    {
 0151                        if (startIndex < binding.Length)
 152                        {
 0153                            tokens[i] = binding.Substring(startIndex, binding.Length - startIndex);
 154                        }
 155                        else
 156                        {
 157                            //splitChar was the last character in the string
 0158                            tokens[i] = string.Empty;
 159                        }
 160                    }
 161                }
 162            }
 0163            return tokens;
 164        }
 165
 166        internal static BaseUriWithWildcard CreateHostedUri(string protocol, string binding, string path)
 167        {
 168            Fx.Assert(protocol != null, "caller must verify");
 169
 0170            if (binding == null)
 171            {
 0172                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(binding));
 173            }
 174
 0175            if (path == null)
 176            {
 0177                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(path));
 178            }
 179
 0180            if (protocol.Equals(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase))
 181            {
 182                // For http, binding format is: "<ipAddress>:<port>:<hostName>"
 183                // as specified in http://www.microsoft.com/resources/documentation/WindowsServ/2003/standard/proddocs/e
 0184                return new BaseUriWithWildcard(Uri.UriSchemeHttp, HttpUriDefaultPort, binding, 3, path, ":80:");
 185            }
 0186            if (protocol.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
 187            {
 188                // For https, binding format is the same as http
 0189                return new BaseUriWithWildcard(Uri.UriSchemeHttps, HttpsUriDefaultPort, binding, 3, path, ":443:");
 190            }
 0191            if (protocol.Equals(Uri.UriSchemeNetTcp, StringComparison.OrdinalIgnoreCase))
 192            {
 193                // For net.tcp, binding format is: "<port>:<hostName>"
 0194                return new BaseUriWithWildcard(Uri.UriSchemeNetTcp, TransportDefaults.TcpUriDefaultPort, binding, 2, pat
 195            }
 196
 0197            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new UriFormatException(SR.Format(SR.Hosting_NotSup
 198        }
 199
 200        public override bool Equals(object o)
 201        {
 37202            if (!(o is BaseUriWithWildcard other) || other._hashCode != _hashCode || other._hostNameComparisonMode != _h
 37203                other._comparand.Port != _comparand.Port)
 204            {
 0205                return false;
 206            }
 37207            if (!ReferenceEquals(other._comparand.Scheme, _comparand.Scheme))
 208            {
 0209                return false;
 210            }
 37211            return _comparand.Address.Equals(other._comparand.Address);
 212        }
 213
 214        public override int GetHashCode()
 215        {
 490216            return _hashCode;
 217        }
 218
 219        internal bool IsBaseOf(Uri fullAddress)
 220        {
 0221            if (_baseAddress.Scheme != (object)fullAddress.Scheme)
 222            {
 0223                return false;
 224            }
 225
 0226            if (_baseAddress.Port != fullAddress.Port)
 227            {
 0228                return false;
 229            }
 230
 0231            if (HostNameComparisonMode == HostNameComparisonMode.Exact)
 232            {
 0233                if (string.Compare(_baseAddress.Host, fullAddress.Host, StringComparison.OrdinalIgnoreCase) != 0)
 234                {
 0235                    return false;
 236                }
 237            }
 0238            string s1 = _baseAddress.GetComponents(UriComponents.Path | UriComponents.KeepDelimiter, UriFormat.Unescaped
 0239            string s2 = fullAddress.GetComponents(UriComponents.Path | UriComponents.KeepDelimiter, UriFormat.Unescaped)
 240
 0241            if (s1.Length > s2.Length)
 242            {
 0243                return false;
 244            }
 245
 0246            if (s1.Length < s2.Length &&
 0247                s1[s1.Length - 1] != segmentDelimiter &&
 0248                s2[s1.Length] != segmentDelimiter)
 249            {
 250                // Matching over segments
 0251                return false;
 252            }
 0253            return string.Compare(s2, 0, s1, 0, s1.Length, StringComparison.OrdinalIgnoreCase) == 0;
 254        }
 255
 256        [OnDeserialized]
 257        internal void OnDeserialized(StreamingContext context)
 258        {
 0259            UriSchemeKeyedCollection.ValidateBaseAddress(_baseAddress, "context");
 260
 0261            if (!HostNameComparisonModeHelper.IsDefined(HostNameComparisonMode))
 262            {
 0263                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(nameof(context), SR.Hosting_BaseUriDeserial
 264            }
 0265            SetComparisonAddressAndHashCode();
 0266        }
 267
 268        private string ParseHostAndHostNameComparisonMode(string host)
 269        {
 0270            if (string.IsNullOrEmpty(host) || host.Equals(star))
 271            {
 0272                _hostNameComparisonMode = HostNameComparisonMode.WeakWildcard;
 0273                host = DnsCache.MachineName;
 274            }
 0275            else if (host.Equals(plus))
 276            {
 0277                _hostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
 0278                host = DnsCache.MachineName;
 279            }
 280            else
 281            {
 0282                _hostNameComparisonMode = HostNameComparisonMode.Exact;
 283            }
 0284            return host;
 285        }
 286
 287        private void SetComparisonAddressAndHashCode()
 288        {
 297289            if (HostNameComparisonMode == HostNameComparisonMode.Exact)
 290            {
 291                // Use canonical string representation of the full base address for comparison
 1292                _comparand.Address = _baseAddress.ToString();
 293            }
 294            else
 295            {
 296                // Use canonical string representation of the absolute path for comparison
 296297                _comparand.Address = _baseAddress.GetComponents(UriComponents.Path | UriComponents.KeepDelimiter, UriFor
 298            }
 299
 297300            _comparand.Port = _baseAddress.Port;
 297301            _comparand.Scheme = _baseAddress.Scheme;
 302
 297303            if ((_comparand.Port == -1) && (_comparand.Scheme == (object)Uri.UriSchemeNetTcp))
 304            {
 305                // Compensate for the fact that the Uri type doesn't know about our default TCP port number
 0306                _comparand.Port = TransportDefaults.TcpUriDefaultPort;
 307            }
 297308            _hashCode = _comparand.Address.GetHashCode() ^ _comparand.Port ^ (int)HostNameComparisonMode;
 297309        }
 310
 311        public override string ToString()
 312        {
 0313            return string.Format(CultureInfo.InvariantCulture, "{0}:{1}", HostNameComparisonMode, BaseAddress);
 314        }
 315
 316        private struct Comparand
 317        {
 318            public string Address;
 319            public int Port;
 320            public string Scheme;
 321        }
 322    }
 323}