< Summary

Information
Class: AsiBackbone.Core.Integrity.AuditIntegrityVerificationResult
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Integrity/AuditIntegrityVerificationResult.cs
Line coverage
90%
Covered lines: 68
Uncovered lines: 7
Coverable lines: 75
Total lines: 163
Line coverage: 90.6%
Branch coverage
83%
Covered branches: 20
Total branches: 24
Branch coverage: 83.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
.ctor(...)50%2295.65%
get_IsValid()100%11100%
get_Category()100%11100%
get_Status()100%210%
get_FailureCode()100%11100%
get_FailureMessage()100%210%
get_ChainId()100%11100%
get_Sequence()100%210%
get_RecordId()100%210%
get_SafeMetadata()100%11100%
Valid(...)100%11100%
Failed(...)85%2020100%
NormalizeOptional(...)100%22100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Integrity/AuditIntegrityVerificationResult.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Integrity;
 4
 5/// <summary>
 6/// Represents the outcome of provider-neutral audit integrity verification.
 7/// </summary>
 8public sealed class AuditIntegrityVerificationResult
 9{
 010    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 011        new ReadOnlyDictionary<string, string>(new Dictionary<string, string>(StringComparer.Ordinal));
 12
 1013    private AuditIntegrityVerificationResult(
 1014        bool isValid,
 1015        AuditIntegrityVerificationCategory category,
 1016        string status,
 1017        string? failureCode,
 1018        string? failureMessage,
 1019        string? chainId,
 1020        long? sequence,
 1021        string? recordId,
 1022        IReadOnlyDictionary<string, string> safeMetadata)
 23    {
 1024        ArgumentException.ThrowIfNullOrWhiteSpace(status);
 25
 1026        if (!Enum.IsDefined(category))
 27        {
 028            throw new ArgumentOutOfRangeException(nameof(category), category, "Verification category must be defined.");
 29        }
 30
 1031        IsValid = isValid;
 1032        Category = category;
 1033        Status = status.Trim();
 1034        FailureCode = NormalizeOptional(failureCode);
 1035        FailureMessage = NormalizeOptional(failureMessage);
 1036        ChainId = NormalizeOptional(chainId);
 1037        Sequence = sequence;
 1038        RecordId = NormalizeOptional(recordId);
 1039        SafeMetadata = safeMetadata;
 1040    }
 41
 42    /// <summary>
 43    /// Gets a value indicating whether the integrity chain verified successfully.
 44    /// </summary>
 1045    public bool IsValid { get; }
 46
 47    /// <summary>
 48    /// Gets the provider-neutral verification category.
 49    /// </summary>
 950    public AuditIntegrityVerificationCategory Category { get; }
 51
 52    /// <summary>
 53    /// Gets a provider-neutral status string.
 54    /// </summary>
 055    public string Status { get; }
 56
 57    /// <summary>
 58    /// Gets the failure code when verification did not succeed.
 59    /// </summary>
 860    public string? FailureCode { get; }
 61
 62    /// <summary>
 63    /// Gets the failure message when verification did not succeed.
 64    /// </summary>
 065    public string? FailureMessage { get; }
 66
 67    /// <summary>
 68    /// Gets the chain identifier associated with the result, when known.
 69    /// </summary>
 170    public string? ChainId { get; }
 71
 72    /// <summary>
 73    /// Gets the sequence associated with the result, when known.
 74    /// </summary>
 075    public long? Sequence { get; }
 76
 77    /// <summary>
 78    /// Gets the record identifier associated with the result, when known.
 79    /// </summary>
 080    public string? RecordId { get; }
 81
 82    /// <summary>
 83    /// Gets safe-to-log verification metadata.
 84    /// </summary>
 685    public IReadOnlyDictionary<string, string> SafeMetadata { get; }
 86
 87    /// <summary>
 88    /// Creates a valid verification result.
 89    /// </summary>
 90    public static AuditIntegrityVerificationResult Valid(string chainId, long linkCount, string tipHash)
 91    {
 292        Dictionary<string, string> metadata = new(StringComparer.Ordinal)
 293        {
 294            ["chain_id"] = chainId,
 295            ["link_count"] = linkCount.ToString(System.Globalization.CultureInfo.InvariantCulture),
 296            ["tip_hash"] = tipHash
 297        };
 98
 299        return new AuditIntegrityVerificationResult(
 2100            true,
 2101            AuditIntegrityVerificationCategory.Valid,
 2102            "Valid",
 2103            null,
 2104            null,
 2105            chainId,
 2106            linkCount,
 2107            null,
 2108            new ReadOnlyDictionary<string, string>(metadata));
 109    }
 110
 111    /// <summary>
 112    /// Creates a failed verification result.
 113    /// </summary>
 114    public static AuditIntegrityVerificationResult Failed(
 115        AuditIntegrityVerificationCategory category,
 116        string failureCode,
 117        string? failureMessage = null,
 118        AuditIntegrityLink? link = null,
 119        IReadOnlyDictionary<string, string>? metadata = null)
 120    {
 8121        ArgumentException.ThrowIfNullOrWhiteSpace(failureCode);
 122
 8123        Dictionary<string, string> safeMetadata = new(StringComparer.Ordinal)
 8124        {
 8125            ["category"] = category.ToString(),
 8126            ["failure_code"] = failureCode.Trim()
 8127        };
 128
 8129        if (link is not null)
 130        {
 7131            safeMetadata["chain_id"] = link.ChainId;
 7132            safeMetadata["record_id"] = link.RecordId;
 7133            safeMetadata["sequence"] = link.Sequence.ToString(System.Globalization.CultureInfo.InvariantCulture);
 134        }
 135
 8136        if (metadata is not null)
 137        {
 18138            foreach (KeyValuePair<string, string> item in metadata)
 139            {
 6140                if (!string.IsNullOrWhiteSpace(item.Key))
 141                {
 6142                    safeMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 143                }
 144            }
 145        }
 146
 8147        return new AuditIntegrityVerificationResult(
 8148            false,
 8149            category,
 8150            "Failed",
 8151            failureCode,
 8152            failureMessage,
 8153            link?.ChainId,
 8154            link?.Sequence,
 8155            link?.RecordId,
 8156            safeMetadata.Count == 0 ? EmptyMetadata : new ReadOnlyDictionary<string, string>(safeMetadata));
 157    }
 158
 159    private static string? NormalizeOptional(string? value)
 160    {
 40161        return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
 162    }
 163}