< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.IdentityModel.IdentityModelUniqueId
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/IdentityModel/IdentityModelUniqueId.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 19
Coverable lines: 19
Total lines: 134
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 6
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%
CreateUniqueId()100%110%
CreateUniqueId(...)0%220%
CreateRandomId()100%110%
CreateRandomId(...)0%220%
CreateRandomUri()100%110%
GetNextId()0%220%
GetRandomUuid()100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/IdentityModel/IdentityModelUniqueId.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.Globalization;
 6using System.Security.Cryptography;
 7using System.Text;
 8
 9namespace CoreWCF.IdentityModel
 10{
 11    /// <summary>
 12    /// Generates unique IDs.
 13    /// </summary>
 14    internal static class IdentityModelUniqueId
 15    {
 16        private const int RandomSaltSize = 16;
 17
 18        // We use UUIDs as the basis for our unique identifiers. UUIDs
 19        // cannot be used in xml:id-typed fields, because xml:id
 20        // is made from the NCNAME production in XML Schema.
 21        //
 22        // An NCNAME looks like this: (simlified out complex unicode)
 23        //     [A-Za-z_][A-Za-z0-9.-_]*
 24        //
 25        // A UUID looks like this:
 26        //     [0-9A-Fa-f]{8}-(?:[0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}
 27        //
 28        // The problem arises when the UUID begins with [0-9], which
 29        // violates the NCNAME production.
 30        //
 31        // This is fixed trivially by prepending an underscore.
 32        private const string NcNamePrefix = "_";
 33
 34        // In some cases we need UniqueId to be a valid URI. In this
 35        // case we use the urn:uuid: namespace established by
 36        // RFC4122. Note that in this case it is not appropriate to
 37        // use the auto-incrementing optimization, as the resulting
 38        // value is no longer properly a UUID.
 39        private const string UuidUriPrefix = "urn:uuid:";
 40
 41        // For non-random identifiers, we optimize the generation of
 42        // unique ids by calculating only one UUID per program invocation
 43        // and adding a 64-bit auto-incrementing value for each id
 44        // that is needed.
 045        private static readonly string reusableUuid = GetRandomUuid();
 46
 47        // The format of the optimized NCNAMEs produced is:
 48        //     _[0-9A-Fa-f]{8}-(?:[0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}-[A-Za-z0-9]{8}
 49        //
 50        // In other words: underscore + UUID + hyphen + 64-bit auto-incrementing id
 051        private static readonly string optimizedNcNamePrefix = NcNamePrefix + reusableUuid + "-";
 52
 53        /// <summary>
 54        /// Creates a unique ID suitable for use in an xml:id field. The value is
 55        /// not hard to guess but is unique.
 56        /// </summary>
 57        /// <returns>The unique ID.</returns>
 58        public static string CreateUniqueId()
 59        {
 060            return optimizedNcNamePrefix + GetNextId();
 61        }
 62
 63        /// <summary>
 64        /// Creates a unique ID similar to that created by CreateNonRandomId,
 65        /// but instead of an underscore, the supplied prefix is used.
 66        /// </summary>
 67        /// <param name="prefix">The prefix to use.</param>
 68        /// <returns>The unique ID, with the given prefix.</returns>
 69        public static string CreateUniqueId(string prefix)
 70        {
 071            if (string.IsNullOrEmpty(prefix))
 72            {
 073                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(prefix));
 74            }
 75
 076            return prefix + reusableUuid + "-" + GetNextId();
 77        }
 78
 79        /// <summary>
 80        /// Creates a unique, random ID suitable for use in an xml:id field. The
 81        /// value is hard to guess and unique.
 82        /// </summary>
 83        /// <returns>The unique ID.</returns>
 84        public static string CreateRandomId()
 85        {
 086            return NcNamePrefix + GetRandomUuid();
 87        }
 88
 89        /// <summary>
 90        /// Creates a unique, random ID similar to that created by CreateRandomId,
 91        /// but instead of an underscore, the supplied prefix is used.
 92        /// </summary>
 93        /// <param name="prefix">The prefix to use.</param>
 94        /// <returns>The random URI.</returns>
 95        public static string CreateRandomId(string prefix)
 96        {
 097            if (string.IsNullOrEmpty(prefix))
 98            {
 099                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(prefix));
 100            }
 101
 0102            return prefix + GetRandomUuid();
 103        }
 104
 105        /// <summary>
 106        /// Creates a unique, random ID suitable for use as a URI. The value is
 107        /// hard to guess and unique. The URI is in the urn:uuid: namespace.
 108        /// </summary>
 109        /// <returns>The random URI.</returns>
 110        public static Uri CreateRandomUri()
 111        {
 0112            return new Uri(UuidUriPrefix + GetRandomUuid());
 113        }
 114
 115        private static string GetNextId()
 116        {
 0117            RandomNumberGenerator rng = RandomNumberGenerator.Create();
 0118            byte[] id = new byte[RandomSaltSize];
 0119            rng.GetBytes(id);
 0120            StringBuilder builder = new StringBuilder();
 0121            for (int i = 0; i < id.Length; i++)
 122            {
 0123                builder.AppendFormat("{0:X2}", id[i]);
 124            }
 125
 0126            return builder.ToString();
 127        }
 128
 129        private static string GetRandomUuid()
 130        {
 0131            return Guid.NewGuid().ToString("D", CultureInfo.InvariantCulture);
 132        }
 133    }
 134}