Skip to content
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
4 changes: 2 additions & 2 deletions Essentials.All/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ public static IServiceCollection AddObfuscationProviders(this IServiceCollection
.AddDefaultOrKeep<CaesarObfuscationProvider>(static s => s.AddCaesarObfuscationProvider())
.AddReverseObfuscationProvider()
.AddDefaultOrKeep<BitRotateObfuscationProvider>(static s => s.AddBitRotateObfuscationProvider())
.AddBase64ObfuscationProvider()
.AddHexObfuscationProvider()
.AddDefaultOrKeep<Base64ObfuscationProvider>(static s => s.AddBase64ObfuscationProvider())
.AddDefaultOrKeep<HexObfuscationProvider>(static s => s.AddHexObfuscationProvider())
// Registered last so that it is the provider an IObfuscationProvider resolves to.
.AddDefaultOrKeep<XorObfuscationProvider>(static s => s.AddXorObfuscationProvider());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
<PackageReference Include="Polyfill" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\Shared\ProviderRegistration.cs" Link="ProviderRegistration.cs" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="ktsu.Essentials.Tests" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ namespace ktsu.Essentials.ObfuscationProviders.Base64;

using ktsu.Essentials;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

/// <summary>
/// Dependency injection registration for the Base64 obfuscation provider.
Expand All @@ -16,7 +15,9 @@ public static class ServiceCollectionExtensions
/// </summary>
/// <remarks>
/// The provider is registered as a singleton, both as its concrete type and as an additional
/// <see cref="IObfuscationProvider"/> in the resolvable set. Calling this more than once is a no-op.
/// <see cref="IObfuscationProvider"/> in the resolvable set.
/// A later call replaces an earlier registration of this provider in place, so an encoder passed
/// after <c>AddEssentials()</c> takes effect.
/// Registration constructs the provider explicitly so the container does not select the greedy
/// <see cref="IEncodingProvider"/> constructor and bind whichever encoder happens to be registered.
/// </remarks>
Expand All @@ -28,8 +29,7 @@ public static IServiceCollection AddBase64ObfuscationProvider(this IServiceColle
Ensure.NotNull(services);

Base64ObfuscationProvider provider = encoder is null ? new() : new(encoder);
services.TryAddSingleton(provider);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IObfuscationProvider>(provider));
ProviderRegistration.AddOrReplaceSingleton<IObfuscationProvider, Base64ObfuscationProvider>(services, provider);
return services;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
<PackageReference Include="Polyfill" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\Shared\ProviderRegistration.cs" Link="ProviderRegistration.cs" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="ktsu.Essentials.Tests" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ namespace ktsu.Essentials.ObfuscationProviders.Hex;

using ktsu.Essentials;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

/// <summary>
/// Dependency injection registration for the hexadecimal obfuscation provider.
Expand All @@ -16,7 +15,9 @@ public static class ServiceCollectionExtensions
/// </summary>
/// <remarks>
/// The provider is registered as a singleton, both as its concrete type and as an additional
/// <see cref="IObfuscationProvider"/> in the resolvable set. Calling this more than once is a no-op.
/// <see cref="IObfuscationProvider"/> in the resolvable set.
/// A later call replaces an earlier registration of this provider in place, so an encoder passed
/// after <c>AddEssentials()</c> takes effect.
/// Registration constructs the provider explicitly so the container does not select the greedy
/// <see cref="IEncodingProvider"/> constructor and bind whichever encoder happens to be registered.
/// </remarks>
Expand All @@ -28,8 +29,7 @@ public static IServiceCollection AddHexObfuscationProvider(this IServiceCollecti
Ensure.NotNull(services);

HexObfuscationProvider provider = encoder is null ? new() : new(encoder);
services.TryAddSingleton(provider);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IObfuscationProvider>(provider));
ProviderRegistration.AddOrReplaceSingleton<IObfuscationProvider, HexObfuscationProvider>(services, provider);
return services;
}
}
47 changes: 47 additions & 0 deletions Essentials.Tests/ParameterizedRegistrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
using ktsu.Essentials.DistributionProviders.Normal;
using ktsu.Essentials.DistributionProviders.Poisson;
using ktsu.Essentials.DistributionProviders.Triangular;
using ktsu.Essentials.EncodingProviders.Base64;
using ktsu.Essentials.EncodingProviders.Hex;
using ktsu.Essentials.ObfuscationProviders.Base64;
using ktsu.Essentials.ObfuscationProviders.BitRotate;
using ktsu.Essentials.ObfuscationProviders.Caesar;
using ktsu.Essentials.ObfuscationProviders.Hex;
using ktsu.Essentials.ObfuscationProviders.Xor;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -89,6 +93,36 @@
Obfuscate(provider.GetServices<IObfuscationProvider>().OfType<BitRotateObfuscationProvider>().Single()));
}

