Skip to content

Commit

Permalink
SNOW-916949: Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-ext-simba-lf committed Feb 9, 2024
1 parent 7e1060c commit 0fd4856
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 2 deletions.
71 changes: 71 additions & 0 deletions Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,40 @@ public void TestOktaConnection()
}
}

[Test]
public void TestOktaConnectionUntilMaxTimeout()
{
var expectedMaxRetryCount = 15;
var expectedMaxConnectionTimeout = 450;
var mockRestRequester = new MockOktaRetryMaxTimeout(expectedMaxRetryCount, expectedMaxConnectionTimeout);
using (DbConnection conn = new MockSnowflakeDbConnection(mockRestRequester))
{
try
{
conn.ConnectionString
= ConnectionStringWithoutAuth
+ String.Format(
";authenticator={0};user={1};password={2};MAXHTTPRETRIES={3};RETRY_TIMEOUT={4};",
testConfig.oktaUrl,
testConfig.oktaUser,
testConfig.oktaPassword,
expectedMaxRetryCount,
expectedMaxConnectionTimeout);
conn.Open();
Assert.Fail();
}
catch (Exception e)
{
Assert.IsInstanceOf<SnowflakeDbException>(e);
Assert.AreEqual(SFError.INTERNAL_ERROR.GetAttribute<SFErrorAttr>().errorCode, ((SnowflakeDbException)e).ErrorCode);
Assert.IsTrue(e.Message.Contains(
$"The retry count has reached its limit of {expectedMaxRetryCount} and " +
$"the timeout elapsed has reached its limit of {expectedMaxConnectionTimeout} " +
"while trying to authenticate through Okta"));
}
}
}

[Test]
[Ignore("This test requires manual setup and therefore cannot be run in CI")]
public void TestOkta2ConnectionsFollowingEachOther()
Expand Down Expand Up @@ -2056,6 +2090,43 @@ public void TestExplicitTransactionOperationsTracked()
Assert.AreEqual(false, conn.HasActiveExplicitTransaction());
}
}


[Test]
public void TestAsyncOktaConnectionUntilMaxTimeout()
{
var expectedMaxRetryCount = 15;
var expectedMaxConnectionTimeout = 450;
var mockRestRequester = new MockOktaRetryMaxTimeout(expectedMaxRetryCount, expectedMaxConnectionTimeout);
using (DbConnection conn = new MockSnowflakeDbConnection(mockRestRequester))
{
Task connectTask = null;
try
{
conn.ConnectionString
= ConnectionStringWithoutAuth
+ String.Format(
";authenticator={0};user={1};password={2};MAXHTTPRETRIES={3};RETRY_TIMEOUT={4};",
testConfig.oktaUrl,
testConfig.oktaUser,
testConfig.oktaPassword,
expectedMaxRetryCount,
expectedMaxConnectionTimeout);
connectTask = conn.OpenAsync(CancellationToken.None);
connectTask.Wait();
Assert.Fail();
}
catch (Exception e)
{
Assert.IsInstanceOf<SnowflakeDbException>(e.InnerException);
Assert.AreEqual(SFError.INTERNAL_ERROR.GetAttribute<SFErrorAttr>().errorCode, ((SnowflakeDbException)e.InnerException).ErrorCode);
Assert.IsTrue(e.InnerException.InnerException.Message.Contains(
$"The retry count has reached its limit of {expectedMaxRetryCount} and " +
$"the timeout elapsed has reached its limit of {expectedMaxConnectionTimeout} " +
"while trying to authenticate through Okta"));
}
}
}
}
}

Expand Down
55 changes: 55 additions & 0 deletions Snowflake.Data.Tests/Mock/MockOktaRetryMaxTimeout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024 Snowflake Computing Inc. All rights reserved.
*/

