< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.KestrunRuntimeInfo
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/KestrunRuntimeInfo.cs
Tag: Kestrun/Kestrun@ca54e35c77799b76774b3805b6f075cdbc0c5fbe
Line coverage
64%
Covered lines: 42
Uncovered lines: 23
Coverable lines: 65
Total lines: 228
Line coverage: 64.6%
Branch coverage
40%
Covered branches: 17
Total branches: 42
Branch coverage: 40.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 10/13/2025 - 16:52:37 Line coverage: 78.6% (48/61) Branch coverage: 45.2% (19/42) Total lines: 202 Tag: Kestrun/Kestrun@10d476bee71c71ad215bb8ab59f219887b5b4a5e11/26/2025 - 04:09:52 Line coverage: 76.1% (48/63) Branch coverage: 45.2% (19/42) Total lines: 218 Tag: Kestrun/Kestrun@783d423774fc9827a03321203e642119023bb30012/15/2025 - 02:23:46 Line coverage: 66.6% (42/63) Branch coverage: 40.4% (17/42) Total lines: 218 Tag: Kestrun/Kestrun@7a3839f4de2254e22daae81ab8dc7cb2f40c833012/21/2025 - 19:25:34 Line coverage: 64.6% (42/65) Branch coverage: 40.4% (17/42) Total lines: 228 Tag: Kestrun/Kestrun@63eee3e6ff7662a7eb5bb3603d667daccb809f2d 10/13/2025 - 16:52:37 Line coverage: 78.6% (48/61) Branch coverage: 45.2% (19/42) Total lines: 202 Tag: Kestrun/Kestrun@10d476bee71c71ad215bb8ab59f219887b5b4a5e11/26/2025 - 04:09:52 Line coverage: 76.1% (48/63) Branch coverage: 45.2% (19/42) Total lines: 218 Tag: Kestrun/Kestrun@783d423774fc9827a03321203e642119023bb30012/15/2025 - 02:23:46 Line coverage: 66.6% (42/63) Branch coverage: 40.4% (17/42) Total lines: 218 Tag: Kestrun/Kestrun@7a3839f4de2254e22daae81ab8dc7cb2f40c833012/21/2025 - 19:25:34 Line coverage: 64.6% (42/65) Branch coverage: 40.4% (17/42) Total lines: 228 Tag: Kestrun/Kestrun@63eee3e6ff7662a7eb5bb3603d667daccb809f2d

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_IsReleaseDistribution()100%210%
get_IsDebugBuild()100%210%
get_AspNetCoreVersion()100%210%
get_KestrunRoot()100%210%
GetBuiltTargetFrameworkVersion()50%8881.81%
.cctor()50%44100%
GetKnownFeatures()100%11100%
Supports(...)50%15637.5%
Supports(...)50%24837.5%
TryGetMinVersion(...)100%22100%
IsAtLeast(...)100%11100%
CheckHttp3Runtime()0%110100%
GetBuiltTargetFrameworkName()50%44100%

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/KestrunRuntimeInfo.cs

