Skip to content

update/cleanup #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 202 additions & 1 deletion OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using OnixLabs.Core.Linq;
using OnixLabs.Core.UnitTests.Data;
Expand Down Expand Up @@ -107,6 +106,62 @@ public void CountNotShouldProduceExpectedResult()
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.FirstOrNone should return none when the enumerable is empty.")]
public void FirstOrNoneShouldReturnNoneWhenEnumerableIsEmpty()
{
// Given
IEnumerable<int> elements = [];
Optional<int> expected = Optional<int>.None;

// When
Optional<int> actual = elements.FirstOrNone();

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.FirstOrNone should return the first element when the collection is not empty.")]
public void FirstOrNoneShouldReturnFirstElementWhenCollectionIsNotEmpty()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Optional<int> expected = 1;

// When
Optional<int> actual = elements.FirstOrNone();

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.FirstOrNone should return the first element matching the predicate when the collection is not empty.")]
public void FirstOrNoneShouldReturnFirstElementMatchingPredicateWhenCollectionIsNotEmpty()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Optional<int> expected = 2;

// When
Optional<int> actual = elements.FirstOrNone(number => number > 1);

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.FirstOrNone should return none when no element matches the predicate and the collection is not empty.")]
public void FirstOrNoneShouldReturnNoneWhenNoElementMatchesPredicateAndCollectionIsNotEmpty()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Optional<int> expected = Optional<int>.None;

// When
Optional<int> actual = elements.FirstOrNone(number => number > 3);

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.ForEach should iterate over every element in the enumerable")]
public void ForEachShouldProduceExpectedResult()
{
Expand Down Expand Up @@ -321,6 +376,62 @@ public void JoinToStringShouldProduceExpectedResultWithCustomSeparator()
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.LastOrNone should return none when the enumerable is empty.")]
public void LastOrNoneShouldReturnNoneWhenEnumerableIsEmpty()
{
// Given
IEnumerable<int> elements = [];
Optional<int> expected = Optional<int>.None;

// When
Optional<int> actual = elements.LastOrNone();

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.LastOrNone should return the last element when the collection is not empty.")]
public void LastOrNoneShouldReturnLastElementWhenCollectionIsNotEmpty()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Optional<int> expected = 3;

// When
Optional<int> actual = elements.LastOrNone();

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.LastOrNone should return the last element matching the predicate when the collection is not empty.")]
public void LastOrNoneShouldReturnFirstElementMatchingPredicateWhenCollectionIsNotEmpty()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Optional<int> expected = 3;

// When
Optional<int> actual = elements.LastOrNone(number => number > 1);

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.LastOrNone should return none when no element matches the predicate and the collection is not empty.")]
public void LastOrNoneShouldReturnNoneWhenNoElementMatchesPredicateAndCollectionIsNotEmpty()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Optional<int> expected = Optional<int>.None;

// When
Optional<int> actual = elements.LastOrNone(number => number > 3);

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.None should return true when none of the elements satisfy the specified predicate condition")]
public void NoneShouldProduceExpectedResultTrue()
{
Expand Down Expand Up @@ -369,6 +480,96 @@ public void NoneShouldProduceExpectedResultFalseAll()
Assert.False(result);
}

[Fact(DisplayName = "IEnumerable.SingleOrNone should return success none when the enumerable contains no elements.")]
public void SingleOrNoneShouldReturnSuccessNoneWhenEnumerableContainsNoElements()
{
// Given
IEnumerable<int> elements = [];
Result<Optional<int>> expected = Optional<int>.None.ToResult();

// When
Result<Optional<int>> actual = elements.SingleOrNone();

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.SingleOrNone should return success some when the enumerable contains a single element.")]
public void SingleOrNoneShouldReturnSuccessSomeWhenEnumerableContainsSingleElement()
{
// Given
IEnumerable<int> elements = [1];
Result<Optional<int>> expected = Optional<int>.Some(1).ToResult();

// When
Result<Optional<int>> actual = elements.SingleOrNone();

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.SingleOrNone should return failure when the enumerable contains more than one element.")]
public void SingleOrNoneShouldReturnFailureSomeWhenEnumerableContainsMoreThanOneElement()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Failure<Optional<int>> expected = Result<Optional<int>>.Failure(new InvalidOperationException("Sequence contains more than one matching element"));

// When
Result<Optional<int>> actual = elements.SingleOrNone();
Exception actualException = Assert.Throws<InvalidOperationException>(actual.Throw);

// Then
Assert.True(actual is Failure<Optional<int>>);
Assert.Equal(expected.Exception.GetType(), actualException.GetType());
Assert.Equal(expected.Exception.Message, actualException.Message);
}

[Fact(DisplayName = "IEnumerable.SingleOrNone should return success none when the enumerable contains no elements matching the predicate.")]
public void SingleOrNoneShouldReturnSuccessNoneWhenEnumerableContainsNoElementsMatchingPredicate()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Result<Optional<int>> expected = Optional<int>.None.ToResult();

// When
Result<Optional<int>> actual = elements.SingleOrNone(number => number > 3);

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.SingleOrNone should return success some when the enumerable contains a single element matching the predicate.")]
public void SingleOrNoneShouldReturnSuccessSomeWhenEnumerableContainsSingleElementMatchingPredicate()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Result<Optional<int>> expected = Optional<int>.Some(1).ToResult();

// When
Result<Optional<int>> actual = elements.SingleOrNone(number => number < 2);

// Then
Assert.Equal(expected, actual);
}

[Fact(DisplayName = "IEnumerable.SingleOrNone should return failure when the enumerable contains more than one element matching the predicate.")]
public void SingleOrNoneShouldReturnFailureSomeWhenEnumerableContainsMoreThanOneElementMatchingPredidate()
{
// Given
IEnumerable<int> elements = [1, 2, 3];
Failure<Optional<int>> expected = Result<Optional<int>>.Failure(new InvalidOperationException("Sequence contains more than one matching element"));

// When
Result<Optional<int>> actual = elements.SingleOrNone(number => number > 1);
Exception actualException = Assert.Throws<InvalidOperationException>(actual.Throw);

// Then
Assert.True(actual is Failure<Optional<int>>);
Assert.Equal(expected.Exception.GetType(), actualException.GetType());
Assert.Equal(expected.Exception.Message, actualException.Message);
}

[Fact(DisplayName = "IEnumerable.Sum should produce the expected result")]
public void SumShouldProduceExpectedResult()
{
Expand Down
10 changes: 2 additions & 8 deletions OnixLabs.Core/Enumeration.Comparable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ public abstract partial class Enumeration<T>
/// </summary>
/// <param name="other">An object to compare with the current instance.</param>
/// <returns>Returns a value that indicates the relative order of the objects being compared.</returns>
public int CompareTo(T? other)
{
return Value.CompareTo(other?.Value);
}
public int CompareTo(T? other) => Value.CompareTo(other?.Value);

/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates
Expand All @@ -35,8 +32,5 @@ public int CompareTo(T? other)
/// </summary>
/// <param name="obj">An object to compare with the current instance.</param>
/// <returns>Returns a value that indicates the relative order of the objects being compared.</returns>
public int CompareTo(object? obj)
{
return this.CompareToObject(obj);
}
public int CompareTo(object? obj) => this.CompareToObject(obj);
}
20 changes: 4 additions & 16 deletions OnixLabs.Core/Enumeration.Equatable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,39 +37,27 @@ public bool Equals(T? other)
/// </summary>
/// <param name="obj">The object to check for equality.</param>
/// <returns>Returns <see langword="true"/> if the object is equal to the current instance; otherwise, <see langword="false"/>.</returns>
public override bool Equals(object? obj)
{
return Equals(obj as T);
}
public override bool Equals(object? obj) => Equals(obj as T);

/// <summary>
/// Serves as a hash code function for the current instance.
/// </summary>
/// <returns>Returns a hash code for the current instance.</returns>
public override int GetHashCode()
{
return HashCode.Combine(GetType(), Name, Value);
}
public override int GetHashCode() => HashCode.Combine(GetType(), Name, Value);

/// <summary>
/// Performs an equality comparison between two object instances.
/// </summary>
/// <param name="left">The left-hand instance to compare.</param>
/// <param name="right">The right-hand instance to compare.</param>
/// <returns>Returns <see langword="true"/> if the left-hand instance is equal to the right-hand instance; otherwise, <see langword="false"/>.</returns>
public static bool operator ==(Enumeration<T> left, Enumeration<T> right)
{
return Equals(left, right);
}
public static bool operator ==(Enumeration<T> left, Enumeration<T> right) => Equals(left, right);

/// <summary>
/// Performs an inequality comparison between two object instances.
/// </summary>
/// <param name="left">The left-hand instance to compare.</param>
/// <param name="right">The right-hand instance to compare.</param>
/// <returns>Returns <see langword="true"/> if the left-hand instance is not equal to the right-hand instance; otherwise, <see langword="false"/>.</returns>
public static bool operator !=(Enumeration<T> left, Enumeration<T> right)
{
return !Equals(left, right);
}
public static bool operator !=(Enumeration<T> left, Enumeration<T> right) => !Equals(left, right);
}
15 changes: 3 additions & 12 deletions OnixLabs.Core/Enumeration.Get.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,17 @@ public static IReadOnlySet<T> GetAll()
/// Gets all of the enumeration entries for the current type.
/// </summary>
/// <returns>Returns all of the enumeration entries for the current type.</returns>
public static IReadOnlySet<(int Value, string Name)> GetEntries()
{
return GetAll().Select(entry => entry.ToEntry()).ToFrozenSet();
}
public static IReadOnlySet<(int Value, string Name)> GetEntries() => GetAll().Select(entry => entry.ToEntry()).ToFrozenSet();

/// <summary>
/// Gets all of the enumeration names for the current type.
/// </summary>
/// <returns>Returns all of the enumeration names for the current type.</returns>
public static IReadOnlySet<string> GetNames()
{
return GetAll().Select(entry => entry.Name).ToFrozenSet();
}
public static IReadOnlySet<string> GetNames() => GetAll().Select(entry => entry.Name).ToFrozenSet();

/// <summary>
/// Gets all of the enumeration values for the current type.
/// </summary>
/// <returns>Returns all of the enumeration values for the current type.</returns>
public static IReadOnlySet<int> GetValues()
{
return GetAll().Select(entry => entry.Value).ToFrozenSet();
}
public static IReadOnlySet<int> GetValues() => GetAll().Select(entry => entry.Value).ToFrozenSet();
}
10 changes: 2 additions & 8 deletions OnixLabs.Core/Enumeration.To.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,11 @@ public abstract partial class Enumeration<T>
/// Returns a <see cref="ValueTuple{T1,T2}"/> that represents the current object.
/// </summary>
/// <returns>Returns a tuple that represents the current object.</returns>
public (int Value, string Name) ToEntry()
{
return (Value, Name);
}
public (int Value, string Name) ToEntry() => (Value, Name);

/// <summary>
/// Returns a <see cref="String"/> that represents the current object.
/// </summary>
/// <returns>Returns a <see cref="String"/> that represents the current object.</returns>
public override string ToString()
{
return Name;
}
public override string ToString() => Name;
}
15 changes: 3 additions & 12 deletions OnixLabs.Core/Extensions.Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ public static class ArrayExtensions
/// <param name="array">The current <see cref="T:T[]"/> to copy.</param>
/// <typeparam name="T">The underlying type of the array.</typeparam>
/// <returns>Returns an exact copy of the current <see cref="T:T[]"/>.</returns>
public static T[] Copy<T>(this T[] array)
{
return [..array];
}
public static T[] Copy<T>(this T[] array) => [..array];

