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

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.Reflection; using System.Text; namespace NUnit.Framework.Constraints { public class CollectionOrderedConstraint : CollectionConstraint { private enum OrderDirection { Unspecified, Ascending, Descending } private sealed class OrderingStep { public string PropertyName { get; set; } public OrderDirection Direction { get; set; } public ComparisonAdapter Comparer { get; set; } public string ComparerName { get; set; } public OrderingStep(string propertyName) { PropertyName = propertyName; Comparer = ComparisonAdapter.Default; } } private sealed class CollectionOrderedConstraintResult : ConstraintResult { private const int MaxDisplayedItems = 10; private readonly int _breakingIndex; private readonly object _breakingValue; public CollectionOrderedConstraintResult(IConstraint constraint, IEnumerable actualValue) : base(constraint, actualValue, ConstraintStatus.Success) { } public CollectionOrderedConstraintResult(IConstraint constraint, IEnumerable actualValue, int breakingIndex, 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); string value = MsgUtils.FormatCollection((IEnumerable)base.ActualValue, num, 10); writer.Write(value); } public override void WriteAdditionalLinesTo(MessageWriter writer) { if (base.Status == ConstraintStatus.Failure) { string value = $"""{_breakingIndex}""" + MsgUtils.FormatValue(_breakingValue); writer.WriteLine(value); } } } private readonly List<OrderingStep> _steps = new List<OrderingStep>(); private OrderingStep _activeStep; private int _breakingIndex; 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<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<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<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) throw new ArgumentNullException("actual", "Null value at index " + _breakingIndex.ToString()); foreach (OrderingStep step in _steps) { string propertyName = step.PropertyName; PropertyInfo property = obj.GetType().GetProperty(propertyName); if (property == (PropertyInfo)null) throw new ArgumentException($"""{propertyName}""{_breakingIndex - 1}", "actual"); object value = property.GetValue(obj, null); PropertyInfo property2 = obj2.GetType().GetProperty(propertyName); if (property2 == (PropertyInfo)null) throw new ArgumentException($"""{propertyName}""{_breakingIndex}", "actual"); object value2 = property2.GetValue(obj2, null); int num = step.Comparer.Compare(value, value2); 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(); } private void CreateNextStep(string propertyName) { _activeStep = new OrderingStep(propertyName); _steps.Add(_activeStep); } } }