Skip to content

Commit a1750f1

Browse files
Merge branch 'master' of https://github.com/snowflakedb/snowflake-connector-net into SNOW-1488703-Arrow-Support-For-Structured-Types
# Conflicts: # Snowflake.Data.Tests/IntegrationTests/StructuredArraysIT.cs # Snowflake.Data.Tests/IntegrationTests/StructuredMapsIT.cs # Snowflake.Data.Tests/IntegrationTests/StructuredObjectsIT.cs
2 parents f55ce82 + f2d4996 commit a1750f1

File tree

257 files changed

+7030
-1600
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

257 files changed

+7030
-1600
lines changed

.github/workflows/main.yml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ name: DotNet Build and Test
33
# Triggers the workflow on push or pull request events but only for the master branch
44
on:
55
push:
6-
branches: [ master ]
6+
branches: [ master, oauth_flows ]
77
pull_request:
8-
branches: [ master ]
8+
branches: [ master, oauth_flows ]
99
workflow_dispatch:
1010
inputs:
1111
logLevel:
@@ -72,7 +72,7 @@ jobs:
7272
- name: Run Tests
7373
run: |
7474
cd Snowflake.Data.Tests
75-
dotnet-coverage collect "dotnet test --framework ${{ matrix.dotnet }} --no-build -l console;verbosity=normal" --output windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_coverage.xml --output-format cobertura --settings coverage.config
75+
dotnet-coverage collect "dotnet test --framework ${{ matrix.dotnet }} --no-build --logger junit;LogFilePath=windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_results.junit.xml --verbosity normal" --output windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_coverage.xml --output-format cobertura --settings coverage.config
7676
env:
7777
snowflake_cloud_env: ${{ matrix.cloud_env }}
7878
net_version: ${{ matrix.dotnet }}
@@ -81,12 +81,16 @@ jobs:
8181
with:
8282
name: code-coverage-report_windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}
8383
path: Snowflake.Data.Tests\windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_coverage.xml
84-
8584
- name: Upload Test Performance Report
8685
uses: actions/upload-artifact@v4
8786
with:
8887
name: tests-performance_windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}
8988
path: Snowflake.Data.Tests\windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_performance.csv
89+
- name: Upload test results to Codecov
90+
if: ${{!cancelled()}}
91+
uses: codecov/test-results-action@v1
92+
with:
93+
token: ${{ secrets.CODE_COV_UPLOAD_TOKEN }}
9094
- name: Upload coverage reports to Codecov
9195
uses: codecov/codecov-action@v4
9296
with:
@@ -140,7 +144,7 @@ jobs:
140144
- name: Run Tests
141145
run: |
142146
cd Snowflake.Data.Tests
143-
dotnet-coverage collect "dotnet test --framework ${{ matrix.dotnet }} --no-build -l console;verbosity=normal" --output linux_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_coverage.xml --output-format cobertura --settings coverage.config
147+
dotnet-coverage collect "dotnet test --framework ${{ matrix.dotnet }} --no-build --logger junit;LogFilePath=linux_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_results.junit.xml --verbosity normal" --output linux_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_coverage.xml --output-format cobertura --settings coverage.config
144148
env:
145149
snowflake_cloud_env: ${{ matrix.cloud_env }}
146150
net_version: ${{ matrix.dotnet }}
@@ -154,6 +158,11 @@ jobs:
154158
with:
155159
name: tests-performance_linux_${{ matrix.dotnet }}_${{ matrix.cloud_env }}
156160
path: Snowflake.Data.Tests/linux_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_performance.csv
161+
- name: Upload test results to Codecov
162+
if: ${{!cancelled()}}
163+
uses: codecov/test-results-action@v1
164+
with:
165+
token: ${{ secrets.CODE_COV_UPLOAD_TOKEN }}
157166
- name: Upload coverage reports to Codecov
158167
uses: codecov/codecov-action@v4
159168
with:
@@ -207,7 +216,7 @@ jobs:
207216
- name: Run Tests
208217
run: |
209218
cd Snowflake.Data.Tests
210-
dotnet-coverage collect "dotnet test --framework ${{ matrix.dotnet }} --no-build -l console;verbosity=normal" --output macos_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_coverage.xml --output-format cobertura --settings coverage.config
219+
dotnet-coverage collect "dotnet test --framework ${{ matrix.dotnet }} --no-build --logger junit;LogFilePath=windows_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_results.junit.xml --verbosity normal" --output macos_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_coverage.xml --output-format cobertura --settings coverage.config
211220
env:
212221
snowflake_cloud_env: ${{ matrix.cloud_env }}
213222
net_version: ${{ matrix.dotnet }}
@@ -221,6 +230,11 @@ jobs:
221230
with:
222231
name: tests-performance_macos_${{ matrix.dotnet }}_${{ matrix.cloud_env }}
223232
path: Snowflake.Data.Tests/macos_${{ matrix.dotnet }}_${{ matrix.cloud_env }}_performance.csv
233+
- name: Upload test results to Codecov
234+
if: ${{!cancelled()}}
235+
uses: codecov/test-results-action@v1
236+
with:
237+
token: ${{ secrets.CODE_COV_UPLOAD_TOKEN }}
224238
- name: Upload coverage reports to Codecov
225239
uses: codecov/codecov-action@v4
226240
with:
Binary file not shown.

