File: XUnit\InvalidEnumDataAttribute.cs
Web Access
Project: src\src\Common\tests\TestUtilities\System.Private.Windows.Core.TestUtilities.csproj (System.Private.Windows.Core.TestUtilities)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Reflection;
using System.Runtime.CompilerServices;
 
namespace Xunit;
 
/// <summary>
///  Generates <see cref="TheoryAttribute"/> data for an invalid enum value.
/// </summary>
public class InvalidEnumDataAttribute<TEnum> : CommonMemberDataAttribute where TEnum : unmanaged, Enum
{
    public InvalidEnumDataAttribute() : base(typeof(InvalidEnumDataAttribute<TEnum>)) { }
 
    public static ReadOnlyTheoryData TheoryData { get; } = InitializeData();
 
    private static unsafe ReadOnlyTheoryData InitializeData()
    {
        ulong maxValue = ulong.MaxValue >>> ((sizeof(ulong) - sizeof(TEnum)) * 8);
        TEnum currentValue = default;
        bool defined;
 
        List<TEnum> data = [];
 
        if (typeof(TEnum).GetCustomAttribute<FlagsAttribute>() is not null)
        {
            // Bit flags, pull the first flag from the top.
            ulong currentFlagValue = 1ul << (sizeof(TEnum) * 8) - 1;
            do
            {
                currentValue = Unsafe.As<ulong, TEnum>(ref currentFlagValue);
                defined = Enum.IsDefined(currentValue);
                currentFlagValue >>>= 1;
            }
            while (defined && currentFlagValue > 0);
 
            if (defined)
            {
                throw new InvalidOperationException("Enum has all flags defined");
            }
 
            data.Add(currentValue);
            return new(data);
        }
 
        // Not a flags enum, add the smallest and largest undefined value.
        ulong minValue = 0;
 
        do
        {
            currentValue = Unsafe.As<ulong, TEnum>(ref minValue);
            defined = Enum.IsDefined(currentValue);
            minValue++;
        }
        while (defined);
 
        data.Add(currentValue);
 
        do
        {
            currentValue = Unsafe.As<ulong, TEnum>(ref maxValue);
            defined = Enum.IsDefined(currentValue);
            maxValue--;
        }
        while (defined);
 
        data.Add(currentValue);
        return new(data);
    }
}