Skip to content

Commit

Permalink
fixes #35
Browse files Browse the repository at this point in the history
  • Loading branch information
Blind-Striker committed Sep 22, 2023
1 parent 5eac143 commit 4e52f89
Show file tree
Hide file tree
Showing 24 changed files with 293 additions and 703 deletions.
10 changes: 10 additions & 0 deletions LocalStack.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{152F3084
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LocalStack.Build", "build\LocalStack.Build\LocalStack.Build.csproj", "{2CA18A71-CA83-4CC4-A777-AA4F56E4413F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{FF7B2686-CC4B-4B6C-B360-E487339DB210}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalStack.Tests.Common", "tests\common\LocalStack.Tests.Common\LocalStack.Tests.Common.csproj", "{7B896BF0-E9E1-44B7-9268-78A6B45CFE0D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -91,6 +95,10 @@ Global
{2CA18A71-CA83-4CC4-A777-AA4F56E4413F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CA18A71-CA83-4CC4-A777-AA4F56E4413F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CA18A71-CA83-4CC4-A777-AA4F56E4413F}.Release|Any CPU.Build.0 = Release|Any CPU
{7B896BF0-E9E1-44B7-9268-78A6B45CFE0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B896BF0-E9E1-44B7-9268-78A6B45CFE0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B896BF0-E9E1-44B7-9268-78A6B45CFE0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B896BF0-E9E1-44B7-9268-78A6B45CFE0D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -106,6 +114,8 @@ Global
{A697D9A2-4DF7-4B4D-A189-EEC7F64B5609} = {3F0F4BAA-02EF-4008-9CF8-E73AA92D4664}
{6CCFBCE0-C7C6-42A7-B39F-665B4C15C6FE} = {962A750E-8FE2-461F-B3FC-2B401309B5FD}
{2CA18A71-CA83-4CC4-A777-AA4F56E4413F} = {152F3084-DC30-4A44-AEBC-E4C0EBFA0F4E}
{FF7B2686-CC4B-4B6C-B360-E487339DB210} = {3F0F4BAA-02EF-4008-9CF8-E73AA92D4664}
{7B896BF0-E9E1-44B7-9268-78A6B45CFE0D} = {FF7B2686-CC4B-4B6C-B360-E487339DB210}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E4925255-67AA-4095-816B-CC10A5490E71}
Expand Down
14 changes: 5 additions & 9 deletions src/LocalStack.Client.Extensions/AwsClientFactoryWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
#pragma warning disable S3011 // We need to use reflection to access private fields for service metadata
#pragma warning disable CS8600,CS8603 // Not possible to get null value from this private field
#pragma warning disable CA1802 // We need to use reflection to access private fields for service metadata
namespace LocalStack.Client.Extensions;

public sealed class AwsClientFactoryWrapper : IAwsClientFactoryWrapper
{
private const string ClientFactoryFullName = "Amazon.Extensions.NETCore.Setup.ClientFactory";
private const string CreateServiceClientMethodName = "CreateServiceClient";
private static readonly string ClientFactoryFullName = "Amazon.Extensions.NETCore.Setup.ClientFactory";
private static readonly string CreateServiceClientMethodName = "CreateServiceClient";

public AmazonServiceClient CreateServiceClient<TClient>(IServiceProvider provider, AWSOptions awsOptions) where TClient : IAmazonService
public AmazonServiceClient CreateServiceClient<TClient>(IServiceProvider provider, AWSOptions? awsOptions) where TClient : IAmazonService
{
if (awsOptions == null)
{
throw new ArgumentNullException(nameof(awsOptions));
}

Type? clientFactoryType = typeof(ConfigurationException).Assembly.GetType(ClientFactoryFullName);

if (clientFactoryType == null)
Expand All @@ -31,7 +27,7 @@ public AmazonServiceClient CreateServiceClient<TClient>(IServiceProvider provide

Type clientType = typeof(TClient);

object clientFactory = constructorInfo.Invoke(new object[] { clientType, awsOptions });
object clientFactory = constructorInfo.Invoke(new object[] { clientType, awsOptions! });

MethodInfo? methodInfo = clientFactory.GetType().GetMethod(CreateServiceClientMethodName, BindingFlags.NonPublic | BindingFlags.Instance);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public interface IAwsClientFactoryWrapper
{
AmazonServiceClient CreateServiceClient<TClient>(IServiceProvider provider, AWSOptions awsOptions) where TClient : IAmazonService;
AmazonServiceClient CreateServiceClient<TClient>(IServiceProvider provider, AWSOptions? awsOptions) where TClient : IAmazonService;
}
401 changes: 71 additions & 330 deletions src/LocalStack.Client.Extensions/README.md

Large diffs are not rendered by default.

401 changes: 71 additions & 330 deletions src/LocalStack.Client/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
namespace LocalStack.Client.Extensions.Tests;

public class AwsClientFactoryWrapperTests
{
private readonly IAwsClientFactoryWrapper _awsClientFactoryWrapper;
private readonly Mock<IServiceProvider> _mockServiceProvider;
private readonly AWSOptions _awsOptions;

public AwsClientFactoryWrapperTests()
{
_awsClientFactoryWrapper = new AwsClientFactoryWrapper();
_mockServiceProvider = new Mock<IServiceProvider>();
_awsOptions = new AWSOptions();
}

[Fact]
public void CreateServiceClient_Should_Throw_LocalStackClientConfigurationException_When_ClientFactoryType_Is_Null()
{
Type type = _awsClientFactoryWrapper.GetType();
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;

FieldInfo? clientFactoryFullNameField = type.GetField("ClientFactoryFullName", bindingFlags);
FieldInfo? createServiceClientMethodNameFieldInfo = type.GetField("CreateServiceClientMethodName", bindingFlags);

Assert.NotNull(clientFactoryFullNameField);
Assert.NotNull(createServiceClientMethodNameFieldInfo);

SetPrivateReadonlyField(clientFactoryFullNameField, "NonExistingType");
SetPrivateReadonlyField(createServiceClientMethodNameFieldInfo, "NonExistingMethod");

Assert.Throws<LocalStackClientConfigurationException>(
() => _awsClientFactoryWrapper.CreateServiceClient<MockAmazonServiceClient>(_mockServiceProvider.Object, _awsOptions));
}

[Fact]
public void CreateServiceClient_Should_Create_Client_When_UseLocalStack_False()
{
ConfigurationBuilder configurationBuilder = new();
configurationBuilder.AddInMemoryCollection(new KeyValuePair<string, string?>[] { new("LocalStack:UseLocalStack", "false") });
IConfigurationRoot configurationRoot = configurationBuilder.Build();

ServiceCollection serviceCollection = new();
serviceCollection.AddLocalStack(configurationRoot);
serviceCollection.AddAWSServiceLocalStack<IAmazonS3>();
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();

var requiredService = serviceProvider.GetRequiredService<IAmazonS3>();

Assert.NotNull(requiredService);
}

private static void SetPrivateReadonlyField(FieldInfo field, string value)
{
var method = new DynamicMethod("SetReadOnlyField", null, new[] { typeof(object), typeof(object) }, typeof(AwsClientFactoryWrapper), true);
var il = method.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, field.DeclaringType!);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, field);
il.Emit(OpCodes.Ret);

method.Invoke(null, new object[] { null!, value });
}
}
6 changes: 5 additions & 1 deletion tests/LocalStack.Client.Extensions.Tests/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
global using System;
global using System.Collections.Generic;
global using System.Globalization;
global using System.Reflection;
global using System.Reflection.Emit;
global using System.Text.Json;

global using Microsoft.Extensions.Configuration;
Expand All @@ -11,14 +13,16 @@
global using Amazon;
global using Amazon.Extensions.NETCore.Setup;
global using Amazon.Runtime;
global using Amazon.S3;

global using LocalStack.Client.Contracts;
global using LocalStack.Client.Extensions.Contracts;
global using LocalStack.Client.Extensions.Exceptions;
global using LocalStack.Client.Extensions.Tests.Extensions;
global using LocalStack.Client.Options;
global using LocalStack.Client.Tests.Mocks.MockServiceClients;
global using LocalStack.Client.Utils;
global using LocalStack.Client.Models;
global using LocalStack.Tests.Common.Mocks.MockServiceClients;

global using Moq;
global using Xunit;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.Core" />
<PackageReference Include="AWSSDK.S3" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />

Expand All @@ -30,4 +30,6 @@
<ProjectReference Include="..\LocalStack.Client.Tests\LocalStack.Client.Tests.csproj" />
</ItemGroup>



</Project>
7 changes: 2 additions & 5 deletions tests/LocalStack.Client.Tests/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@
global using Amazon;
global using Amazon.Runtime;
global using Amazon.Runtime.Internal;
global using Amazon.Runtime.Internal.Auth;
global using Amazon.Util.Internal;

global using LocalStack.Client.Contracts;
global using LocalStack.Client.Enums;
global using LocalStack.Client.Exceptions;
global using LocalStack.Client.Models;
global using LocalStack.Client.Options;
global using LocalStack.Client.Tests.Mocks;
global using LocalStack.Client.Tests.Mocks.MockServiceClients;
global using LocalStack.Tests.Common.Mocks;
global using LocalStack.Tests.Common.Mocks.MockServiceClients;
global using LocalStack.Client.Utils;

global using Moq;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@

<ItemGroup>
<ProjectReference Include="..\..\src\LocalStack.Client\LocalStack.Client.csproj" />
<ProjectReference Include="..\common\LocalStack.Tests.Common\LocalStack.Tests.Common.csproj" />
</ItemGroup>
</Project>

This file was deleted.

15 changes: 15 additions & 0 deletions tests/common/LocalStack.Tests.Common/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Global using directives

global using System;
global using System.Collections.Generic;

global using Amazon.Runtime;
global using Amazon.Runtime.Internal;
global using Amazon.Runtime.Internal.Auth;
global using Amazon.Util.Internal;

global using LocalStack.Client;
global using LocalStack.Client.Contracts;
global using LocalStack.Client.Models;

global using Moq;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net461;net6.0;net7.0</TargetFrameworks>
<NoWarn>$(NoWarn);CA1707;MA0006</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.Core"/>
<PackageReference Include="Moq" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\LocalStack.Client\LocalStack.Client.csproj" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\LocalStack.Client\LocalStack.Client.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
namespace LocalStack.Client.Tests.Mocks;
namespace LocalStack.Tests.Common.Mocks;

internal static class Extensions
public static class Extensions
{
public static (string awsAccessKeyId, string awsAccessKey, string awsSessionToken, string regionName)
SetupDefault(this Mock<ISessionOptions> mock,
string awsAccessKeyId = "AwsAccessKeyId",
string awsAccessKey = "AwsAccessKey",
string awsSessionToken = "AwsSessionToken",
string regionName = "eu-central-1")
public static (string awsAccessKeyId, string awsAccessKey, string awsSessionToken, string regionName) SetupDefault(
this Mock<ISessionOptions> mock, string awsAccessKeyId = "AwsAccessKeyId", string awsAccessKey = "AwsAccessKey", string awsSessionToken = "AwsSessionToken",
string regionName = "eu-central-1")
{
if (mock == null)
{
throw new ArgumentNullException(nameof(mock));
}

mock.SetupGet(options => options.AwsAccessKeyId).Returns(awsAccessKeyId);
mock.SetupGet(options => options.AwsAccessKey).Returns(awsAccessKey);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public interface IMockAmazonService : IDisposable, IAmazonService
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public interface IMockAmazonServiceWithServiceMetadata : IDisposable, IAmazonService
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public class MockAmazonServiceClient : AmazonServiceClient, IMockAmazonService
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma warning disable S1144, CA1823
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public class MockAmazonServiceWithServiceMetadataClient : AmazonServiceClient, IMockAmazonServiceWithServiceMetadata
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public record MockAwsServiceEndpoint() : AwsServiceEndpoint(MockServiceMetadata.MockServiceId, "mockService", Client.Enums.AwsService.ApiGateway, 1234, "localhost",
new Uri("http://localhost:1234/"));
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public class MockClientConfig : ClientConfig, IClientConfig
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public class MockClientConfigWithForcePathStyle : MockClientConfig
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

internal sealed class MockCredentials : BasicAWSCredentials
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks.MockServiceClients;
namespace LocalStack.Tests.Common.Mocks.MockServiceClients;

public class MockServiceMetadata : IServiceMetadata
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace LocalStack.Client.Tests.Mocks;
namespace LocalStack.Tests.Common.Mocks;

public class MockSession : Session
{
Expand All @@ -18,8 +18,6 @@ private MockSession(Mock<ISessionOptions> sessionOptionsMock, Mock<IConfig> conf

public static MockSession Create()
{
return new MockSession(new Mock<ISessionOptions>(MockBehavior.Strict),
new Mock<IConfig>(MockBehavior.Strict),
new Mock<ISessionReflection>(MockBehavior.Strict));
return new MockSession(new Mock<ISessionOptions>(MockBehavior.Strict), new Mock<IConfig>(MockBehavior.Strict), new Mock<ISessionReflection>(MockBehavior.Strict));
}
}
}

0 comments on commit 4e52f89

Please sign in to comment.