Skip to content

Commit

Permalink
SAVEPOINT
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisdoomen committed Dec 26, 2024
1 parent f94f597 commit 1e77b2d
Show file tree
Hide file tree
Showing 48 changed files with 629 additions and 941 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ dotnet_diagnostic.CA1307.severity = error
dotnet_diagnostic.CA1308.severity = error
# CA1309: Use ordinal StringComparison
dotnet_diagnostic.CA1309.severity = error

# Purpose: Rename virtual/interface member ITestFramework.Throw(string) so that it no longer conflicts with the reserved language keyword 'Throw'
# Reason: We don't care about other languages than C#
dotnet_diagnostic.CA1716.severity = none

# CA1724: Type names should not match namespaces
dotnet_diagnostic.CA1724.severity = none
# CA1819: Properties should not return arrays
Expand Down
2 changes: 1 addition & 1 deletion Src/FluentAssertions/AndWhichConstraint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private static TSubject Single(IEnumerable<TSubject> subjects)
string message = "More than one object found. FluentAssertions cannot determine which object is meant."
+ $" Found objects:{Environment.NewLine}{foundObjects}";

Services.ThrowException(message);
AssertionEngine.TestFramework.Throw(message);
}

return matchedElements.Single();
Expand Down
11 changes: 11 additions & 0 deletions Src/FluentAssertions/AssertionConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using FluentAssertions.Configuration;

namespace FluentAssertions;

/// <summary>
/// Provides access to the global configuration and options to customize the behavior of FluentAssertions.
/// </summary>
public static class AssertionConfiguration
{
public static GlobalConfiguration Current => AssertionEngine.Configuration;
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,29 @@
using System;
using System.Linq;
using System.Reflection;
using FluentAssertions.Configuration;
using FluentAssertions.Execution;
using FluentAssertions.Extensibility;
using JetBrains.Annotations;

namespace FluentAssertions.Common;
namespace FluentAssertions;

/// <summary>
/// Maintains the framework-specific services.
/// </summary>
public static class Services
public static class AssertionEngine
{
private static readonly object Lockable = new();
private static Configuration configuration;
private static bool isInitialized;
private static GlobalConfiguration configuration;

static Services()
static AssertionEngine()
{
EnsureInitialized();
}

public static IConfigurationStore ConfigurationStore { get; set; }

public static Configuration Configuration
{
get
{
lock (Lockable)
{
return configuration ??= new Configuration(ConfigurationStore);
}
}
}

public static Action<string> ThrowException { get; set; }

public static IReflector Reflector { get; set; }

[PublicAPI]
public static void ResetToDefaults()
{
isInitialized = false;
configuration = null;
EnsureInitialized();
}

Expand All @@ -58,19 +40,15 @@ internal static void EnsureInitialized()
{
ExecuteCustomInitializers();

Reflector = new FullFrameworkReflector();
#if NETFRAMEWORK || NET6_0_OR_GREATER
ConfigurationStore = new ConfigurationStoreExceptionInterceptor(new AppSettingsConfigurationStore());
#else
ConfigurationStore = new NullConfigurationStore();
#endif
ThrowException = new TestFrameworkProvider(Configuration).Throw;
TestFramework = TestFrameworkFactory.GetFramework(Configuration.TestFrameworkName);

isInitialized = true;
}
}
}

public static ITestFramework TestFramework { get; set; }

private static void ExecuteCustomInitializers()
{
var currentAssembly = Assembly.GetExecutingAssembly();
Expand Down Expand Up @@ -105,6 +83,24 @@ private static void ExecuteCustomInitializers()
}
}

public static GlobalConfiguration Configuration
{
get
{
if (configuration is not null)
{
return configuration;
}

lock (Lockable)
{
configuration = new GlobalConfiguration();

return configuration;
}
}
}

