Skip to content

Commit

Permalink
Assuming types that override Equals to have value semantics (#740)
Browse files Browse the repository at this point in the history
Replaced all mechanisms and options to control whether or not an object has value semantics by a single algorithm. Any object that overrides object.Equals and is not an anonymous type or tuple is treated as a value type, unless ComparingByMembers<T>() is used. Also removes the global AssertionOptions.IsValueType
  • Loading branch information
dennisdoomen committed Jan 27, 2018
1 parent 27321e5 commit 530de04
Show file tree
Hide file tree
Showing 19 changed files with 583 additions and 374 deletions.
7 changes: 6 additions & 1 deletion Src/FluentAssertions.nuspec
Expand Up @@ -29,15 +29,20 @@
<frameworkAssembly assemblyName="System.Xml.Linq" targetFramework="net45" />
</frameworkAssemblies>
<dependencies>
<group targetFramework="net45">
<dependency id="System.ValueType" version="4.3.0" />
</group>
<group targetFramework="netstandard1.4">
<dependency id="NETStandard.Library" version="1.6.1" />
<dependency id="System.Reflection.TypeExtensions" version="4.3.0" />
<dependency id="System.Reflection.Emit.Lightweight" version="4.3.0" />
<dependency id="System.ValueType" version="4.3.0" />
</group>
<group targetFramework="netstandard1.6">
<dependency id="NETStandard.Library" version="1.6.1" />
<dependency id="System.Reflection.TypeExtensions" version="4.3.0" />
<dependency id="System.Reflection.Emit.Lightweight" version="4.3.0" />
<dependency id="System.ValueType" version="4.3.0" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="System.Configuration.ConfigurationManager" version="4.4.0" />
Expand All @@ -47,7 +52,7 @@
</dependencies>
</metadata>
<files>
<file src="..\Artifacts\Release\net45\*.*" target="lib\net45" />
<file src="..\Artifacts\Release\net45\*.*" target="lib\net45" exclude="**\System.*" />
<file src="..\Artifacts\Release\netstandard1.4\FluentAssertions.*" exclude="**\*.json" target="lib\netstandard1.4" />
<file src="..\Artifacts\Release\netstandard1.6\FluentAssertions*.*" exclude="**\*.json" target="lib\netstandard1.6" />
<file src="..\Artifacts\Release\netstandard2.0\FluentAssertions*.*" exclude="**\*.json" target="lib\netstandard2.0" />
Expand Down
14 changes: 1 addition & 13 deletions Src/FluentAssertions/AssertionOptions.cs
Expand Up @@ -25,18 +25,6 @@ public static EquivalencyAssertionOptions<T> CloneDefaults<T>()
return new EquivalencyAssertionOptions<T>(defaults);
}

/// <summary>
/// Defines a predicate with which the <see cref="EquivalencyValidator"/> determines if it should process
/// an object's properties or not.
/// </summary>
/// <returns>
/// Returns <c>true</c> if the object should be treated as a value type and its <see cref="object.Equals(object)"/>
/// must be used during a structural equivalency check.
/// </returns>
public static Func<Type, bool> IsValueType { get; set; } = type =>
(type.Namespace == typeof(int).Namespace) &&
!type.IsSameOrInherits(typeof(Exception));

/// <summary>
/// Allows configuring the defaults used during a structural equivalency assertion.
/// </summary>
Expand All @@ -50,7 +38,7 @@ public static EquivalencyAssertionOptions<T> CloneDefaults<T>()
}

/// <summary>
/// Represents a mutable collection of steps that are executed while asserting a (collection of) object(s)
/// Represents a mutable collection of steps that are executed while asserting a (collection of) object(s)
/// is structurally equivalent to another (collection of) object(s).
/// </summary>
public static EquivalencyStepCollection EquivalencySteps { get; private set; }
Expand Down
177 changes: 97 additions & 80 deletions Src/FluentAssertions/Common/TypeExtensions.cs

Large diffs are not rendered by default.

Expand Up @@ -82,9 +82,9 @@ public bool IncludeFields
get { return inner.IncludeFields; }
}

public bool IsValueType(Type type)
public EqualityStrategy GetEqualityStrategy(Type type)
{
return inner.IsValueType(type);
return inner.GetEqualityStrategy(type);
}

public ITraceWriter TraceWriter => inner.TraceWriter;
Expand Down
7 changes: 4 additions & 3 deletions Src/FluentAssertions/Equivalency/CyclicReferenceDetector.cs
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;

using FluentAssertions.Execution;
Expand All @@ -23,7 +24,7 @@ public CyclicReferenceDetector(CyclicReferenceHandling handling)
}

/// <summary>
/// Determines whether the specified object reference is a cyclic reference to the same object earlier in the
/// Determines whether the specified object reference is a cyclic reference to the same object earlier in the
/// equivalency validation.
/// </summary>
/// <remarks>
Expand Down Expand Up @@ -57,7 +58,7 @@ public bool IsCyclicReference(ObjectReference reference)
/// <summary>
/// Creates a new object that is a copy of the current instance.
/// </summary>
///
///
/// <returns>
/// A new object that is a copy of this instance.
/// </returns>
Expand All @@ -69,4 +70,4 @@ public object Clone()
};
}
}
}
}
27 changes: 25 additions & 2 deletions Src/FluentAssertions/Equivalency/IEquivalencyAssertionOptions.cs
Expand Up @@ -76,8 +76,31 @@ public interface IEquivalencyAssertionOptions
ITraceWriter TraceWriter { get; }

/// <summary>
/// Gets a value indicating whether the <paramref name="type"/> should be treated as having value semantics.
/// Determines the right strategy for evaluating the equality of objects of this type.
/// </summary>
bool IsValueType(Type type);
EqualityStrategy GetEqualityStrategy(Type type);
}

public enum EqualityStrategy
{
/// <summary>
/// The object overrides <see cref="object.Equals"/>, so use that.
/// </summary>
Equals,

/// <summary>
/// The object does not seem to override <see cref="object.Equals"/>, so compare by members
/// </summary>
Members,

/// <summary>
/// Compare using <see cref="object.Equals(object)"/>, whether or not the object overrides it.
/// </summary>
ForceEquals,

/// <summary>
/// Compare the members, regardless of an <see cref="object.Equals(object)"/> override exists or not.
/// </summary>
ForceMembers,
}
}
11 changes: 4 additions & 7 deletions Src/FluentAssertions/Equivalency/ObjectReference.cs
Expand Up @@ -43,7 +43,7 @@ private bool IsParentOf(ObjectReference other)
}

/// <summary>
/// Serves as a hash function for a particular type.
/// Serves as a hash function for a particular type.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
Expand All @@ -59,12 +59,9 @@ public override int GetHashCode()

public override string ToString()
{
return string.Format("{{\"{0}\", {1}}}", path, @object);
return $"{{\"{path}\", {@object}}}";
}

public bool IsComplexType
{
get { return !ReferenceEquals(@object, null) && @object.GetType().IsComplexType(); }
}
public bool IsComplexType => !ReferenceEquals(@object, null) && !@object.GetType().OverridesEquals();
}
}
}

0 comments on commit 530de04

Please sign in to comment.