using Newtonsoft.Json;
using Snowflake.Data.Core;
using Snowflake.Data.Core.Authenticator;
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Snowflake.Data.Tests.Mock
{

class MockOktaRetryMaxTimeout : RestRequester, IMockRestRequester
{
internal bool _forceTimeoutForNonLoginRequestsOnly = false;
internal int _maxRetryCount;
internal int _maxRetryTimeout;

public MockOktaRetryMaxTimeout(int maxRetryCount, int maxRetryTimeout) : base(null)
{
_maxRetryCount = maxRetryCount;
_maxRetryTimeout = maxRetryTimeout;
}

public void setHttpClient(HttpClient httpClient)
{
_HttpClient = httpClient;
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage message,
TimeSpan restTimeout,
CancellationToken externalCancellationToken,
string sid = "")
{
if (HttpUtil.IsOktaSSORequest(message.RequestUri.Host, message.RequestUri.AbsolutePath))
{
var mockContent = new StringContent(JsonConvert.SerializeObject("<form=error}"), Encoding.UTF8, "application/json");
mockContent.Headers.Add(OktaAuthenticator.RetryCountHeader, _maxRetryCount.ToString());
mockContent.Headers.Add(OktaAuthenticator.TimeoutElapsedHeader, _maxRetryTimeout.ToString());

return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = mockContent
};
}

return await base.SendAsync(message, restTimeout, externalCancellationToken).ConfigureAwait(false);
}
}
}
18 changes: 18 additions & 0 deletions Snowflake.Data.Tests/UnitTests/HttpUtilTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ public void TestIsLoginUrl(string requestUrl, bool expectedIsLoginEndpoint)
Assert.AreEqual(expectedIsLoginEndpoint, isLoginEndpoint);
}

// Parameters: request url, expected value
[TestCase("https://dev.okta.com/sso/saml", true)]
[TestCase("https://test.snowflakecomputing.com/session/v1/login-request", false)]
[TestCase("https://test.snowflakecomputing.com/session/authenticator-request", false)]
[TestCase("https://test.snowflakecomputing.com/session/token-request", false)]
[Test]
public void TestIsOktaSSORequest(string requestUrl, bool expectedIsOktaSSORequest)
{
// given
var uri = new Uri(requestUrl);

// when
bool isOktaSSORequest = HttpUtil.IsOktaSSORequest(uri.Host, uri.AbsolutePath);

// then
Assert.AreEqual(expectedIsOktaSSORequest, isOktaSSORequest);
}

// Parameters: time in seconds
[TestCase(4)]
[TestCase(8)]
Expand Down
12 changes: 10 additions & 2 deletions Snowflake.Data.Tests/UnitTests/SFOktaTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using NUnit.Framework;
using Snowflake.Data.Client;
using Snowflake.Data.Core;
using Snowflake.Data.Core.Authenticator;
using System.Net.Http;

namespace Snowflake.Data.Tests.UnitTests
Expand Down Expand Up @@ -33,6 +34,10 @@ public void TestSsoTokenUrlMismatch()
[Test]
public void TestMissingPostbackUrl()
{
const int retryCount = 1;
const int retryTimeout = 1;
noPostbackContent.Headers.Add(OktaAuthenticator.RetryCountHeader, retryCount.ToString());
noPostbackContent.Headers.Add(OktaAuthenticator.TimeoutElapsedHeader, retryTimeout.ToString());
try
{
var restRequester = new Mock.MockOktaRestRequester()
Expand All @@ -41,13 +46,16 @@ public void TestMissingPostbackUrl()
SSOUrl = "https://snowflakecomputing.okta.com/app/snowflake_testaccountdev_1/blah/sso/saml",
ResponseContent = noPostbackContent,
};
var sfSession = new SFSession("account=test;user=test;password=test;authenticator=https://snowflakecomputing.okta.com;host=test", null, restRequester);
var sfSession = new SFSession("account=test;user=test;password=test;authenticator=https://snowflakecomputing.okta.com;" +
$"host=test;MAXHTTPRETRIES={retryCount};RETRY_TIMEOUT={retryTimeout};", null, restRequester);
sfSession.Open();
Assert.Fail("Should not pass");
} catch (SnowflakeDbException e)
{
Assert.AreEqual(SFError.IDP_SAML_POSTBACK_NOTFOUND.GetAttribute<SFErrorAttr>().errorCode, e.ErrorCode);
Assert.AreEqual(SFError.IDP_SAML_POSTBACK_NOTFOUND.GetAttribute<SFErrorAttr>().errorCode, ((SnowflakeDbException)e.InnerException).ErrorCode);
}
noPostbackContent.Headers.Remove(OktaAuthenticator.RetryCountHeader);
noPostbackContent.Headers.Remove(OktaAuthenticator.TimeoutElapsedHeader);
}

[Test]
Expand Down

0 comments on commit 0fd4856

Please sign in to comment.