private static bool IsFramework(Assembly assembly)
{
#if NET6_0_OR_GREATER
Expand Down
2 changes: 1 addition & 1 deletion Src/FluentAssertions/AssertionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static class AssertionExtensions

static AssertionExtensions()
{
Services.EnsureInitialized();
AssertionEngine.EnsureInitialized();
}

/// <summary>
Expand Down
32 changes: 16 additions & 16 deletions Src/FluentAssertions/Collections/GenericCollectionAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public AndConstraint<TAssertions> AllBeAssignableTo(Type expectedType,
/// and the result is equal.
/// The type of a collection property is ignored as long as the collection implements <see cref="IEnumerable{T}"/> and all
/// items in the collection are structurally equal.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </remarks>
/// <param name="expectation">The expected element.</param>
/// <param name="because">
Expand All @@ -162,14 +162,14 @@ public AndConstraint<TAssertions> AllBeEquivalentTo<TExpectation>(TExpectation e
/// and the result is equal.
/// The type of a collection property is ignored as long as the collection implements <see cref="IEnumerable{T}"/> and all
/// items in the collection are structurally equal.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </remarks>
/// <param name="expectation">The expected element.</param>
/// <param name="config">
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="AssertionConfiguration"/> class.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand Down Expand Up @@ -309,7 +309,7 @@ public AndConstraint<TAssertions> BeEmpty([StringSyntax("CompositeFormat")] stri
/// and the result is equal.
/// The type of a collection property is ignored as long as the collection implements <see cref="IEnumerable{T}"/> and all
/// items in the collection are structurally equal.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </remarks>
/// <param name="expectation">An <see cref="IEnumerable{T}"/> with the expected elements.</param>
/// <param name="because">
Expand All @@ -334,14 +334,14 @@ public AndConstraint<TAssertions> BeEquivalentTo<TExpectation>(IEnumerable<TExpe
/// and the result is equal.
/// The type of a collection property is ignored as long as the collection implements <see cref="IEnumerable{T}"/> and all
/// items in the collection are structurally equal.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </remarks>
/// <param name="expectation">An <see cref="IEnumerable{T}"/> with the expected elements.</param>
/// <param name="config">
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="AssertionConfiguration"/> class.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand All @@ -359,7 +359,7 @@ public AndConstraint<TAssertions> BeEquivalentTo<TExpectation>(IEnumerable<TExpe
Guard.ThrowIfArgumentIsNull(config);

EquivalencyOptions<IEnumerable<TExpectation>> options =
config(AssertionOptions.CloneDefaults<TExpectation>()).AsCollection();
config(AssertionConfiguration.Current.Equivalency.CloneDefaults<TExpectation>()).AsCollection();

var context =
new EquivalencyValidationContext(
Expand Down Expand Up @@ -844,7 +844,7 @@ public AndConstraint<TAssertions> Contain(IEnumerable<T> expected, [StringSyntax
/// <para>
/// By default, objects within the collection are seen as equivalent to the expected object when both object graphs have equally named properties with the same
/// value, irrespective of the type of those objects.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </para>
/// </remarks>
/// <param name="expectation">The expected element.</param>
Expand Down Expand Up @@ -873,15 +873,15 @@ public AndWhichConstraint<TAssertions, T> ContainEquivalentOf<TExpectation>(TExp
/// <para>
/// By default, objects within the collection are seen as equivalent to the expected object when both object graphs have equally named properties with the same
/// value, irrespective of the type of those objects.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </para>
/// </remarks>
/// <param name="expectation">The expected element.</param>
/// <param name="config">
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="AssertionConfiguration"/> class.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand All @@ -905,7 +905,7 @@ public AndWhichConstraint<TAssertions, T> ContainEquivalentOf<TExpectation>(TExp

if (assertionChain.Succeeded)
{
EquivalencyOptions<TExpectation> options = config(AssertionOptions.CloneDefaults<TExpectation>());
EquivalencyOptions<TExpectation> options = config(AssertionConfiguration.Current.Equivalency.CloneDefaults<TExpectation>());

using var scope = new AssertionScope();
assertionChain.AddReportable("configuration", () => options.ToString());
Expand Down Expand Up @@ -1849,7 +1849,7 @@ public AndConstraint<TAssertions> NotBeEquivalentTo<TExpectation>(IEnumerable<TE
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="AssertionConfiguration"/> class.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand Down Expand Up @@ -2339,7 +2339,7 @@ public AndConstraint<TAssertions> NotContain(IEnumerable<T> unexpected, [StringS
/// <para>
/// By default, objects within the collection are seen as not equivalent to the expected object when both object graphs have unequally named properties with the same
/// value, irrespective of the type of those objects.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </para>
/// </remarks>
/// <param name="unexpected">The unexpected element.</param>
Expand Down Expand Up @@ -2368,15 +2368,15 @@ public AndConstraint<TAssertions> NotContainEquivalentOf<TExpectation>(TExpectat
/// <para>
/// By default, objects within the collection are seen as not equivalent to the expected object when both object graphs have unequally named properties with the same
/// value, irrespective of the type of those objects.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionOptions"/>.
/// Notice that actual behavior is determined by the global defaults managed by <see cref="AssertionConfiguration"/>.
/// </para>
/// </remarks>
/// <param name="unexpected">The unexpected element.</param>
/// <param name="config">
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="AssertionConfiguration"/> class.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand All @@ -2402,7 +2402,7 @@ public AndConstraint<TAssertions> NotContainEquivalentOf<TExpectation>(TExpectat

if (assertionChain.Succeeded)
{
EquivalencyOptions<TExpectation> options = config(AssertionOptions.CloneDefaults<TExpectation>());
EquivalencyOptions<TExpectation> options = config(AssertionConfiguration.Current.Equivalency.CloneDefaults<TExpectation>());

var foundIndices = new List<int>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public AndConstraint<TAssertions> NotEqual<T>(T unexpected,
/// and the result is equal.
/// The type of the values in the dictionaries are ignored as long as both dictionaries contain the same keys and
/// the values for each key are structurally equivalent. Notice that actual behavior is determined by the global
/// defaults managed by the <see cref="AssertionOptions"/> class.
/// defaults managed by the <see cref="AssertionConfiguration"/> class.
/// </remarks>
/// <param name="expectation">The expected element.</param>
/// <param name="because">
Expand All @@ -197,14 +197,14 @@ public AndConstraint<TAssertions> BeEquivalentTo<TExpectation>(TExpectation expe
/// and the result is equal.
/// The type of the values in the dictionaries are ignored as long as both dictionaries contain the same keys and
/// the values for each key are structurally equivalent. Notice that actual behavior is determined by the global
/// defaults managed by the <see cref="AssertionOptions"/> class.
/// defaults managed by the <see cref="AssertionConfiguration"/> class.
/// </remarks>
/// <param name="expectation">The expected element.</param>
/// <param name="config">
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="AssertionConfiguration"/> class.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand All @@ -220,7 +220,7 @@ public AndConstraint<TAssertions> BeEquivalentTo<TExpectation>(TExpectation expe
{
Guard.ThrowIfArgumentIsNull(config);

EquivalencyOptions<TExpectation> options = config(AssertionOptions.CloneDefaults<TExpectation>());
EquivalencyOptions<TExpectation> options = config(AssertionConfiguration.Current.Equivalency.CloneDefaults<TExpectation>());

var context =
new EquivalencyValidationContext(Node.From<TExpectation>(() => CurrentAssertionChain.CallerIdentifier), options)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ public AndConstraint<TAssertions> BeEquivalentTo(IEnumerable<string> expectation
/// <param name="config">
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults can be modified through
/// <see cref="AssertionConfiguration"/>.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand All @@ -131,7 +131,7 @@ public AndConstraint<TAssertions> BeEquivalentTo(IEnumerable<string> expectation
Guard.ThrowIfArgumentIsNull(config);

EquivalencyOptions<IEnumerable<string>>
options = config(AssertionOptions.CloneDefaults<string>()).AsCollection();
options = config(AssertionConfiguration.Current.Equivalency.CloneDefaults<string>()).AsCollection();

var context =
new EquivalencyValidationContext(Node.From<IEnumerable<string>>(() => CurrentAssertionChain.CallerIdentifier), options)
Expand Down Expand Up @@ -177,7 +177,7 @@ public AndConstraint<TAssertions> AllBe(string expectation,
/// A reference to the <see cref="EquivalencyOptions{TExpectation}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyOptions{TExpectation}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// <see cref="AssertionConfiguration"/> class.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand Down
17 changes: 0 additions & 17 deletions Src/FluentAssertions/Common/AppSettingsConfigurationStore.cs

This file was deleted.

Loading

0 comments on commit 1e77b2d

Please sign in to comment.