Skip to content

Commit

Permalink
Consider null values during comparison operations
Browse files Browse the repository at this point in the history
Resolves #11
  • Loading branch information
cutig3r authored Jun 10, 2020
1 parent 218769f commit a77a339
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 7 deletions.
44 changes: 37 additions & 7 deletions EFCore.SqlServer.HierarchyId.Abstractions/HierarchyId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,12 @@ public override string ToString()
/// <param name="hid2">The second node to compare.</param>
/// <returns>True if <paramref name="hid1"/> and <paramref name="hid2"/> are equal; otherwise, false.</returns>
public static bool operator ==(HierarchyId hid1, HierarchyId hid2)
=> Unwrap(hid1).CompareTo(Unwrap(hid2)) == 0;
{
var sh1 = Unwrap(hid1);
var sh2 = Unwrap(hid2);

return sh1.IsNull == sh2.IsNull && sh1.CompareTo(sh2) == 0;
}

/// <summary>
/// Evaluates whether two nodes are unequal.
Expand All @@ -140,7 +145,12 @@ public override string ToString()
/// <param name="hid2">The second node to compare.</param>
/// <returns>True if <paramref name="hid1"/> and <paramref name="hid2"/> are unequal; otherwise, false.</returns>
public static bool operator !=(HierarchyId hid1, HierarchyId hid2)
=> Unwrap(hid1).CompareTo(Unwrap(hid2)) != 0;
{
var sh1 = Unwrap(hid1);
var sh2 = Unwrap(hid2);

return sh1.IsNull != sh2.IsNull || sh1.CompareTo(sh2) != 0;
}

/// <summary>
/// Evaluates whether one node is less than another.
Expand All @@ -149,7 +159,12 @@ public override string ToString()
/// <param name="hid2">The second node to compare.</param>
/// <returns>True if <paramref name="hid1"/> is less than <paramref name="hid2"/>; otherwise, false.</returns>
public static bool operator <(HierarchyId hid1, HierarchyId hid2)
=> Unwrap(hid1).CompareTo(Unwrap(hid2)) < 0;
{
var sh1 = Unwrap(hid1);
var sh2 = Unwrap(hid2);

return !sh1.IsNull && !sh2.IsNull && sh1.CompareTo(sh2) < 0;
}

/// <summary>
/// Evaluates whether one node is greater than another.
Expand All @@ -158,7 +173,12 @@ public override string ToString()
/// <param name="hid2">The second node to compare.</param>
/// <returns>True if <paramref name="hid1"/> is greather than <paramref name="hid2"/>; otherwise, false.</returns>
public static bool operator >(HierarchyId hid1, HierarchyId hid2)
=> Unwrap(hid1).CompareTo(Unwrap(hid2)) > 0;
{
var sh1 = Unwrap(hid1);
var sh2 = Unwrap(hid2);

return !sh1.IsNull && !sh2.IsNull && sh1.CompareTo(sh2) > 0;
}

/// <summary>
/// Evaluates whether one node is less than or equal to another.
Expand All @@ -167,7 +187,12 @@ public override string ToString()
/// <param name="hid2">The second node to compare.</param>
/// <returns>True if <paramref name="hid1"/> is less than or equal to <paramref name="hid2"/>; otherwise, false.</returns>
public static bool operator <=(HierarchyId hid1, HierarchyId hid2)
=> Unwrap(hid1).CompareTo(Unwrap(hid2)) <= 0;
{
var sh1 = Unwrap(hid1);
var sh2 = Unwrap(hid2);

return !sh1.IsNull && !sh2.IsNull && sh1.CompareTo(sh2) <= 0;
}

/// <summary>
/// Evaluates whether one node is greater than or equal to another.
Expand All @@ -176,12 +201,17 @@ public override string ToString()
/// <param name="hid2">The second node to compare.</param>
/// <returns>True if <paramref name="hid1"/> is greater than or equal to <paramref name="hid2"/>; otherwise, false.</returns>
public static bool operator >=(HierarchyId hid1, HierarchyId hid2)
=> Unwrap(hid1).CompareTo(Unwrap(hid2)) >= 0;
{
var sh1 = Unwrap(hid1);
var sh2 = Unwrap(hid2);

return !sh1.IsNull && !sh2.IsNull && sh1.CompareTo(sh2) >= 0;
}

private static SqlHierarchyId Unwrap(HierarchyId value)
=> value?._value ?? SqlHierarchyId.Null;

private static HierarchyId Wrap(SqlHierarchyId value)
=> value.IsNull ? null : new HierarchyId(value);
}
}
}
80 changes: 80 additions & 0 deletions EFCore.SqlServer.HierarchyId.Test/NullabilityTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System.Linq;
using Xunit;

namespace Microsoft.EntityFrameworkCore.SqlServer
{
public class NullabilityTests
{
[Fact]
public void Null_against_null()
{
Assert.True((HierarchyId)null == (HierarchyId)null);
Assert.False((HierarchyId)null != (HierarchyId)null);
Assert.False((HierarchyId)null > (HierarchyId)null);
Assert.False((HierarchyId)null >= (HierarchyId)null);
Assert.False((HierarchyId)null < (HierarchyId)null);
Assert.False((HierarchyId)null <= (HierarchyId)null);
}

[Fact]
public void Null_against_nonNull()
{
var hid = HierarchyId.GetRoot();
Assert.False(hid == (HierarchyId)null);
Assert.False((HierarchyId)null == hid);

Assert.True(hid != (HierarchyId)null);
Assert.True((HierarchyId)null != hid);

Assert.False(hid > (HierarchyId)null);
Assert.False((HierarchyId)null > hid);

Assert.False(hid >= (HierarchyId)null);
Assert.False((HierarchyId)null >= hid);

Assert.False(hid < (HierarchyId)null);
Assert.False((HierarchyId)null < hid);

Assert.False(hid <= (HierarchyId)null);
Assert.False((HierarchyId)null <= hid);
}

[Fact]
public void NullOnly_aggregates_equalTo_null()
{
var hid = (HierarchyId)null;
var collection = new[] { (HierarchyId)null, (HierarchyId)null, };
var min = collection.Min();
var max = collection.Max();

Assert.True(hid == min);
Assert.True(min == hid);
Assert.False(hid != min);
Assert.False(min != hid);

Assert.True(hid == max);
Assert.True(max == hid);
Assert.False(hid != max);
Assert.False(max != hid);
}

[Fact]
public void Aggregates_including_nulls_equalTo_nonNull()
{
var hid = HierarchyId.GetRoot();
var collection = new[] { (HierarchyId)null, (HierarchyId)null, HierarchyId.GetRoot(), HierarchyId.GetRoot(), };
var min = collection.Min();
var max = collection.Max();

Assert.True(hid == min);
Assert.True(min == hid);
Assert.False(hid != min);
Assert.False(min != hid);

Assert.True(hid == max);
Assert.True(max == hid);
Assert.False(hid != max);
Assert.False(max != hid);
}
}
}

0 comments on commit a77a339

Please sign in to comment.