/// <summary>
/// Creates a copy of the current <see cref="T:T[]"/>.
Expand All @@ -41,10 +38,7 @@ public static T[] Copy<T>(this T[] array)
/// <param name="count">The number of elements of the array to copy.</param>
/// <typeparam name="T">The underlying type of the array.</typeparam>
/// <returns>Returns an exact copy of the current <see cref="T:T[]"/>.</returns>
public static T[] Copy<T>(this T[] array, int index, int count)
{
return [..array[index..(index + count)]];
}
public static T[] Copy<T>(this T[] array, int index, int count) => [..array[index..(index + count)]];

/// <summary>
/// Concatenates the current <see cref="T:T[]"/> with another <see cref="T:T[]"/>.
Expand All @@ -53,8 +47,5 @@ public static T[] Copy<T>(this T[] array, int index, int count)
/// <param name="other">The other <see cref="T:T[]"/> to concatenate with the source <see cref="T:T[]"/>.</param>
/// <typeparam name="T">The underlying type of the <see cref="T:T[]"/>.</typeparam>
/// <returns>Returns the current <see cref="T:T[]"/> concatenated with the other <see cref="T:T[]"/>.</returns>
public static T[] ConcatenateWith<T>(this T[] array, T[] other)
{
return [..array, ..other];
}
public static T[] ConcatenateWith<T>(this T[] array, T[] other) => [..array, ..other];
}
10 changes: 5 additions & 5 deletions OnixLabs.Core/Extensions.Object.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ public static class ObjectExtensions
/// <typeparam name="T">The underlying type of the current <see cref="IComparable{T}"/>.</typeparam>
/// <returns>Returns a signed integer that indicates the relative order of the objects being compared.</returns>
/// <exception cref="ArgumentException">If the specified object is not <see langword="null"/>, or of the specified type.</exception>
public static int CompareToObject<T>(this IComparable<T> comparable, object? obj)
public static int CompareToObject<T>(this IComparable<T> comparable, object? obj) => obj switch
{
if (obj is null) return 1;
if (obj is T other) return comparable.CompareTo(other);
throw new ArgumentException($"Object must be of type {typeof(T).Name}", nameof(obj));
}
null => 1,
T other => comparable.CompareTo(other),
_ => throw new ArgumentException($"Object must be of type {typeof(T).Name}", nameof(obj))
};

/// <summary>
/// Gets a record-like <see cref="String"/> representation of the current <see cref="Object"/> instance.
Expand Down
Loading
Loading