2023-08-26 17:11:29 +00:00
|
|
|
using NUnit.Framework;
|
2023-03-26 16:03:40 +00:00
|
|
|
using X10D.Linq;
|
|
|
|
|
|
|
|
namespace X10D.Tests.Linq;
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[TestFixture]
|
2023-08-22 16:32:47 +00:00
|
|
|
internal class EnumerableTests
|
2023-03-26 16:03:40 +00:00
|
|
|
{
|
2023-04-13 19:55:24 +00:00
|
|
|
[Test]
|
|
|
|
public void Except_ShouldFilterElements_GivenMatchingElements()
|
|
|
|
{
|
|
|
|
int[] source = Enumerable.Range(1, 10).ToArray();
|
|
|
|
int[] result = source.Except(5).ToArray();
|
|
|
|
|
|
|
|
Assert.That(result, Is.EquivalentTo(new[] {1, 2, 3, 4, 6, 7, 8, 9, 10}));
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Except_ShouldReturnSameElements_GivenNoMatchingElements()
|
|
|
|
{
|
|
|
|
int[] source = Enumerable.Range(1, 10).ToArray();
|
|
|
|
int[] result = source.Except(11).ToArray();
|
|
|
|
|
|
|
|
Assert.That(result, Is.EquivalentTo(source));
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Except_ShouldThrowArgumentNullException_GivenNullSource()
|
|
|
|
{
|
|
|
|
IEnumerable<int> source = null!;
|
|
|
|
Assert.Throws<ArgumentNullException>(() => source.Except(42));
|
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMax_ShouldReturnCorrectValues_UsingDefaultComparer()
|
|
|
|
{
|
|
|
|
IEnumerable<int> source = Enumerable.Range(1, 10);
|
|
|
|
(int minimum, int maximum) = source.MinMax();
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(1));
|
|
|
|
Assert.That(maximum, Is.EqualTo(10));
|
|
|
|
});
|
2023-03-28 15:28:38 +00:00
|
|
|
|
|
|
|
source = Enumerable.Range(1, 10).ToArray();
|
|
|
|
(minimum, maximum) = source.MinMax();
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(1));
|
|
|
|
Assert.That(maximum, Is.EqualTo(10));
|
|
|
|
});
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMax_ShouldReturnCorrectSelectedValues_UsingDefaultComparer()
|
|
|
|
{
|
|
|
|
IEnumerable<Person> source = Enumerable.Range(1, 10).Select(i => new Person {Age = i});
|
|
|
|
(int minimum, int maximum) = source.MinMax(p => p.Age);
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(1));
|
|
|
|
Assert.That(maximum, Is.EqualTo(10));
|
|
|
|
});
|
2023-03-28 15:28:38 +00:00
|
|
|
|
|
|
|
source = Enumerable.Range(1, 10).Select(i => new Person {Age = i}).ToArray();
|
|
|
|
(minimum, maximum) = source.MinMax(p => p.Age);
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(1));
|
|
|
|
Assert.That(maximum, Is.EqualTo(10));
|
|
|
|
});
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMax_ShouldReturnOppositeSelectedValues_UsingInverseComparer()
|
|
|
|
{
|
|
|
|
IEnumerable<Person> source = Enumerable.Range(1, 10).Select(i => new Person {Age = i});
|
|
|
|
(int minimum, int maximum) = source.MinMax(p => p.Age, new InverseComparer<int>());
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(10));
|
|
|
|
Assert.That(maximum, Is.EqualTo(1));
|
|
|
|
});
|
2023-03-28 15:28:38 +00:00
|
|
|
|
|
|
|
source = Enumerable.Range(1, 10).Select(i => new Person {Age = i}).ToArray();
|
|
|
|
(minimum, maximum) = source.MinMax(p => p.Age, new InverseComparer<int>());
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(10));
|
|
|
|
Assert.That(maximum, Is.EqualTo(1));
|
|
|
|
});
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMax_ShouldReturnOppositeValues_UsingInverseComparer()
|
|
|
|
{
|
2023-03-28 15:28:38 +00:00
|
|
|
(int minimum, int maximum) = Enumerable.Range(1, 10).MinMax(new InverseComparer<int>());
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(10));
|
|
|
|
Assert.That(maximum, Is.EqualTo(1));
|
|
|
|
});
|
2023-03-28 15:28:38 +00:00
|
|
|
|
|
|
|
(minimum, maximum) = Enumerable.Range(1, 10).ToArray().MinMax(new InverseComparer<int>());
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum, Is.EqualTo(10));
|
|
|
|
Assert.That(maximum, Is.EqualTo(1));
|
|
|
|
});
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMax_ShouldThrowArgumentNullException_GivenNullSelector()
|
|
|
|
{
|
2023-04-02 03:16:33 +00:00
|
|
|
IEnumerable<int> source = Enumerable.Empty<int>();
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<ArgumentNullException>(() => source.MinMax((Func<int, int>)(null!)));
|
|
|
|
Assert.Throws<ArgumentNullException>(() => source.MinMax((Func<int, int>)(null!), null));
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMax_ShouldThrowArgumentNullException_GivenNullSource()
|
|
|
|
{
|
|
|
|
IEnumerable<int>? source = null;
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<ArgumentNullException>(() => source!.MinMax());
|
|
|
|
Assert.Throws<ArgumentNullException>(() => source!.MinMax(v => v));
|
|
|
|
Assert.Throws<ArgumentNullException>(() => source!.MinMax(null));
|
|
|
|
Assert.Throws<ArgumentNullException>(() => source!.MinMax(v => v, null));
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMax_ShouldThrowInvalidOperationException_GivenEmptySource()
|
|
|
|
{
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<InvalidOperationException>(() => Enumerable.Empty<int>().MinMax());
|
|
|
|
Assert.Throws<InvalidOperationException>(() => Array.Empty<int>().MinMax());
|
|
|
|
Assert.Throws<InvalidOperationException>(() => new List<int>().MinMax());
|
2023-03-28 15:28:38 +00:00
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<InvalidOperationException>(() => Enumerable.Empty<int>().MinMax(i => i * 2));
|
|
|
|
Assert.Throws<InvalidOperationException>(() => Array.Empty<int>().MinMax(i => i * 2));
|
|
|
|
Assert.Throws<InvalidOperationException>(() => new List<int>().MinMax(i => i * 2));
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMaxBy_ShouldReturnCorrectSelectedValues_UsingDefaultComparer()
|
|
|
|
{
|
|
|
|
IEnumerable<Person> source = Enumerable.Range(1, 10).Select(i => new Person {Age = i});
|
|
|
|
(Person minimum, Person maximum) = source.MinMaxBy(p => p.Age);
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum.Age, Is.EqualTo(1));
|
|
|
|
Assert.That(maximum.Age, Is.EqualTo(10));
|
|
|
|
});
|
2023-03-28 15:28:38 +00:00
|
|
|
|
|
|
|
source = Enumerable.Range(1, 10).Select(i => new Person {Age = i}).ToArray();
|
|
|
|
(minimum, maximum) = source.MinMaxBy(p => p.Age);
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum.Age, Is.EqualTo(1));
|
|
|
|
Assert.That(maximum.Age, Is.EqualTo(10));
|
|
|
|
});
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMaxBy_ShouldReturnOppositeSelectedValues_UsingInverseComparer()
|
|
|
|
{
|
|
|
|
IEnumerable<Person> source = Enumerable.Range(1, 10).Select(i => new Person {Age = i});
|
|
|
|
(Person minimum, Person maximum) = source.MinMaxBy(p => p.Age, new InverseComparer<int>());
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum.Age, Is.EqualTo(10));
|
|
|
|
Assert.That(maximum.Age, Is.EqualTo(1));
|
|
|
|
});
|
2023-03-28 15:28:38 +00:00
|
|
|
|
|
|
|
source = Enumerable.Range(1, 10).Select(i => new Person {Age = i}).ToArray();
|
|
|
|
(minimum, maximum) = source.MinMaxBy(p => p.Age, new InverseComparer<int>());
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
{
|
|
|
|
Assert.That(minimum.Age, Is.EqualTo(10));
|
|
|
|
Assert.That(maximum.Age, Is.EqualTo(1));
|
|
|
|
});
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMaxBy_ShouldThrowArgumentNullException_GivenNullSelector()
|
|
|
|
{
|
2023-04-02 03:16:33 +00:00
|
|
|
Person[] source = Enumerable.Range(1, 10).Select(i => new Person {Age = i}).ToArray();
|
2023-03-28 15:28:38 +00:00
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<ArgumentNullException>(() => source.MinMaxBy((Func<Person, int>)null!));
|
|
|
|
Assert.Throws<ArgumentNullException>(() => source.MinMaxBy((Func<Person, int>)null!, null));
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMaxBy_ShouldThrowArgumentNullException_GivenNullSource()
|
|
|
|
{
|
|
|
|
IEnumerable<Person>? source = null;
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<ArgumentNullException>(() => source!.MinMaxBy(p => p.Age));
|
|
|
|
Assert.Throws<ArgumentNullException>(() => source!.MinMaxBy(p => p.Age, null));
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
[Test]
|
2023-03-26 16:03:40 +00:00
|
|
|
public void MinMaxBy_ShouldThrowInvalidOperationException_GivenEmptySource()
|
|
|
|
{
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
2023-03-28 15:28:38 +00:00
|
|
|
{
|
|
|
|
IEnumerable<Person> source = Enumerable.Empty<Person>();
|
2023-04-05 21:26:31 +00:00
|
|
|
_ = source.MinMaxBy(p => p.Age);
|
2023-03-28 15:28:38 +00:00
|
|
|
});
|
|
|
|
|
2023-04-05 21:26:31 +00:00
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
2023-03-28 15:28:38 +00:00
|
|
|
{
|
|
|
|
Person[] source = Array.Empty<Person>();
|
2023-04-05 21:26:31 +00:00
|
|
|
_ = source.MinMaxBy(p => p.Age);
|
2023-03-28 15:28:38 +00:00
|
|
|
});
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private struct InverseComparer<T> : IComparer<T> where T : IComparable<T>
|
|
|
|
{
|
|
|
|
public int Compare(T? x, T? y)
|
|
|
|
{
|
|
|
|
if (x is null)
|
|
|
|
{
|
|
|
|
return y is null ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return y is null ? -1 : y.CompareTo(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private struct Person : IComparable<Person>, IComparable
|
|
|
|
{
|
|
|
|
public int Age { get; set; }
|
|
|
|
|
|
|
|
public static bool operator <(Person left, Person right)
|
|
|
|
{
|
|
|
|
return left.CompareTo(right) < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool operator >(Person left, Person right)
|
|
|
|
{
|
|
|
|
return left.CompareTo(right) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool operator <=(Person left, Person right)
|
|
|
|
{
|
|
|
|
return left.CompareTo(right) <= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool operator >=(Person left, Person right)
|
|
|
|
{
|
|
|
|
return left.CompareTo(right) >= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int CompareTo(Person other)
|
|
|
|
{
|
|
|
|
return Age.CompareTo(other.Age);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int CompareTo(object? obj)
|
|
|
|
{
|
|
|
|
if (ReferenceEquals(null, obj))
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj is Person other
|
|
|
|
? CompareTo(other)
|
2023-04-03 14:57:31 +00:00
|
|
|
: throw new ArgumentException(ExceptionMessages.ObjectIsNotAValidType);
|
2023-03-26 16:03:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|