Skip to content

Commit

Permalink
refactor(#603): Add default console logger
Browse files Browse the repository at this point in the history
  • Loading branch information
HofmeisterAn committed Nov 22, 2022
1 parent 446f002 commit c6188be
Show file tree
Hide file tree
Showing 36 changed files with 139 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ public virtual bool IsAvailable()
{
try
{
TaskFactory.StartNew(() => dockerClient.System.PingAsync()).Unwrap().GetAwaiter().GetResult();
TaskFactory.StartNew(() => dockerClient.System.PingAsync())
.Unwrap()
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();

return true;
}
catch (Exception)
Expand Down
4 changes: 3 additions & 1 deletion src/Testcontainers/Clients/DockerImageOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ await this.DeleteAsync(image, ct)
await this.Docker.Images.BuildImageFromDockerfileAsync(buildParameters, dockerfileStream, Array.Empty<AuthConfig>(), new Dictionary<string, string>(), this.traceProgress, ct)
.ConfigureAwait(false);

var imageHasBeenCreated = await this.ExistsWithNameAsync(image.FullName, ct).ConfigureAwait(false);
var imageHasBeenCreated = await this.ExistsWithNameAsync(image.FullName, ct)
.ConfigureAwait(false);

if (!imageHasBeenCreated)
{
throw new InvalidOperationException($"Docker image {image.FullName} has not been created.");
Expand Down
3 changes: 1 addition & 2 deletions src/Testcontainers/Configurations/TestcontainersSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace DotNet.Testcontainers.Configurations
using DotNet.Testcontainers.Images;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

/// <summary>
/// This class represents the Testcontainers settings.
Expand Down Expand Up @@ -83,7 +82,7 @@ static TestcontainersSettings()
[PublicAPI]
[NotNull]
public static ILogger Logger { get; set; }
= NullLogger.Instance;
= new Logger();

/// <summary>
/// Gets or sets the host operating system.
Expand Down
2 changes: 1 addition & 1 deletion src/Testcontainers/Containers/TestcontainersContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ private void ThrowIfContainerHasNotBeenCreated()

private string GetContainerGateway()
{
const string localhost = "localhost";
const string localhost = "127.0.0.1";

if (!ContainerHasBeenCreatedStates.HasFlag(this.State))
{
Expand Down
112 changes: 112 additions & 0 deletions src/Testcontainers/Logger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
namespace DotNet.Testcontainers
{
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;

/// <summary>
/// An <see cref="ILogger" /> implementation that forwards messages to the console. Not every test framework or environment supports this approach. Developers may still need to configure their own logging implementation.
/// If VSTest.Console.exe loads the test adapter in a deterministic order, we can write our own test adapter and intercept the IMessageLogger instance: https://github.com/microsoft/vstest/issues/4125#issuecomment-1320880502.
/// To debug the test host and runner set the environment variables VSTEST_HOST_DEBUG and VSTEST_RUNNER_DEBUG to 1. To enable VSTest logging set VSTEST_DIAG to 1 and VSTEST_DIAG_VERBOSITY to verbose.
/// The following example contains the ITestExecutor implementations. It is important that the assembly ends with TestAdapter.dll.
/// </summary>
/// <example>
/// <code>
/// [FileExtension(DllFileExtension)]
/// [FileExtension(ExeFileExtension)]
/// [DefaultExecutorUri(ExecutorUri)]
/// [ExtensionUri(ExecutorUri)]
/// [Category(Category)]
/// internal sealed class UssDiscovery : ITestDiscoverer, ITestExecutor
/// {
/// private const string DllFileExtension = &quot;.dll&quot;;
///
/// private const string ExeFileExtension = &quot;.exe&quot;;
///
/// private const string ExecutorUri = &quot;executor://testcontainers.org/v1&quot;;
///
/// private const string Category = &quot;managed&quot;;
///
/// public void DiscoverTests(IEnumerable&lt;string&gt; sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink)
/// {
/// }
///
/// public void RunTests(IEnumerable&lt;TestCase&gt; tests, IRunContext runContext, IFrameworkHandle frameworkHandle)
/// {
/// SetLogger(frameworkHandle);
/// }
///
/// public void RunTests(IEnumerable&lt;string&gt; sources, IRunContext runContext, IFrameworkHandle frameworkHandle)
/// {
/// SetLogger(frameworkHandle);
/// }
///
/// public void Cancel()
/// {
/// }
///
/// private static void SetLogger(IMessageLogger logger)
/// {
/// // Set the TestcontainersSettings.Logger. Use a semaphore to block the test execution until the logger is set.
/// }
/// }
/// </code>
/// </example>
internal sealed class Logger : ILogger, IDisposable
{
private readonly Stopwatch stopwatch = Stopwatch.StartNew();

public Logger()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Console.IsOutputRedirected && !Console.IsErrorRedirected)
{
Console.BufferWidth = short.MaxValue - 1;
}
}

public void Dispose()
{
}

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
TextWriter console;

switch (logLevel)
{
case LogLevel.Information:
console = Console.Out;
break;
case LogLevel.Warning:
console = Console.Out;
break;
case LogLevel.Error:
console = Console.Error;
break;
case LogLevel.Critical:
console = Console.Error;
break;
default:
console = TextWriter.Null;
break;
}

var message = string.Format(CultureInfo.CurrentCulture, "[testcontainers.org {0:hh\\:mm\\:ss\\.ff}] {1}", this.stopwatch.Elapsed, formatter.Invoke(state, exception));
Debug.WriteLine(message);
console.WriteLine(message);
}

public bool IsEnabled(LogLevel logLevel)
{
return true;
}

public IDisposable BeginScope<TState>(TState state)
{
return this;
}
}
}
12 changes: 6 additions & 6 deletions src/Testcontainers/Logging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ internal static class Logging
= LoggerMessage.Define<string>(LogLevel.Information, default, "Delete Docker container {Id}");

private static readonly Action<ILogger, string, string, Exception> _ExtractArchiveToDockerContainer
= LoggerMessage.Define<string, string>(LogLevel.Information, default, "Copy tar archive to {Path} at Docker container {Id}");
= LoggerMessage.Define<string, string>(LogLevel.Information, default, "Copy tar archive to \"{Path}\" at Docker container {Id}");

private static readonly Action<ILogger, string, string, Exception> _GetArchiveFromDockerContainer
= LoggerMessage.Define<string, string>(LogLevel.Information, default, "Read {Path} from Docker container {Id}");
= LoggerMessage.Define<string, string>(LogLevel.Information, default, "Read \"{Path}\" from Docker container {Id}");

private static readonly Action<ILogger, Type, string, Exception> _AttachToDockerContainer
= LoggerMessage.Define<Type, string>(LogLevel.Information, default, "Attach {OutputConsumer} at Docker container {Id}");

private static readonly Action<ILogger, IEnumerable<string>, string, Exception> _ExecuteCommandInDockerContainer
= LoggerMessage.Define<IEnumerable<string>, string>(LogLevel.Information, default, "Execute {Command} at Docker container {Id}");
private static readonly Action<ILogger, string, string, Exception> _ExecuteCommandInDockerContainer
= LoggerMessage.Define<string, string>(LogLevel.Information, default, "Execute \"{Command}\" at Docker container {Id}");

private static readonly Action<ILogger, string, Exception> _DockerImageCreated
= LoggerMessage.Define<string>(LogLevel.Information, default, "Docker image {FullName} created");
Expand Down Expand Up @@ -75,7 +75,7 @@ internal static class Logging
= LoggerMessage.Define<Guid, string>(LogLevel.Debug, default, "Lost connection to resource reaper {Id} at {Endpoint}");

private static readonly Action<ILogger, string, Exception> _DockerConfigFileNotFound
= LoggerMessage.Define<string>(LogLevel.Information, default, "Docker config {DockerConfigFilePath} not found");
= LoggerMessage.Define<string>(LogLevel.Information, default, "Docker config \"{DockerConfigFilePath}\" not found");

private static readonly Action<ILogger, string, Exception> _SearchingDockerRegistryCredential
= LoggerMessage.Define<string>(LogLevel.Information, default, "Searching Docker registry credential in {CredentialStore}");
Expand Down Expand Up @@ -144,7 +144,7 @@ public static void AttachToDockerContainer(this ILogger logger, string id, Type

public static void ExecuteCommandInDockerContainer(this ILogger logger, string id, IEnumerable<string> command)
{
_ExecuteCommandInDockerContainer(logger, command, id, null);
_ExecuteCommandInDockerContainer(logger, string.Join(" ", command), id, null);
}

public static void DockerImageCreated(this ILogger logger, IDockerImage image)
Expand Down
2 changes: 0 additions & 2 deletions src/Testcontainers/Networks/NonExistingDockerNetwork.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
namespace DotNet.Testcontainers.Networks
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet.Models;
Expand Down
19 changes: 0 additions & 19 deletions tests/Testcontainers.Tests/CustomSerilogLoggerFactory.cs

This file was deleted.

28 changes: 0 additions & 28 deletions tests/Testcontainers.Tests/Initialization.cs

This file was deleted.

39 changes: 0 additions & 39 deletions tests/Testcontainers.Tests/Initialized.cs

This file was deleted.

8 changes: 6 additions & 2 deletions tests/Testcontainers.Tests/SkipOnLinuxEngineAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ namespace DotNet.Testcontainers.Tests
{
using System;
using System.Diagnostics;
using DotNet.Testcontainers.Configurations;
using Xunit;

public sealed class SkipOnLinuxEngineAttribute : FactAttribute
{
private static readonly bool IsLinuxEngineEnabled = GetIsLinuxEngineEnabled();
static SkipOnLinuxEngineAttribute()
{
TestcontainersSettings.ResourceReaperEnabled = GetIsLinuxEngineEnabled();
}

public SkipOnLinuxEngineAttribute()
{
if (IsLinuxEngineEnabled)
if (TestcontainersSettings.ResourceReaperEnabled)
{
this.Skip = "Windows Docker engine is not available.";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ private sealed class AuthProviderTestData : List<object[]>
{
public AuthProviderTestData()
{
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
var defaultConfiguration = new PropertiesFileConfiguration(Array.Empty<string>());
var dockerTlsConfiguration = new PropertiesFileConfiguration("docker.tls=true", $"docker.cert.path={CertificatesDirectoryPath}");
var dockerMTlsConfiguration = new PropertiesFileConfiguration("docker.tls.verify=true", $"docker.cert.path={CertificatesDirectoryPath}");
Expand All @@ -66,8 +65,8 @@ public AuthProviderTestData()
this.Add(new object[] { new EnvironmentEndpointAuthenticationProvider(DockerHostConfiguration), true });
this.Add(new object[] { new EnvironmentEndpointAuthenticationProvider(Array.Empty<ICustomConfiguration>()), false });
this.Add(new object[] { new EnvironmentEndpointAuthenticationProvider(defaultConfiguration, DockerHostConfiguration), true });
this.Add(new object[] { new NpipeEndpointAuthenticationProvider(), isWindows });
this.Add(new object[] { new UnixEndpointAuthenticationProvider(), !isWindows });
this.Add(new object[] { new NpipeEndpointAuthenticationProvider(), RuntimeInformation.IsOSPlatform(OSPlatform.Windows) });
this.Add(new object[] { new UnixEndpointAuthenticationProvider(), !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace DotNet.Testcontainers.Tests.Unit

public static class TestcontainersAccessInformationTest
{
[Collection(nameof(Testcontainers))]
public sealed class AccessDockerInformation
{
private const string DoesNotExist = nameof(TestcontainersAccessInformationTest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ private static async Task EstablishConnection(AzuriteFixture.AzuriteDefaultFixtu
Assert.Contains(TableServiceDataFileName, execResult.Stdout);
}

[Collection(nameof(Testcontainers))]
public sealed class CommonContainerPorts : IClassFixture<AzuriteFixture.AzuriteDefaultFixture>
{
private readonly AzuriteFixture.AzuriteDefaultFixture commonContainerPorts;
Expand All @@ -109,7 +108,6 @@ public async Task ConnectionEstablished()
}
}

[Collection(nameof(Testcontainers))]
public sealed class CustomContainerPorts : IClassFixture<AzuriteFixture.AzuriteWithCustomContainerPortsFixture>
{
private readonly AzuriteFixture.AzuriteDefaultFixture customContainerPorts;
Expand All @@ -128,7 +126,6 @@ public async Task ConnectionEstablished()
}
}

[Collection(nameof(Testcontainers))]
public sealed class BlobServiceEnabled : IClassFixture<AzuriteFixture.AzuriteWithBlobOnlyFixture>
{
private readonly AzuriteFixture.AzuriteDefaultFixture azurite;
Expand Down Expand Up @@ -171,7 +168,6 @@ await Assert.ThrowsAsync<RequestFailedException>(() => tableServiceClient.GetPro
}
}

[Collection(nameof(Testcontainers))]
public sealed class QueueServiceEnabled : IClassFixture<AzuriteFixture.AzuriteWithQueueOnlyFixture>
{
private readonly AzuriteFixture.AzuriteDefaultFixture azurite;
Expand Down Expand Up @@ -214,7 +210,6 @@ await Assert.ThrowsAsync<RequestFailedException>(() => tableServiceClient.GetPro
}
}

[Collection(nameof(Testcontainers))]
public sealed class TableServiceEnabled : IClassFixture<AzuriteFixture.AzuriteWithTableOnlyFixture>
{
private readonly AzuriteFixture.AzuriteDefaultFixture azurite;
Expand Down Expand Up @@ -257,7 +252,6 @@ await Assert.ThrowsAsync<RequestFailedException>(() => queueServiceClient.GetPro
}
}

[Collection(nameof(Testcontainers))]
public sealed class CustomLocation : IClassFixture<AzuriteFixture.AzuriteWithCustomWorkspaceFixture>
{
private readonly IEnumerable<string> dataFiles;
Expand Down
Loading

0 comments on commit c6188be

Please sign in to comment.