#LineLine coverage
 1using System.Reflection;
 2using System.Runtime.Versioning;
 3using System.Diagnostics.CodeAnalysis;
 4
 5namespace Kestrun;
 6
 7/// <summary>
 8/// Utility class to expose information about the runtime environment
 9/// that Kestrun was built for, and to gate features by TFM and runtime.
 10/// </summary>
 11public static class KestrunRuntimeInfo
 12{
 13    /// <summary>
 14    /// Determines whether the current distribution is a release distribution.
 15    /// </summary>
 16    /// <returns> True if the current distribution is a release distribution; otherwise, false.</returns>
 17#if DEBUG
 18    public static bool IsReleaseDistribution => false;
 19#else
 020    public static bool IsReleaseDistribution => true;
 21#endif
 22
 23    /// <summary>
 24    /// Determines whether the current build is a debug build.
 25    /// </summary>
 26    /// <returns> True if the current build is a debug build; otherwise, false.</returns>
 027    public static bool IsDebugBuild => !IsReleaseDistribution;
 28
 29    /// <summary>
 30    /// Gets or sets the ASP.NET Core version detected at runtime.
 31    /// </summary>
 032    public static string? AspNetCoreVersion { get; set; }
 33
 34    /// <summary>
 35    /// Gets the Kestrun root path as set in the KestrunHostManager.
 36    /// </summary>
 037    public static string? KestrunRoot => KestrunHostManager.KestrunRoot;
 38
 39    /// <summary>
 40    /// Returns the target framework version this assembly was built against
 41    /// as a System.Version (e.g., 8.0, 9.0).
 42    /// </summary>
 43    public static Version GetBuiltTargetFrameworkVersion()
 44    {
 345        var asm = typeof(KestrunRuntimeInfo).Assembly;
 346        var tfm = asm.GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName;
 347        if (string.IsNullOrEmpty(tfm))
 48        {
 049            return new Version(0, 0);
 50        }
 51
 352        var key = "Version=";
 353        var idx = tfm.IndexOf(key, StringComparison.OrdinalIgnoreCase);
 354        if (idx >= 0)
 55        {
 356            var ver = tfm[(idx + key.Length)..].TrimStart('v');
 357            if (Version.TryParse(ver, out var parsed))
 58            {
 359                return parsed;
 60            }
 61        }
 62
 063        return new Version(0, 0);
 64    }
 65
 66    // --- Feature gating ---
 67
 68    /// <summary>
 69    /// Built-in Kestrun feature keys. Add more as you gate new APIs by TFM.
 70    /// </summary>
 71    public enum KnownFeature
 72    {
 73        /// <summary>
 74        /// Kestrel HTTP/3 listener support (requires QUIC at runtime)
 75        /// </summary>
 76        Http3 = 0,
 77        /// <summary>
 78        /// Suppresses reading the antiforgery token from the form body
 79        /// </summary>
 80        SuppressReadingTokenFromFormBody = 1
 81    }
 82
 83    // Minimal TFM required for each feature.
 84    // Extend this table as you add features.
 185    private static readonly Dictionary<string, Version> FeatureMinByName =
 186        new(StringComparer.OrdinalIgnoreCase)
 187        {
 188            [nameof(KnownFeature.Http3)] = new Version(8, 0),
 189            // New in .NET 9+: Antiforgery option to suppress reading token from request form body.
 190            [nameof(KnownFeature.SuppressReadingTokenFromFormBody)] = new Version(9, 0),
 191        };
 92
 93    /// <summary>
 94    /// Returns the set of known feature identifiers (enum names) that have a
 95    /// compile-time (TFM) gate registered. This does not guarantee that
 96    /// <see cref="Supports(string)"/> will return true, only that the feature
 97    /// is recognized and has a minimum version entry.
 98    /// </summary>
 199    public static IEnumerable<string> GetKnownFeatures() => FeatureMinByName.Keys;
 100
 101    /// <summary>
 102    /// True if the loaded Kestrun assembly supports the feature,
 103    /// considering both build-time TFM and runtime requirements.
 104    /// </summary>
 105    public static bool Supports(KnownFeature feature)
 106    {
 1107        var name = feature.ToString();
 1108        if (!TryGetMinVersion(name, out var min) || !IsAtLeast(min))
 109        {
 1110            return false; // compile-time gate failed
 111        }
 112
 113        // runtime-sensitive checks
 0114        return feature switch
 0115        {
 0116            KnownFeature.Http3 => CheckHttp3Runtime(),
 0117            _ => true,
 0118        };
 119    }
 120
 121    /// <summary>
 122    /// True if the loaded Kestrun assembly supports the feature,
 123    /// considering both build-time TFM and runtime requirements.
 124    /// Unknown names return false.
 125    /// </summary>
 126    public static bool Supports(string featureName)
 127    {
 2128        if (string.IsNullOrWhiteSpace(featureName))
 129        {
 0130            return false;
 131        }
 132
 2133        if (!TryGetMinVersion(featureName, out var min) || !IsAtLeast(min))
 134        {
 2135            return false; // compile-time/TFM gate failed or unknown
 136        }
 137
 138        // Central runtime-sensitive feature dispatch (mirrors enum switch in Supports(KnownFeature))
 139        // Extend this map when adding new runtime-validated features.
 140        // For features with no runtime conditions, omission implies success.
 0141        var runtimeChecks = RuntimeFeatureChecks;
 0142        if (runtimeChecks.TryGetValue(featureName, out var checker))
 143        {
 0144            return checker();
 145        }
 0146        return true; // Known (by TFM table) & no runtime check required
 147    }
 148
 149    // Provides a single place to register runtime-sensitive checks by feature name.
 150    // Note: Uses StringComparer.OrdinalIgnoreCase to keep behavior consistent with FeatureMinByName.
 1151    private static readonly Dictionary<string, Func<bool>> RuntimeFeatureChecks =
 1152        new(StringComparer.OrdinalIgnoreCase)
 1153        {
 1154            [nameof(KnownFeature.Http3)] = CheckHttp3Runtime,
 1155        };
 156
 157    /// <summary>
 158    /// Returns the minimum TFM required for a feature, if known.
 159    /// </summary>
 160    /// <param name="featureName">Feature identifier (case-insensitive).</param>
 161    /// <param name="minVersion">
 162    /// When this method returns true, contains the minimum target framework version required for the feature.
 163    /// When it returns false, the value is set to <c>0.0</c> as a harmless placeholder.
 164    /// </param>
 165    /// <returns>True if the feature is known; otherwise false.</returns>
 166    public static bool TryGetMinVersion(string featureName, [NotNullWhen(true)] out Version minVersion)
 167    {
 5168        if (FeatureMinByName.TryGetValue(featureName, out var value))
 169        {
 4170            minVersion = value; // non-null by construction
 4171            return true;
 172        }
 173
 174        // Provide a non-null sentinel to satisfy non-nullable contract while indicating absence.
 1175        minVersion = new Version(0, 0);
 1176        return false;
 177    }
 178
 179    private static bool IsAtLeast(Version min)
 180    {
 2181        var built = GetBuiltTargetFrameworkVersion();
 2182        return built >= min;
 183    }
 184
 185    #region Runtime checks
 186    // ---------- Runtime-sensitive checks ----------
 187    /// <summary>
 188    /// Checks runtime support for HTTP/3 (QUIC) in addition to compile-time gating.
 189    /// </summary>
 190    private static bool CheckHttp3Runtime()
 191    {
 192        // Use cached reflection metadata to avoid repeated lookups on hot paths.
 0193        if (_quicListenerType == null)
 194        {
 0195            return false;
 196        }
 197
 0198        if (_quicIsSupportedProperty != null)
 199        {
 0200            var value = _quicIsSupportedProperty.GetValue(null);
 0201            if (value is bool supported && !supported)
 202            {
 0203                return false;
 204            }
 205        }
 206
 207        // Kestrel HTTP/3 enum field presence check
 0208        return _httpProtocolsType != null && _http3Field != null;
 209    }
 210    #endregion
 211
 212    // Cached reflection metadata for runtime checks (initialized once).
 1213    private static readonly Type? _quicListenerType = Type.GetType("System.Net.Quic.QuicListener, System.Net.Quic");
 1214    private static readonly PropertyInfo? _quicIsSupportedProperty = _quicListenerType?.GetProperty("IsSupported", Bindi
 1215    private static readonly Type? _httpProtocolsType = Type.GetType("Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtoc
 1216    private static readonly FieldInfo? _http3Field = _httpProtocolsType?.GetField("Http3", BindingFlags.Public | Binding
 217
 218    /// <summary>
 219    /// Returns the full target framework name this assembly was built against,
 220    /// e.g., ".NETCoreApp,Version=v9.0".
 221    /// </summary>
 222    public static string GetBuiltTargetFrameworkName()
 223    {
 1224        var tfm = typeof(KestrunRuntimeInfo).Assembly
 1225            .GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName;
 1226        return tfm ?? "Unknown";
 227    }
 228}