<PackageReference Include="NUnit" Version="4.2.1" />

RandomAttribute

Supplies a set of random values to a single parameter of a parameterized test.
using NUnit.Framework.Interfaces; using NUnit.Framework.Internal; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; namespace NUnit.Framework { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] public class RandomAttribute : NUnitAttribute, IParameterDataSource { [System.Runtime.CompilerServices.Nullable(0)] private abstract class RandomDataSource : IParameterDataSource { public Type DataType { get; set; } public bool Distinct { get; set; } protected RandomDataSource(Type dataType) { DataType = dataType; } public abstract IEnumerable GetData(IParameterInfo parameter); } [System.Runtime.CompilerServices.Nullable(0)] private abstract class RandomDataSource<[System.Runtime.CompilerServices.Nullable(2)] T> : RandomDataSource { [AllowNull] [MaybeNull] private readonly T _min; [AllowNull] [MaybeNull] private readonly T _max; private readonly int _count; private readonly bool _inRange; private readonly List<T> _previousValues = new List<T>(); protected RandomDataSource(int count) : base(typeof(T)) { _min = default(T); _max = default(T); _count = count; _inRange = false; } protected RandomDataSource(T min, T max, int count) : base(typeof(T)) { _min = min; _max = max; _count = count; _inRange = true; } public override IEnumerable GetData(IParameterInfo parameter) { Randomizer randomizer = Randomizer.GetRandomizer(parameter.ParameterInfo); bool condition = this.CanUseRange() || !this._inRange; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(49, 1); defaultInterpolatedStringHandler.AppendLiteral("The value type "); defaultInterpolatedStringHandler.AppendFormatted<Type>(parameter.ParameterType); defaultInterpolatedStringHandler.AppendLiteral(" does not support range of values."); Guard.OperationValid(condition, defaultInterpolatedStringHandler.ToStringAndClear()); bool condition2 = !base.Distinct || !this._inRange || this.CanBeDistinct(this._min, this._max, this._count); defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(92, 3); defaultInterpolatedStringHandler.AppendLiteral("The range of values is ["); defaultInterpolatedStringHandler.AppendFormatted<T>(this._min); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted<T>(this._max); defaultInterpolatedStringHandler.AppendLiteral("[ and the random value count is "); defaultInterpolatedStringHandler.AppendFormatted<int>(this._count); defaultInterpolatedStringHandler.AppendLiteral(" so the values cannot be distinct."); Guard.OperationValid(condition2, defaultInterpolatedStringHandler.ToStringAndClear()); for (int i = 0; i < this._count; i++) { if (base.Distinct) { T val; do { val = (this._inRange ? this.GetNext(randomizer, this._min, this._max) : this.GetNext(randomizer)); } while (this._previousValues.Contains(val)); this._previousValues.Add(val); yield return (object)val; } else yield return (object)(this._inRange ? this.GetNext(randomizer, this._min, this._max) : this.GetNext(randomizer)); } } protected virtual bool CanUseRange() { return true; } protected abstract T GetNext(Randomizer randomizer); protected abstract T GetNext(Randomizer randomizer, T min, T max); protected abstract bool CanBeDistinct(T min, T max, int count); } [System.Runtime.CompilerServices.Nullable(0)] private class RandomDataConverter : RandomDataSource { private readonly IParameterDataSource _source; public RandomDataConverter(RandomDataSource source) : base(source.DataType) { _source = source; } public override IEnumerable GetData(IParameterInfo parameter) { Type parmType = parameter.ParameterType; foreach (object datum in _source.GetData(parameter)) { if (datum is int) { int num = (int)datum; if (parmType == typeof(short)) yield return (object)(short)num; else if (parmType == typeof(ushort)) { yield return (object)(ushort)num; } else if (parmType == typeof(byte)) { yield return (object)(byte)num; } else if (parmType == typeof(sbyte)) { yield return (object)(sbyte)num; } else if (parmType == typeof(decimal)) { yield return (object)(decimal)num; } } else if (datum is double) { double value = (double)datum; if (parmType == typeof(decimal)) yield return (object)(decimal)value; } } } } [System.Runtime.CompilerServices.Nullable(0)] private class IntDataSource : RandomDataSource<int> { public IntDataSource(int count) : base(count) { } public IntDataSource(int min, int max, int count) : base(min, max, count) { } protected override int GetNext(Randomizer randomizer) { return randomizer.Next(); } protected override int GetNext(Randomizer randomizer, int min, int max) { return randomizer.Next(min, max); } protected override bool CanBeDistinct(int min, int max, int count) { if (min + count > min) return min + count <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class UIntDataSource : RandomDataSource<uint> { public UIntDataSource(int count) : base(count) { } public UIntDataSource(uint min, uint max, int count) : base(min, max, count) { } protected override uint GetNext(Randomizer randomizer) { return randomizer.NextUInt(); } protected override uint GetNext(Randomizer randomizer, uint min, uint max) { return randomizer.NextUInt(min, max); } protected override bool CanBeDistinct(uint min, uint max, int count) { if (min + count > min) return min + count <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class LongDataSource : RandomDataSource<long> { public LongDataSource(int count) : base(count) { } public LongDataSource(long min, long max, int count) : base(min, max, count) { } protected override long GetNext(Randomizer randomizer) { return randomizer.NextLong(); } protected override long GetNext(Randomizer randomizer, long min, long max) { return randomizer.NextLong(min, max); } protected override bool CanBeDistinct(long min, long max, int count) { if (min + count > min) return min + count <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class ULongDataSource : RandomDataSource<ulong> { public ULongDataSource(int count) : base(count) { } public ULongDataSource(ulong min, ulong max, int count) : base(min, max, count) { } protected override ulong GetNext(Randomizer randomizer) { return randomizer.NextULong(); } protected override ulong GetNext(Randomizer randomizer, ulong min, ulong max) { return randomizer.NextULong(min, max); } protected override bool CanBeDistinct(ulong min, ulong max, int count) { if (count >= 0 && (ulong)((long)min + (long)count) > min) return (ulong)((long)min + (long)count) <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class ShortDataSource : RandomDataSource<short> { public ShortDataSource(int count) : base(count) { } public ShortDataSource(short min, short max, int count) : base(min, max, count) { } protected override short GetNext(Randomizer randomizer) { return randomizer.NextShort(); } protected override short GetNext(Randomizer randomizer, short min, short max) { return randomizer.NextShort(min, max); } protected override bool CanBeDistinct(short min, short max, int count) { if (min + count > min) return min + count <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class UShortDataSource : RandomDataSource<ushort> { public UShortDataSource(int count) : base(count) { } public UShortDataSource(ushort min, ushort max, int count) : base(min, max, count) { } protected override ushort GetNext(Randomizer randomizer) { return randomizer.NextUShort(); } protected override ushort GetNext(Randomizer randomizer, ushort min, ushort max) { return randomizer.NextUShort(min, max); } protected override bool CanBeDistinct(ushort min, ushort max, int count) { if (min + count > min) return min + count <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class DoubleDataSource : RandomDataSource<double> { public DoubleDataSource(int count) : base(count) { } public DoubleDataSource(double min, double max, int count) : base(min, max, count) { } protected override double GetNext(Randomizer randomizer) { return randomizer.NextDouble(); } protected override double GetNext(Randomizer randomizer, double min, double max) { return randomizer.NextDouble(min, max); } protected override bool CanBeDistinct(double min, double max, int count) { return true; } } [System.Runtime.CompilerServices.Nullable(0)] private class FloatDataSource : RandomDataSource<float> { public FloatDataSource(int count) : base(count) { } public FloatDataSource(float min, float max, int count) : base(min, max, count) { } protected override float GetNext(Randomizer randomizer) { return randomizer.NextFloat(); } protected override float GetNext(Randomizer randomizer, float min, float max) { return randomizer.NextFloat(min, max); } protected override bool CanBeDistinct(float min, float max, int count) { return true; } } [System.Runtime.CompilerServices.Nullable(0)] private class ByteDataSource : RandomDataSource<byte> { public ByteDataSource(int count) : base(count) { } public ByteDataSource(byte min, byte max, int count) : base(min, max, count) { } protected override byte GetNext(Randomizer randomizer) { return randomizer.NextByte(); } protected override byte GetNext(Randomizer randomizer, byte min, byte max) { return randomizer.NextByte(min, max); } protected override bool CanBeDistinct(byte min, byte max, int count) { if (min + count > min) return min + count <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class SByteDataSource : RandomDataSource<sbyte> { public SByteDataSource(int count) : base(count) { } public SByteDataSource(sbyte min, sbyte max, int count) : base(min, max, count) { } protected override sbyte GetNext(Randomizer randomizer) { return randomizer.NextSByte(); } protected override sbyte GetNext(Randomizer randomizer, sbyte min, sbyte max) { return randomizer.NextSByte(min, max); } protected override bool CanBeDistinct(sbyte min, sbyte max, int count) { if (min + count > min) return min + count <= max; return false; } } [System.Runtime.CompilerServices.Nullable(0)] private class EnumDataSource : RandomDataSource { private readonly int _count; private readonly List<object> _previousValues = new List<object>(); public EnumDataSource(int count) : base(typeof(Enum)) { _count = count; } public override IEnumerable GetData(IParameterInfo parameter) { Guard.ArgumentValid(parameter.ParameterType.IsEnum, "EnumDataSource requires an enum parameter", "parameter"); Randomizer randomizer = Randomizer.GetRandomizer(parameter.ParameterInfo); base.DataType = parameter.ParameterType; int num = Enum.GetValues(base.DataType).Cast<int>().Distinct() .Count(); bool condition = !base.Distinct || _count <= num; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(88, 3); defaultInterpolatedStringHandler.AppendLiteral("The enum \""); defaultInterpolatedStringHandler.AppendFormatted(base.DataType.Name); defaultInterpolatedStringHandler.AppendLiteral("\" has "); defaultInterpolatedStringHandler.AppendFormatted(num); defaultInterpolatedStringHandler.AppendLiteral(" values and the random value count is "); defaultInterpolatedStringHandler.AppendFormatted(_count); defaultInterpolatedStringHandler.AppendLiteral(" so the values cannot be distinct."); Guard.OperationValid(condition, defaultInterpolatedStringHandler.ToStringAndClear()); for (int i = 0; i < _count; i++) { if (base.Distinct) { object obj; do { obj = randomizer.NextEnum(parameter.ParameterType); } while (_previousValues.Contains(obj)); _previousValues.Add(obj); yield return obj; } else yield return randomizer.NextEnum(parameter.ParameterType); } } } [System.Runtime.CompilerServices.Nullable(0)] private class DecimalDataSource : RandomDataSource<decimal> { public DecimalDataSource(int count) : base(count) { } protected override decimal GetNext(Randomizer randomizer) { return randomizer.NextDecimal(); } protected override decimal GetNext(Randomizer randomizer, decimal min, decimal max) { return randomizer.NextDecimal(min, max); } protected override bool CanBeDistinct(decimal min, decimal max, int count) { return true; } } [System.Runtime.CompilerServices.Nullable(0)] private class GuidDataSource : RandomDataSource<Guid> { public GuidDataSource(int count) : base(count) { } protected override Guid GetNext(Randomizer randomizer) { return randomizer.NextGuid(); } protected override Guid GetNext(Randomizer randomizer, Guid min, Guid max) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 1); defaultInterpolatedStringHandler.AppendFormatted(typeof(Guid)); defaultInterpolatedStringHandler.AppendLiteral(" does not support range of parameters being specified."); throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear()); } protected override bool CanBeDistinct(Guid min, Guid max, int count) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(54, 1); defaultInterpolatedStringHandler.AppendFormatted(typeof(Guid)); defaultInterpolatedStringHandler.AppendLiteral(" does not support range of parameters being specified."); throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear()); } protected override bool CanUseRange() { return false; } } [System.Runtime.CompilerServices.Nullable(2)] private RandomDataSource _source; private readonly int _count; public bool Distinct { get; set; } public RandomAttribute(int count) { _count = count; } public RandomAttribute(int min, int max, int count) { _source = new IntDataSource(min, max, count); } [CLSCompliant(false)] public RandomAttribute(uint min, uint max, int count) { _source = new UIntDataSource(min, max, count); } public RandomAttribute(long min, long max, int count) { _source = new LongDataSource(min, max, count); } [CLSCompliant(false)] public RandomAttribute(ulong min, ulong max, int count) { _source = new ULongDataSource(min, max, count); } public RandomAttribute(short min, short max, int count) { _source = new ShortDataSource(min, max, count); } [CLSCompliant(false)] public RandomAttribute(ushort min, ushort max, int count) { _source = new UShortDataSource(min, max, count); } public RandomAttribute(double min, double max, int count) { _source = new DoubleDataSource(min, max, count); } public RandomAttribute(float min, float max, int count) { _source = new FloatDataSource(min, max, count); } public RandomAttribute(byte min, byte max, int count) { _source = new ByteDataSource(min, max, count); } [CLSCompliant(false)] public RandomAttribute(sbyte min, sbyte max, int count) { _source = new SByteDataSource(min, max, count); } public IEnumerable GetData(IParameterInfo parameter) { Type parameterType = parameter.ParameterType; if (_source == null) { if (parameterType == typeof(int)) _source = new IntDataSource(_count); else if (parameterType == typeof(uint)) { _source = new UIntDataSource(_count); } else if (parameterType == typeof(long)) { _source = new LongDataSource(_count); } else if (parameterType == typeof(ulong)) { _source = new ULongDataSource(_count); } else if (parameterType == typeof(short)) { _source = new ShortDataSource(_count); } else if (parameterType == typeof(ushort)) { _source = new UShortDataSource(_count); } else if (parameterType == typeof(double)) { _source = new DoubleDataSource(_count); } else if (parameterType == typeof(float)) { _source = new FloatDataSource(_count); } else if (parameterType == typeof(byte)) { _source = new ByteDataSource(_count); } else if (parameterType == typeof(sbyte)) { _source = new SByteDataSource(_count); } else if (parameterType == typeof(decimal)) { _source = new DecimalDataSource(_count); } else if (parameterType == typeof(Guid)) { _source = new GuidDataSource(_count); } else if (parameterType.IsEnum) { _source = new EnumDataSource(_count); } else { _source = new IntDataSource(_count); } } else if (_source.DataType != parameterType && WeConvert(_source.DataType, parameterType)) { _source.Distinct = Distinct; _source = new RandomDataConverter(_source); } _source.Distinct = Distinct; return _source.GetData(parameter); } private bool WeConvert(Type sourceType, Type targetType) { if (targetType == typeof(short) || targetType == typeof(ushort) || targetType == typeof(byte) || targetType == typeof(sbyte)) return sourceType == typeof(int); if (targetType == typeof(decimal)) { if (!(sourceType == typeof(int))) return sourceType == typeof(double); return true; } return false; } } }