Skip to content

Commit 9e47e5f

Browse files
Release 4.14.0
- refactor: introduces AuthenticationClient and reorganise authentication standalone module
1 parent be3a12c commit 9e47e5f

File tree

4 files changed

+97
-9
lines changed

4 files changed

+97
-9
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>4.13.1</Version>
3+
<Version>4.14.0</Version>
44
</PropertyGroup>
55
</Project>

src/CheckoutSdk/LogProvider.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,42 @@
22
using Microsoft.Extensions.Logging;
33
using Microsoft.Extensions.Logging.Abstractions;
44
using System;
5+
using System.Collections.Concurrent;
56

67
namespace Checkout
78
{
8-
99
public static class LogProvider
1010
{
11+
private static readonly object SyncRoot = new object();
1112
private static ILoggerFactory _loggerFactory = new LoggerFactory();
13+
private static readonly ConcurrentDictionary<Type, ILogger> Loggers = new ConcurrentDictionary<Type, ILogger>();
1214

1315
public static void SetLogFactory(ILoggerFactory factory)
1416
{
15-
_loggerFactory?.Dispose();
16-
_loggerFactory = factory ?? new LoggerFactory();
17+
lock (SyncRoot)
18+
{
19+
_loggerFactory?.Dispose();
20+
_loggerFactory = factory ?? new LoggerFactory();
21+
Loggers.Clear();
22+
}
1723
}
1824

1925
public static ILogger GetLogger(Type loggerType)
2026
{
21-
return loggerType is null ? NullLogger.Instance : _loggerFactory.CreateLogger(loggerType) ?? NullLogger.Instance;;
27+
if (loggerType == null)
28+
{
29+
return NullLogger.Instance;
30+
}
31+
32+
return Loggers.GetOrAdd(loggerType, type =>
33+
{
34+
lock (SyncRoot)
35+
{
36+
var name = type.FullName ?? type.Name;
37+
var logger = _loggerFactory.CreateLogger(name);
38+
return logger ?? NullLogger.Instance;
39+
}
40+
});
2241
}
2342
}
2443
}

test/CheckoutSdkTest/CheckoutSdkIntegrationTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ private class TestingClientFactory : IHttpClientFactory
7272
public HttpClient CreateClient()
7373
{
7474
var httpClient = new HttpClient(new CustomMessageHandler());
75-
httpClient.Timeout = TimeSpan.FromSeconds(2);
75+
httpClient.Timeout = TimeSpan.FromSeconds(3);
7676
return httpClient;
7777
}
7878
}

test/CheckoutSdkTest/LogProviderTest.cs

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ namespace Checkout
99
public sealed class LogProviderTests : IDisposable
1010
{
1111
private readonly ILoggerFactory _loggerFactory;
12+
13+
private static readonly object RandLock = new object();
14+
private static readonly Random Random = new Random();
1215

1316
public LogProviderTests()
1417
{
@@ -25,14 +28,20 @@ public void ShouldGetLoggerReturnsValidLogger()
2528
public async Task ShouldCreateASingleLoggerInstanceForMultipleConcurrentRequests()
2629
{
2730
LogProvider.SetLogFactory(_loggerFactory);
28-
Type[] loggerTypes = new[] { typeof(LogProviderTests), typeof(AnotherTestClass), typeof(NoInitializedType) };
31+
Type[] loggerTypes = { typeof(LogProviderTests), typeof(AnotherTestClass), typeof(NoInitializedType) };
32+
2933
Task<ILogger>[] createLoggerTasks = Enumerable.Range(1, 50)
3034
.Select(async index =>
3135
{
32-
int randomDelayMs = new Random().Next(1, 5);
33-
await Task.Delay(randomDelayMs);
36+
int delay;
37+
lock (RandLock)
38+
{
39+
delay = Random.Next(1, 5);
40+
}
41+
await Task.Delay(delay);
3442
return await Task.FromResult(LogProvider.GetLogger(loggerTypes[index % loggerTypes.Length]));
3543
}).ToArray();
44+
3645
ILogger[] loggers = await Task.WhenAll(createLoggerTasks);
3746
Assert.Equal(loggerTypes.Length, loggers.Distinct().Count());
3847
}
@@ -54,6 +63,66 @@ public void ShouldNotThrowExceptionWhenSetLogFactoryWithNullParameter()
5463
{
5564
Assert.Null(Record.Exception(() => LogProvider.SetLogFactory(null)));
5665
}
66+
67+
[Fact]
68+
public void ShouldReplaceLoggerFactoryCorrectly()
69+
{
70+
var loggerBefore = LogProvider.GetLogger(typeof(LogProviderTests));
71+
72+
var newFactory = LoggerFactory.Create(builder => builder.AddFilter(_ => false));
73+
LogProvider.SetLogFactory(newFactory);
74+
75+
var loggerAfter = LogProvider.GetLogger(typeof(LogProviderTests));
76+
77+
Assert.NotSame(loggerBefore, loggerAfter);
78+
}
79+
80+
[Fact]
81+
public void ShouldClearLoggersWhenFactoryChanges()
82+
{
83+
LogProvider.SetLogFactory(_loggerFactory);
84+
var logger1 = LogProvider.GetLogger(typeof(LogProviderTests));
85+
86+
var newFactory = new LoggerFactory();
87+
LogProvider.SetLogFactory(newFactory);
88+
var logger2 = LogProvider.GetLogger(typeof(LogProviderTests));
89+
90+
Assert.NotSame(logger1, logger2);
91+
}
92+
93+
[Fact]
94+
public void ShouldReturnSameLoggerOnMultipleCalls()
95+
{
96+
LogProvider.SetLogFactory(_loggerFactory);
97+
98+
var logger1 = LogProvider.GetLogger(typeof(LogProviderTests));
99+
var logger2 = LogProvider.GetLogger(typeof(LogProviderTests));
100+
101+
Assert.Same(logger1, logger2);
102+
}
103+
104+
[Fact]
105+
public async Task ShouldNotThrowWhenCallingSetLogFactoryConcurrently()
106+
{
107+
var tasks = Enumerable.Range(0, 10).Select(_ => Task.Run(() =>
108+
{
109+
LogProvider.SetLogFactory(new LoggerFactory());
110+
}));
111+
112+
var exception = await Record.ExceptionAsync(async () => await Task.WhenAll(tasks));
113+
114+
Assert.Null(exception);
115+
}
116+
117+
[Fact]
118+
public void ShouldAllowMultipleNullLoggerFactoryAssignments()
119+
{
120+
LogProvider.SetLogFactory(null);
121+
LogProvider.SetLogFactory(null);
122+
var logger = LogProvider.GetLogger(typeof(LogProviderTests));
123+
124+
Assert.NotNull(logger);
125+
}
57126

58127
public void Dispose()
59128
{

0 commit comments

Comments
 (0)