Snowflake.Data.Tests/AuthenticationTests/AuthConnectionString.cs

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ static class AuthConnectionString
1717
public static readonly string SsoUser = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_BROWSER_USER");
1818
public static readonly string Host = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_HOST");
1919
public static readonly string SsoPassword = Environment.GetEnvironmentVariable("SNOWFLAKE_TEST_OKTA_PASS");
20+
public static readonly string SnowflakeUser = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_SNOWFLAKE_USER");
21+
public static readonly string SnowflakeRole = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_ROLE");
22+
2023

2124
private static SFSessionProperties GetBaseConnectionParameters()
2225
{
@@ -29,7 +32,20 @@ private static SFSessionProperties GetBaseConnectionParameters()
2932
{SFSessionProperty.DB, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_DATABASE") },
3033
{SFSessionProperty.SCHEMA, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_SCHEMA") },
3134
{SFSessionProperty.WAREHOUSE, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_WAREHOUSE") },
35+
{SFSessionProperty.MINPOOLSIZE, "0"},
36+
{SFSessionProperty.CLIENT_STORE_TEMPORARY_CREDENTIAL, "false"}
37+
};
38+
return properties;
39+
}
40+
41+
public static SFSessionProperties GetSnowflakeLoginCredentials()
42+
{
43+
var properties = new SFSessionProperties()
44+
{
45+
{ SFSessionProperty.USER, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_ID") },
46+
{ SFSessionProperty.PASSWORD, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_USER_PASSWORD") }
3247
};
48+
3349
return properties;
3450
}
3551

@@ -41,6 +57,57 @@ public static SFSessionProperties GetExternalBrowserConnectionString()
4157
return properties;
4258
}
4359

60+
public static SFSessionProperties GetOAuthExternalAuthorizationCodeConnectionString()
61+
{
62+
var properties = GetBaseConnectionParameters();
63+
properties.Add(SFSessionProperty.AUTHENTICATOR, "OAUTH_AUTHORIZATION_CODE");
64+
properties.Add(SFSessionProperty.OAUTHCLIENTID, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_ID"));
65+
properties.Add(SFSessionProperty.OAUTHCLIENTSECRET, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_SECRET"));
66+
properties.Add(SFSessionProperty.OAUTHREDIRECTURI, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_REDIRECT_URI"));
67+
properties.Add(SFSessionProperty.OAUTHAUTHORIZATIONURL, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_AUTH_URL"));
68+
properties.Add(SFSessionProperty.OAUTHTOKENREQUESTURL, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_TOKEN"));
69+
properties.Add(SFSessionProperty.USER, SsoUser);
70+
71+
return properties;
72+
}
73+
74+
public static SFSessionProperties GetOAuthSnowflakeAuthorizationCodeConnectionParameters()
75+
{
76+
var properties = GetBaseConnectionParameters();
77+
properties.Add(SFSessionProperty.AUTHENTICATOR, "OAUTH_AUTHORIZATION_CODE");
78+
properties.Add(SFSessionProperty.OAUTHCLIENTID, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_CLIENT_ID"));
79+
properties.Add(SFSessionProperty.OAUTHCLIENTSECRET, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_CLIENT_SECRET"));
80+
properties.Add(SFSessionProperty.OAUTHREDIRECTURI, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_REDIRECT_URI"));
81+
properties[SFSessionProperty.ROLE] = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_ROLE");
82+
properties.Add(SFSessionProperty.USER, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_ID"));
83+
84+
return properties;
85+
}
86+
87+
public static SFSessionProperties GetOAuthSnowflakeAuthorizationCodeWilidcardsConnectionParameters()
88+
{
89+
var properties = GetBaseConnectionParameters();
90+
properties.Add(SFSessionProperty.AUTHENTICATOR, "OAUTH_AUTHORIZATION_CODE");
91+
properties.Add(SFSessionProperty.OAUTHCLIENTID, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_WILDCARDS_CLIENT_ID"));
92+
properties.Add(SFSessionProperty.OAUTHCLIENTSECRET, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_WILDCARDS_CLIENT_SECRET"));
93+
properties[SFSessionProperty.ROLE] = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_INTERNAL_OAUTH_SNOWFLAKE_ROLE");
94+
properties.Add(SFSessionProperty.USER, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_ID"));
95+
96+
return properties;
97+
}
98+
99+
public static SFSessionProperties GetOAuthExternalClientCredentialParameters()
100+
{
101+
var properties = GetBaseConnectionParameters();
102+
properties.Add(SFSessionProperty.AUTHENTICATOR, "OAUTH_CLIENT_CREDENTIALS");
103+
properties.Add(SFSessionProperty.OAUTHCLIENTID, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_ID"));
104+
properties.Add(SFSessionProperty.OAUTHCLIENTSECRET, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_SECRET"));
105+
properties.Add(SFSessionProperty.OAUTHTOKENREQUESTURL, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_TOKEN"));
106+
properties.Add(SFSessionProperty.USER, Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_EXTERNAL_OAUTH_OKTA_CLIENT_ID"));
107+
108+
return properties;
109+
}
110+
44111
public static SFSessionProperties GetOauthConnectionString(string token)
45112
{
46113
var properties = GetBaseConnectionParameters();
@@ -71,6 +138,13 @@ public static SFSessionProperties GetKeyPairFromFileContentParameters(string pri
71138
return properties;
72139
}
73140

141+
public static SFSessionProperties GetPatConnectionParameters()
142+
{
143+
var properties = GetBaseConnectionParameters();
144+
properties.Add(SFSessionProperty.AUTHENTICATOR, "PROGRAMMATIC_ACCESS_TOKEN");
145+
properties.Add(SFSessionProperty.USER, SsoUser);
146+
return properties;
147+
}
74148

75149
public static SFSessionProperties GetKeyPairFromFilePathConnectionString(string privateKeyPath)
76150
{
@@ -115,13 +189,13 @@ public static string GetOauthToken()
115189
try
116190
{
117191
using (var client = new HttpClient(new HttpClientHandler
118-
{
119-
CheckCertificateRevocationList = true,
120-
SslProtocols = SslProtocols.Tls12,
121-
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
122-
UseProxy = false,
123-
UseCookies = false
124-
}))
192+
{
193+
CheckCertificateRevocationList = true,
194+
SslProtocols = SslProtocols.Tls12,
195+
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
196+
UseProxy = false,
197+
UseCookies = false
198+
}))
125199
{
126200
var authUrl = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_OAUTH_URL");
127201
var clientId = Environment.GetEnvironmentVariable("SNOWFLAKE_AUTH_TEST_OAUTH_CLIENT_ID");

Snowflake.Data.Tests/AuthenticationTests/AuthTestHelper.cs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Data;
55
using NUnit.Framework;
66
using Snowflake.Data.Client;
7+
using Snowflake.Data.Core.CredentialManager;
78
using Snowflake.Data.Log;
89

910
namespace Snowflake.Data.AuthenticationTests
@@ -61,6 +62,36 @@ public void ConnectAndExecuteSimpleQuery(string connectionString)
6162
}
6263
}
6364

65+
public string ConnectUsingOktaConnectionAndExecuteCustomCommand(string command, bool returnToken = false)
66+
{
67+
try
68+
{
69+
using (IDbConnection conn = new SnowflakeDbConnection())
70+
{
71+
var parameters = AuthConnectionString.GetOktaConnectionString();
72+
conn.ConnectionString = AuthConnectionString.ConvertToConnectionString(parameters);
73+
conn.Open();
74+
Assert.AreEqual(ConnectionState.Open, conn.State);
75+
using (IDbCommand dbCommand = conn.CreateCommand())
76+
{
77+
dbCommand.CommandText = command;
78+
using (var reader = dbCommand.ExecuteReader())
79+
{
80+
if (returnToken && reader.Read())
81+
{
82+
return reader["token_secret"].ToString();
83+
}
84+
}
85+
}
86+
}
87+
}
88+
catch (SnowflakeDbException e)
89+
{
90+
_exception = e;
91+
}
92+
return null;
93+
}
94+
6495
public Thread GetConnectAndExecuteSimpleQueryThread(string parameters)
6596
{
6697
return new Thread(() => ConnectAndExecuteSimpleQuery(parameters));
@@ -71,11 +102,13 @@ public Thread GetProvideCredentialsThread(string scenario, string login, string
71102
return new Thread(() => ProvideCredentials(scenario, login, password));
72103
}
73104

74-
public void VerifyExceptionIsNotThrown() {
105+
public void VerifyExceptionIsNotThrown()
106+
{
75107
Assert.That(_exception, Is.Null, "Unexpected exception thrown");
76108
}
77109

78-
public void VerifyExceptionIsThrown(string error) {
110+
public void VerifyExceptionIsThrown(string error)
111+
{
79112
Assert.That(_exception, Is.Not.Null, "Expected exception was not thrown");
80113
Assert.That(_exception.Message, Does.Contain(error), "Unexpected exception message.");
81114

@@ -111,7 +144,7 @@ private void StartNodeProcess(string path, TimeSpan timeout)
111144
using (var process = new Process { StartInfo = startInfo })
112145
{
113146
process.Start();
114-
if (!process.WaitForExit((int) timeout.TotalMilliseconds))
147+
if (!process.WaitForExit((int)timeout.TotalMilliseconds))
115148
{
116149
process.Kill();
117150
throw new TimeoutException("The process did not complete in the allotted time.");
@@ -124,11 +157,17 @@ private void StartNodeProcess(string path, TimeSpan timeout)
124157
}
125158
}
126159

160+
internal void RemoveTokenFromCache(string tokenHost, string user, TokenType tokenType)
161+
{
162+
var cacheKey = SnowflakeCredentialManagerFactory.GetSecureCredentialKey(tokenHost, user, tokenType);
163+
SnowflakeCredentialManagerFactory.GetCredentialManager().RemoveCredentials(cacheKey);
164+
}
165+
127166
private void ProvideCredentials(string scenario, string login, string password)
128167
{
129168
try
130169
{
131-
StartNodeProcess($"/externalbrowser/provideBrowserCredentials.js {scenario} {login} {password}", TimeSpan.FromSeconds(15));
170+
StartNodeProcess($"/externalbrowser/provideBrowserCredentials.js {scenario} {login} {password}", TimeSpan.FromSeconds(25));
132171
}
133172
catch (Exception e)
134173
{
@@ -137,4 +176,3 @@ private void ProvideCredentials(string scenario, string login, string password)
137176
}
138177
}
139178
}
140-

Snowflake.Data.Tests/AuthenticationTests/ExternalBrowserConnectionTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public void TestAuthenticateUsingExternalBrowserWrongCredentials()
7070

7171
authTestHelper.ConnectAndProvideCredentials(provideCredentialsThread, connectThread);
7272
authTestHelper.VerifyExceptionIsThrown("Browser response timed out after 15 seconds");
73-
}
73+
}
7474

7575
[Test, IgnoreOnCI]
7676
public void TestAuthenticateUsingExternalBrowserTimeout()
@@ -87,5 +87,5 @@ public void TestAuthenticateUsingExternalBrowserTimeout()
8787
authTestHelper.ConnectAndProvideCredentials(provideCredentialsThread, connectThread);
8888
authTestHelper.VerifyExceptionIsThrown("Browser response timed out after 1 seconds");
8989
}
90-
}
90+
}
9191
}

0 commit comments

Comments
 (0)