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

CollectionOrderedConstraint

CollectionOrderedConstraint is used to test whether a collection is ordered.
using NUnit.Framework.Internal; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; namespace NUnit.Framework.Constraints { [NullableContext(1)] [Nullable(0)] public class CollectionOrderedConstraint : CollectionConstraint { [NullableContext(0)] private enum OrderDirection { Unspecified, Ascending, Descending } [NullableContext(2)] [Nullable(0)] private sealed class OrderingStep { public string PropertyName { get; set; } public OrderDirection Direction { get; set; } [Nullable(1)] [field: Nullable(1)] public ComparisonAdapter Comparer { [NullableContext(1)] get; [NullableContext(1)] set; } public string ComparerName { get; set; } public OrderingStep(string propertyName) { PropertyName = propertyName; Comparer = ComparisonAdapter.Default; } } [Nullable(0)] private sealed class CollectionOrderedConstraintResult : ConstraintResult { private readonly int _breakingIndex; [Nullable(2)] private readonly object _breakingValue; public CollectionOrderedConstraintResult(IConstraint constraint, IEnumerable actualValue) : base(constraint, actualValue, ConstraintStatus.Success) { } public CollectionOrderedConstraintResult(IConstraint constraint, IEnumerable actualValue, int breakingIndex, [Nullable(2)] object breakingValue) : base(constraint, actualValue, ConstraintStatus.Failure) { _breakingIndex = breakingIndex; _breakingValue = breakingValue; } public override void WriteActualValueTo(MessageWriter writer) { int num = Math.Max(0, _breakingIndex - 10 + 2); IEnumerable enumerable = (IEnumerable)base.ActualValue; string value = (enumerable == null) ? "null" : MsgUtils.FormatCollection(enumerable, num, 10); writer.Write(value); } public override void WriteAdditionalLinesTo(MessageWriter writer) { if (base.Status == ConstraintStatus.Failure) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(32, 1); defaultInterpolatedStringHandler.AppendLiteral(" Ordering breaks at index ["); defaultInterpolatedStringHandler.AppendFormatted(_breakingIndex); defaultInterpolatedStringHandler.AppendLiteral("]: "); string value = defaultInterpolatedStringHandler.ToStringAndClear() + MsgUtils.FormatValue(_breakingValue); writer.WriteLine(value); } } } private readonly List<OrderingStep> _steps = new List<OrderingStep>(); private OrderingStep _activeStep; private int _breakingIndex; [Nullable(2)] private object _breakingValue; public override string DisplayName => "Ordered"; public CollectionOrderedConstraint Ascending { get { if (_activeStep.Direction != 0) throw new InvalidOperationException("Only one directional modifier may be used"); _activeStep.Direction = OrderDirection.Ascending; return this; } } public CollectionOrderedConstraint Descending { get { if (_activeStep.Direction != 0) throw new InvalidOperationException("Only one directional modifier may be used"); _activeStep.Direction = OrderDirection.Descending; return this; } } public CollectionOrderedConstraint Then { get { CreateNextStep(null); return this; } } public override string Description { get { string text = "collection ordered"; int num = 0; foreach (OrderingStep step in _steps) { if (num++ != 0) text += " then"; if (step.PropertyName != null) text = text + " by " + MsgUtils.FormatValue(step.PropertyName); if (step.Direction == OrderDirection.Descending) text += ", descending"; } return text; } } public CollectionOrderedConstraint() { CreateNextStep(null); } public CollectionOrderedConstraint Using(IComparer comparer) { if (_activeStep.ComparerName != null) throw new InvalidOperationException("Only one Using modifier may be used"); _activeStep.Comparer = ComparisonAdapter.For(comparer); _activeStep.ComparerName = comparer.GetType().FullName; return this; } public CollectionOrderedConstraint Using<[Nullable(2)] T>(IComparer<T> comparer) { if (_activeStep.ComparerName != null) throw new InvalidOperationException("Only one Using modifier may be used"); _activeStep.Comparer = ComparisonAdapter.For(comparer); _activeStep.ComparerName = comparer.GetType().FullName; return this; } public CollectionOrderedConstraint Using<[Nullable(2)] T>(Comparison<T> comparer) { if (_activeStep.ComparerName != null) throw new InvalidOperationException("Only one Using modifier may be used"); _activeStep.Comparer = ComparisonAdapter.For(comparer); _activeStep.ComparerName = comparer.GetType().FullName; return this; } public CollectionOrderedConstraint By(string propertyName) { if (_activeStep.PropertyName == null) _activeStep.PropertyName = propertyName; else CreateNextStep(propertyName); return this; } public override ConstraintResult ApplyTo<[Nullable(2)] TActual>(TActual actual) { IEnumerable enumerable = ConstraintUtils.RequireActual<IEnumerable>(actual, "actual", false); if (!Matches(enumerable)) return new CollectionOrderedConstraintResult(this, enumerable, _breakingIndex, _breakingValue); return new CollectionOrderedConstraintResult(this, enumerable); } protected override bool Matches(IEnumerable actual) { object obj = null; _breakingIndex = 0; foreach (object item in actual) { object obj2 = _breakingValue = item; if (obj != null) { if (_steps[0].PropertyName != null) { if (obj2 == null) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(20, 1); defaultInterpolatedStringHandler.AppendLiteral("Null value at index "); defaultInterpolatedStringHandler.AppendFormatted(_breakingIndex); throw new ArgumentNullException("actual", defaultInterpolatedStringHandler.ToStringAndClear()); } foreach (OrderingStep step in _steps) { string propertyName = step.PropertyName; object expected = ExtractValue(actual, obj, propertyName, _breakingIndex - 1); object actual2 = ExtractValue(actual, obj2, propertyName, _breakingIndex); int num = step.Comparer.Compare(expected, actual2); if (num < 0) { if (step.Direction != OrderDirection.Descending) break; return false; } if (num > 0) { if (step.Direction == OrderDirection.Descending) break; return false; } } } else { int num2 = _activeStep.Comparer.Compare(obj, obj2); if (_activeStep.Direction == OrderDirection.Descending && num2 < 0) return false; if (_activeStep.Direction != OrderDirection.Descending && num2 > 0) return false; } } obj = obj2; _breakingIndex++; } _breakingValue = null; return true; } protected override string GetStringRepresentation() { StringBuilder stringBuilder = new StringBuilder("<ordered"); if (_steps.Count > 0) { OrderingStep orderingStep = _steps[0]; if (orderingStep.PropertyName != null) stringBuilder.Append("by " + orderingStep.PropertyName); if (orderingStep.Direction == OrderDirection.Descending) stringBuilder.Append(" descending"); if (orderingStep.ComparerName != null) stringBuilder.Append(" " + orderingStep.ComparerName); } stringBuilder.Append(">"); return stringBuilder.ToString(); } [NullableContext(2)] [MemberNotNull("_activeStep")] private void CreateNextStep(string propertyName) { _activeStep = new OrderingStep(propertyName); _steps.Add(_activeStep); } [return: Nullable(2)] private object ExtractValue(IEnumerable actual, object item, string propertyName, int index) { PropertyInfo property = item.GetType().GetProperty(propertyName); if ((object)property != null) return property.GetValue(item, null); FieldInfo field = item.GetType().GetField(propertyName); if ((object)field != null) return field.GetValue(item); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(51, 2); defaultInterpolatedStringHandler.AppendLiteral("No property or field with name "); defaultInterpolatedStringHandler.AppendFormatted(propertyName); defaultInterpolatedStringHandler.AppendLiteral(" was found at index "); defaultInterpolatedStringHandler.AppendFormatted(index); throw new ArgumentException(defaultInterpolatedStringHandler.ToStringAndClear(), "actual"); } } }