From 0fd4856de7c07ca5f8b368e2b88a21cc425cfa53 Mon Sep 17 00:00:00 2001 From: sfc-gh-ext-simba-lf Date: Fri, 9 Feb 2024 10:08:56 -0800 Subject: [PATCH] SNOW-916949: Add tests --- .../IntegrationTests/SFConnectionIT.cs | 71 +++++++++++++++++++ .../Mock/MockOktaRetryMaxTimeout.cs | 55 ++++++++++++++ .../UnitTests/HttpUtilTest.cs | 18 +++++ Snowflake.Data.Tests/UnitTests/SFOktaTest.cs | 12 +++- 4 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 Snowflake.Data.Tests/Mock/MockOktaRetryMaxTimeout.cs diff --git a/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs b/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs index 5a4976162..2470068eb 100644 --- a/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs +++ b/Snowflake.Data.Tests/IntegrationTests/SFConnectionIT.cs @@ -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(e); + Assert.AreEqual(SFError.INTERNAL_ERROR.GetAttribute().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() @@ -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(e.InnerException); + Assert.AreEqual(SFError.INTERNAL_ERROR.GetAttribute().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")); + } + } + } } } diff --git a/Snowflake.Data.Tests/Mock/MockOktaRetryMaxTimeout.cs b/Snowflake.Data.Tests/Mock/MockOktaRetryMaxTimeout.cs new file mode 100644 index 000000000..20f7c573d --- /dev/null +++ b/Snowflake.Data.Tests/Mock/MockOktaRetryMaxTimeout.cs @@ -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 SendAsync(HttpRequestMessage message, + TimeSpan restTimeout, + CancellationToken externalCancellationToken, + string sid = "") + { + if (HttpUtil.IsOktaSSORequest(message.RequestUri.Host, message.RequestUri.AbsolutePath)) + { + var mockContent = new StringContent(JsonConvert.SerializeObject("().errorCode, e.ErrorCode); + Assert.AreEqual(SFError.IDP_SAML_POSTBACK_NOTFOUND.GetAttribute().errorCode, ((SnowflakeDbException)e.InnerException).ErrorCode); } + noPostbackContent.Headers.Remove(OktaAuthenticator.RetryCountHeader); + noPostbackContent.Headers.Remove(OktaAuthenticator.TimeoutElapsedHeader); } [Test]