From f0484f602abafc8b100c60f95bc34cef2db338fa Mon Sep 17 00:00:00 2001 From: Louie Farol Date: Fri, 8 Nov 2024 16:24:12 -0800 Subject: [PATCH] SNOW-834781: Refactor/add tests --- .../ConnectionMultiplePoolsAsyncIT.cs | 3 +- .../ConnectionPoolCommonIT.cs | 7 +- .../IntegrationTests/EasyLoggingIT.cs | 124 -------- .../IntegrationTests/SFBindTestIT.cs | 11 +- .../IntegrationTests/SFConnectionIT.cs | 19 +- .../Mock/MockSnowflakeDbConnection.cs | 11 +- Snowflake.Data.Tests/SFBaseTest.cs | 22 +- .../Snowflake.Data.Tests.csproj | 21 ++ Snowflake.Data.Tests/TestLog4Net.config | 20 ++ Snowflake.Data.Tests/TestNLog.config | 23 ++ Snowflake.Data.Tests/TestSerilog.config | 15 + .../EasyLoggingConfigFinderTest.cs | 259 ----------------- .../EasyLoggingConfigParserTest.cs | 132 --------- .../EasyLoggingConfigProviderTest.cs | 58 ---- .../Configuration/EasyLoggingLogLevelTest.cs | 38 --- .../UnitTests/Logger/EasyLoggerManagerTest.cs | 150 ---------- .../Logger/EasyLoggingStarterTest.cs | 274 ------------------ .../UnitTests/Logger/SFLoggerTest.cs | 241 ++++++++++----- .../UnitTests/SFSessionTest.cs | 20 -- .../Util/ConnectingThreads.cs | 23 +- .../Util/DbConnectionExtensions.cs | 7 +- Snowflake.Data.Tests/log4net.config | 20 ++ 22 files changed, 321 insertions(+), 1177 deletions(-) delete mode 100644 Snowflake.Data.Tests/IntegrationTests/EasyLoggingIT.cs create mode 100644 Snowflake.Data.Tests/TestLog4Net.config create mode 100644 Snowflake.Data.Tests/TestNLog.config create mode 100644 Snowflake.Data.Tests/TestSerilog.config delete mode 100644 Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigFinderTest.cs delete mode 100644 Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigParserTest.cs delete mode 100644 Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigProviderTest.cs delete mode 100644 Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingLogLevelTest.cs delete mode 100644 Snowflake.Data.Tests/UnitTests/Logger/EasyLoggerManagerTest.cs delete mode 100644 Snowflake.Data.Tests/UnitTests/Logger/EasyLoggingStarterTest.cs create mode 100644 Snowflake.Data.Tests/log4net.config diff --git a/Snowflake.Data.Tests/IntegrationTests/ConnectionMultiplePoolsAsyncIT.cs b/Snowflake.Data.Tests/IntegrationTests/ConnectionMultiplePoolsAsyncIT.cs index e263cb9d3..0d61e5933 100644 --- a/Snowflake.Data.Tests/IntegrationTests/ConnectionMultiplePoolsAsyncIT.cs +++ b/Snowflake.Data.Tests/IntegrationTests/ConnectionMultiplePoolsAsyncIT.cs @@ -1,6 +1,7 @@ using System.Data.Common; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Snowflake.Data.Client; @@ -17,7 +18,7 @@ namespace Snowflake.Data.Tests.IntegrationTests public class ConnectionMultiplePoolsAsyncIT: SFBaseTestAsync { private readonly PoolConfig _previousPoolConfig = new PoolConfig(); - private readonly SFLogger logger = SFLoggerFactory.GetLogger(); + private readonly ILogger logger = SFLoggerFactory.GetLogger(); [SetUp] public new void BeforeTest() diff --git a/Snowflake.Data.Tests/IntegrationTests/ConnectionPoolCommonIT.cs b/Snowflake.Data.Tests/IntegrationTests/ConnectionPoolCommonIT.cs index 9bf78ffbe..db7fd0c20 100644 --- a/Snowflake.Data.Tests/IntegrationTests/ConnectionPoolCommonIT.cs +++ b/Snowflake.Data.Tests/IntegrationTests/ConnectionPoolCommonIT.cs @@ -11,6 +11,7 @@ using Snowflake.Data.Core.Session; using Snowflake.Data.Log; using Snowflake.Data.Tests.Util; +using Microsoft.Extensions.Logging; namespace Snowflake.Data.Tests.IntegrationTests { @@ -20,7 +21,7 @@ namespace Snowflake.Data.Tests.IntegrationTests class ConnectionPoolCommonIT : SFBaseTest { private readonly ConnectionPoolType _connectionPoolTypeUnderTest; - private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger(); + private static readonly ILogger s_logger = SFLoggerFactory.GetLogger(); private readonly PoolConfig _previousPoolConfig; public ConnectionPoolCommonIT(ConnectionPoolType connectionPoolTypeUnderTest) @@ -38,8 +39,8 @@ public ConnectionPoolCommonIT(ConnectionPoolType connectionPoolTypeUnderTest) { SnowflakeDbConnectionPool.SetPooling(true); } - s_logger.Debug($"---------------- BeforeTest ---------------------"); - s_logger.Debug($"Testing Pool Type: {SnowflakeDbConnectionPool.GetConnectionPoolVersion()}"); + s_logger.LogDebug($"---------------- BeforeTest ---------------------"); + s_logger.LogDebug($"Testing Pool Type: {SnowflakeDbConnectionPool.GetConnectionPoolVersion()}"); } [TearDown] diff --git a/Snowflake.Data.Tests/IntegrationTests/EasyLoggingIT.cs b/Snowflake.Data.Tests/IntegrationTests/EasyLoggingIT.cs deleted file mode 100644 index fd2e79409..000000000 --- a/Snowflake.Data.Tests/IntegrationTests/EasyLoggingIT.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System.Data; -using System.IO; -using System.Runtime.InteropServices; -using Mono.Unix.Native; -using NUnit.Framework; -using Snowflake.Data.Client; -using Snowflake.Data.Configuration; -using Snowflake.Data.Core; -using Snowflake.Data.Log; -using static Snowflake.Data.Tests.UnitTests.Configuration.EasyLoggingConfigGenerator; - -namespace Snowflake.Data.Tests.IntegrationTests -{ - [TestFixture, NonParallelizable] - public class EasyLoggingIT: SFBaseTest - { - private static readonly string s_workingDirectory = Path.Combine(Path.GetTempPath(), "easy_logging_test_configs_", Path.GetRandomFileName()); - - [OneTimeSetUp] - public static void BeforeAll() - { - if (!Directory.Exists(s_workingDirectory)) - { - Directory.CreateDirectory(s_workingDirectory); - } - } - - [OneTimeTearDown] - public static void AfterAll() - { - Directory.Delete(s_workingDirectory, true); - } - - [TearDown] - public static void AfterEach() - { - EasyLoggingStarter.Instance.Reset(EasyLoggingLogLevel.Warn); - } - - [Test] - public void TestEnableEasyLogging() - { - // arrange - var configFilePath = CreateConfigTempFile(s_workingDirectory, Config("WARN", s_workingDirectory)); - using (IDbConnection conn = new SnowflakeDbConnection()) - { - conn.ConnectionString = ConnectionString + $"CLIENT_CONFIG_FILE={configFilePath}"; - - // act - conn.Open(); - - // assert - Assert.IsTrue(EasyLoggerManager.HasEasyLoggingAppender()); - } - } - - [Test] - public void TestFailToEnableEasyLoggingForWrongConfiguration() - { - // arrange - var configFilePath = CreateConfigTempFile(s_workingDirectory, "random config content"); - using (IDbConnection conn = new SnowflakeDbConnection()) - { - conn.ConnectionString = ConnectionString + $"CLIENT_CONFIG_FILE={configFilePath}"; - - // act - var thrown = Assert.Throws(() => conn.Open()); - - // assert - Assert.That(thrown.Message, Does.Contain("Connection string is invalid: Unable to initialize session")); - Assert.IsFalse(EasyLoggerManager.HasEasyLoggingAppender()); - } - } - - [Test] - public void TestFailToEnableEasyLoggingWhenConfigHasWrongPermissions() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Assert.Ignore("skip test on Windows"); - } - - // arrange - var configFilePath = CreateConfigTempFile(s_workingDirectory, Config("WARN", s_workingDirectory)); - Syscall.chmod(configFilePath, FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IWGRP); - using (IDbConnection conn = new SnowflakeDbConnection()) - { - conn.ConnectionString = ConnectionString + $"CLIENT_CONFIG_FILE={configFilePath}"; - - // act - var thrown = Assert.Throws(() => conn.Open()); - - // assert - Assert.That(thrown.Message, Does.Contain("Connection string is invalid: Unable to initialize session")); - Assert.IsFalse(EasyLoggerManager.HasEasyLoggingAppender()); - } - } - - [Test] - public void TestFailToEnableEasyLoggingWhenLogDirectoryNotAccessible() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Assert.Ignore("skip test on Windows"); - } - - // arrange - var configFilePath = CreateConfigTempFile(s_workingDirectory, Config("WARN", "/")); - using (IDbConnection conn = new SnowflakeDbConnection()) - { - conn.ConnectionString = ConnectionString + $"CLIENT_CONFIG_FILE={configFilePath}"; - - // act - var thrown = Assert.Throws(() => conn.Open()); - - // assert - Assert.That(thrown.Message, Does.Contain("Connection string is invalid: Unable to initialize session")); - Assert.That(thrown.InnerException.Message, Does.Contain("Failed to create logs directory")); - Assert.IsFalse(EasyLoggerManager.HasEasyLoggingAppender()); - } - - } - } -} diff --git a/Snowflake.Data.Tests/IntegrationTests/SFBindTestIT.cs b/Snowflake.Data.Tests/IntegrationTests/SFBindTestIT.cs index 1683700cb..fce90502b 100755 --- a/Snowflake.Data.Tests/IntegrationTests/SFBindTestIT.cs +++ b/Snowflake.Data.Tests/IntegrationTests/SFBindTestIT.cs @@ -15,6 +15,7 @@ using System.Globalization; using System.Collections.Generic; using Snowflake.Data.Tests.Util; +using Microsoft.Extensions.Logging; namespace Snowflake.Data.Tests.IntegrationTests { @@ -22,7 +23,7 @@ namespace Snowflake.Data.Tests.IntegrationTests [TestFixture] class SFBindTestIT : SFBaseTest { - private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger(); + private static readonly ILogger s_logger = SFLoggerFactory.GetLogger(); [Test] public void TestArrayBind() @@ -896,7 +897,7 @@ public void TestDateTimeBinding(ResultFormat resultFormat, SFTableType tableType var bindingThreshold = 65280; // when exceeded enforces bindings via file on stage var smallBatchRowCount = 2; var bigBatchRowCount = bindingThreshold / 2; - s_logger.Info(testCase); + s_logger.LogInformation(testCase); using (IDbConnection conn = new SnowflakeDbConnection(ConnectionString)) { @@ -925,7 +926,7 @@ public void TestDateTimeBinding(ResultFormat resultFormat, SFTableType tableType var row = 0; using (var select = conn.CreateCommand($"select id, ts from {TableName} order by id")) { - s_logger.Debug(select.CommandText); + s_logger.LogDebug(select.CommandText); var reader = select.ExecuteReader(); while (reader.Read()) { @@ -956,7 +957,7 @@ private void InsertSingleRecord(IDbConnection conn, string sqlInsert, DbType bin } // Act - s_logger.Info(sqlInsert); + s_logger.LogInformation(sqlInsert); var rowsAffected = insert.ExecuteNonQuery(); // Assert @@ -982,7 +983,7 @@ private void InsertMultipleRecords(IDbConnection conn, string sqlInsert, DbType } // Act - s_logger.Debug(sqlInsert); + s_logger.LogDebug(sqlInsert); var rowsAffected = insert.ExecuteNonQuery(); // Assert diff --git a/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs b/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs index 6f3c87291..68b96d0c6 100644 --- a/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs +++ b/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs @@ -21,11 +21,12 @@ namespace Snowflake.Data.Tests.IntegrationTests using Snowflake.Data.Tests.Mock; using System.Runtime.InteropServices; using System.Net.Http; + using Microsoft.Extensions.Logging; [TestFixture] class SFConnectionIT : SFBaseTest { - private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger(); + private static readonly ILogger s_logger = SFLoggerFactory.GetLogger(); [Test] public void TestBasicConnection() @@ -83,14 +84,14 @@ public void TestApplicationName() try { conn.Open(); - s_logger.Debug("{appName}"); + s_logger.LogDebug("{appName}"); Assert.Fail(); } catch (SnowflakeDbException e) { // Expected - s_logger.Debug("Failed opening connection ", e); + s_logger.LogDebug("Failed opening connection ", e); AssertIsConnectionFailure(e); } @@ -127,7 +128,7 @@ public void TestIncorrectUserOrPasswordBasicConnection() catch (SnowflakeDbException e) { // Expected - s_logger.Debug("Failed opening connection ", e); + s_logger.LogDebug("Failed opening connection ", e); AssertIsConnectionFailure(e); } @@ -142,7 +143,7 @@ public void TestConnectionIsNotMarkedAsOpenWhenWasNotCorrectlyOpenedBefore(bool { for (int i = 0; i < 2; ++i) { - s_logger.Debug($"Running try #{i}"); + s_logger.LogDebug($"Running try #{i}"); SnowflakeDbConnection snowflakeConnection = null; try { @@ -168,7 +169,7 @@ public void TestConnectionIsNotMarkedAsOpenWhenWasNotCorrectlyOpenedWithUsingCla { for (int i = 0; i < 2; ++i) { - s_logger.Debug($"Running try #{i}"); + s_logger.LogDebug($"Running try #{i}"); SnowflakeDbConnection snowflakeConnection = null; try { @@ -1559,7 +1560,7 @@ public void TestInvalidProxySettingFromConnectionString() catch (SnowflakeDbException e) { // Expected - s_logger.Debug("Failed opening connection ", e); + s_logger.LogDebug("Failed opening connection ", e); Assert.AreEqual(270001, e.ErrorCode); //Internal error AssertIsConnectionFailure(e); } @@ -1868,7 +1869,7 @@ public void TestKeepAlive() [TestFixture] class SFConnectionITAsync : SFBaseTestAsync { - private static SFLogger logger = SFLoggerFactory.GetLogger(); + private static ILogger logger = SFLoggerFactory.GetLogger(); [Test] @@ -1898,7 +1899,7 @@ public void TestCancelLoginBeforeTimeout() // Cancel the connection because it will never succeed since there is no // connection_timeout defined - logger.Debug("connectionCancelToken.Cancel "); + logger.LogDebug("connectionCancelToken.Cancel "); connectionCancelToken.Cancel(); try diff --git a/Snowflake.Data.Tests/Mock/MockSnowflakeDbConnection.cs b/Snowflake.Data.Tests/Mock/MockSnowflakeDbConnection.cs index c6d8f0698..0c3d59e1a 100644 --- a/Snowflake.Data.Tests/Mock/MockSnowflakeDbConnection.cs +++ b/Snowflake.Data.Tests/Mock/MockSnowflakeDbConnection.cs @@ -9,12 +9,13 @@ using System.Data; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; namespace Snowflake.Data.Tests.Mock { class MockSnowflakeDbConnection : SnowflakeDbConnection { - private SFLogger logger = SFLoggerFactory.GetLogger(); + private ILogger logger = SFLoggerFactory.GetLogger(); private IMockRestRequester _restRequester; @@ -31,7 +32,7 @@ public MockSnowflakeDbConnection() public override void Open() { - logger.Debug("Open Connection."); + logger.LogDebug("Open Connection."); SetMockSession(); try { @@ -41,7 +42,7 @@ public override void Open() { // Otherwise when Dispose() is called, the close request would timeout. _connectionState = System.Data.ConnectionState.Closed; - logger.Error("Unable to connect", e); + logger.LogError("Unable to connect", e); throw; } OnSessionEstablished(); @@ -61,14 +62,14 @@ public override Task OpenAsync(CancellationToken cancellationToken) // Exception from SfSession.OpenAsync Exception sfSessionEx = previousTask.Exception; _connectionState = ConnectionState.Closed; - logger.Error("Unable to connect", sfSessionEx); + logger.LogError("Unable to connect", sfSessionEx); throw //sfSessionEx.InnerException; new SnowflakeDbException(sfSessionEx, SFError.INTERNAL_ERROR, "Unable to connect"); } if (previousTask.IsCanceled) { _connectionState = ConnectionState.Closed; - logger.Debug("Connection canceled"); + logger.LogDebug("Connection canceled"); } else { diff --git a/Snowflake.Data.Tests/SFBaseTest.cs b/Snowflake.Data.Tests/SFBaseTest.cs index 1e8e13018..390fbf789 100755 --- a/Snowflake.Data.Tests/SFBaseTest.cs +++ b/Snowflake.Data.Tests/SFBaseTest.cs @@ -14,6 +14,7 @@ using Snowflake.Data.Client; using Snowflake.Data.Log; using Snowflake.Data.Tests.Util; +using Microsoft.Extensions.Logging; [assembly:LevelOfParallelism(10)] @@ -57,7 +58,7 @@ public static void TearDownContext() #endif public class SFBaseTestAsync { - private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger(); + private static readonly ILogger s_logger = SFLoggerFactory.GetLogger(); private const string ConnectionStringWithoutAuthFmt = "scheme={0};host={1};port={2};" + "account={3};role={4};db={5};schema={6};warehouse={7}"; @@ -118,7 +119,7 @@ protected void CreateOrReplaceTable(IDbConnection conn, string tableName, string var columnsStr = string.Join(", ", columns); var cmd = conn.CreateCommand(); cmd.CommandText = $"CREATE OR REPLACE {tableType} TABLE {tableName}({columnsStr}) {additionalQueryStr}"; - s_logger.Debug(cmd.CommandText); + s_logger.LogDebug(cmd.CommandText); cmd.ExecuteNonQuery(); _tablesToRemove.Add(tableName); @@ -186,14 +187,19 @@ public static void RecordTestPerformance(string name, TimeSpan time) public void Setup() { #if NETFRAMEWORK - log4net.GlobalContext.Properties["framework"] = "net471"; - log4net.Config.XmlConfigurator.Configure(); - + Environment.SetEnvironmentVariable("net_test_framework", "net471"); #else - log4net.GlobalContext.Properties["framework"] = "net6.0"; - var logRepository = log4net.LogManager.GetRepository(Assembly.GetEntryAssembly()); - log4net.Config.XmlConfigurator.Configure(logRepository, new FileInfo("App.config")); + Environment.SetEnvironmentVariable("net_test_framework", "net6.0"); #endif + ILoggerFactory factory = LoggerFactory.Create( + builder => builder + .AddLog4Net() + .SetMinimumLevel(LogLevel.Debug)); + + var logger = factory.CreateLogger("SFBaseTest"); + SFLoggerFactory.SetCustomLogger(logger); + SFLoggerFactory.EnableLogger(); + var cloud = Environment.GetEnvironmentVariable("snowflake_cloud_env"); Assert.IsTrue(cloud == null || cloud == "AWS" || cloud == "AZURE" || cloud == "GCP", "{0} is not supported. Specify AWS, AZURE or GCP as cloud environment", cloud); diff --git a/Snowflake.Data.Tests/Snowflake.Data.Tests.csproj b/Snowflake.Data.Tests/Snowflake.Data.Tests.csproj index cc895154e..1d08fb783 100644 --- a/Snowflake.Data.Tests/Snowflake.Data.Tests.csproj +++ b/Snowflake.Data.Tests/Snowflake.Data.Tests.csproj @@ -13,10 +13,16 @@ + + + + + + @@ -35,6 +41,21 @@ + + + Always + + + Always + + + Always + + + Always + + + full True diff --git a/Snowflake.Data.Tests/TestLog4Net.config b/Snowflake.Data.Tests/TestLog4Net.config new file mode 100644 index 000000000..784355885 --- /dev/null +++ b/Snowflake.Data.Tests/TestLog4Net.config @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Snowflake.Data.Tests/TestNLog.config b/Snowflake.Data.Tests/TestNLog.config new file mode 100644 index 000000000..85c376043 --- /dev/null +++ b/Snowflake.Data.Tests/TestNLog.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/Snowflake.Data.Tests/TestSerilog.config b/Snowflake.Data.Tests/TestSerilog.config new file mode 100644 index 000000000..65bf5c82c --- /dev/null +++ b/Snowflake.Data.Tests/TestSerilog.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigFinderTest.cs b/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigFinderTest.cs deleted file mode 100644 index b23fbbf0e..000000000 --- a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigFinderTest.cs +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2023 Snowflake Computing Inc. All rights reserved. - */ - -using System; -using System.IO; -using System.Runtime.InteropServices; -using Mono.Unix; -using Moq; -using NUnit.Framework; -using Snowflake.Data.Configuration; -using Snowflake.Data.Core.Tools; - -namespace Snowflake.Data.Tests.UnitTests.Configuration -{ - [TestFixture] - public class EasyLoggingConfigFinderTest - { - private const string InputConfigFilePath = "input_config.json"; - private const string EnvironmentalConfigFilePath = "environmental_config.json"; - private const string HomeDirectory = "/home/user"; - private const string DriverDirectory = "."; - private static readonly string s_driverConfigFilePath = Path.Combine(DriverDirectory, EasyLoggingConfigFinder.ClientConfigFileName); - private static readonly string s_homeConfigFilePath = Path.Combine(HomeDirectory, EasyLoggingConfigFinder.ClientConfigFileName); - - [ThreadStatic] - private static Mock t_fileOperations; - - [ThreadStatic] - private static Mock t_unixOperations; - - [ThreadStatic] - private static Mock t_environmentOperations; - - [ThreadStatic] - private static EasyLoggingConfigFinder t_finder; - - [SetUp] - public void Setup() - { - t_fileOperations = new Mock(); - t_unixOperations = new Mock(); - t_environmentOperations = new Mock(); - t_finder = new EasyLoggingConfigFinder(t_fileOperations.Object, t_unixOperations.Object, t_environmentOperations.Object); - MockHomeDirectory(); - MockExecutionDirectory(); - } - - [Test] - public void TestThatTakesFilePathFromTheInput() - { - // arrange - MockFileFromEnvironmentalVariable(); - MockFileOnDriverPath(); - MockFileOnHomePath(); - - // act - var filePath = t_finder.FindConfigFilePath(InputConfigFilePath); - - // assert - Assert.AreEqual(InputConfigFilePath, filePath); - t_fileOperations.VerifyNoOtherCalls(); - t_environmentOperations.VerifyNoOtherCalls(); - } - - [Test] - public void TestThatTakesFilePathFromEnvironmentVariableIfInputNotPresent( - [Values(null, "")] string inputFilePath) - { - // arrange - MockFileFromEnvironmentalVariable(); - MockFileOnDriverPath(); - MockFileOnHomePath(); - - // act - var filePath = t_finder.FindConfigFilePath(inputFilePath); - - // assert - Assert.AreEqual(EnvironmentalConfigFilePath, filePath); - } - - [Test] - public void TestThatTakesFilePathFromDriverLocationWhenNoInputParameterNorEnvironmentVariable() - { - // arrange - MockFileOnDriverPath(); - MockFileOnHomePath(); - - // act - var filePath = t_finder.FindConfigFilePath(null); - - // assert - Assert.AreEqual(s_driverConfigFilePath, filePath); - } - - [Test] - public void TestThatTakesFilePathFromHomeLocationWhenNoInputParamEnvironmentVarNorDriverLocation() - { - // arrange - MockFileOnHomePath(); - - // act - var filePath = t_finder.FindConfigFilePath(null); - - // assert - Assert.AreEqual(s_homeConfigFilePath, filePath); - } - - [Test] - public void TestThatTakesFilePathFromHomeDirectoryWhenNoOtherWaysPossible() - { - // arrange - MockFileOnHomePath(); - - // act - var filePath = t_finder.FindConfigFilePath(null); - - // assert - Assert.AreEqual(s_homeConfigFilePath, filePath); - } - - [Test] - public void TestThatConfigFileIsNotUsedIfOthersCanModifyTheConfigFile() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Assert.Ignore("skip test on Windows"); - } - - // arrange - MockFileOnHomePath(); - MockHasFlagReturnsTrue(); - - // act - var thrown = Assert.Throws(() => t_finder.FindConfigFilePath(null)); - - // assert - Assert.IsNotNull(thrown); - Assert.AreEqual(thrown.Message, $"Error due to other users having permission to modify the config file: {s_homeConfigFilePath}"); - } - - [Test] - public void TestThatReturnsNullIfNoWayOfGettingTheFile() - { - // act - var filePath = t_finder.FindConfigFilePath(null); - - // assert - Assert.IsNull(filePath); - } - - [Test] - public void TestThatDoesNotFailWhenSearchForOneOfDirectoriesFails() - { - // arrange - MockHomeDirectoryFails(); - - // act - var filePath = t_finder.FindConfigFilePath(null); - - // assert - Assert.IsNull(filePath); - t_environmentOperations.Verify(e => e.GetFolderPath(Environment.SpecialFolder.UserProfile), Times.Once); - } - - [Test] - public void TestThatDoesNotFailWhenHomeDirectoryReturnsNull() - { - // arrange - MockHomeDirectoryReturnsNull(); - - // act - var filePath = t_finder.FindConfigFilePath(null); - - // assert - Assert.IsNull(filePath); - t_environmentOperations.Verify(e => e.GetFolderPath(Environment.SpecialFolder.UserProfile), Times.Once); - } - - [Test] - public void TestThatDoesNotFailWhenHomeDirectoryDoesNotExist() - { - // arrange - MockFileOnHomePath(); - MockFileOnHomePathDoesNotExist(); - - // act - var filePath = t_finder.FindConfigFilePath(null); - - // assert - Assert.IsNull(filePath); - t_environmentOperations.Verify(e => e.GetFolderPath(Environment.SpecialFolder.UserProfile), Times.Once); - } - - private static void MockHasFlagReturnsTrue() - { - t_unixOperations - .Setup(f => f.CheckFileHasAnyOfPermissions(s_homeConfigFilePath, - It.Is(p => p.Equals(FileAccessPermissions.GroupWrite | FileAccessPermissions.OtherWrite)))) - .Returns(true); - } - - private static void MockHomeDirectory() - { - t_environmentOperations - .Setup(e => e.GetFolderPath(Environment.SpecialFolder.UserProfile)) - .Returns(HomeDirectory); - } - - private static void MockHomeDirectoryFails() - { - t_environmentOperations - .Setup(e => e.GetFolderPath(Environment.SpecialFolder.UserProfile)) - .Throws(() => new Exception("No home directory")); - } - - private static void MockExecutionDirectory() - { - t_environmentOperations - .Setup(e => e.GetExecutionDirectory()) - .Returns(DriverDirectory); - } - - private static void MockFileOnHomePathDoesNotExist() - { - t_fileOperations - .Setup(f => f.Exists(s_homeConfigFilePath)) - .Returns(false); - } - - private static void MockHomeDirectoryReturnsNull() - { - t_environmentOperations - .Setup(e => e.GetFolderPath(Environment.SpecialFolder.UserProfile)) - .Returns((string) null); - } - - private static void MockFileFromEnvironmentalVariable() - { - t_environmentOperations - .Setup(e => e.GetEnvironmentVariable(EasyLoggingConfigFinder.ClientConfigEnvironmentName)) - .Returns(EnvironmentalConfigFilePath); - } - - private static void MockFileOnDriverPath() - { - t_fileOperations - .Setup(f => f.Exists(s_driverConfigFilePath)) - .Returns(true); - } - - private static void MockFileOnHomePath() - { - t_fileOperations - .Setup(f => f.Exists(s_homeConfigFilePath)) - .Returns(true); - } - } -} diff --git a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigParserTest.cs b/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigParserTest.cs deleted file mode 100644 index 847d57c51..000000000 --- a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigParserTest.cs +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2023 Snowflake Computing Inc. All rights reserved. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using NUnit.Framework; -using Snowflake.Data.Configuration; -using static Snowflake.Data.Tests.UnitTests.Configuration.EasyLoggingConfigGenerator; - -namespace Snowflake.Data.Tests.UnitTests.Configuration -{ - [TestFixture, NonParallelizable] - public class EasyLoggingConfigParserTest - { - private const string NotExistingFilePath = "../../../Resources/EasyLogging/not_existing_config.json"; - private const string LogLevel = "info"; - private const string LogPath = "./test-logs/log_file.log"; - private static readonly string s_workingDirectory = Path.Combine(Path.GetTempPath(), "easy_logging_test_configs_", Path.GetRandomFileName()); - - [OneTimeSetUp] - public static void BeforeAll() - { - if (!Directory.Exists(s_workingDirectory)) - { - Directory.CreateDirectory(s_workingDirectory); - } - } - - [OneTimeTearDown] - public static void AfterAll() - { - Directory.Delete(s_workingDirectory, true); - } - - [Test] - public void TestThatParsesConfigFile() - { - // arrange - var parser = new EasyLoggingConfigParser(); - var configFilePath = CreateConfigTempFile(s_workingDirectory, Config(LogLevel, LogPath)); - - // act - var config = parser.Parse(configFilePath); - - // assert - Assert.IsNotNull(config); - Assert.IsNotNull(config.CommonProps); - Assert.AreEqual(LogLevel, config.CommonProps.LogLevel); - Assert.AreEqual(LogPath, config.CommonProps.LogPath); - } - - [Test, TestCaseSource(nameof(ConfigFilesWithoutValues))] - public void TestThatParsesConfigFileWithNullValues(string filePath) - { - // arrange - var parser = new EasyLoggingConfigParser(); - - // act - var config = parser.Parse(filePath); - - // assert - Assert.IsNotNull(config); - Assert.IsNotNull(config.CommonProps); - Assert.IsNull(config.CommonProps.LogLevel); - Assert.IsNull(config.CommonProps.LogPath); - } - - [Test] - [TestCase(null)] - [TestCase("")] - public void TestThatReturnsNullWhenNothingToParse(string noFilePath) - { - // arrange - var parser = new EasyLoggingConfigParser(); - - // act - var config = parser.Parse(noFilePath); - - // assert - Assert.IsNull(config); - } - - [Test] - public void TestThatFailsWhenTheFileDoesNotExist() - { - // arrange - var parser = new EasyLoggingConfigParser(); - - // act - var thrown = Assert.Throws(() => parser.Parse(NotExistingFilePath)); - - // assert - Assert.IsNotNull(thrown); - Assert.AreEqual("Finding easy logging configuration failed", thrown.Message); - } - - [Test, TestCaseSource(nameof(WrongConfigFiles))] - public void TestThatFailsIfMissingOrInvalidRequiredFields(string filePath) - { - // arrange - var parser = new EasyLoggingConfigParser(); - - // act - var thrown = Assert.Throws(() => parser.Parse(filePath)); - // assert - Assert.IsNotNull(thrown); - Assert.IsTrue(thrown.Message == "Parsing easy logging configuration failed"); - } - - public static IEnumerable ConfigFilesWithoutValues() - { - BeforeAll(); - return new[] - { - CreateConfigTempFile(s_workingDirectory, EmptyCommonConfig), - CreateConfigTempFile(s_workingDirectory, Config(null, null)) - }; - } - - public static IEnumerable WrongConfigFiles() - { - BeforeAll(); - return new[] - { - CreateConfigTempFile(s_workingDirectory, EmptyConfig), - CreateConfigTempFile(s_workingDirectory, Config("unknown", LogPath)), - }; - } - } -} diff --git a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigProviderTest.cs b/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigProviderTest.cs deleted file mode 100644 index f61d51503..000000000 --- a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingConfigProviderTest.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2023 Snowflake Computing Inc. All rights reserved. - */ - -using Moq; -using NUnit.Framework; -using Snowflake.Data.Configuration; - -namespace Snowflake.Data.Tests.UnitTests.Configuration -{ - [TestFixture] - public class EasyLoggingConfigProviderTest - { - private const string FilePathFromConnectionString = "/Users/dotnet/config.json"; - private const string FilePathToUse = "/home/config.json"; - - [Test] - public void TestThatProvidesConfiguration() - { - // arrange - var configFinder = new Mock(); - var configParser = new Mock(); - var configProvider = new EasyLoggingConfigProvider(configFinder.Object, configParser.Object); - var config = new ClientConfig(); - configFinder - .Setup(finder => finder.FindConfigFilePath(FilePathFromConnectionString)) - .Returns(FilePathToUse); - configParser - .Setup(parser => parser.Parse(FilePathToUse)) - .Returns(config); - - // act - var result = configProvider.ProvideConfig(FilePathFromConnectionString); - - // assert - Assert.AreSame(config, result); - } - - [Test] - public void TestThatReturnsNullWhenNoConfigurationFound() - { - // arrange - var configFinder = new Mock(); - var configParser = new Mock(); - var configProvider = new EasyLoggingConfigProvider(configFinder.Object, configParser.Object); - configFinder - .Setup(finder => finder.FindConfigFilePath(FilePathFromConnectionString)) - .Returns((string) null); - - // act - var result = configProvider.ProvideConfig(FilePathFromConnectionString); - - // assert - Assert.IsNull(result); - configParser.Verify(parser => parser.Parse(It.IsAny()), Times.Never); - } - } -} diff --git a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingLogLevelTest.cs b/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingLogLevelTest.cs deleted file mode 100644 index d61cfaeec..000000000 --- a/Snowflake.Data.Tests/UnitTests/Configuration/EasyLoggingLogLevelTest.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 Snowflake Computing Inc. All rights reserved. - */ - -using System; -using NUnit.Framework; -using Snowflake.Data.Configuration; - -namespace Snowflake.Data.Tests.UnitTests.Configuration -{ - [TestFixture] - class EasyLoggingLogLevelTest - { - [Test] - [TestCase("OFF", EasyLoggingLogLevel.Off)] - [TestCase("off", EasyLoggingLogLevel.Off)] - [TestCase("iNfO", EasyLoggingLogLevel.Info)] - public void TestThatGetsLogLevelValueIgnoringLetterCase(string loglevelString, EasyLoggingLogLevel expectedLogLevel) - { - // act - var logLevel = EasyLoggingLogLevelExtensions.From(loglevelString); - - // assert - Assert.AreEqual(expectedLogLevel, logLevel); - } - - [Test] - public void TestThatFailsToParseLogLevelFromUnknownValue() - { - // act - var thrown = Assert.Throws(() => EasyLoggingLogLevelExtensions.From("unknown")); - - // assert - Assert.IsNotNull(thrown); - Assert.AreEqual("Requested value 'unknown' was not found.", thrown.Message); - } - } -} diff --git a/Snowflake.Data.Tests/UnitTests/Logger/EasyLoggerManagerTest.cs b/Snowflake.Data.Tests/UnitTests/Logger/EasyLoggerManagerTest.cs deleted file mode 100644 index 4dfba8c83..000000000 --- a/Snowflake.Data.Tests/UnitTests/Logger/EasyLoggerManagerTest.cs +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2023 Snowflake Computing Inc. All rights reserved. - */ - -using System; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using NUnit.Framework; -using Snowflake.Data.Configuration; -using Snowflake.Data.Core; -using Snowflake.Data.Log; - -namespace Snowflake.Data.Tests.UnitTests.Logger -{ - [TestFixture, NonParallelizable] - public class EasyLoggerManagerTest - { - - private const string InfoMessage = "Easy logging Info message"; - private const string DebugMessage = "Easy logging Debug message"; - private const string WarnMessage = "Easy logging Warn message"; - private const string ErrorMessage = "Easy logging Error message"; - private const string FatalMessage = "Easy logging Fatal message"; - private static readonly string s_logsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - - [ThreadStatic] - private static string t_directoryLogPath; - - [OneTimeTearDown] - public static void CleanUp() - { - RemoveEasyLoggingLogFiles(); - } - - [SetUp] - public void BeforeEach() - { - t_directoryLogPath = RandomLogsDirectoryPath(); - } - - [TearDown] - public void AfterEach() - { - EasyLoggerManager.Instance.ReconfigureEasyLogging(EasyLoggingLogLevel.Warn, t_directoryLogPath); - } - - [Test] - public void TestThatChangesLogLevel() - { - // arrange - var logger = SFLoggerFactory.GetLogger(); - EasyLoggerManager.Instance.ReconfigureEasyLogging(EasyLoggingLogLevel.Warn, t_directoryLogPath); - - // assert - Assert.IsFalse(logger.IsDebugEnabled()); - Assert.IsFalse(logger.IsInfoEnabled()); - Assert.IsTrue(logger.IsWarnEnabled()); - Assert.IsTrue(logger.IsErrorEnabled()); - Assert.IsTrue(logger.IsFatalEnabled()); - - // act - EasyLoggerManager.Instance.ReconfigureEasyLogging(EasyLoggingLogLevel.Debug, t_directoryLogPath); - - // assert - Assert.IsTrue(logger.IsDebugEnabled()); - Assert.IsTrue(logger.IsInfoEnabled()); - Assert.IsTrue(logger.IsWarnEnabled()); - Assert.IsTrue(logger.IsErrorEnabled()); - Assert.IsTrue(logger.IsFatalEnabled()); - } - - [Test] - public void TestThatLogsToProperFileWithProperLogLevelOnly() - { - // arrange - var logger = SFLoggerFactory.GetLogger(); - EasyLoggerManager.Instance.ReconfigureEasyLogging(EasyLoggingLogLevel.Info, t_directoryLogPath); - - // act - logger.Debug(DebugMessage); - logger.Info(InfoMessage); - logger.Warn(WarnMessage); - logger.Error(ErrorMessage); - logger.Fatal(FatalMessage); - - // assert - var logLines = File.ReadLines(FindLogFilePath(t_directoryLogPath)); - Assert.That(logLines, Has.Exactly(0).Matches(s => s.Contains(DebugMessage))); - Assert.That(logLines, Has.Exactly(1).Matches(s => s.Contains(InfoMessage))); - Assert.That(logLines, Has.Exactly(1).Matches(s => s.Contains(WarnMessage))); - Assert.That(logLines, Has.Exactly(1).Matches(s => s.Contains(ErrorMessage))); - Assert.That(logLines, Has.Exactly(1).Matches(s => s.Contains(FatalMessage))); - } - - [Test] - public void TestThatOnlyUnknownFieldsAreLogged() - { - // arrange - string expectedFakeLogField = "fake_log_field"; - string ConfigWithUnknownFields = $@"{{ - ""common"": {{ - ""LOG_LEVEL"": ""warn"", - ""lOg_PaTh"": ""path"", - ""{expectedFakeLogField}_1"": ""abc"", - ""{expectedFakeLogField}_2"": ""123"" - }} - }}"; - var configFilePath = Guid.NewGuid().ToString() + ".json"; - using (var writer = File.CreateText(configFilePath)) - { - writer.Write(ConfigWithUnknownFields); - } - EasyLoggerManager.Instance.ReconfigureEasyLogging(EasyLoggingLogLevel.Warn, t_directoryLogPath); - var parser = new EasyLoggingConfigParser(); - - // act - parser.Parse(configFilePath); - - // assert - var logLines = File.ReadLines(FindLogFilePath(t_directoryLogPath)); - Assert.That(logLines, Has.Exactly(2).Matches(s => s.Contains($"Unknown field from config: {expectedFakeLogField}"))); - - // cleanup - File.Delete(configFilePath); - } - - private static string RandomLogsDirectoryPath() - { - var randomName = Path.GetRandomFileName(); - return Path.Combine(s_logsDirectory, $"easy_logging_logs_{randomName}", "dotnet"); - } - - private static string FindLogFilePath(string directoryLogPath) - { - Assert.IsTrue(Directory.Exists(directoryLogPath)); - var files = Directory.GetFiles(directoryLogPath); - Assert.AreEqual(1, files.Length); - return files.First(); - } - - private static void RemoveEasyLoggingLogFiles() - { - Directory.GetFiles(s_logsDirectory) - .Where(filePath => filePath.StartsWith(Path.Combine(s_logsDirectory, "easy_logging_logs"))) - .AsParallel() - .ForAll(filePath => File.Delete(filePath)); - } - } -} diff --git a/Snowflake.Data.Tests/UnitTests/Logger/EasyLoggingStarterTest.cs b/Snowflake.Data.Tests/UnitTests/Logger/EasyLoggingStarterTest.cs deleted file mode 100644 index 8b1c6ebfe..000000000 --- a/Snowflake.Data.Tests/UnitTests/Logger/EasyLoggingStarterTest.cs +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2023 Snowflake Computing Inc. All rights reserved. - */ - -using System; -using System.IO; -using System.Runtime.InteropServices; -using Mono.Unix; -using Mono.Unix.Native; -using Moq; -using NUnit.Framework; -using Snowflake.Data.Configuration; -using Snowflake.Data.Core; -using Snowflake.Data.Core.Tools; -using Snowflake.Data.Log; - -namespace Snowflake.Data.Tests.UnitTests.Session -{ - [TestFixture] - public class EasyLoggingStarterTest - { - private static readonly string HomeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - private static readonly string LogPath = Path.Combine(HomeDirectory, "some-logs-path/some-folder"); - private const string ConfigPath = "/some-path/config.json"; - private const string AnotherConfigPath = "/another/path"; - private static readonly string s_expectedLogPath = Path.Combine(LogPath, "dotnet"); - - private static readonly ClientConfig s_configWithErrorLevel = new ClientConfig - { - CommonProps = new ClientConfigCommonProps - { - LogLevel = "Error", - LogPath = LogPath - } - }; - - private static readonly ClientConfig s_configWithInfoLevel = new ClientConfig - { - CommonProps = new ClientConfigCommonProps - { - LogLevel = "Info", - LogPath = LogPath - } - }; - - private static readonly ClientConfig s_configWithNoLogPath = new ClientConfig - { - CommonProps = new ClientConfigCommonProps - { - LogLevel = "Info" - } - }; - - [ThreadStatic] - private static Mock t_easyLoggingProvider; - - [ThreadStatic] - private static Mock t_easyLoggerManager; - - [ThreadStatic] - private static Mock t_unixOperations; - - [ThreadStatic] - private static Mock t_directoryOperations; - - [ThreadStatic] - private static Mock t_environmentOperations; - - [ThreadStatic] - private static EasyLoggingStarter t_easyLoggerStarter; - - [SetUp] - public void BeforeEach() - { - t_easyLoggingProvider = new Mock(); - t_easyLoggerManager = new Mock(); - t_unixOperations = new Mock(); - t_directoryOperations = new Mock(); - t_environmentOperations = new Mock(); - t_easyLoggerStarter = new EasyLoggingStarter( - t_easyLoggingProvider.Object, - t_easyLoggerManager.Object, - t_unixOperations.Object, - t_directoryOperations.Object, - t_environmentOperations.Object); - } - - [Test] - public void TestThatThrowsErrorWhenLogPathAndHomeDirectoryIsNotSet() - { - // arrange - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(ConfigPath)) - .Returns(s_configWithNoLogPath); - t_environmentOperations - .Setup(env => env.GetFolderPath(Environment.SpecialFolder.UserProfile)) - .Returns(""); - - // act - var thrown = Assert.Throws(() => t_easyLoggerStarter.Init(ConfigPath)); - - // assert - Assert.IsNotNull(thrown); - Assert.AreEqual(thrown.Message, "No log path found for easy logging. Home directory is not configured and log path is not provided"); - } - - [Test] - public void TestThatThrowsErrorWhenLogPathIsNotSetAndHomeDirectoryThrowsAnException() - { - // arrange - var ex = new Exception("No home directory"); - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(ConfigPath)) - .Returns(s_configWithNoLogPath); - t_environmentOperations - .Setup(env => env.GetFolderPath(Environment.SpecialFolder.UserProfile)) - .Throws(() => ex); - - // act - var thrown = Assert.Throws(() => t_easyLoggerStarter.Init(ConfigPath)); - - // assert - Assert.IsNotNull(thrown); - Assert.AreEqual(thrown.Message, "No log path found for easy logging. Home directory is not configured and log path is not provided"); - } - - [Test] - public void TestThatDoesNotFailWhenLogDirectoryPermissionIsNot700() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Assert.Ignore("skip test on Windows"); - } - - // arrange - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(ConfigPath)) - .Returns(s_configWithInfoLevel); - t_directoryOperations - .Setup(dir => dir.Exists(s_expectedLogPath)) - .Returns(true); - t_unixOperations - .Setup(unix => unix.GetDirPermissions(s_expectedLogPath)) - .Returns(FileAccessPermissions.AllPermissions); - - // act - t_easyLoggerStarter.Init(ConfigPath); - - // assert - t_unixOperations.Verify(u => u.CreateDirectoryWithPermissions(s_expectedLogPath, - FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR), Times.Never); - } - - [Test] - public void TestFailIfDirectoryCreationFails() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Assert.Ignore("skip test on Windows"); - } - - // arrange - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(ConfigPath)) - .Returns(s_configWithErrorLevel); - t_unixOperations - .Setup(u => u.CreateDirectoryWithPermissions(s_expectedLogPath, FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR)) - .Returns((int)Errno.EPERM); - - // act - var thrown = Assert.Throws(() => t_easyLoggerStarter.Init(ConfigPath)); - - // assert - Assert.That(thrown.Message, Does.Contain("Failed to create logs directory")); - } - - [Test] - public void TestThatConfiguresEasyLoggingOnlyOnceWhenInitializedWithConfigPath() - { - // arrange - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(ConfigPath)) - .Returns(s_configWithErrorLevel); - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(null)) - .Returns(s_configWithInfoLevel); - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(AnotherConfigPath)) - .Returns(s_configWithInfoLevel); - - // act - t_easyLoggerStarter.Init(ConfigPath); - - // assert - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - t_directoryOperations.Verify(d => d.CreateDirectory(s_expectedLogPath), Times.Once); - } - else - { - t_unixOperations.Verify(u => u.CreateDirectoryWithPermissions(s_expectedLogPath, - FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR), Times.Once); - } - t_easyLoggerManager.Verify(manager => manager.ReconfigureEasyLogging(EasyLoggingLogLevel.Error, s_expectedLogPath), Times.Once); - - // act - t_easyLoggerStarter.Init(null); - t_easyLoggerStarter.Init(ConfigPath); - t_easyLoggerStarter.Init(AnotherConfigPath); - - // assert - t_easyLoggerManager.VerifyNoOtherCalls(); - } - - [Test] - public void TestThatConfiguresEasyLoggingOnlyOnceForInitializationsWithoutConfigPath() - { - // arrange - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(null)) - .Returns(s_configWithErrorLevel); - - // act - t_easyLoggerStarter.Init(null); - t_easyLoggerStarter.Init(null); - - // assert - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - t_directoryOperations.Verify(d => d.CreateDirectory(s_expectedLogPath), Times.Once); - } - else - { - t_unixOperations.Verify(u => u.CreateDirectoryWithPermissions(s_expectedLogPath, - FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR), Times.Once); - } - t_easyLoggerManager.Verify(manager => manager.ReconfigureEasyLogging(EasyLoggingLogLevel.Error, s_expectedLogPath), Times.Once); - } - - [Test] - public void TestThatReconfiguresEasyLoggingWithConfigPathIfNotGivenForTheFirstTime() - { - // arrange - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(null)) - .Returns(s_configWithErrorLevel); - t_easyLoggingProvider - .Setup(provider => provider.ProvideConfig(ConfigPath)) - .Returns(s_configWithInfoLevel); - - // act - t_easyLoggerStarter.Init(null); - - // assert - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - t_directoryOperations.Verify(d => d.CreateDirectory(s_expectedLogPath), Times.Once); - } - else - { - t_unixOperations.Verify(u => u.CreateDirectoryWithPermissions(s_expectedLogPath, - FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR), Times.Once); - } - t_easyLoggerManager.Verify(manager => manager.ReconfigureEasyLogging(EasyLoggingLogLevel.Error, s_expectedLogPath), Times.Once); - - // act - t_easyLoggerStarter.Init(ConfigPath); - - // assert - t_easyLoggerManager.Verify(manager => manager.ReconfigureEasyLogging(EasyLoggingLogLevel.Info, s_expectedLogPath), Times.Once); - t_easyLoggerManager.VerifyNoOtherCalls(); - } - } -} diff --git a/Snowflake.Data.Tests/UnitTests/Logger/SFLoggerTest.cs b/Snowflake.Data.Tests/UnitTests/Logger/SFLoggerTest.cs index 710a8d645..26d2010d8 100644 --- a/Snowflake.Data.Tests/UnitTests/Logger/SFLoggerTest.cs +++ b/Snowflake.Data.Tests/UnitTests/Logger/SFLoggerTest.cs @@ -2,112 +2,199 @@ * Copyright (c) 2023 Snowflake Computing Inc. All rights reserved. */ -using Snowflake.Data.Configuration; +using NUnit.Framework; +using Snowflake.Data.Log; +using Microsoft.Extensions.Logging; +using ILogger = Microsoft.Extensions.Logging.ILogger; +using NLog.Extensions.Logging; +using Serilog; +using Serilog.Extensions.Logging; +using System.IO; namespace Snowflake.Data.Tests.UnitTests { - using NUnit.Framework; - using Snowflake.Data.Log; - [TestFixture, NonParallelizable] class SFLoggerTest { - SFLogger _logger; + private const string InfoMessage = "Info message"; + private const string DebugMessage = "Debug message"; + private const string WarnMessage = "Warn message"; + private const string ErrorMessage = "Error message"; + private const string CriticalMessage = "critical message"; - [OneTimeSetUp] - public static void BeforeTest() + public abstract class SFBaseLoggerTest { - // Log level defaults to Warn on net6.0 builds in github actions - // Set the root level to Debug - EasyLoggerManager.Instance.ReconfigureEasyLogging(EasyLoggingLogLevel.Debug, "STDOUT"); - } + protected ILogger _logger; + protected string _logFile; - [OneTimeTearDown] - public static void AfterAll() - { - EasyLoggerManager.Instance.ReconfigureEasyLogging(EasyLoggingLogLevel.Warn, "STDOUT"); - } - - [TearDown] public void AfterTest() - { - // Return to default setting - SFLoggerFactory.useDefaultLogger(); - SFLoggerFactory.enableLogger(); - } + [OneTimeSetUp] + public void BeforeTest() + { + SFLoggerFactory.EnableLogger(); + } - [Test] - public void TestUsingDefaultLogger() - { - SFLoggerFactory.useDefaultLogger(); - _logger = SFLoggerFactory.GetLogger(); - Assert.IsInstanceOf(_logger); - } + [OneTimeTearDown] + public void AfterTest() + { + // Return to default setting + SFLoggerFactory.UseDefaultLogger(); + SFLoggerFactory.DisableLogger(); + if (_logFile != null) + { + File.Delete(_logFile); + _logFile = null; + } + } - [Test] - public void TestSettingCustomLogger() - { - SFLoggerFactory.Instance(new SFLoggerEmptyImpl()); - _logger = SFLoggerFactory.GetLogger(); - Assert.IsInstanceOf(_logger); - } + [Test] + public void TestUsingDefaultLogger() + { + var originalLogger = SFLoggerFactory.GetLogger(); + SFLoggerFactory.UseDefaultLogger(); + _logger = SFLoggerFactory.GetLogger(); + Assert.IsInstanceOf(_logger); + SFLoggerFactory.SetCustomLogger(originalLogger); + } - [Test] - public void TestIsDebugEnabled( - [Values(false, true)] bool isEnabled) - { - _logger = GetLogger(isEnabled); + [Test] + public void TestSettingCustomLogger() + { + var originalLogger = SFLoggerFactory.GetLogger(); + SFLoggerFactory.SetCustomLogger(new SFLoggerEmptyImpl()); + _logger = SFLoggerFactory.GetLogger(); + Assert.IsInstanceOf(_logger); + SFLoggerFactory.SetCustomLogger(originalLogger); + } - Assert.AreEqual(isEnabled, _logger.IsDebugEnabled()); - } + [Test] + public void TestIsDebugEnabled( + [Values(false, true)] bool isEnabled) + { + _logger = GetLogger(isEnabled); + Assert.AreEqual(isEnabled, _logger.IsEnabled(LogLevel.Debug)); + } - [Test] - public void TestIsInfoEnabled( - [Values(false, true)] bool isEnabled) - { - _logger = GetLogger(isEnabled); + [Test] + public void TestIsInfoEnabled( + [Values(false, true)] bool isEnabled) + { + _logger = GetLogger(isEnabled); + Assert.AreEqual(isEnabled, _logger.IsEnabled(LogLevel.Information)); + } - Assert.AreEqual(isEnabled, _logger.IsInfoEnabled()); - } + [Test] + public void TestIsWarnEnabled( + [Values(false, true)] bool isEnabled) + { + _logger = GetLogger(isEnabled); + Assert.AreEqual(isEnabled, _logger.IsEnabled(LogLevel.Warning)); + } - [Test] - public void TestIsWarnEnabled( - [Values(false, true)] bool isEnabled) - { - _logger = GetLogger(isEnabled); + [Test] + public void TestIsErrorEnabled( + [Values(false, true)] bool isEnabled) + { + _logger = GetLogger(isEnabled); + Assert.AreEqual(isEnabled, _logger.IsEnabled(LogLevel.Error)); + } - Assert.AreEqual(isEnabled, _logger.IsWarnEnabled()); - } + [Test] + public void TestIsFatalEnabled( + [Values(false, true)] bool isEnabled) + { + _logger = GetLogger(isEnabled); + Assert.AreEqual(isEnabled, _logger.IsEnabled(LogLevel.Critical)); + } - [Test] - public void TestIsErrorEnabled( - [Values(false, true)] bool isEnabled) - { - _logger = GetLogger(isEnabled); + private ILogger GetLogger(bool isEnabled) + { + if (isEnabled) + { + SFLoggerFactory.EnableLogger(); + } + else + { + SFLoggerFactory.DisableLogger(); + } + + return SFLoggerFactory.GetLogger(); + } - Assert.AreEqual(isEnabled, _logger.IsErrorEnabled()); + [Test] + public void TestThatLogsToProperFileWithProperLogLevelOnly() + { + _logger = SFLoggerFactory.GetLogger(); + + // act + _logger.LogDebug(DebugMessage); + _logger.LogInformation(InfoMessage); + _logger.LogWarning(WarnMessage); + _logger.LogError(ErrorMessage); + _logger.LogCritical(CriticalMessage); + + // assert + using (FileStream logFileStream = new FileStream(_logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + using (StreamReader logFileReader = new StreamReader(logFileStream)) + { + string logLines = logFileReader.ReadToEnd(); + Assert.IsTrue(logLines.Contains(DebugMessage)); + Assert.IsTrue(logLines.Contains(InfoMessage)); + Assert.IsTrue(logLines.Contains(WarnMessage)); + Assert.IsTrue(logLines.Contains(ErrorMessage)); + Assert.IsTrue(logLines.Contains(CriticalMessage)); + } + } + } } - [Test] - public void TestIsFatalEnabled( - [Values(false, true)] bool isEnabled) + [TestFixture] + public class Log4NetTest : SFBaseLoggerTest { - _logger = GetLogger(isEnabled); - - Assert.AreEqual(isEnabled, _logger.IsFatalEnabled()); + [OneTimeSetUp] + public void SetUp() + { + var factory = LoggerFactory.Create( + builder => builder + .AddLog4Net("TestLog4Net.config") + .SetMinimumLevel(LogLevel.Trace)); + + var log4netLogger = factory.CreateLogger("Log4NetTest"); + SFLoggerFactory.SetCustomLogger(log4netLogger); + _logFile = "test_log4net.log"; + } } - private SFLogger GetLogger(bool isEnabled) + [TestFixture] + public class SerilogTest : SFBaseLoggerTest { - if (isEnabled) + [OneTimeSetUp] + public void SetUp() { - SFLoggerFactory.enableLogger(); + var loggerSerilog = new LoggerConfiguration() + .ReadFrom.Xml("TestSerilog.Config") + .CreateLogger(); + var serilogLogger = new SerilogLoggerFactory(loggerSerilog).CreateLogger("SerilogTest"); + SFLoggerFactory.SetCustomLogger(serilogLogger); + _logFile = "test_serilog.log"; } - else + } + + [TestFixture] + public class NlogTest : SFBaseLoggerTest + { + [OneTimeSetUp] + public void SetUp() { - SFLoggerFactory.disableLogger(); + var factory = LoggerFactory.Create( + builder => builder + .AddNLog("TestNLog.config") + .SetMinimumLevel(LogLevel.Trace)); + + var nlogLogger = factory.CreateLogger("NlogTest"); + SFLoggerFactory.SetCustomLogger(nlogLogger); + _logFile = "test_nlog.log"; } - - return SFLoggerFactory.GetLogger(); } } } diff --git a/Snowflake.Data.Tests/UnitTests/SFSessionTest.cs b/Snowflake.Data.Tests/UnitTests/SFSessionTest.cs index 262122b2d..c7e3942c9 100644 --- a/Snowflake.Data.Tests/UnitTests/SFSessionTest.cs +++ b/Snowflake.Data.Tests/UnitTests/SFSessionTest.cs @@ -85,26 +85,6 @@ public void TestSkipUpdateSessionPropertiesWhenPropertiesMissing() Assert.AreEqual(roleName, sfSession.role); } - [Test] - [TestCase(null)] - [TestCase("/some-path/config.json")] - [TestCase("C:\\some-path\\config.json")] - public void TestThatConfiguresEasyLogging(string configPath) - { - // arrange - var easyLoggingStarter = new Moq.Mock(); - var simpleConnectionString = "account=test;user=test;password=test;"; - var connectionString = configPath == null - ? simpleConnectionString - : $"{simpleConnectionString}client_config_file={configPath};"; - - // act - new SFSession(connectionString, null, easyLoggingStarter.Object); - - // assert - easyLoggingStarter.Verify(starter => starter.Init(configPath)); - } - [TestCase(null, "accountDefault", "accountDefault", false)] [TestCase("initial", "initial", "initial", false)] [TestCase("initial", null, "initial", false)] diff --git a/Snowflake.Data.Tests/Util/ConnectingThreads.cs b/Snowflake.Data.Tests/Util/ConnectingThreads.cs index beba4720c..de5b6e462 100644 --- a/Snowflake.Data.Tests/Util/ConnectingThreads.cs +++ b/Snowflake.Data.Tests/Util/ConnectingThreads.cs @@ -7,6 +7,7 @@ using Snowflake.Data.Core.Session; using Snowflake.Data.Log; using Snowflake.Data.Tests.Util; +using Microsoft.Extensions.Logging; namespace Snowflake.Data.Tests.IntegrationTests { @@ -55,12 +56,12 @@ public ConnectingThreads JoinAll() public void Enqueue(ThreadEvent threadEvent) => _events.Enqueue(threadEvent); - public static SFLogger Logger() => SFLoggerFactory.GetLogger(); // we have to choose a class from Snowflake.Data package otherwise it will be visible in GH build output + public static ILogger Logger() => SFLoggerFactory.GetLogger(); // we have to choose a class from Snowflake.Data package otherwise it will be visible in GH build output } class ConnectingThread { - private static readonly SFLogger s_logger = ConnectingThreads.Logger(); + private static readonly ILogger s_logger = ConnectingThreads.Logger(); private string _name; @@ -103,21 +104,21 @@ private void Execute() { var connection = new SnowflakeDbConnection(); connection.ConnectionString = _connectionString; - s_logger.Debug($"Execution started, will sleep for {_waitBeforeConnectMillis} ms"); + s_logger.LogDebug($"Execution started, will sleep for {_waitBeforeConnectMillis} ms"); Sleep(_waitBeforeConnectMillis); var watch = new StopWatch(); watch.Start(); var connected = false; try { - s_logger.Debug("Opening the connection"); + s_logger.LogDebug("Opening the connection"); connection.Open(); connected = true; } catch (Exception exception) { watch.Stop(); - s_logger.Error($"Execution failed because of the error: {exception}"); + s_logger.LogError($"Execution failed because of the error: {exception}"); _events.Enqueue(ThreadEvent.EventConnectingFailed(_name, exception, watch.ElapsedMilliseconds)); } if (connected) @@ -128,7 +129,7 @@ private void Execute() Sleep(_waitAfterConnectMillis); if (_closeOnExit) { - s_logger.Debug($"Closing the connection"); + s_logger.LogDebug($"Closing the connection"); connection.Close(); } } @@ -184,7 +185,7 @@ public static ThreadEvent EventWaitingForSessionStarted(string threadName) => class SessionPoolThreadEventHandler: SessionPoolEventHandler { - private static readonly SFLogger s_logger = ConnectingThreads.Logger(); + private static readonly ILogger s_logger = ConnectingThreads.Logger(); private readonly ConnectingThreads _connectingThreads; public SessionPoolThreadEventHandler(ConnectingThreads connectingThreads) @@ -197,24 +198,24 @@ public override void OnWaitingForSessionStarted(SessionPool sessionPool) var threadName = Thread.CurrentThread.Name; var realThreadName = threadName.StartsWith(ConnectingThread.NamePrefix) ? threadName.Substring(ConnectingThread.NamePrefix.Length) : threadName; - s_logger.Warn($"Thread is going to wait for an available session. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); + s_logger.LogWarning($"Thread is going to wait for an available session. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); var waitingStartedEvent = ThreadEvent.EventWaitingForSessionStarted(realThreadName); _connectingThreads.Enqueue(waitingStartedEvent); } public override void OnWaitingForSessionStarted(SessionPool sessionPool, long millisLeft) { - s_logger.Warn($"Thread is going to wait with milliseconds timeout of {millisLeft}. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); + s_logger.LogWarning($"Thread is going to wait with milliseconds timeout of {millisLeft}. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); } public override void OnWaitingForSessionSuccessful(SessionPool sessionPool) { - s_logger.Warn($"Thread has been woken with a session granted. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); + s_logger.LogWarning($"Thread has been woken with a session granted. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); } public override void OnSessionProvided(SessionPool sessionPool) { - s_logger.Warn($"Thread has got a session. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); + s_logger.LogWarning($"Thread has got a session. Current time in milliseconds: {DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); } } } diff --git a/Snowflake.Data.Tests/Util/DbConnectionExtensions.cs b/Snowflake.Data.Tests/Util/DbConnectionExtensions.cs index e8efc371d..8f91c11bf 100644 --- a/Snowflake.Data.Tests/Util/DbConnectionExtensions.cs +++ b/Snowflake.Data.Tests/Util/DbConnectionExtensions.cs @@ -3,26 +3,27 @@ using Snowflake.Data.Client; using Snowflake.Data.Log; using Snowflake.Data.Tests.IcebergTests; +using Microsoft.Extensions.Logging; namespace Snowflake.Data.Tests.Util { public static class DbConnectionExtensions { - private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger(); + private static readonly ILogger s_logger = SFLoggerFactory.GetLogger(); internal static IDbCommand CreateCommand(this IDbConnection connection, string commandText) { var command = connection.CreateCommand(); command.Connection = connection; command.CommandText = commandText; - s_logger.Debug(commandText); + s_logger.LogDebug(commandText); return command; } internal static int ExecuteNonQuery(this IDbConnection connection, string commandText) { var rowsAffected = connection.CreateCommand(commandText).ExecuteNonQuery(); - s_logger.Debug($"Affected row(s): {rowsAffected}"); + s_logger.LogDebug($"Affected row(s): {rowsAffected}"); return rowsAffected; } diff --git a/Snowflake.Data.Tests/log4net.config b/Snowflake.Data.Tests/log4net.config new file mode 100644 index 000000000..0dffc1970 --- /dev/null +++ b/Snowflake.Data.Tests/log4net.config @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + +