From e7c8dc93000415807e1fd46d76a43ffbf2d9517a Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 17:57:28 +0200 Subject: [PATCH 1/9] chore: add Light.TemporaryStreams.csproj --- Directory.Packages.props | 1 + Light.TemporaryStreams.sln | 15 +++++++++ .../Light.TemporaryStreams.csproj | 17 ++++++++++ src/Light.TemporaryStreams/packages.lock.json | 31 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 src/Light.TemporaryStreams/Light.TemporaryStreams.csproj create mode 100644 src/Light.TemporaryStreams/packages.lock.json diff --git a/Directory.Packages.props b/Directory.Packages.props index db2e2a7..e00a931 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,6 +7,7 @@ + diff --git a/Light.TemporaryStreams.sln b/Light.TemporaryStreams.sln index e94d64b..90021e6 100644 --- a/Light.TemporaryStreams.sln +++ b/Light.TemporaryStreams.sln @@ -28,6 +28,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{048D0C61-6CF EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DA93B299-75F5-4A49-B2A6-4A1247047E5E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Light.TemporaryStreams", "src\Light.TemporaryStreams\Light.TemporaryStreams.csproj", "{61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -62,6 +64,18 @@ Global {4D6B4F48-1E4B-4ACA-9F32-829442DB5E56}.Release|x64.Build.0 = Release|Any CPU {4D6B4F48-1E4B-4ACA-9F32-829442DB5E56}.Release|x86.ActiveCfg = Release|Any CPU {4D6B4F48-1E4B-4ACA-9F32-829442DB5E56}.Release|x86.Build.0 = Release|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Debug|x64.ActiveCfg = Debug|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Debug|x64.Build.0 = Debug|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Debug|x86.ActiveCfg = Debug|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Debug|x86.Build.0 = Debug|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|Any CPU.Build.0 = Release|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|x64.ActiveCfg = Release|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|x64.Build.0 = Release|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|x86.ActiveCfg = Release|Any CPU + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -70,5 +84,6 @@ Global {05D48EEC-A2AB-4143-9533-A633E7B25EA3} = {677E4EE1-7062-46AB-81FF-8D20E9316ED6} {C86E6D31-A10A-4B61-B490-5A7AC4451BA5} = {048D0C61-6CF0-43E6-B7DB-1FDD8F791D57} {4D6B4F48-1E4B-4ACA-9F32-829442DB5E56} = {DA93B299-75F5-4A49-B2A6-4A1247047E5E} + {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1} = {048D0C61-6CF0-43E6-B7DB-1FDD8F791D57} EndGlobalSection EndGlobal diff --git a/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj b/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj new file mode 100644 index 0000000..d375331 --- /dev/null +++ b/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj @@ -0,0 +1,17 @@ + + + + true + true + Light.TemporaryStreams + + + + + + + + + + + diff --git a/src/Light.TemporaryStreams/packages.lock.json b/src/Light.TemporaryStreams/packages.lock.json new file mode 100644 index 0000000..3b867e9 --- /dev/null +++ b/src/Light.TemporaryStreams/packages.lock.json @@ -0,0 +1,31 @@ +{ + "version": 2, + "dependencies": { + "net8.0": { + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[8.0.17, )", + "resolved": "8.0.17", + "contentHash": "x5/y4l8AtshpBOrCZdlE4txw8K3e3s9meBFeZeR3l8hbbku2V7kK6ojhXvrbjg1rk3G+JqL1BI26gtgc1ZrdUw==" + }, + "light.temporarystreams.core": { + "type": "Project", + "dependencies": { + "Light.GuardClauses": "[13.0.0, )" + } + }, + "Light.GuardClauses": { + "type": "CentralTransitive", + "requested": "[13.0.0, )", + "resolved": "13.0.0", + "contentHash": "mhlWUk0o+XibJgYuPlO9vQQpMmh4EAeDRFAac7pP6W3zmpjEeyUVGOiw+mdCxX469QQ2rkMYjWyHoDlZv599/w==" + } + } + } +} \ No newline at end of file From 5e1988f80cf8dbbbed8806d6bcd478a275c6ed87 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 22:13:30 +0200 Subject: [PATCH 2/9] test: replace SHA3_512 with SHA1 as the former is not available on Mac OS X Signed-off-by: Kenny Pflug --- .../Hashing/CopyToHashCalculatorTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Light.TemporaryStreams.Core.Tests/Hashing/CopyToHashCalculatorTests.cs b/tests/Light.TemporaryStreams.Core.Tests/Hashing/CopyToHashCalculatorTests.cs index 9593db8..e02053f 100644 --- a/tests/Light.TemporaryStreams.Core.Tests/Hashing/CopyToHashCalculatorTests.cs +++ b/tests/Light.TemporaryStreams.Core.Tests/Hashing/CopyToHashCalculatorTests.cs @@ -35,7 +35,7 @@ public static async Task HashArray_ShouldThrow_WhenObtainHashFromAlgorithmWasNot [Fact] public static async Task ObtainHashFromAlgorithm_ShouldThrow_WhenNothingWasWrittenToUnderlyingCryptoStream() { - await using CopyToHashCalculator calculator = SHA3_512.Create(); + await using CopyToHashCalculator calculator = SHA1.Create(); // ReSharper disable once AccessToDisposedClosure -- delegate called before calculator is disposed of var act = () => calculator.ObtainHashFromAlgorithm(); From 674aa087123a9e0fc852899e8d2a9924133f3635 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 22:15:35 +0200 Subject: [PATCH 3/9] fix: HashingPlugin.SetUpAsync now throws if cancellation was requested Signed-off-by: Kenny Pflug --- src/Light.TemporaryStreams.Core/Hashing/HashingPlugin.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Light.TemporaryStreams.Core/Hashing/HashingPlugin.cs b/src/Light.TemporaryStreams.Core/Hashing/HashingPlugin.cs index 6e4257f..14ce42c 100644 --- a/src/Light.TemporaryStreams.Core/Hashing/HashingPlugin.cs +++ b/src/Light.TemporaryStreams.Core/Hashing/HashingPlugin.cs @@ -78,7 +78,8 @@ public async ValueTask DisposeAsync() public ValueTask SetUpAsync(Stream innerStream, CancellationToken cancellationToken = default) { innerStream.MustNotBeNull(); - Stream currentStream = innerStream; + cancellationToken.ThrowIfCancellationRequested(); + var currentStream = innerStream; for (var i = 0; i < HashCalculators.Length; i++) { currentStream = HashCalculators[i].CreateWrappingCryptoStream(currentStream, leaveWrappedStreamOpen: true); From ef3b401bbcb3ceb689a38b898c74c7ca059d0446 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 22:16:54 +0200 Subject: [PATCH 4/9] feat: add Microsoft.Extensions.Logging support when Temporary Streams cannot be deleted Signed-off-by: Kenny Pflug --- Directory.Packages.props | 1 + .../Light.TemporaryStreams.csproj | 3 +- .../MicrosoftLoggingExtensions.cs | 29 +++++++++++++++++++ src/Light.TemporaryStreams/packages.lock.json | 9 ++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/Light.TemporaryStreams/MicrosoftLoggingExtensions.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index e00a931..e2718e6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,6 +8,7 @@ + diff --git a/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj b/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj index d375331..e7fc9eb 100644 --- a/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj +++ b/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj @@ -5,9 +5,10 @@ true Light.TemporaryStreams - + + diff --git a/src/Light.TemporaryStreams/MicrosoftLoggingExtensions.cs b/src/Light.TemporaryStreams/MicrosoftLoggingExtensions.cs new file mode 100644 index 0000000..7a87b40 --- /dev/null +++ b/src/Light.TemporaryStreams/MicrosoftLoggingExtensions.cs @@ -0,0 +1,29 @@ +using System; +using Microsoft.Extensions.Logging; + +namespace Light.TemporaryStreams; + +/// +/// Provides extension methods for that are specifically designed for use with the +/// . +/// +public static partial class MicrosoftLoggingExtensions +{ + /// + /// Logs an error message when an exception occurs while deleting a temporary stream. + /// + /// The logger to write the error message to. + /// The exception that occurred. + /// The file path of the temporary stream. + [LoggerMessage( + EventId = 1001, + Level = LogLevel.Error, + Message = "An error occurred while deleting the temporary stream '{TemporaryStreamFilePath}'" + ) + ] + public static partial void LogErrorDeletingTemporaryStream( + this ILogger logger, + Exception exception, + string temporaryStreamFilePath + ); +} diff --git a/src/Light.TemporaryStreams/packages.lock.json b/src/Light.TemporaryStreams/packages.lock.json index 3b867e9..74dee5a 100644 --- a/src/Light.TemporaryStreams/packages.lock.json +++ b/src/Light.TemporaryStreams/packages.lock.json @@ -8,6 +8,15 @@ "resolved": "8.0.0", "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==" }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, "Microsoft.NET.ILLink.Tasks": { "type": "Direct", "requested": "[8.0.17, )", From e4bac1a4f49e3a833bdad9320897a27cca169679 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 22:17:15 +0200 Subject: [PATCH 5/9] chore: remove empty line in TemporaryStreamErrorHandlerProvider Signed-off-by: Kenny Pflug --- .../TemporaryStreamErrorHandlerProvider.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Light.TemporaryStreams.Core/TemporaryStreamErrorHandlerProvider.cs b/src/Light.TemporaryStreams.Core/TemporaryStreamErrorHandlerProvider.cs index 952a831..88ec810 100644 --- a/src/Light.TemporaryStreams.Core/TemporaryStreamErrorHandlerProvider.cs +++ b/src/Light.TemporaryStreams.Core/TemporaryStreamErrorHandlerProvider.cs @@ -9,7 +9,6 @@ public sealed class TemporaryStreamErrorHandlerProvider { private readonly Action? _errorHandler; - /// /// Initializes a new instance of . /// From 749e6d058918507b26259bfeeb48692802bc00ca Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 22:20:33 +0200 Subject: [PATCH 6/9] chore: add Directory.Build.props for src folder Signed-off-by: Kenny Pflug --- Light.TemporaryStreams.sln | 3 +++ src/Directory.Build.props | 13 +++++++++++++ .../Light.TemporaryStreams.Core.csproj | 6 ------ .../Light.TemporaryStreams.csproj | 6 ------ 4 files changed, 16 insertions(+), 12 deletions(-) create mode 100644 src/Directory.Build.props diff --git a/Light.TemporaryStreams.sln b/Light.TemporaryStreams.sln index 90021e6..fbc8ed3 100644 --- a/Light.TemporaryStreams.sln +++ b/Light.TemporaryStreams.sln @@ -25,6 +25,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{048D0C61-6CF0-43E6-B7DB-1FDD8F791D57}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DA93B299-75F5-4A49-B2A6-4A1247047E5E}" EndProject diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..4d31c2b --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,13 @@ + + + $([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')) + + + + + + true + true + Light.TemporaryStreams + + diff --git a/src/Light.TemporaryStreams.Core/Light.TemporaryStreams.Core.csproj b/src/Light.TemporaryStreams.Core/Light.TemporaryStreams.Core.csproj index b96a5a5..17f6863 100644 --- a/src/Light.TemporaryStreams.Core/Light.TemporaryStreams.Core.csproj +++ b/src/Light.TemporaryStreams.Core/Light.TemporaryStreams.Core.csproj @@ -1,11 +1,5 @@ - - true - true - Light.TemporaryStreams - - diff --git a/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj b/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj index e7fc9eb..9deda95 100644 --- a/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj +++ b/src/Light.TemporaryStreams/Light.TemporaryStreams.csproj @@ -1,11 +1,5 @@  - - true - true - Light.TemporaryStreams - - From 0b23fdd87a31fab3c050023af1f22b3668ea87b2 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 22:24:52 +0200 Subject: [PATCH 7/9] test: introduce Directory.Build.props for test projects Signed-off-by: Kenny Pflug --- Light.TemporaryStreams.sln | 3 +++ tests/Directory.Build.props | 23 +++++++++++++++++++ .../Light.TemporaryStreams.Core.Tests.csproj | 16 ------------- 3 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 tests/Directory.Build.props diff --git a/Light.TemporaryStreams.sln b/Light.TemporaryStreams.sln index fbc8ed3..2109c8c 100644 --- a/Light.TemporaryStreams.sln +++ b/Light.TemporaryStreams.sln @@ -30,6 +30,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{048D0C61-6CF EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DA93B299-75F5-4A49-B2A6-4A1247047E5E}" + ProjectSection(SolutionItems) = preProject + tests\Directory.Build.props = tests\Directory.Build.props + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Light.TemporaryStreams", "src\Light.TemporaryStreams\Light.TemporaryStreams.csproj", "{61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}" EndProject diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props new file mode 100644 index 0000000..b6f38ce --- /dev/null +++ b/tests/Directory.Build.props @@ -0,0 +1,23 @@ + + + $([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')) + + + + + + Exe + true + false + true + true + Light.TemporaryStreams + + + + + + + + + diff --git a/tests/Light.TemporaryStreams.Core.Tests/Light.TemporaryStreams.Core.Tests.csproj b/tests/Light.TemporaryStreams.Core.Tests/Light.TemporaryStreams.Core.Tests.csproj index fd61100..786fc4a 100644 --- a/tests/Light.TemporaryStreams.Core.Tests/Light.TemporaryStreams.Core.Tests.csproj +++ b/tests/Light.TemporaryStreams.Core.Tests/Light.TemporaryStreams.Core.Tests.csproj @@ -1,21 +1,5 @@ - - Exe - true - false - true - true - Light.TemporaryStreams - - - - - - - - - From 51dd1d7d3f93ba0aa00e82d8c9cd79a424b4d7e4 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 23:21:19 +0200 Subject: [PATCH 8/9] feat: add support for Microsoft.Extensions.DependencyInjection Signed-off-by: Kenny Pflug --- Directory.Packages.props | 3 + Light.TemporaryStreams.sln | 15 + .../ServiceCollectionExtensions.cs | 71 +++++ .../Light.TemporaryStreams.Tests.csproj | 15 + .../ServiceCollectionExtensionsTests.cs | 92 ++++++ .../packages.lock.json | 298 ++++++++++++++++++ .../xunit.runner.json | 3 + 7 files changed, 497 insertions(+) create mode 100644 src/Light.TemporaryStreams/ServiceCollectionExtensions.cs create mode 100644 tests/Light.TemporaryStreams.Tests/Light.TemporaryStreams.Tests.csproj create mode 100644 tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs create mode 100644 tests/Light.TemporaryStreams.Tests/packages.lock.json create mode 100644 tests/Light.TemporaryStreams.Tests/xunit.runner.json diff --git a/Directory.Packages.props b/Directory.Packages.props index e2718e6..2425cd9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,9 +7,12 @@ + + + diff --git a/Light.TemporaryStreams.sln b/Light.TemporaryStreams.sln index 2109c8c..bf0074f 100644 --- a/Light.TemporaryStreams.sln +++ b/Light.TemporaryStreams.sln @@ -36,6 +36,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DA93B299 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Light.TemporaryStreams", "src\Light.TemporaryStreams\Light.TemporaryStreams.csproj", "{61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Light.TemporaryStreams.Tests", "tests\Light.TemporaryStreams.Tests\Light.TemporaryStreams.Tests.csproj", "{93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -82,6 +84,18 @@ Global {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|x64.Build.0 = Release|Any CPU {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|x86.ActiveCfg = Release|Any CPU {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1}.Release|x86.Build.0 = Release|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Debug|x64.ActiveCfg = Debug|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Debug|x64.Build.0 = Debug|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Debug|x86.ActiveCfg = Debug|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Debug|x86.Build.0 = Debug|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Release|Any CPU.Build.0 = Release|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Release|x64.ActiveCfg = Release|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Release|x64.Build.0 = Release|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Release|x86.ActiveCfg = Release|Any CPU + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -91,5 +105,6 @@ Global {C86E6D31-A10A-4B61-B490-5A7AC4451BA5} = {048D0C61-6CF0-43E6-B7DB-1FDD8F791D57} {4D6B4F48-1E4B-4ACA-9F32-829442DB5E56} = {DA93B299-75F5-4A49-B2A6-4A1247047E5E} {61725DD8-D81C-4EC0-A0A1-63D96A87DAC1} = {048D0C61-6CF0-43E6-B7DB-1FDD8F791D57} + {93CCDAD2-A16A-4BA3-A805-4FC7C4B518C8} = {DA93B299-75F5-4A49-B2A6-4A1247047E5E} EndGlobalSection EndGlobal diff --git a/src/Light.TemporaryStreams/ServiceCollectionExtensions.cs b/src/Light.TemporaryStreams/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..4fe0760 --- /dev/null +++ b/src/Light.TemporaryStreams/ServiceCollectionExtensions.cs @@ -0,0 +1,71 @@ +using System; +using Light.GuardClauses; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; + +namespace Light.TemporaryStreams; + +/// +/// Provides extension methods for to register +/// and corresponding dependencies. +/// +public static class ServiceCollectionExtensions +{ + /// + /// Adds the to the specified . + /// + /// The to add the service to. + /// An optional delegate to create the . + /// + /// When true, the returns a delegate which logs exceptions + /// that occur during the deletion of temporary streams to Microsoft.Extensions.Logging. If false, the provider + /// will simply return null and logging will occur against the .NET Trace. + /// + /// The so that additional calls can be chained. + /// Thrown when is null. + public static IServiceCollection AddTemporaryStreamService( + this IServiceCollection services, + Func? createOptions = null, + bool integrateIntoMicrosoftExtensionsLogging = true + ) + { + services.MustNotBeNull(); + if (createOptions is null) + { + services.TryAddSingleton(); + } + else + { + services.TryAddSingleton(createOptions); + } + + if (integrateIntoMicrosoftExtensionsLogging) + { + services.TryAddSingleton( + sp => + { + var loggerFactory = sp.GetRequiredService(); + var logger = loggerFactory.CreateLogger(nameof(TemporaryStreamService)); + return new TemporaryStreamErrorHandlerProvider( + (stream, exception) => + logger.LogErrorDeletingTemporaryStream( + exception, + stream.GetUnderlyingFilePath() + ) + ); + } + ); + } + else + { + services.TryAddSingleton( + _ => new TemporaryStreamErrorHandlerProvider(null) + ); + } + + services.TryAddSingleton(); + services.TryAddSingleton(sp => sp.GetRequiredService()); + return services; + } +} diff --git a/tests/Light.TemporaryStreams.Tests/Light.TemporaryStreams.Tests.csproj b/tests/Light.TemporaryStreams.Tests/Light.TemporaryStreams.Tests.csproj new file mode 100644 index 0000000..21f0d65 --- /dev/null +++ b/tests/Light.TemporaryStreams.Tests/Light.TemporaryStreams.Tests.csproj @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs b/tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs new file mode 100644 index 0000000..163d583 --- /dev/null +++ b/tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs @@ -0,0 +1,92 @@ +using System; +using System.Threading.Tasks; +using FluentAssertions; +using Light.GuardClauses; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Neovolve.Logging.Xunit; +using Xunit; +using Xunit.Sdk; + +namespace Light.TemporaryStreams; + +public sealed class ServiceCollectionExtensionsTests +{ + private readonly ITestOutputHelper _output; + + public ServiceCollectionExtensionsTests(ITestOutputHelper output) => _output = output; + + [Fact] + public async Task AddTemporaryStreamService_ShouldRegisterAllNecessaryTypes_WhenNoConfigurationProvided() + { + await using var serviceProvider = new ServiceCollection() + .AddLogging(builder => builder.AddXunit(_output)) + .AddTemporaryStreamService() + .BuildServiceProvider(); + + serviceProvider.GetService().Should().NotBeNull(); + serviceProvider.GetService().Should().NotBeNull(); + serviceProvider.GetService().Should().NotBeNull() + .And.Be(new TemporaryStreamServiceOptions()); + var errorHandlerProvider = serviceProvider.GetRequiredService(); + var errorHandler = errorHandlerProvider.GetErrorHandlerDelegate(); + errorHandler.Should().NotBeNull(); + } + + [Fact] + public async Task AddTemporaryStreamService_ShouldNotIncorporateMicrosoftLogging_When() + { + await using var serviceProvider = new ServiceCollection() + .AddTemporaryStreamService(integrateIntoMicrosoftExtensionsLogging: false) + .BuildServiceProvider(); + + serviceProvider.GetService().Should().NotBeNull(); + serviceProvider.GetService().Should().NotBeNull(); + serviceProvider.GetService().Should().NotBeNull() + .And.Be(new TemporaryStreamServiceOptions()); + var errorHandlerProvider = serviceProvider.GetRequiredService(); + var errorHandler = errorHandlerProvider.GetErrorHandlerDelegate(); + errorHandler.Should().BeNull(); + } + + [Fact] + public async Task AddTemporaryStreamService_ShouldNotRegisterDefaultOptions_WhenDelegateIsProvided() + { + await using var serviceProvider = new ServiceCollection() + .AddLogging(builder => builder.AddXunit(_output)) + .AddTemporaryStreamService(_ => new TemporaryStreamServiceOptions { FileThresholdInBytes = 0 }) + .BuildServiceProvider(); + + serviceProvider.GetService().Should().NotBeNull(); + serviceProvider.GetService().Should().NotBeNull(); + serviceProvider.GetService().Should().NotBeNull() + .And.NotBe(new TemporaryStreamServiceOptions()); + } + + [Fact] + public async Task MicrosoftErrorHandler_ShouldLogErrorMessage_WhenExceptionIsReported() + { + using var logger = _output.BuildLogger(); + await using var serviceProvider = new ServiceCollection() + .AddSingleton(new LoggerFactoryStub(logger)) + .AddTemporaryStreamService() + .BuildServiceProvider(); + + var errorHandler = + serviceProvider.GetRequiredService().GetErrorHandlerDelegate(); + await using var temporaryStream = + serviceProvider.GetRequiredService().CreateTemporaryStream(100_000); + var exception = new XunitException("Just for testing purposes"); + errorHandler.MustNotBeNull().Invoke(temporaryStream, exception); + logger.Entries.Should().HaveCount(1); + } + + private sealed class LoggerFactoryStub(ICacheLogger logger) : ILoggerFactory + { + public void Dispose() { } + + public ILogger CreateLogger(string categoryName) => logger; + + public void AddProvider(ILoggerProvider provider) => throw new NotSupportedException(); + } +} diff --git a/tests/Light.TemporaryStreams.Tests/packages.lock.json b/tests/Light.TemporaryStreams.Tests/packages.lock.json new file mode 100644 index 0000000..371e013 --- /dev/null +++ b/tests/Light.TemporaryStreams.Tests/packages.lock.json @@ -0,0 +1,298 @@ +{ + "version": 2, + "dependencies": { + "net8.0": { + "FluentAssertions": { + "type": "Direct", + "requested": "[7.2.0, 7.2.0]", + "resolved": "7.2.0", + "contentHash": "k94gV49Otru4e9nKtj36KpA9UkjuAGKPmhfM0oqyI+rrtxhSrgaeEhILR0AbJ9iNaoagAeQtawPz6njQOC6WQA==", + "dependencies": { + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Direct", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Direct", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.14.1, )", + "resolved": "17.14.1", + "contentHash": "HJKqKOE+vshXra2aEHpi2TlxYX7Z9VFYkr+E5rwEvHC8eIXiyO+K9kNm8vmNom3e2rA56WqxU+/N9NJlLGXsJQ==", + "dependencies": { + "Microsoft.CodeCoverage": "17.14.1", + "Microsoft.TestPlatform.TestHost": "17.14.1" + } + }, + "Neovolve.Logging.Xunit.v3": { + "type": "Direct", + "requested": "[7.1.0, )", + "resolved": "7.1.0", + "contentHash": "qv7m92tiB9thOhzWawD7XjkV08ifPFg+tMAXh8GmL+1F4k8lqJNpdIPzDBM0ZkPwqFR4wkZx4bFi8z+YoyUqNg==", + "dependencies": { + "Microsoft.Extensions.Logging": "7.0.0", + "System.Text.Json": "6.0.11", + "xunit.v3.extensibility.core": "1.0.0" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[3.1.1, )", + "resolved": "3.1.1", + "contentHash": "gNu2zhnuwjq5vQlU4S7yK/lfaKZDLmtcu+vTjnhfTlMAUYn+Hmgu8IIX0UCwWepYkk+Szx03DHx1bDnc9Fd+9w==" + }, + "xunit.v3": { + "type": "Direct", + "requested": "[2.0.3, )", + "resolved": "2.0.3", + "contentHash": "Zx2r5xnUgyAIhI3cvfKaAr7Mj0Enn0zFhaMoTJ2hRYEPJlqlllUkTUvBBYalZQvpXGub/UQWq1nY5erD7Zv1cA==", + "dependencies": { + "xunit.analyzers": "1.22.0", + "xunit.v3.assert": "[2.0.3]", + "xunit.v3.core": "[2.0.3]" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.14.1", + "contentHash": "pmTrhfFIoplzFVbhVwUquT+77CbGH+h4/3mBpdmIlYtBi9nAB+kKI6dN3A/nV4DFi3wLLx/BlHIPK+MkbQ6Tpg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Microsoft.Testing.Extensions.TrxReport.Abstractions": { + "type": "Transitive", + "resolved": "1.6.3", + "contentHash": "0MdowM+3IDVWE5VBzVe9NvxsE4caSbM3fO+jlWVzEBr/Vnc3BWx+uV/Ex0dLLpkxkeUKH2gGWTNLb39rw3DDqw==", + "dependencies": { + "Microsoft.Testing.Platform": "1.6.3" + } + }, + "Microsoft.Testing.Platform": { + "type": "Transitive", + "resolved": "1.6.3", + "contentHash": "DqMZukaPo+vKzColfqd1I5qZebfISZT6ND70AOem/dYQmHsaMN0xg/JG7E0e80rwfxL7wAA4ylSg8j6KJf1Tuw==" + }, + "Microsoft.Testing.Platform.MSBuild": { + "type": "Transitive", + "resolved": "1.6.3", + "contentHash": "PXSYI5Iae29GM5636zOL8PlQD1YyOa9cfzfYLR43hrLjjK7RDJgMTvgAet3oZLgDTvz6pbzABZvhx+S/W5m8YA==", + "dependencies": { + "Microsoft.Testing.Platform": "1.6.3" + } + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.14.1", + "contentHash": "xTP1W6Mi6SWmuxd3a+jj9G9UoC850WGwZUps1Wah9r1ZxgXhdJfj1QqDLJkFjHDCvN42qDL2Ps5KjQYWUU0zcQ==", + "dependencies": { + "System.Reflection.Metadata": "8.0.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.14.1", + "contentHash": "d78LPzGKkJwsJXAQwsbJJ7LE7D1wB+rAyhHHAaODF+RDSQ0NgMjDFkSA1Djw18VrxO76GlKAjRUhl+H8NL8Z+Q==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.14.1", + "Newtonsoft.Json": "13.0.3" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==" + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ptvgrFh7PvWI8bcVqG5rsA/weWM09EnthFHR5SCnS6IN+P4mj6rE1lBDC4U8HL9/57htKAqy4KQ3bBj84cfYyQ==", + "dependencies": { + "System.Collections.Immutable": "8.0.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.11", + "contentHash": "xqC1HIbJMBFhrpYs76oYP+NAskNVjc6v73HqLal7ECRDPIp4oRU5pPavkD//vNactCn9DA2aaald/I5N+uZ5/g==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "1.22.0", + "contentHash": "MXTmnlJLQPSJfgxibeFgpUP5sj+3649BWkf3WgeUhAVUrI3nXzWE+BGH4OPfWkG2Q5x0SzIKgegikNhnfMgaXQ==" + }, + "xunit.v3.assert": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "6uTT9zLyg7YtP8fAZqOFcCpeGXtsh6K1+QVHHJl/aoQObr2qHvhGMuZbm5UYf4z49ytpQt6NzP6Iq4uWEBBh4g==" + }, + "xunit.v3.common": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "u3kTB9Fqo6X8keccsW4Zkn87nQNxMNZGm1rjJjCC0yThKP77N8H52Fx6CaochjGeGzEc2w9CUDu7C2ygu61bYg==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "6.0.0" + } + }, + "xunit.v3.core": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "KN2xOHNVGXI6AsPKatV9urqVs2YIGQ+2klY6HLys/oQauBVoS2W2+BRZz1rnwoJ+5aK+2+gfe1rLKi8iInT9Ow==", + "dependencies": { + "Microsoft.Testing.Platform.MSBuild": "1.6.3", + "xunit.v3.extensibility.core": "[2.0.3]", + "xunit.v3.runner.inproc.console": "[2.0.3]" + } + }, + "xunit.v3.extensibility.core": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "1uxfWR72veq0b5/3ghEA2zRAkdqmnA9ahCxWr1VEb2q6MBNKx6aHsAL85PyY172f1dsvUMqh7BSelaHsR5Df5w==", + "dependencies": { + "xunit.v3.common": "[2.0.3]" + } + }, + "xunit.v3.runner.common": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "Q+43ogqiJlWOG3l6Me7iNTm68CvVdX16OsHDoQcKCUEvWXHyiSRGBkcmMAT3OVENH0wS69QHi0q4mb3VsAbclA==", + "dependencies": { + "xunit.v3.common": "[2.0.3]" + } + }, + "xunit.v3.runner.inproc.console": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "S65IrpHbt9nHotyfs6MnjNsc8bZUMBLHHJcyky4ywDNKx+k07sjwaGb+otLQA4Z6FPCGIPrL7u0ThQm76FxBZw==", + "dependencies": { + "Microsoft.Testing.Extensions.TrxReport.Abstractions": "1.6.3", + "Microsoft.Testing.Platform": "1.6.3", + "xunit.v3.extensibility.core": "[2.0.3]", + "xunit.v3.runner.common": "[2.0.3]" + } + }, + "light.temporarystreams": { + "type": "Project", + "dependencies": { + "Light.TemporaryStreams.Core": "[1.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[8.0.0, )", + "Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )" + } + }, + "light.temporarystreams.core": { + "type": "Project", + "dependencies": { + "Light.GuardClauses": "[13.0.0, )" + } + }, + "Light.GuardClauses": { + "type": "CentralTransitive", + "requested": "[13.0.0, )", + "resolved": "13.0.0", + "contentHash": "mhlWUk0o+XibJgYuPlO9vQQpMmh4EAeDRFAac7pP6W3zmpjEeyUVGOiw+mdCxX469QQ2rkMYjWyHoDlZv599/w==" + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[8.0.0, )", + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "CentralTransitive", + "requested": "[8.0.0, )", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + } + } + } +} \ No newline at end of file diff --git a/tests/Light.TemporaryStreams.Tests/xunit.runner.json b/tests/Light.TemporaryStreams.Tests/xunit.runner.json new file mode 100644 index 0000000..c2f8426 --- /dev/null +++ b/tests/Light.TemporaryStreams.Tests/xunit.runner.json @@ -0,0 +1,3 @@ +{ + "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json" +} From 0209a16f33df5f09763b5c876265b542687bade8 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 6 Jul 2025 23:28:13 +0200 Subject: [PATCH 9/9] test: fix name of AddTemporaryStreamService_ShouldNotIncorporateMicrosoftLogging_WhenCorrespondingArgumentIsFalse Signed-off-by: Kenny Pflug --- .../ServiceCollectionExtensionsTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs b/tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs index 163d583..a5ddd11 100644 --- a/tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs +++ b/tests/Light.TemporaryStreams.Tests/ServiceCollectionExtensionsTests.cs @@ -34,7 +34,7 @@ public async Task AddTemporaryStreamService_ShouldRegisterAllNecessaryTypes_When } [Fact] - public async Task AddTemporaryStreamService_ShouldNotIncorporateMicrosoftLogging_When() + public async Task AddTemporaryStreamService_ShouldNotIncorporateMicrosoftLogging_WhenCorrespondingArgumentIsFalse() { await using var serviceProvider = new ServiceCollection() .AddTemporaryStreamService(integrateIntoMicrosoftExtensionsLogging: false)