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);
}
}
}