[TestMethod]
public void Hex_Encoder_Takes_Effect_On_Either_Side_Of_AddEssentials()
{
// Before issue #151 the Hex and Base64 overloads still used TryAdd…, so an encoder passed after
// AddEssentials() was dropped and data was obfuscated with the default encoder instead.
ServiceCollection after = new();
after.AddEssentials();
after.AddHexObfuscationProvider(new Base64EncodingProvider());
AssertResolvesEncoder<HexObfuscationProvider>(after, new HexObfuscationProvider(new Base64EncodingProvider()));

ServiceCollection before = new();
before.AddHexObfuscationProvider(new Base64EncodingProvider());
before.AddEssentials();
AssertResolvesEncoder<HexObfuscationProvider>(before, new HexObfuscationProvider(new Base64EncodingProvider()));
}

[TestMethod]
public void Base64_Encoder_Takes_Effect_On_Either_Side_Of_AddEssentials()
{
ServiceCollection after = new();
after.AddEssentials();
after.AddBase64ObfuscationProvider(new HexEncodingProvider());
AssertResolvesEncoder<Base64ObfuscationProvider>(after, new Base64ObfuscationProvider(new HexEncodingProvider()));

ServiceCollection before = new();
before.AddBase64ObfuscationProvider(new HexEncodingProvider());
before.AddEssentials();
AssertResolvesEncoder<Base64ObfuscationProvider>(before, new Base64ObfuscationProvider(new HexEncodingProvider()));
}

[TestMethod]
public void A_Second_Call_Replaces_A_Distribution_Outside_AddEssentials()
{
Expand All @@ -115,6 +149,19 @@
Assert.AreEqual(1, provider.GetServices<IObfuscationProvider>().Count(o => o is XorObfuscationProvider));
}

private static void AssertResolvesEncoder<TProvider>(ServiceCollection services, TProvider configured)
where TProvider : class, IObfuscationProvider
{
using ServiceProvider provider = services.BuildServiceProvider();

byte[] expected = Obfuscate(configured);
CollectionAssert.AreEqual(expected, Obfuscate(provider.GetRequiredService<TProvider>()));

Check warning on line 158 in Essentials.Tests/ParameterizedRegistrationTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.AreSequenceEqual' instead of 'CollectionAssert.AreEqual'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Essentials&issues=AaFTNCQwES0AxtXJ51-e&open=AaFTNCQwES0AxtXJ51-e&pullRequest=152
CollectionAssert.AreEqual(expected, Obfuscate(provider.GetServices<IObfuscationProvider>().OfType<TProvider>().Single()));

Check warning on line 159 in Essentials.Tests/ParameterizedRegistrationTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.AreSequenceEqual' instead of 'CollectionAssert.AreEqual'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Essentials&issues=AaFTNCQwES0AxtXJ51-f&open=AaFTNCQwES0AxtXJ51-f&pullRequest=152

// Xor stays the default obfuscator, so replacing this one leaves the order AddEssentials() chose.
Assert.IsInstanceOfType<XorObfuscationProvider>(provider.GetRequiredService<IObfuscationProvider>());
}

private static void AssertResolvesNormal(ServiceCollection services, double mean, double standardDeviation)
{
using ServiceProvider provider = services.BuildServiceProvider();
Expand Down
Loading