-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SNOW-1444876: Support for TOML connections (#995)
Co-authored-by: Krzysztof Nozderko <[email protected]>
- Loading branch information
1 parent
4392447
commit f27eb2a
Showing
18 changed files
with
1,602 additions
and
363 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
Snowflake.Data.Tests/IntegrationTests/SFConnectionWithTomlIT.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
* Copyright (c) 2024 Snowflake Computing Inc. All rights reserved. | ||
*/ | ||
|
||
using System; | ||
using System.Data; | ||
using System.IO; | ||
using System.Runtime.InteropServices; | ||
using Mono.Unix.Native; | ||
using NUnit.Framework; | ||
using Snowflake.Data.Client; | ||
using Snowflake.Data.Core; | ||
using Snowflake.Data.Log; | ||
using Tomlyn; | ||
using Tomlyn.Model; | ||
|
||
namespace Snowflake.Data.Tests.IntegrationTests | ||
{ | ||
|
||
[TestFixture, NonParallelizable] | ||
class SFConnectionWithTomlIT : SFBaseTest | ||
{ | ||
private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger<SFConnectionIT>(); | ||
|
||
private static string s_workingDirectory; | ||
|
||
|
||
[SetUp] | ||
public new void BeforeTest() | ||
{ | ||
s_workingDirectory ??= Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../..", "toml_config_folder"); | ||
if (!Directory.Exists(s_workingDirectory)) | ||
{ | ||
Directory.CreateDirectory(s_workingDirectory); | ||
} | ||
CreateTomlConfigBaseOnConnectionString(ConnectionString); | ||
} | ||
|
||
[TearDown] | ||
public new void AfterTest() | ||
{ | ||
Directory.Delete(s_workingDirectory, true); | ||
} | ||
|
||
[Test] | ||
public void TestLocalDefaultConnectStringReadFromToml() | ||
{ | ||
var snowflakeHome = Environment.GetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome); | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome, s_workingDirectory); | ||
try | ||
{ | ||
using (var conn = new SnowflakeDbConnection()) | ||
{ | ||
conn.Open(); | ||
Assert.AreEqual(ConnectionState.Open, conn.State); | ||
} | ||
} | ||
finally | ||
{ | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome, snowflakeHome); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestThrowExceptionIfTomlNotFoundWithOtherConnectionString() | ||
{ | ||
var snowflakeHome = Environment.GetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome); | ||
var connectionName = Environment.GetEnvironmentVariable(TomlConnectionBuilder.SnowflakeDefaultConnectionName); | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome, s_workingDirectory); | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeDefaultConnectionName, "notfoundconnection"); | ||
try | ||
{ | ||
using (var conn = new SnowflakeDbConnection()) | ||
{ | ||
Assert.Throws<SnowflakeDbException>(() => conn.Open(), "Unable to connect. Specified connection name does not exist in connections.toml"); | ||
} | ||
} | ||
finally | ||
{ | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome, snowflakeHome); | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeDefaultConnectionName, connectionName); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestThrowExceptionIfTomlFromNotFoundFromDbConnection() | ||
{ | ||
var snowflakeHome = Environment.GetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome); | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome, Path.Combine(s_workingDirectory, "InvalidFolder")); | ||
try | ||
{ | ||
using (var conn = new SnowflakeDbConnection()) | ||
{ | ||
Assert.Throws<SnowflakeDbException>(() => conn.Open(), "Error: Required property ACCOUNT is not provided"); | ||
} | ||
} | ||
finally | ||
{ | ||
Environment.SetEnvironmentVariable(TomlConnectionBuilder.SnowflakeHome, snowflakeHome); | ||
} | ||
} | ||
|
||
private static void CreateTomlConfigBaseOnConnectionString(string connectionString) | ||
{ | ||
var tomlModel = new TomlTable(); | ||
var properties = SFSessionProperties.ParseConnectionString(connectionString, null); | ||
|
||
var defaultTomlTable = new TomlTable(); | ||
tomlModel.Add("default", defaultTomlTable); | ||
|
||
foreach (var property in properties) | ||
{ | ||
defaultTomlTable.Add(property.Key.ToString(), property.Value); | ||
} | ||
|
||
var filePath = Path.Combine(s_workingDirectory, "connections.toml"); | ||
|
||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
{ | ||
using (var writer = File.CreateText(filePath)) | ||
{ | ||
writer.Write(Toml.FromModel(tomlModel)); | ||
} | ||
} | ||
else | ||
{ | ||
using (var writer = File.CreateText(filePath)) | ||
{ | ||
writer.Write(string.Empty); | ||
} | ||
Syscall.chmod(filePath, FilePermissions.S_IRUSR | FilePermissions.S_IWUSR); | ||
using (var writer = File.CreateText(filePath)) | ||
{ | ||
writer.Write(Toml.FromModel(tomlModel)); | ||
} | ||
Syscall.chmod(filePath, FilePermissions.S_IRUSR | FilePermissions.S_IWUSR); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
Snowflake.Data.Tests/UnitTests/SnowflakeDbConnectionTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
|
||
|
||
using System; | ||
using System.IO; | ||
using Mono.Unix; | ||
|
||
namespace Snowflake.Data.Tests.UnitTests | ||
{ | ||
using Core; | ||
using Core.Tools; | ||
using Moq; | ||
using NUnit.Framework; | ||
using Snowflake.Data.Client; | ||
|
||
public class SnowflakeDbConnectionTest | ||
{ | ||
[Test] | ||
public void TestFillConnectionStringFromTomlConfig() | ||
{ | ||
// Arrange | ||
var mockFileOperations = new Mock<FileOperations>(); | ||
var mockEnvironmentOperations = new Mock<EnvironmentOperations>(); | ||
mockEnvironmentOperations.Setup(e => e.GetFolderPath(Environment.SpecialFolder.UserProfile)) | ||
.Returns($"{Path.DirectorySeparatorChar}home"); | ||
mockFileOperations.Setup(f => f.Exists(It.IsAny<string>())).Returns(true); | ||
mockFileOperations.Setup(f => f.ReadAllText(It.IsAny<string>(), It.IsAny<Action<UnixStream>>())) | ||
.Returns("[default]\naccount=\"testaccount\"\nuser=\"testuser\"\npassword=\"testpassword\"\n"); | ||
var tomlConnectionBuilder = new TomlConnectionBuilder(mockFileOperations.Object, mockEnvironmentOperations.Object); | ||
|
||
// Act | ||
using (var conn = new SnowflakeDbConnection(tomlConnectionBuilder)) | ||
{ | ||
conn.FillConnectionStringFromTomlConfigIfNotSet(); | ||
// Assert | ||
Assert.AreEqual("account=testaccount;user=testuser;password=testpassword;", conn.ConnectionString); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestTomlConfigurationDoesNotOverrideExistingConnectionString() | ||
{ | ||
// Arrange | ||
var connectionTest = "account=user1account;user=user1;password=user1password;"; | ||
var mockFileOperations = new Mock<FileOperations>(); | ||
var mockEnvironmentOperations = new Mock<EnvironmentOperations>(); | ||
mockFileOperations.Setup(f => f.Exists(It.IsAny<string>())).Returns(true); | ||
mockFileOperations.Setup(f => f.ReadAllText(It.IsAny<string>())) | ||
.Returns("[default]\naccount=\"testaccount\"\nuser=\"testuser\"\npassword=\"testpassword\"\n"); | ||
var tomlConnectionBuilder = new TomlConnectionBuilder(mockFileOperations.Object, mockEnvironmentOperations.Object); | ||
|
||
// Act | ||
using (var conn = new SnowflakeDbConnection(tomlConnectionBuilder)) | ||
{ | ||
conn.ConnectionString = connectionTest; | ||
conn.FillConnectionStringFromTomlConfigIfNotSet(); | ||
// Assert | ||
Assert.AreEqual(connectionTest, conn.ConnectionString); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.