From d5efe7e8bfb66bc8a54e5b022527ecd24f2fa8d6 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Mon, 15 Dec 2025 07:45:43 -0800 Subject: [PATCH 01/15] Hot Reload test fix for non GQL schema changes --- .../HotReload/ConfigurationHotReloadTests.cs | 215 ++++++++++++------ 1 file changed, 146 insertions(+), 69 deletions(-) diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index d2ea7708ce..16dbf9ab57 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -28,6 +28,8 @@ public class ConfigurationHotReloadTests private static StringWriter _writer; private const string CONFIG_FILE_NAME = "hot-reload.dab-config.json"; private const string GQL_QUERY_NAME = "books"; + private const string HOT_RELOAD_SUCCESS_MESSAGE = "Validated hot-reloaded configuration file"; + private const string HOT_RELOAD_FAILURE_MESSAGE = "Unable to hot reload configuration file due to"; private const string GQL_QUERY = @"{ books(first: 100) { @@ -59,6 +61,7 @@ private static void GenerateConfigFile( string restEntityEnabled = "true", string entityBackingColumn = "title", string entityExposedName = "title", + string mcpEnabled = "true", string configFileName = CONFIG_FILE_NAME) { File.WriteAllText(configFileName, @" @@ -82,6 +85,9 @@ private static void GenerateConfigFile( ""path"": """ + gQLPath + @""", ""allow-introspection"": true }, + ""mcp"": { + ""enabled"": " + mcpEnabled + @" + }, ""host"": { ""cors"": { ""origins"": [ @@ -228,12 +234,14 @@ public static void ClassCleanup() /// Hot reload the configuration by saving a new file with different rest and graphQL paths. /// Validate that the response is correct when making a request with the newly hot-reloaded paths. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod("Hot-reload runtime paths.")] public async Task HotReloadConfigRuntimePathsEndToEndTest() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + string restBookContents = $"{{\"value\":{_bookDBOContents}}}"; string restPath = "restApi"; string gQLPath = "/gQLApi"; @@ -250,7 +258,12 @@ public async Task HotReloadConfigRuntimePathsEndToEndTest() connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", restPath: restPath, gQLPath: gQLPath); - System.Threading.Thread.Sleep(2000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); // Act HttpResponseMessage badPathRestResult = await _testClient.GetAsync($"rest/Book"); @@ -278,18 +291,25 @@ public async Task HotReloadConfigRuntimePathsEndToEndTest() /// set to false. Validate that the response from the server is NOT FOUND when making a request after /// the hot reload. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod("Hot-reload rest enabled.")] public async Task HotReloadConfigRuntimeRestEnabledEndToEndTest() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + string restEnabled = "false"; GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", restEnabled: restEnabled); - System.Threading.Thread.Sleep(2000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); // Act HttpResponseMessage restResult = await _testClient.GetAsync($"rest/Book"); @@ -303,12 +323,14 @@ public async Task HotReloadConfigRuntimeRestEnabledEndToEndTest() /// set to false. Validate that the response from the server is NOT FOUND when making a request after /// the hot reload. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod("Hot-reload gql enabled.")] public async Task HotReloadConfigRuntimeGQLEnabledEndToEndTest() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + string gQLEnabled = "false"; string query = GQL_QUERY; object payload = @@ -318,10 +340,16 @@ public async Task HotReloadConfigRuntimeGQLEnabledEndToEndTest() { Content = JsonContent.Create(payload) }; + GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", gQLEnabled: gQLEnabled); - System.Threading.Thread.Sleep(2000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); // Act HttpResponseMessage gQLResult = await _testClient.SendAsync(request); @@ -337,10 +365,13 @@ public async Task HotReloadConfigRuntimeGQLEnabledEndToEndTest() /// [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod("Hot-reload gql disabled at entity level.")] - [Ignore] + [Ignore] // This test requires GraphQL schema reload public async Task HotReloadEntityGQLEnabledFlag() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + string gQLEntityEnabled = "false"; string query = @"{ book_by_pk(id: 1) { @@ -359,7 +390,12 @@ public async Task HotReloadEntityGQLEnabledFlag() GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", gQLEntityEnabled: gQLEntityEnabled); - System.Threading.Thread.Sleep(2000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); // Act HttpResponseMessage gQLResult = await _testClient.SendAsync(request); @@ -376,10 +412,13 @@ public async Task HotReloadEntityGQLEnabledFlag() /// [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] - [Ignore] + [Ignore] // This test requires GraphQL schema reload public async Task HotReloadConfigAddEntity() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + string newEntityName = "Author"; string newEntitySource = "authors"; string newEntityGQLSingular = "author"; @@ -391,7 +430,12 @@ public async Task HotReloadConfigAddEntity() sourceObject: newEntitySource, gQLEntitySingular: newEntityGQLSingular, gQLEntityPlural: newEntityGQLPlural); - System.Threading.Thread.Sleep(2000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); // Act string queryWithOldEntity = @"{ @@ -453,17 +497,25 @@ public async Task HotReloadConfigAddEntity() /// results in bad request, while the new mappings results in a correct response as "title" field is no longer valid. [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] - [Ignore] + [Ignore] // This test requires GraphQL schema reload public async Task HotReloadConfigUpdateMappings() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + string newMappingFieldName = "bookTitle"; // Update the configuration with new mappings GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", entityBackingColumn: "title", entityExposedName: newMappingFieldName); - System.Threading.Thread.Sleep(2000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); // Act string queryWithOldMapping = @"{ @@ -524,12 +576,14 @@ public async Task HotReloadConfigUpdateMappings() /// By asserting that hot reload worked properly for the session-context it also implies that /// the new connection string with additional parameters is also valid. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] public async Task HotReloadConfigDataSource() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + RuntimeConfig previousRuntimeConfig = _configProvider.GetConfig(); MsSqlOptions previousSessionContext = previousRuntimeConfig.DataSource.GetTypedOptions(); @@ -540,7 +594,12 @@ public async Task HotReloadConfigDataSource() GenerateConfigFile( sessionContext: "false", connectionString: expectedConnectionString); - System.Threading.Thread.Sleep(3000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); RuntimeConfig updatedRuntimeConfig = _configProvider.GetConfig(); MsSqlOptions actualSessionContext = updatedRuntimeConfig.DataSource.GetTypedOptions(); @@ -561,27 +620,34 @@ public async Task HotReloadConfigDataSource() /// Then we assert that the log-level property is properly updated by ensuring it is /// not the same as the previous log-level and asserting it is the expected log-level. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] - public void HotReloadLogLevel() + public async Task HotReloadLogLevel() { - // Arange + // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + LogLevel expectedLogLevel = LogLevel.Trace; string expectedFilter = "trace"; RuntimeConfig previousRuntimeConfig = _configProvider.GetConfig(); LogLevel previouslogLevel = previousRuntimeConfig.GetConfiguredLogLevel(); - //Act + // Act GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", logFilter: expectedFilter); - System.Threading.Thread.Sleep(3000); + + // Wait for hot-reload to complete successfully + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); RuntimeConfig updatedRuntimeConfig = _configProvider.GetConfig(); LogLevel actualLogLevel = updatedRuntimeConfig.GetConfiguredLogLevel(); - //Assert + // Assert Assert.AreNotEqual(previouslogLevel, actualLogLevel); Assert.AreEqual(expectedLogLevel, actualLogLevel); } @@ -591,7 +657,6 @@ public void HotReloadLogLevel() /// to an invalid connection string, then it hot reloads once more to the original /// connection string. Lastly, we assert that the first reload fails while the second one succeeds. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] public async Task HotReloadConfigConnectionString() @@ -600,15 +665,12 @@ public async Task HotReloadConfigConnectionString() _writer = new StringWriter(); Console.SetOut(_writer); - string failedKeyWord = "Unable to hot reload configuration file due to"; - string succeedKeyWord = "Validated hot-reloaded configuration file"; - // Act // Hot Reload should fail here GenerateConfigFile( connectionString: $"WrongConnectionString"); - await ConfigurationHotReloadTests.WaitForConditionAsync( - () => _writer.ToString().Contains(failedKeyWord), + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), TimeSpan.FromSeconds(12), TimeSpan.FromMilliseconds(500)); @@ -619,8 +681,8 @@ await ConfigurationHotReloadTests.WaitForConditionAsync( // Hot Reload should succeed here GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}"); - await ConfigurationHotReloadTests.WaitForConditionAsync( - () => _writer.ToString().Contains(succeedKeyWord), + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(12), TimeSpan.FromMilliseconds(500)); @@ -630,8 +692,8 @@ await ConfigurationHotReloadTests.WaitForConditionAsync( HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); // Assert - Assert.IsTrue(failedConfigLog.Contains(failedKeyWord)); - Assert.IsTrue(succeedConfigLog.Contains(succeedKeyWord)); + Assert.IsTrue(failedConfigLog.Contains(HOT_RELOAD_FAILURE_MESSAGE)); + Assert.IsTrue(succeedConfigLog.Contains(HOT_RELOAD_SUCCESS_MESSAGE)); Assert.AreEqual(HttpStatusCode.OK, restResult.StatusCode); } @@ -643,7 +705,6 @@ await ConfigurationHotReloadTests.WaitForConditionAsync( /// Then it hot reloads once more to the original database type. We assert that the /// first reload fails while the second one succeeds. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] public async Task HotReloadConfigDatabaseType() @@ -652,16 +713,13 @@ public async Task HotReloadConfigDatabaseType() _writer = new StringWriter(); Console.SetOut(_writer); - string failedKeyWord = "Unable to hot reload configuration file due to"; - string succeedKeyWord = "Validated hot-reloaded configuration file"; - // Act // Hot Reload should fail here GenerateConfigFile( databaseType: DatabaseType.PostgreSQL, connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.POSTGRESQL).Replace("\\", "\\\\")}"); - await ConfigurationHotReloadTests.WaitForConditionAsync( - () => _writer.ToString().Contains(failedKeyWord), + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), TimeSpan.FromSeconds(12), TimeSpan.FromMilliseconds(500)); @@ -673,8 +731,8 @@ await ConfigurationHotReloadTests.WaitForConditionAsync( GenerateConfigFile( databaseType: DatabaseType.MSSQL, connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}"); - await ConfigurationHotReloadTests.WaitForConditionAsync( - () => _writer.ToString().Contains(succeedKeyWord), + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(12), TimeSpan.FromMilliseconds(500)); @@ -684,56 +742,59 @@ await ConfigurationHotReloadTests.WaitForConditionAsync( HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); // Assert - Assert.IsTrue(failedConfigLog.Contains(failedKeyWord)); - Assert.IsTrue(succeedConfigLog.Contains(succeedKeyWord)); + Assert.IsTrue(failedConfigLog.Contains(HOT_RELOAD_FAILURE_MESSAGE)); + Assert.IsTrue(succeedConfigLog.Contains(HOT_RELOAD_SUCCESS_MESSAGE)); Assert.AreEqual(HttpStatusCode.OK, restResult.StatusCode); } /// - /// Creates a hot reload scenario in which the schema file is invalid which causes - /// hot reload to fail, then we check that the program is still able to work + /// Creates a hot reload scenario in which the configuration file has validation errors + /// which causes hot reload to fail, then we check that the program is still able to work /// properly by validating that the DAB engine is still using the same configuration file /// from before the hot reload. /// - /// Invalid change that was added is a schema file that is not complete, which should be - /// catched by the validator. + /// Invalid change: Setting both REST, GraphQL, and MCP to disabled, which is not allowed. /// - [Ignore] [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] - public void HotReloadValidationFail() + public async Task HotReloadValidationFail() { // Arrange - string schemaName = "hot-reload.draft.schema.json"; - string schemaConfig = TestHelper.GenerateInvalidSchema(); - - if (File.Exists(schemaName)) - { - File.Delete(schemaName); - } + _writer = new StringWriter(); + Console.SetOut(_writer); - File.WriteAllText(schemaName, schemaConfig); RuntimeConfig lkgRuntimeConfig = _configProvider.GetConfig(); Assert.IsNotNull(lkgRuntimeConfig); + // Capture properties to verify config hasn't changed + bool originalRestEnabled = lkgRuntimeConfig.Runtime.Rest.Enabled; + bool originalGraphQLEnabled = lkgRuntimeConfig.Runtime.GraphQL.Enabled; + bool originalMcpEnabled = lkgRuntimeConfig.Runtime.Mcp.Enabled; + // Act - // Simulate an invalid change to the schema file while the config is updated to a valid state + // Generate a config that will fail validation by disabling REST, GraphQL, and MCP (which is not allowed) GenerateConfigFile( - schema: schemaName, connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", restEnabled: "false", - gQLEnabled: "false"); - System.Threading.Thread.Sleep(10000); + gQLEnabled: "false", + mcpEnabled: "false"); + + // Wait for hot-reload to fail + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); RuntimeConfig newRuntimeConfig = _configProvider.GetConfig(); - // Assert - Assert.AreEqual(expected: lkgRuntimeConfig, actual: newRuntimeConfig); - - if (File.Exists(schemaName)) - { - File.Delete(schemaName); - } + // Assert - Verify the configuration hasn't changed by comparing properties + Assert.IsNotNull(newRuntimeConfig, "RuntimeConfig should not be null after failed hot-reload."); + Assert.AreEqual(originalRestEnabled, newRuntimeConfig.Runtime.Rest.Enabled, + "REST enabled setting should remain unchanged after hot-reload failure."); + Assert.AreEqual(originalGraphQLEnabled, newRuntimeConfig.Runtime.GraphQL.Enabled, + "GraphQL enabled setting should remain unchanged after hot-reload failure."); + Assert.AreEqual(originalMcpEnabled, newRuntimeConfig.Runtime.Mcp.Enabled, + "MCP enabled setting should remain unchanged after hot-reload failure."); } /// @@ -746,23 +807,39 @@ public void HotReloadValidationFail() /// [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] - public void HotReloadParsingFail() + public async Task HotReloadParsingFail() { // Arrange + _writer = new StringWriter(); + Console.SetOut(_writer); + RuntimeConfig lkgRuntimeConfig = _configProvider.GetConfig(); Assert.IsNotNull(lkgRuntimeConfig); + // Capture properties to verify config hasn't changed + bool originalRestEnabled = lkgRuntimeConfig.Runtime.Rest.Enabled; + bool originalGraphQLEnabled = lkgRuntimeConfig.Runtime.GraphQL.Enabled; + // Act GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", restEnabled: "invalid", gQLEnabled: "invalid"); - System.Threading.Thread.Sleep(5000); + + // Wait for hot-reload to fail (parsing error should trigger failure message) + await WaitForConditionAsync( + () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), + TimeSpan.FromSeconds(12), + TimeSpan.FromMilliseconds(500)); RuntimeConfig newRuntimeConfig = _configProvider.GetConfig(); - // Assert - Assert.AreEqual(expected: lkgRuntimeConfig, actual: newRuntimeConfig); + // Assert - Verify the configuration hasn't changed by comparing properties + Assert.IsNotNull(newRuntimeConfig, "RuntimeConfig should not be null after failed hot-reload."); + Assert.AreEqual(originalRestEnabled, newRuntimeConfig.Runtime.Rest.Enabled, + "REST enabled setting should remain unchanged after hot-reload failure."); + Assert.AreEqual(originalGraphQLEnabled, newRuntimeConfig.Runtime.GraphQL.Enabled, + "GraphQL enabled setting should remain unchanged after hot-reload failure."); } /// From f39705ccce28b51bfde8aaa42b476e6d1ef17499 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Tue, 16 Dec 2025 19:47:49 -0800 Subject: [PATCH 02/15] timeout to 30 seconds --- .../HotReload/ConfigurationHotReloadTests.cs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index 16dbf9ab57..b8cd9198fe 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -30,6 +30,7 @@ public class ConfigurationHotReloadTests private const string GQL_QUERY_NAME = "books"; private const string HOT_RELOAD_SUCCESS_MESSAGE = "Validated hot-reloaded configuration file"; private const string HOT_RELOAD_FAILURE_MESSAGE = "Unable to hot reload configuration file due to"; + private const int HOT_RELOAD_TIMEOUT_SECONDS = 30; private const string GQL_QUERY = @"{ books(first: 100) { @@ -308,7 +309,7 @@ public async Task HotReloadConfigRuntimeRestEnabledEndToEndTest() // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Act @@ -348,7 +349,7 @@ public async Task HotReloadConfigRuntimeGQLEnabledEndToEndTest() // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Act @@ -394,7 +395,7 @@ public async Task HotReloadEntityGQLEnabledFlag() // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Act @@ -434,7 +435,7 @@ public async Task HotReloadConfigAddEntity() // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Act @@ -514,7 +515,7 @@ public async Task HotReloadConfigUpdateMappings() // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Act @@ -598,7 +599,7 @@ public async Task HotReloadConfigDataSource() // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); RuntimeConfig updatedRuntimeConfig = _configProvider.GetConfig(); @@ -641,7 +642,7 @@ public async Task HotReloadLogLevel() // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); RuntimeConfig updatedRuntimeConfig = _configProvider.GetConfig(); @@ -671,7 +672,7 @@ public async Task HotReloadConfigConnectionString() connectionString: $"WrongConnectionString"); await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload was not able to validate properly @@ -683,7 +684,7 @@ await WaitForConditionAsync( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}"); await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload validated properly @@ -720,7 +721,7 @@ public async Task HotReloadConfigDatabaseType() connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.POSTGRESQL).Replace("\\", "\\\\")}"); await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload was not able to validate properly @@ -733,7 +734,7 @@ await WaitForConditionAsync( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}"); await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload validated properly @@ -782,7 +783,7 @@ public async Task HotReloadValidationFail() // Wait for hot-reload to fail await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); RuntimeConfig newRuntimeConfig = _configProvider.GetConfig(); @@ -829,7 +830,7 @@ public async Task HotReloadParsingFail() // Wait for hot-reload to fail (parsing error should trigger failure message) await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); RuntimeConfig newRuntimeConfig = _configProvider.GetConfig(); From dc4ef4b2635d0f5795ecc3cd6df42d0e3a05daa3 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Tue, 16 Dec 2025 19:50:32 -0800 Subject: [PATCH 03/15] format --- .../HotReload/ConfigurationHotReloadTests.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index b8cd9198fe..d49ecfc96b 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -259,11 +259,11 @@ public async Task HotReloadConfigRuntimePathsEndToEndTest() connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", restPath: restPath, gQLPath: gQLPath); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), - TimeSpan.FromSeconds(12), + TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Act @@ -305,7 +305,7 @@ public async Task HotReloadConfigRuntimeRestEnabledEndToEndTest() GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", restEnabled: restEnabled); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), @@ -345,7 +345,7 @@ public async Task HotReloadConfigRuntimeGQLEnabledEndToEndTest() GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", gQLEnabled: gQLEnabled); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), @@ -391,7 +391,7 @@ public async Task HotReloadEntityGQLEnabledFlag() GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", gQLEntityEnabled: gQLEntityEnabled); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), @@ -431,7 +431,7 @@ public async Task HotReloadConfigAddEntity() sourceObject: newEntitySource, gQLEntitySingular: newEntityGQLSingular, gQLEntityPlural: newEntityGQLPlural); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), @@ -511,7 +511,7 @@ public async Task HotReloadConfigUpdateMappings() connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", entityBackingColumn: "title", entityExposedName: newMappingFieldName); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), @@ -595,7 +595,7 @@ public async Task HotReloadConfigDataSource() GenerateConfigFile( sessionContext: "false", connectionString: expectedConnectionString); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), @@ -638,7 +638,7 @@ public async Task HotReloadLogLevel() GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", logFilter: expectedFilter); - + // Wait for hot-reload to complete successfully await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), @@ -779,7 +779,7 @@ public async Task HotReloadValidationFail() restEnabled: "false", gQLEnabled: "false", mcpEnabled: "false"); - + // Wait for hot-reload to fail await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), @@ -826,7 +826,7 @@ public async Task HotReloadParsingFail() connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", restEnabled: "invalid", gQLEnabled: "invalid"); - + // Wait for hot-reload to fail (parsing error should trigger failure message) await WaitForConditionAsync( () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), From e01885e9b16e5ac479c6b9724bcd2dd58e6865aa Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Tue, 16 Dec 2025 20:00:13 -0800 Subject: [PATCH 04/15] format --- .../HotReload/ConfigurationHotReloadTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index d49ecfc96b..c8ababa6c0 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -341,7 +341,7 @@ public async Task HotReloadConfigRuntimeGQLEnabledEndToEndTest() { Content = JsonContent.Create(payload) }; - + GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}", gQLEnabled: gQLEnabled); @@ -790,11 +790,11 @@ await WaitForConditionAsync( // Assert - Verify the configuration hasn't changed by comparing properties Assert.IsNotNull(newRuntimeConfig, "RuntimeConfig should not be null after failed hot-reload."); - Assert.AreEqual(originalRestEnabled, newRuntimeConfig.Runtime.Rest.Enabled, + Assert.AreEqual(originalRestEnabled, newRuntimeConfig.Runtime.Rest.Enabled, "REST enabled setting should remain unchanged after hot-reload failure."); - Assert.AreEqual(originalGraphQLEnabled, newRuntimeConfig.Runtime.GraphQL.Enabled, + Assert.AreEqual(originalGraphQLEnabled, newRuntimeConfig.Runtime.GraphQL.Enabled, "GraphQL enabled setting should remain unchanged after hot-reload failure."); - Assert.AreEqual(originalMcpEnabled, newRuntimeConfig.Runtime.Mcp.Enabled, + Assert.AreEqual(originalMcpEnabled, newRuntimeConfig.Runtime.Mcp.Enabled, "MCP enabled setting should remain unchanged after hot-reload failure."); } From a8011643a2e8ef58dcb191cc09ec60e459349b61 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Tue, 16 Dec 2025 20:43:31 -0800 Subject: [PATCH 05/15] add issue number to comment --- .../Configuration/HotReload/ConfigurationHotReloadTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index c8ababa6c0..d6daeaac76 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -366,7 +366,7 @@ await WaitForConditionAsync( /// [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod("Hot-reload gql disabled at entity level.")] - [Ignore] // This test requires GraphQL schema reload + [Ignore] // This test requires GraphQL schema reload. See: issue #3019 public async Task HotReloadEntityGQLEnabledFlag() { // Arrange @@ -413,7 +413,7 @@ await WaitForConditionAsync( /// [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] - [Ignore] // This test requires GraphQL schema reload + [Ignore] // This test requires GraphQL schema reload. See: issue #3019 public async Task HotReloadConfigAddEntity() { // Arrange @@ -498,7 +498,7 @@ await WaitForConditionAsync( /// results in bad request, while the new mappings results in a correct response as "title" field is no longer valid. [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] - [Ignore] // This test requires GraphQL schema reload + [Ignore] // This test requires GraphQL schema reload. See: issue #3019 public async Task HotReloadConfigUpdateMappings() { // Arrange From 75acf6349450bcd9bba0d383cb8cdba7f1b9e393 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Wed, 28 Jan 2026 12:21:56 -0800 Subject: [PATCH 06/15] try using write lock to avoid race condition --- .../HotReload/ConfigurationHotReloadTests.cs | 69 +++++++++++++------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index 13970b9de8..8bb9b44b78 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -26,6 +26,7 @@ public class ConfigurationHotReloadTests private static HttpClient _testClient; private static RuntimeConfigProvider _configProvider; private static StringWriter _writer; + private static readonly object _writerLock = new(); private const string CONFIG_FILE_NAME = "hot-reload.dab-config.json"; private const string GQL_QUERY_NAME = "books"; private const string HOT_RELOAD_SUCCESS_MESSAGE = "Validated hot-reloaded configuration file"; @@ -231,6 +232,17 @@ public static void ClassCleanup() _testClient.Dispose(); } + /// + /// Thread-safe helper to check if the writer contains a specific message + /// + private static bool WriterContains(string message) + { + lock (_writerLock) + { + return _writer.ToString().Contains(message); + } + } + /// /// Hot reload the configuration by saving a new file with different rest and graphQL paths. /// Validate that the response is correct when making a request with the newly hot-reloaded paths. @@ -262,7 +274,7 @@ public async Task HotReloadConfigRuntimePathsEndToEndTest() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -308,7 +320,7 @@ public async Task HotReloadConfigRuntimeRestEnabledEndToEndTest() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -348,7 +360,7 @@ public async Task HotReloadConfigRuntimeGQLEnabledEndToEndTest() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -394,7 +406,7 @@ public async Task HotReloadEntityGQLEnabledFlag() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -434,7 +446,7 @@ public async Task HotReloadConfigAddEntity() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -496,6 +508,7 @@ await WaitForConditionAsync( /// Here, we updated the old mappings of the entity book field "title" to "bookTitle". /// Validate that the response from the server is correct, by ensuring that the old mappings when used in the query /// results in bad request, while the new mappings results in a correct response as "title" field is no longer valid. + /// [TestCategory(MSSQL_ENVIRONMENT)] [TestMethod] [Ignore] // This test requires GraphQL schema reload. See: issue #3019 @@ -514,7 +527,7 @@ public async Task HotReloadConfigUpdateMappings() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -598,7 +611,7 @@ public async Task HotReloadConfigDataSource() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -641,7 +654,7 @@ public async Task HotReloadLogLevel() // Wait for hot-reload to complete successfully await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -671,24 +684,32 @@ public async Task HotReloadConfigConnectionString() GenerateConfigFile( connectionString: $"WrongConnectionString"); await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), + () => WriterContains(HOT_RELOAD_FAILURE_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload was not able to validate properly - string failedConfigLog = $"{_writer.ToString()}"; - _writer.GetStringBuilder().Clear(); + string failedConfigLog; + lock (_writerLock) + { + failedConfigLog = _writer.ToString(); + _writer.GetStringBuilder().Clear(); + } // Hot Reload should succeed here GenerateConfigFile( connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}"); await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload validated properly - string succeedConfigLog = $"{_writer.ToString()}"; + string succeedConfigLog; + lock (_writerLock) + { + succeedConfigLog = _writer.ToString(); + } HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); @@ -720,25 +741,33 @@ public async Task HotReloadConfigDatabaseType() databaseType: DatabaseType.PostgreSQL, connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.POSTGRESQL).Replace("\\", "\\\\")}"); await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), + () => WriterContains(HOT_RELOAD_FAILURE_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload was not able to validate properly - string failedConfigLog = $"{_writer.ToString()}"; - _writer.GetStringBuilder().Clear(); + string failedConfigLog; + lock (_writerLock) + { + failedConfigLog = _writer.ToString(); + _writer.GetStringBuilder().Clear(); + } // Hot Reload should succeed here GenerateConfigFile( databaseType: DatabaseType.MSSQL, connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}"); await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_SUCCESS_MESSAGE), + () => WriterContains(HOT_RELOAD_SUCCESS_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); // Log that shows that hot-reload validated properly - string succeedConfigLog = $"{_writer.ToString()}"; + string succeedConfigLog; + lock (_writerLock) + { + succeedConfigLog = _writer.ToString(); + } HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); @@ -782,7 +811,7 @@ public async Task HotReloadValidationFail() // Wait for hot-reload to fail await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), + () => WriterContains(HOT_RELOAD_FAILURE_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); @@ -829,7 +858,7 @@ public async Task HotReloadParsingFail() // Wait for hot-reload to fail (parsing error should trigger failure message) await WaitForConditionAsync( - () => _writer.ToString().Contains(HOT_RELOAD_FAILURE_MESSAGE), + () => WriterContains(HOT_RELOAD_FAILURE_MESSAGE), TimeSpan.FromSeconds(HOT_RELOAD_TIMEOUT_SECONDS), TimeSpan.FromMilliseconds(500)); From 8b3515822ee5d9d71c37ef62e18b38ed4e8675e9 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Wed, 28 Jan 2026 16:30:07 -0800 Subject: [PATCH 07/15] adjust pipline timeouts --- $tf/localversion.tf1 | Bin 0 -> 11 bytes $tf/localversion.tfb | Bin 0 -> 11 bytes $tf/pendingchanges.tf1 | Bin 0 -> 108567 bytes $tf/pendingchanges.tfb | Bin 0 -> 108567 bytes $tf/properties.tf1 | Bin 0 -> 190 bytes .pipelines/mssql-pipelines.yml | 6 +- .../HotReload/ConfigurationHotReloadTests.cs | 15 ++++- test/test-config.json | 55 ++++++++++++++++++ 8 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 $tf/localversion.tf1 create mode 100644 $tf/localversion.tfb create mode 100644 $tf/pendingchanges.tf1 create mode 100644 $tf/pendingchanges.tfb create mode 100644 $tf/properties.tf1 create mode 100644 test/test-config.json diff --git a/$tf/localversion.tf1 b/$tf/localversion.tf1 new file mode 100644 index 0000000000000000000000000000000000000000..f8ca6aaa19d10f2816c47bb393645602a6419eaf GIT binary patch literal 11 McmX@JoQVMn01syYb^rhX literal 0 HcmV?d00001 diff --git a/$tf/localversion.tfb b/$tf/localversion.tfb new file mode 100644 index 0000000000000000000000000000000000000000..f8ca6aaa19d10f2816c47bb393645602a6419eaf GIT binary patch literal 11 McmX@JoQVMn01syYb^rhX literal 0 HcmV?d00001 diff --git a/$tf/pendingchanges.tf1 b/$tf/pendingchanges.tf1 new file mode 100644 index 0000000000000000000000000000000000000000..f96a78b4af919599a3f54aec4e26ca69530ae801 GIT binary patch literal 108567 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 O7VKv~d!hN{{{I6Irvjn? literal 0 HcmV?d00001 diff --git a/$tf/pendingchanges.tfb b/$tf/pendingchanges.tfb new file mode 100644 index 0000000000000000000000000000000000000000..f96a78b4af919599a3f54aec4e26ca69530ae801 GIT binary patch literal 108567 zcmeI5U5I7bRe-OPCl!JaAAFKQ5>c_M`u`^kV*gA}_oREe(>0TkBxKUnx2n23)zvjs zx2Jy?f`kx6LXa4Ogdh?$N(do}1Rr7)2_hnS@F@@w5fKS_7ZftCZ?C&+?|sfb`<`?5 zKDTa7cQsvA_owb&|7-2F)?WJqljlD0^S}64KleXZKlFEh`AaXo=RMoMFp{s6?;kCX zmPWTm_eWc!_0gTthCCk2qlr9TlkbP*|9$zlIog%?-IedW(|x^Hetqtz@4WMldFl(# zop|5Je*B|L?sfOua~E{24OwL}x;=U@T9vi7<>#jSdt%A$D)?|%|Jf6sJ_vH1> z(M|LFk~|u_j~jJZ`Fd>S%cB+f_uA-1S?g8#esy$xbY*nb{Jt!(JrG(bRNI2{j=-=q zdMvQq6Nubb2Pl49q1YDuw*|LN`3a48g$g%EPh>qPa7bROzRtR-RsZnU6I4&E3XXRK zj&b=_&o$$UtnCUue4i(_gx>^)0DpWV?BXILxteKsY^ zK(Q;H$$f>^Jqg1nkdd}9So=2?Kl6rA3tOm`iBGsE|B#!pk&(&hky{}bYp5M29O97gAw1|8hy&>s78DC(IF$j_e2+gglGgx zSZU3QLrg@_Wo0K3^Iq4=LDsrP_qyO4<9-$d&m(sV0T!6(@}@k#CqL7%bkfdw62zzC zYpthU9$gY?nT&48bDQ!Tt6dO(bJIvPkux5TD8YSoux2LmaQMt#87a@e^wp4l&~0q6 z0qdJ$xev+r9a-bHJWDKcOTODE{{HAKd1gnx-;tjW1&(d8=shw2O(5Bl&&Ib-g5Tee z&qqhM@>ckj>IyexM|4)WcU697(C}qGcUS0yP1zLak(pI_jLZ;+=pJt(JDfv%R8@R* zH<}qEeLS|l+iitAFI|@?Nq1&DhQmZ|>{O69aJVn9F3B@J+j$> zIf_-``F-)1Z6fwRzn<8O|L)J^f_G1Z&xVQ$9BG7AK?Z~nOh@iRqICA%2rS`*`wEGg z1p7sCtE(?{<41~(yfUo9CPAD}?q6j!G-6FF|TXUjO z*?J{q<55|-s&w?FSux0B|5vlwACj>u!EI!^FiKN@LKK28#j{%5x+L}s!>}%lhHUOV zv%PAP=_Ur`^L9jlw&l}VlSf3DSXE39JJ>t2w&rsWnd~wVz^t8qa^;IEZsE!{8dJN? zzJ~mUUDt;*YwbNs`&hGg*PIHghPe;T^JK008!>#znXejKNfeUx`R8Jv@BAZtboonc zG!ZS|@zls#a}<>1|SPlNupV#^QOeL<`0NTrx7>nVjG(Ea>)^)*<{XDxa zbRc_0vk$V^ofWE4y;&A2>Tlq9N2sj1MWVT@vMzK+FZp>%9&ZZ9&>47c^~K#}Qeu$U z>d7n~TbLCF<-}dbhAuq66iS(;%H;%IZWw-0OS3xEn-WvKRf#)qY{8OLuGHpXjn4}8 z$Fg_Z5)R<#AA7H+Iq-jPCn8u=O|l$_ty_Pt9j%kAnoM_kRpd^0j4ufl!u+$N%aE8u z>#F>IMC$SYFCA}W3hJNYF8$!MX>rrp2HjV#&sH1G*fv+ z@WjHhcfBHzY#6(qwWi6WrS!?t)wkRkIL@T7UC+nQR?YA)#IL<6JahHe#5bw0S}Sic zr@5DA{=O#OP`NwHHzsvvCQqGaT54yl_s`RR~eEAr_WJc6sq$i9=1Xx(f(2*NOi=jDBbu1iz5%j+a%$MQ_NxRxaN z59dmN>q0{8%`LID5Mw;T`Vv=-rEf(eN-Pn?!SB2=IyE{hudR)ajZVtC!P`LsF3C4)DWH) zvYa%AkOa<}km}Sk0v!_>Ixa*yCgi|R92U2U1mQVO%kNLUiX9VT95+GL5s{t4#<3z* zC>pBwj6gC8{ z3;t{@kDqxlqh4bpL6C&h!6{>f*e0Hm|4+S*2SN6Ai@|4+RHjYWRQu$&RUh18IDIW5nTiy^vx>IsCr+!XSh5~84P zNX}vTji3?IJ@o`y7kSbAEpan82nkv>N`}KPOrU=oJl&Db-q;j~O?YT)0rdn9$7mwF zp8g;a?%EM3a}>?@{YNjNkdADs4~H2bEpHq^!t^VNv?0uS;ds2jPpooQ4CzFy#g6<& z}x9ZKMxdntR=c2lCmx` zLpuNs2#+P*T73KYlYJ+RtBE%&)4od2R|X@|Ww8x3ms~Ve1ys!*2)H1%W(qAUrkB33 zSNYyx2vvER<5>zL{a*(H>3xbbzT2BP>5ecPZQum!@3dWAmqqN=&+JZJ<=8ylF=aKn zTQ|#>Qop}1D1SukIW1N;64)2i`v*^T9$F3)`r6;=649a-shuse>%1neEG-4srlE7S z`KC&;;z9Q3dr5+|-4g0L3lxV5`N^(9+oMnt1fLf4 zHzaXK%9peY1xy;F=o#ZV9v?5gV|;fJkFFtzMgEhT3|(d9L+LOh?N>NPcy|$x3Jr&% zju`S$E50e@qaTgpR`EK`yNh^~(ONz^>_U ziuqZaW?X0n_1hN2q|!!7_BD5?K_$@l$Dyq1D;%?7BcOg3`LzcX3M=Bbi*eYZOn)7~ zE6V3Z$xuB`&Q0Wbf&_>%XEgt%7n*K+-+X+*qOAyNmeUR*V-w(~a;}Miy*uSB?SnLs zV`$ZLQIDZug~_E#Q<&3>NP;6%B2d(%n0ZDBL~(O$oc8+DKmz*PX!koV$ZKV8T^7y;V+eR7ta^wf4>8xL-F5kXR3Mar;Y$~lz?ySn;KYdUllQD zo}UVT@tVa?_8r0Q$ApRH*vinBNK%dco*wcc+AF@lJBTEL9NM2r+)w)lxo=W$dJd|v zp*)BrqRW?KJ%q>X4=4w)Z9ZkP2E`Mz`{z)tC7G2!B6~EjwV8Lc7*1ap7`ZRb)s*^X zv#>V*?_3eF3G7(M%8Hn*iOJTorP-bKH>I0_v{uSCm#*xi@{>b*Xga+TF=3@2@&l1d?bvN+DUnizDli&9x)^%9Z!Do8Nn(9<2ViD ze{JQROthY+<;YF(V-g2nB~J)hsIK#m12=lUgfrVnUGcQt!6(>BArh5#q>B7D2LL(N zMZKLN3C~ng$l=>C6p*vG9PDDE&?!+)l$0IS08=CmzJxJ<1kVV`C@3<5gJbU~C=Gef zB&;G~#9FInXGIX9AqFZ52~o;t1gj7Xd16)oDGi$Z=osRR+^P_bo%=I_)d+UV*ekL@ z%niT=pq|JYxuItSs}PLffp9|o;}Q8ukfHvP%HT7CRS2dBo+*}M!PrOQ1W;1K*~8BW zh9~sHigh6n#Tm#$izr1RV!yr1bHl88J6BZla9B9_;z7vU-GAH|2o z9840C?q^60dqtuul7w0W;BjH!cMwTL3J^)+A5}GM5;BAtCnZ>zMBf}N)$CW{Q+DP< zA_I@T$;8DgtY6!A6z$aM!o2&|z9UA@I~~xB)Sk$Hy{n_>K!jhbA1zpx9&6@W>wNcF zH*zEgaz}0r;M1E1M{w{gW2$^)u6wu|qe^z9(8BkOb@V+zC)U>XxzY z^yZ-*vF(;e%W_uqk#tY!ME*>?qOuUquFZfx`sqp?&P?iEq`hwxcz=v1ZoYm7+>!fL zRI2YbdzwY2TuQ&6+Ke%P1Gwzzx8`k{2zU7vk-k}kk{!NB_Y;}dr z_ZEIvZ5@+~f(32I#1&l5(AzJ6ItRw^h;C^0284NffvSzOe0i&{%FS**U2VJ1+@Q^p z0$)n&xD}IvCw-)VVQ|=$dnS*uGqRQiYV+EF@cv$9>(@>M>O)_uBUum*E-Xj6Ky1wz zY{<-Ma-F}SM_ouG_f|T4sdak^4mB;bs&kX%&QfA^ZJ*%n>>ENjoz>9GaO(1$Ap&>1 zYMh_DwwhLlsF+3QOgr{+RQ4=v@ZQEWL|u4OhS=Cca2d2)ZKj>|?shy8QO+GvWOiV8 z%peH-LG@jJu0I2=1Wz>ure`Qz=d8-rvJ9zUBqFy_bNw5X8q3HfcHGs!$ny1xIL)Vk zHE^5ePE<~QxRH&$P2OfR&r)k+jKk4HbcrKH8$vHG$P2As2KN$D)eIq{QI&7Vmp?+O z7+i^6#w@sq4#Rtf3ve>A^J;?UyvQ;~<&b8*1C)G72CsTZvgSoB%uu}p3#h;LJ4 z5V##^1}r^z@}kJ%uIQp223LS5l}ue5$#9WYmR0D5zst}1JMIiFe7w7T@bUMdKq~aU zQmTTzeQyuX)&vn=jVzTL6_^26K}xxpDocVsna8_umsTtS_?|tqNH9lDr-VCHH*sGAR zDO!Qlc#`Z1*U3;(W}K2%6_}P!zGq!1l|hl3-0sNdcdcFXHwr^m-TF~gZY?a$nWRgy z^5!(|Rth0I)cAMIT?CXW?EY;{s8!8GWl-)5wK~i2;97<=TdT-64gj^NNi8bY7yk_;uu%Q1`KuS`et%z>kGvbV`#1<@zYp6b#`h-FC`#TGd zenE@y*9(tqF&k1Vb%v^l9EOD_!Yx&>`fE2t5#N+o?-);JyDqYf^J+TGs>3h~zFp(= zwJ|Ki9DHtuh{OPE8++9Mws7RJ)t#te)}&bkiV5cJ?l2;LWKiY+T`jkuYUA(EX)(FhfDcasK%Exq#Ub)CDk=_}IS`IG;%>{|QlvClA z8176}1_YHeA;=_Kq>vs!a6_KwVl6Hv)vo!BRcm>=*s7sLRDIS?W5t}@hn^$rP5)X2 zHU@{yI4KXXe{3)4sL7x}Eh{&BWpJlEtnkLNl>}HC_&fP5{9lM$uTbtTo37bHy7qFL z6|b7m%Xt-*dir3p1DaZXFUD~sdqX^gcDHE*TpKsU@g(kBN5C|?xtW!g+zy912;#vp!hyx3 zcARfVXvDEXQqwm4AY7zPgG|!yUIVagU3*R5d1o3t6>%dC=CcaZi^59|o!pn7n5Zy! zl_7==+o1aTu3gM;kkDpr%&Gqu8SpfOaQ>$w?@i%j#>x#_)auHZF&rq(2W%zW9T@rw zPSzf@%-j+-1eH~YuI;t;pA|dssy9;OBO&=8qahxOL7=xczbSF)pimLAH6*a}jqgC7nd+4XF1G27q4_c+-t zNR5U}MNDQ?r&*i59%T#%(SF4y3e!MwK?g6Oa1aw!lkl$zrReR;h}AlHXobV^rBIB} zL31$0#RSjcNhgF}Iw9~kQYY)1<(=QY{9ux)t_ZtdCd6ZZ1{ZM7Fq~MVB z_lt=G(Z7RF>nc41K|CbE{VAUZ6ntA<90>e|e94N~9CuuaY!R8&9kavpkAq*9%3k5N z)rPEm9ip%`Yegb3+ABGQbl$*eJM1%}<%a!T9TuW>Mhju)9?I%euhvRarXjyshXyF# z+-n#q+Pc`VkBP(JSDFe-Nkhf82@Y)+bP}B*6X)X5ZGC0iIOOkFGS+R1Y3d7Cd$p>C zA*;@|h@_5S)?a0S-gJbiAL#Xlyefjlb_xxxM1A2NoY3`2l^Q(u19+B16eDv((9##` z-DwhX7W^3!T^M4U${i5mrlTzVh#Y1!2bb$dZEfx>0%H0Ghjz6swA$9cC3&RlQjMb` z=bmAZ;{}PisEXYae@_2SW^Jr>WaXexxa^Qn+fQaaTZRJFMmIGXswyn*@cZ z#6h7HS}{k(H>UYMvQ}g1v$`)lgl}XyIJQbmok6o8zklCUOP57HILxyw>(Btq#n^}C zk*>FEo+D>W9|jH6cjY^IRQJ`P43`7^0%L z3~ASe+#9*14$Amx=s5wjIyzKx^&myxXLVOV&J?-MkRU*$z^3Qe)lT>m=a~wgqM3)jcj}Bd9bMqws(b_xJ2c z8h<6IFq9>77346*SZ&lOBsAgFreP7vv8G9`1Sc}u;1Ca6x&#hMc!J*hHt=+F+R3%Q z-C06ozFUtWJdjvs)6^p$h})rEc1aFP=t;oq@(O8Z=B+V)%e`{Z#6ZNP56x?zlGmu7 zk(AbX{1`ui>__riM0Fw;h&xj4~D4EJUj+PkIV zE;LA;%%)a*NC$DCgV9yXR~$nqWVNHANeKxU$k7i5Z`EfOqHj0`u%zHt0iKJK4-d`` ziOygyKFlBwiNdRU#=Mxi&QF|t;0NPHG%wO@ee{@^ix2Sph4eIN6rU{=F-QiZ(rPy^ zjgQa?8#+y4MIJM2g2PHo5xp<*)9zj}SCgtPbP5vz$p|JWqR*xoB>-X@Ztd-w=S#xT zk$16>{ds}tdD9%SEmJy{ggUnRHap*zge@pm%%)KcwnHY~g>sp&1nrLfU|BLWvK4m@ z9K9j=!TZx~un@V5!ig9kUo7TlR7s`>~ynAv5btBsoZKxQqIFRuh}H(4(MRv*0-X0ujZ&U2KvHhy*g$n zI4r`nLY=o+uhSB94ipu1^eeL;Zx9lvnsh=(u%M+U9Ziz(DN?(v4(O!mTe!M8_Zwpk9r(?5-`_C^KXmph=Z|7vo$OZBZJw9HuVPUWr5XVvNSq1dg7FZ5+}b=-gTfsb*D zlZAzDTcBHCSm<_yay_9dV&xdnsbc{`nY(H32I~pgYPXmpE^|$gts3v;7&=^J*bOf3 z=-PE)b@8Qx(u*#Q)dhrWP59VTz6O>2H8TXJCuD%KbZbs*G6s~QFD(*RQEsO=*7W>t6uQV{d$Y8mzMUk&<$*C=(+>?P_M0)K=rf(7L z7XvSEI`LWh3Fq>zB`eu=#-FX+Iklemd9Y@X7WV-DUB`oSsP^%1^HL z$3fFWm)`O&MC$Un1xOg2=IXNc@+j=4*PC{<$eTgr;P65YJj^=euoSmUsVMk2PE`;1 zrLJ^L3PsR5mjkbz_)E)UZ)k$4vE86K@3kJ&Fu-9ny?09QEhm&EJZm=*BuTSya%49! zFNoEJsd}vuJ>1la^(@tW5lK#^F?@s5aFhtiHxYM z7A16sV1&-ViUGpWB--{p8D!2dcg^r#6XBrud`G4LKQ3YJf-wx;WT6?#6)_dWbhtRR zbe5i34&>8*MAZ$}>ac8h@5Xa7A~U>(r+_W=$Gq8NgWVKfa}hTXuqVM4#cv~8swIwV=&0A3frsl>6}?}5$x@~&dm0s zWRvSBJ$kr)+g*G!7V62jg<`#T^g-Wq^GeG`nyNkaIVTj8R17jRU7^Z751523IA7Ww zvM!zeNjQ=^=*t;apvt%WGk{6hvT4-*)Ik!CkEdd**)-~R${-0*GI`-cWb=BtXYA$! zjpJAP{8|#4)wbM9(BskWL z=Vx&K9kB-FtDneoSx^Kg4$@HAlQMBjly^!iDN(KUpU60MlB}53E(np+xmo9)k~C`V zM`qC|u6J3mwbncbTkdJBB&}X(YYDoXJW8&3vF(c1cbpgfo``O5m^{U-3(=BmpX<7I zp$IyithR{yAv`H)OdC0LelmbHg?b!cj(V8l)t7JRjcY^4z*P$M~My>v5zMR@e53x!fqOOWo3anwths;anEAG^eHGoOkg z^$&yai=7F3-dpltyB9(sP1T>Oxd!)HR4R3EZ|^S6Fn{4#<5I@N0UJl$@pn#W?hk)c zHLy7${+&4qwo6pB7jY*gPNcIUtYNIK1Jep~6S7XM-QN^KZNK@L66FJotj%RT6+#3>w_v5<|hFPhDhJ_G=j^&66{}|F|ZJ zo)rO~D`zf?3NvgZ1C938iG0qG3ni(zySG;^z=!skk9-7tn}60M+$>6kx$?z1s=bfY zu4qkB@k(}CT5ZG_b!QHuj}OZb{`PKF!P7hJ806@3mM)_fE5!MKr>9DEJgwHhin`Tg z%V?d{aa??OLp)zJ^1dx`E@#YWn#@RWwQd(_hR2Fb3=fCxBEYC)KmEfam&FJcfw6UC z#JpnhPqf>TXv z0lXH6VuhKG;d4wsmW}jLECO1FycSA`wXXW6XlXUWf6qnXI`CS5o7t|`$t~HT;TA6I zuI%%E{nWiDLn1qI*h1k}R?Ap@KHQM>KH=KBK^*Q?VSsYgnxBJvKPl$Y6)I^Hk+njF z)J|K<7{wfHMQ9aV_cO~f$KbJ06ex7Hj#>Xr@9}}_=XT>b7{X`npcynTi zQ4x4sd*Ipd`Zf9iAZ;BDrXh8DG60P2JIK;N`eqn&7{1#wK73b(VQk$<6T%S^kX9P* zESPmp%R)a(&0hJl7n)~^v`)fY3ZZ34SH?irjvOvXxsPE zwgGp=s3X0OvB@^!2oxoGhJ<{twS=sQ`XG)>rceQGn}r$82(K zc(^p}Ze<=G{TO3W3Z`8(&(2S(Mf(chypeWICQlK{wvJyI<$qjQ(GIKm8vGPS{x7nT zZ%Wx&ZN{iAS{Y8EohS;ne%G`+KchP3Z`$U(=~65Wv8HrmpJSXSIWFO;0t435&* zJ9uKUAlARu&2cluX}0kj1eM=m0;Bn_GkndT6hn^9CD*jD$*|{jnn{s*cLB|6-%~zI zvr>S<;U?`$|6K;h=80Nd%LYR&ytO#Tyr)5IqiyL=$lzbOn8M|=oAs>zo&wrcEba82tov$74x4DQOS^) z`JiB})F3G2Bud(HA+}>}MkXt((7p`XMJvdA(j~fV5{LX2ickSrz~=<_%^F|9kur7sO)mmI)xU2w052xVEPVWOk!X7-kET=kg)1h|ua#)uUJe3%`ArFbl` zE>8R8#UXY-$kwY%VCpca6TE=V{$LQDwNVC*n`7y8c}0G5#+CL>rhrZMuFvwx;v(-p zf1j~CT`VG46`L~=ez-uA5L4GVljHjfM2QIoK@D5BeNB&DM(194y{_C4ObwsG z&}-7GOrPsRd7Po^t&cz14u4iA$BNibc6CPoehlS+{gfgS(z<3~SM`a0)exIbpg6pA-P*q^0&VL<)pk`M z+G~{U&1KXC3uSu96rzVqDt4+mZc3@6w?L1@rE(<_xi4fHtHA3-gIKLL O7VKv~d!hN{{{I6Irvjn? literal 0 HcmV?d00001 diff --git a/$tf/properties.tf1 b/$tf/properties.tf1 new file mode 100644 index 0000000000000000000000000000000000000000..96ddc950c29feb3b8dffb3ec797011db9fdcac6c GIT binary patch literal 190 zcmb7-u?~Vj5JVpr<2P7X(h?I&V(Dkt2%JK4feWam-|kbtz+!hcJ8v?_S18z?XgJgS zWFeB7S$*|fxI2}T8P%4Dnsg$IM5%uz1a`?xCzp7By;W{z0`}R*WMp*Tga)zC6)k~+ KP04}!|N1w4=OL>A literal 0 HcmV?d00001 diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index 8ddbbbd88b..5b465065a2 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -122,8 +122,9 @@ jobs: displayName: 'Run MsSql Integration Tests' inputs: command: test - arguments: '--filter "TestCategory=MsSql" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage"' + arguments: '--filter "TestCategory=MsSql" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=7200000' projects: '**/*Tests/*.csproj' + timeoutInMinutes: 120 - task: CmdLine@2 displayName: 'Set flag to publish Verify *.received files when tests fail' @@ -249,8 +250,9 @@ jobs: displayName: 'Run MsSql Integration Tests' inputs: command: test - arguments: '--filter "TestCategory=MsSql" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage"' + arguments: '--filter "TestCategory=MsSql" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=7200000' projects: '**/*Tests/*.csproj' + timeoutInMinutes: 120 - task: PublishCodeCoverageResults@1 displayName: 'Publish code coverage' diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index 8bb9b44b78..bfbba8ee8d 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -31,7 +31,7 @@ public class ConfigurationHotReloadTests private const string GQL_QUERY_NAME = "books"; private const string HOT_RELOAD_SUCCESS_MESSAGE = "Validated hot-reloaded configuration file"; private const string HOT_RELOAD_FAILURE_MESSAGE = "Unable to hot reload configuration file due to"; - private const int HOT_RELOAD_TIMEOUT_SECONDS = 30; + private const int HOT_RELOAD_TIMEOUT_SECONDS = 120; // Increased from 30 to 120 for CI/CD environments private const string GQL_QUERY = @"{ books(first: 100) { @@ -879,16 +879,29 @@ await WaitForConditionAsync( private static async Task WaitForConditionAsync(Func condition, TimeSpan timeout, TimeSpan pollingInterval) { System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); + int attemptCount = 0; while (stopwatch.Elapsed < timeout) { + attemptCount++; if (condition()) { + Console.WriteLine($"Hot-reload condition met after {stopwatch.Elapsed.TotalSeconds:F2} seconds ({attemptCount} attempts)"); return; } + if (attemptCount % 10 == 0) // Log every 10 attempts (every 5 seconds) + { + Console.WriteLine($"Still waiting for hot-reload condition... Elapsed: {stopwatch.Elapsed.TotalSeconds:F2}s, Attempts: {attemptCount}"); + } + await Task.Delay(pollingInterval); } + Console.WriteLine($"Hot-reload timeout after {stopwatch.Elapsed.TotalSeconds:F2} seconds ({attemptCount} attempts)"); + lock (_writerLock) + { + Console.WriteLine($"Console output captured:\n{_writer.ToString()}"); + } throw new TimeoutException("The condition was not met within the timeout period."); } } diff --git a/test/test-config.json b/test/test-config.json new file mode 100644 index 0000000000..a06bc6f7fd --- /dev/null +++ b/test/test-config.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://github.com/Azure/data-api-builder/releases/download/v0.13.0/dab.draft.schema.json", + "data-source": { + "database-type": "mssql", + "connection-string": "", + "options": { + "set-session-context": false + } + }, + "runtime": { + "graphql": { + "enabled": true, + "path": "/graphql", + "allow-introspection": true + }, + "host": { + "cors": { + "origins": [], + "allow-credentials": false + }, + "authentication": { + "provider": "StaticWebApps" + }, + "mode": "production" + } + }, + "entities": { + "Book": { + "source": { + "object": "dbo.books", + "type": "table" + }, + "graphql": { + "enabled": true, + "type": { + "singular": "Book", + "plural": "Books" + } + }, + "rest": { + "enabled": true + }, + "permissions": [ + { + "role": "anonymouse", + "actions": [ + { + "action": "*" + } + ] + } + ] + } + } +} \ No newline at end of file From 1652d5605e68746fb093c128c4bf92e9c79ce81e Mon Sep 17 00:00:00 2001 From: aaronburtle <93220300+aaronburtle@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:31:19 -0800 Subject: [PATCH 08/15] Delete $tf directory --- $tf/localversion.tf1 | Bin 11 -> 0 bytes $tf/localversion.tfb | Bin 11 -> 0 bytes $tf/pendingchanges.tf1 | Bin 108567 -> 0 bytes $tf/pendingchanges.tfb | Bin 108567 -> 0 bytes $tf/properties.tf1 | Bin 190 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 $tf/localversion.tf1 delete mode 100644 $tf/localversion.tfb delete mode 100644 $tf/pendingchanges.tf1 delete mode 100644 $tf/pendingchanges.tfb delete mode 100644 $tf/properties.tf1 diff --git a/$tf/localversion.tf1 b/$tf/localversion.tf1 deleted file mode 100644 index f8ca6aaa19d10f2816c47bb393645602a6419eaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11 McmX@JoQVMn01syYb^rhX diff --git a/$tf/localversion.tfb b/$tf/localversion.tfb deleted file mode 100644 index f8ca6aaa19d10f2816c47bb393645602a6419eaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11 McmX@JoQVMn01syYb^rhX diff --git a/$tf/pendingchanges.tf1 b/$tf/pendingchanges.tf1 deleted file mode 100644 index f96a78b4af919599a3f54aec4e26ca69530ae801..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108567 zcmeI5U5I7bRe-OPCl!JaAAFKQ5>c_M`u`^kV*gA}_oREe(>0TkBxKUnx2n23)zvjs zx2Jy?f`kx6LXa4Ogdh?$N(do}1Rr7)2_hnS@F@@w5fKS_7ZftCZ?C&+?|sfb`<`?5 zKDTa7cQsvA_owb&|7-2F)?WJqljlD0^S}64KleXZKlFEh`AaXo=RMoMFp{s6?;kCX zmPWTm_eWc!_0gTthCCk2qlr9TlkbP*|9$zlIog%?-IedW(|x^Hetqtz@4WMldFl(# zop|5Je*B|L?sfOua~E{24OwL}x;=U@T9vi7<>#jSdt%A$D)?|%|Jf6sJ_vH1> z(M|LFk~|u_j~jJZ`Fd>S%cB+f_uA-1S?g8#esy$xbY*nb{Jt!(JrG(bRNI2{j=-=q zdMvQq6Nubb2Pl49q1YDuw*|LN`3a48g$g%EPh>qPa7bROzRtR-RsZnU6I4&E3XXRK zj&b=_&o$$UtnCUue4i(_gx>^)0DpWV?BXILxteKsY^ zK(Q;H$$f>^Jqg1nkdd}9So=2?Kl6rA3tOm`iBGsE|B#!pk&(&hky{}bYp5M29O97gAw1|8hy&>s78DC(IF$j_e2+gglGgx zSZU3QLrg@_Wo0K3^Iq4=LDsrP_qyO4<9-$d&m(sV0T!6(@}@k#CqL7%bkfdw62zzC zYpthU9$gY?nT&48bDQ!Tt6dO(bJIvPkux5TD8YSoux2LmaQMt#87a@e^wp4l&~0q6 z0qdJ$xev+r9a-bHJWDKcOTODE{{HAKd1gnx-;tjW1&(d8=shw2O(5Bl&&Ib-g5Tee z&qqhM@>ckj>IyexM|4)WcU697(C}qGcUS0yP1zLak(pI_jLZ;+=pJt(JDfv%R8@R* zH<}qEeLS|l+iitAFI|@?Nq1&DhQmZ|>{O69aJVn9F3B@J+j$> zIf_-``F-)1Z6fwRzn<8O|L)J^f_G1Z&xVQ$9BG7AK?Z~nOh@iRqICA%2rS`*`wEGg z1p7sCtE(?{<41~(yfUo9CPAD}?q6j!G-6FF|TXUjO z*?J{q<55|-s&w?FSux0B|5vlwACj>u!EI!^FiKN@LKK28#j{%5x+L}s!>}%lhHUOV zv%PAP=_Ur`^L9jlw&l}VlSf3DSXE39JJ>t2w&rsWnd~wVz^t8qa^;IEZsE!{8dJN? zzJ~mUUDt;*YwbNs`&hGg*PIHghPe;T^JK008!>#znXejKNfeUx`R8Jv@BAZtboonc zG!ZS|@zls#a}<>1|SPlNupV#^QOeL<`0NTrx7>nVjG(Ea>)^)*<{XDxa zbRc_0vk$V^ofWE4y;&A2>Tlq9N2sj1MWVT@vMzK+FZp>%9&ZZ9&>47c^~K#}Qeu$U z>d7n~TbLCF<-}dbhAuq66iS(;%H;%IZWw-0OS3xEn-WvKRf#)qY{8OLuGHpXjn4}8 z$Fg_Z5)R<#AA7H+Iq-jPCn8u=O|l$_ty_Pt9j%kAnoM_kRpd^0j4ufl!u+$N%aE8u z>#F>IMC$SYFCA}W3hJNYF8$!MX>rrp2HjV#&sH1G*fv+ z@WjHhcfBHzY#6(qwWi6WrS!?t)wkRkIL@T7UC+nQR?YA)#IL<6JahHe#5bw0S}Sic zr@5DA{=O#OP`NwHHzsvvCQqGaT54yl_s`RR~eEAr_WJc6sq$i9=1Xx(f(2*NOi=jDBbu1iz5%j+a%$MQ_NxRxaN z59dmN>q0{8%`LID5Mw;T`Vv=-rEf(eN-Pn?!SB2=IyE{hudR)ajZVtC!P`LsF3C4)DWH) zvYa%AkOa<}km}Sk0v!_>Ixa*yCgi|R92U2U1mQVO%kNLUiX9VT95+GL5s{t4#<3z* zC>pBwj6gC8{ z3;t{@kDqxlqh4bpL6C&h!6{>f*e0Hm|4+S*2SN6Ai@|4+RHjYWRQu$&RUh18IDIW5nTiy^vx>IsCr+!XSh5~84P zNX}vTji3?IJ@o`y7kSbAEpan82nkv>N`}KPOrU=oJl&Db-q;j~O?YT)0rdn9$7mwF zp8g;a?%EM3a}>?@{YNjNkdADs4~H2bEpHq^!t^VNv?0uS;ds2jPpooQ4CzFy#g6<& z}x9ZKMxdntR=c2lCmx` zLpuNs2#+P*T73KYlYJ+RtBE%&)4od2R|X@|Ww8x3ms~Ve1ys!*2)H1%W(qAUrkB33 zSNYyx2vvER<5>zL{a*(H>3xbbzT2BP>5ecPZQum!@3dWAmqqN=&+JZJ<=8ylF=aKn zTQ|#>Qop}1D1SukIW1N;64)2i`v*^T9$F3)`r6;=649a-shuse>%1neEG-4srlE7S z`KC&;;z9Q3dr5+|-4g0L3lxV5`N^(9+oMnt1fLf4 zHzaXK%9peY1xy;F=o#ZV9v?5gV|;fJkFFtzMgEhT3|(d9L+LOh?N>NPcy|$x3Jr&% zju`S$E50e@qaTgpR`EK`yNh^~(ONz^>_U ziuqZaW?X0n_1hN2q|!!7_BD5?K_$@l$Dyq1D;%?7BcOg3`LzcX3M=Bbi*eYZOn)7~ zE6V3Z$xuB`&Q0Wbf&_>%XEgt%7n*K+-+X+*qOAyNmeUR*V-w(~a;}Miy*uSB?SnLs zV`$ZLQIDZug~_E#Q<&3>NP;6%B2d(%n0ZDBL~(O$oc8+DKmz*PX!koV$ZKV8T^7y;V+eR7ta^wf4>8xL-F5kXR3Mar;Y$~lz?ySn;KYdUllQD zo}UVT@tVa?_8r0Q$ApRH*vinBNK%dco*wcc+AF@lJBTEL9NM2r+)w)lxo=W$dJd|v zp*)BrqRW?KJ%q>X4=4w)Z9ZkP2E`Mz`{z)tC7G2!B6~EjwV8Lc7*1ap7`ZRb)s*^X zv#>V*?_3eF3G7(M%8Hn*iOJTorP-bKH>I0_v{uSCm#*xi@{>b*Xga+TF=3@2@&l1d?bvN+DUnizDli&9x)^%9Z!Do8Nn(9<2ViD ze{JQROthY+<;YF(V-g2nB~J)hsIK#m12=lUgfrVnUGcQt!6(>BArh5#q>B7D2LL(N zMZKLN3C~ng$l=>C6p*vG9PDDE&?!+)l$0IS08=CmzJxJ<1kVV`C@3<5gJbU~C=Gef zB&;G~#9FInXGIX9AqFZ52~o;t1gj7Xd16)oDGi$Z=osRR+^P_bo%=I_)d+UV*ekL@ z%niT=pq|JYxuItSs}PLffp9|o;}Q8ukfHvP%HT7CRS2dBo+*}M!PrOQ1W;1K*~8BW zh9~sHigh6n#Tm#$izr1RV!yr1bHl88J6BZla9B9_;z7vU-GAH|2o z9840C?q^60dqtuul7w0W;BjH!cMwTL3J^)+A5}GM5;BAtCnZ>zMBf}N)$CW{Q+DP< zA_I@T$;8DgtY6!A6z$aM!o2&|z9UA@I~~xB)Sk$Hy{n_>K!jhbA1zpx9&6@W>wNcF zH*zEgaz}0r;M1E1M{w{gW2$^)u6wu|qe^z9(8BkOb@V+zC)U>XxzY z^yZ-*vF(;e%W_uqk#tY!ME*>?qOuUquFZfx`sqp?&P?iEq`hwxcz=v1ZoYm7+>!fL zRI2YbdzwY2TuQ&6+Ke%P1Gwzzx8`k{2zU7vk-k}kk{!NB_Y;}dr z_ZEIvZ5@+~f(32I#1&l5(AzJ6ItRw^h;C^0284NffvSzOe0i&{%FS**U2VJ1+@Q^p z0$)n&xD}IvCw-)VVQ|=$dnS*uGqRQiYV+EF@cv$9>(@>M>O)_uBUum*E-Xj6Ky1wz zY{<-Ma-F}SM_ouG_f|T4sdak^4mB;bs&kX%&QfA^ZJ*%n>>ENjoz>9GaO(1$Ap&>1 zYMh_DwwhLlsF+3QOgr{+RQ4=v@ZQEWL|u4OhS=Cca2d2)ZKj>|?shy8QO+GvWOiV8 z%peH-LG@jJu0I2=1Wz>ure`Qz=d8-rvJ9zUBqFy_bNw5X8q3HfcHGs!$ny1xIL)Vk zHE^5ePE<~QxRH&$P2OfR&r)k+jKk4HbcrKH8$vHG$P2As2KN$D)eIq{QI&7Vmp?+O z7+i^6#w@sq4#Rtf3ve>A^J;?UyvQ;~<&b8*1C)G72CsTZvgSoB%uu}p3#h;LJ4 z5V##^1}r^z@}kJ%uIQp223LS5l}ue5$#9WYmR0D5zst}1JMIiFe7w7T@bUMdKq~aU zQmTTzeQyuX)&vn=jVzTL6_^26K}xxpDocVsna8_umsTtS_?|tqNH9lDr-VCHH*sGAR zDO!Qlc#`Z1*U3;(W}K2%6_}P!zGq!1l|hl3-0sNdcdcFXHwr^m-TF~gZY?a$nWRgy z^5!(|Rth0I)cAMIT?CXW?EY;{s8!8GWl-)5wK~i2;97<=TdT-64gj^NNi8bY7yk_;uu%Q1`KuS`et%z>kGvbV`#1<@zYp6b#`h-FC`#TGd zenE@y*9(tqF&k1Vb%v^l9EOD_!Yx&>`fE2t5#N+o?-);JyDqYf^J+TGs>3h~zFp(= zwJ|Ki9DHtuh{OPE8++9Mws7RJ)t#te)}&bkiV5cJ?l2;LWKiY+T`jkuYUA(EX)(FhfDcasK%Exq#Ub)CDk=_}IS`IG;%>{|QlvClA z8176}1_YHeA;=_Kq>vs!a6_KwVl6Hv)vo!BRcm>=*s7sLRDIS?W5t}@hn^$rP5)X2 zHU@{yI4KXXe{3)4sL7x}Eh{&BWpJlEtnkLNl>}HC_&fP5{9lM$uTbtTo37bHy7qFL z6|b7m%Xt-*dir3p1DaZXFUD~sdqX^gcDHE*TpKsU@g(kBN5C|?xtW!g+zy912;#vp!hyx3 zcARfVXvDEXQqwm4AY7zPgG|!yUIVagU3*R5d1o3t6>%dC=CcaZi^59|o!pn7n5Zy! zl_7==+o1aTu3gM;kkDpr%&Gqu8SpfOaQ>$w?@i%j#>x#_)auHZF&rq(2W%zW9T@rw zPSzf@%-j+-1eH~YuI;t;pA|dssy9;OBO&=8qahxOL7=xczbSF)pimLAH6*a}jqgC7nd+4XF1G27q4_c+-t zNR5U}MNDQ?r&*i59%T#%(SF4y3e!MwK?g6Oa1aw!lkl$zrReR;h}AlHXobV^rBIB} zL31$0#RSjcNhgF}Iw9~kQYY)1<(=QY{9ux)t_ZtdCd6ZZ1{ZM7Fq~MVB z_lt=G(Z7RF>nc41K|CbE{VAUZ6ntA<90>e|e94N~9CuuaY!R8&9kavpkAq*9%3k5N z)rPEm9ip%`Yegb3+ABGQbl$*eJM1%}<%a!T9TuW>Mhju)9?I%euhvRarXjyshXyF# z+-n#q+Pc`VkBP(JSDFe-Nkhf82@Y)+bP}B*6X)X5ZGC0iIOOkFGS+R1Y3d7Cd$p>C zA*;@|h@_5S)?a0S-gJbiAL#Xlyefjlb_xxxM1A2NoY3`2l^Q(u19+B16eDv((9##` z-DwhX7W^3!T^M4U${i5mrlTzVh#Y1!2bb$dZEfx>0%H0Ghjz6swA$9cC3&RlQjMb` z=bmAZ;{}PisEXYae@_2SW^Jr>WaXexxa^Qn+fQaaTZRJFMmIGXswyn*@cZ z#6h7HS}{k(H>UYMvQ}g1v$`)lgl}XyIJQbmok6o8zklCUOP57HILxyw>(Btq#n^}C zk*>FEo+D>W9|jH6cjY^IRQJ`P43`7^0%L z3~ASe+#9*14$Amx=s5wjIyzKx^&myxXLVOV&J?-MkRU*$z^3Qe)lT>m=a~wgqM3)jcj}Bd9bMqws(b_xJ2c z8h<6IFq9>77346*SZ&lOBsAgFreP7vv8G9`1Sc}u;1Ca6x&#hMc!J*hHt=+F+R3%Q z-C06ozFUtWJdjvs)6^p$h})rEc1aFP=t;oq@(O8Z=B+V)%e`{Z#6ZNP56x?zlGmu7 zk(AbX{1`ui>__riM0Fw;h&xj4~D4EJUj+PkIV zE;LA;%%)a*NC$DCgV9yXR~$nqWVNHANeKxU$k7i5Z`EfOqHj0`u%zHt0iKJK4-d`` ziOygyKFlBwiNdRU#=Mxi&QF|t;0NPHG%wO@ee{@^ix2Sph4eIN6rU{=F-QiZ(rPy^ zjgQa?8#+y4MIJM2g2PHo5xp<*)9zj}SCgtPbP5vz$p|JWqR*xoB>-X@Ztd-w=S#xT zk$16>{ds}tdD9%SEmJy{ggUnRHap*zge@pm%%)KcwnHY~g>sp&1nrLfU|BLWvK4m@ z9K9j=!TZx~un@V5!ig9kUo7TlR7s`>~ynAv5btBsoZKxQqIFRuh}H(4(MRv*0-X0ujZ&U2KvHhy*g$n zI4r`nLY=o+uhSB94ipu1^eeL;Zx9lvnsh=(u%M+U9Ziz(DN?(v4(O!mTe!M8_Zwpk9r(?5-`_C^KXmph=Z|7vo$OZBZJw9HuVPUWr5XVvNSq1dg7FZ5+}b=-gTfsb*D zlZAzDTcBHCSm<_yay_9dV&xdnsbc{`nY(H32I~pgYPXmpE^|$gts3v;7&=^J*bOf3 z=-PE)b@8Qx(u*#Q)dhrWP59VTz6O>2H8TXJCuD%KbZbs*G6s~QFD(*RQEsO=*7W>t6uQV{d$Y8mzMUk&<$*C=(+>?P_M0)K=rf(7L z7XvSEI`LWh3Fq>zB`eu=#-FX+Iklemd9Y@X7WV-DUB`oSsP^%1^HL z$3fFWm)`O&MC$Un1xOg2=IXNc@+j=4*PC{<$eTgr;P65YJj^=euoSmUsVMk2PE`;1 zrLJ^L3PsR5mjkbz_)E)UZ)k$4vE86K@3kJ&Fu-9ny?09QEhm&EJZm=*BuTSya%49! zFNoEJsd}vuJ>1la^(@tW5lK#^F?@s5aFhtiHxYM z7A16sV1&-ViUGpWB--{p8D!2dcg^r#6XBrud`G4LKQ3YJf-wx;WT6?#6)_dWbhtRR zbe5i34&>8*MAZ$}>ac8h@5Xa7A~U>(r+_W=$Gq8NgWVKfa}hTXuqVM4#cv~8swIwV=&0A3frsl>6}?}5$x@~&dm0s zWRvSBJ$kr)+g*G!7V62jg<`#T^g-Wq^GeG`nyNkaIVTj8R17jRU7^Z751523IA7Ww zvM!zeNjQ=^=*t;apvt%WGk{6hvT4-*)Ik!CkEdd**)-~R${-0*GI`-cWb=BtXYA$! zjpJAP{8|#4)wbM9(BskWL z=Vx&K9kB-FtDneoSx^Kg4$@HAlQMBjly^!iDN(KUpU60MlB}53E(np+xmo9)k~C`V zM`qC|u6J3mwbncbTkdJBB&}X(YYDoXJW8&3vF(c1cbpgfo``O5m^{U-3(=BmpX<7I zp$IyithR{yAv`H)OdC0LelmbHg?b!cj(V8l)t7JRjcY^4z*P$M~My>v5zMR@e53x!fqOOWo3anwths;anEAG^eHGoOkg z^$&yai=7F3-dpltyB9(sP1T>Oxd!)HR4R3EZ|^S6Fn{4#<5I@N0UJl$@pn#W?hk)c zHLy7${+&4qwo6pB7jY*gPNcIUtYNIK1Jep~6S7XM-QN^KZNK@L66FJotj%RT6+#3>w_v5<|hFPhDhJ_G=j^&66{}|F|ZJ zo)rO~D`zf?3NvgZ1C938iG0qG3ni(zySG;^z=!skk9-7tn}60M+$>6kx$?z1s=bfY zu4qkB@k(}CT5ZG_b!QHuj}OZb{`PKF!P7hJ806@3mM)_fE5!MKr>9DEJgwHhin`Tg z%V?d{aa??OLp)zJ^1dx`E@#YWn#@RWwQd(_hR2Fb3=fCxBEYC)KmEfam&FJcfw6UC z#JpnhPqf>TXv z0lXH6VuhKG;d4wsmW}jLECO1FycSA`wXXW6XlXUWf6qnXI`CS5o7t|`$t~HT;TA6I zuI%%E{nWiDLn1qI*h1k}R?Ap@KHQM>KH=KBK^*Q?VSsYgnxBJvKPl$Y6)I^Hk+njF z)J|K<7{wfHMQ9aV_cO~f$KbJ06ex7Hj#>Xr@9}}_=XT>b7{X`npcynTi zQ4x4sd*Ipd`Zf9iAZ;BDrXh8DG60P2JIK;N`eqn&7{1#wK73b(VQk$<6T%S^kX9P* zESPmp%R)a(&0hJl7n)~^v`)fY3ZZ34SH?irjvOvXxsPE zwgGp=s3X0OvB@^!2oxoGhJ<{twS=sQ`XG)>rceQGn}r$82(K zc(^p}Ze<=G{TO3W3Z`8(&(2S(Mf(chypeWICQlK{wvJyI<$qjQ(GIKm8vGPS{x7nT zZ%Wx&ZN{iAS{Y8EohS;ne%G`+KchP3Z`$U(=~65Wv8HrmpJSXSIWFO;0t435&* zJ9uKUAlARu&2cluX}0kj1eM=m0;Bn_GkndT6hn^9CD*jD$*|{jnn{s*cLB|6-%~zI zvr>S<;U?`$|6K;h=80Nd%LYR&ytO#Tyr)5IqiyL=$lzbOn8M|=oAs>zo&wrcEba82tov$74x4DQOS^) z`JiB})F3G2Bud(HA+}>}MkXt((7p`XMJvdA(j~fV5{LX2ickSrz~=<_%^F|9kur7sO)mmI)xU2w052xVEPVWOk!X7-kET=kg)1h|ua#)uUJe3%`ArFbl` zE>8R8#UXY-$kwY%VCpca6TE=V{$LQDwNVC*n`7y8c}0G5#+CL>rhrZMuFvwx;v(-p zf1j~CT`VG46`L~=ez-uA5L4GVljHjfM2QIoK@D5BeNB&DM(194y{_C4ObwsG z&}-7GOrPsRd7Po^t&cz14u4iA$BNibc6CPoehlS+{gfgS(z<3~SM`a0)exIbpg6pA-P*q^0&VL<)pk`M z+G~{U&1KXC3uSu96rzVqDt4+mZc3@6w?L1@rE(<_xi4fHtHA3-gIKLL O7VKv~d!hN{{{I6Irvjn? diff --git a/$tf/pendingchanges.tfb b/$tf/pendingchanges.tfb deleted file mode 100644 index f96a78b4af919599a3f54aec4e26ca69530ae801..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108567 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 O7VKv~d!hN{{{I6Irvjn? diff --git a/$tf/properties.tf1 b/$tf/properties.tf1 deleted file mode 100644 index 96ddc950c29feb3b8dffb3ec797011db9fdcac6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmb7-u?~Vj5JVpr<2P7X(h?I&V(Dkt2%JK4feWam-|kbtz+!hcJ8v?_S18z?XgJgS zWFeB7S$*|fxI2}T8P%4Dnsg$IM5%uz1a`?xCzp7By;W{z0`}R*WMp*Tga)zC6)k~+ KP04}!|N1w4=OL>A From 9c16c215b62f64b4ac933c089a8eb832c2a70bd8 Mon Sep 17 00:00:00 2001 From: aaronburtle <93220300+aaronburtle@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:32:51 -0800 Subject: [PATCH 09/15] Delete test directory --- test/test-config.json | 55 ------------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 test/test-config.json diff --git a/test/test-config.json b/test/test-config.json deleted file mode 100644 index a06bc6f7fd..0000000000 --- a/test/test-config.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "https://github.com/Azure/data-api-builder/releases/download/v0.13.0/dab.draft.schema.json", - "data-source": { - "database-type": "mssql", - "connection-string": "", - "options": { - "set-session-context": false - } - }, - "runtime": { - "graphql": { - "enabled": true, - "path": "/graphql", - "allow-introspection": true - }, - "host": { - "cors": { - "origins": [], - "allow-credentials": false - }, - "authentication": { - "provider": "StaticWebApps" - }, - "mode": "production" - } - }, - "entities": { - "Book": { - "source": { - "object": "dbo.books", - "type": "table" - }, - "graphql": { - "enabled": true, - "type": { - "singular": "Book", - "plural": "Books" - } - }, - "rest": { - "enabled": true - }, - "permissions": [ - { - "role": "anonymouse", - "actions": [ - { - "action": "*" - } - ] - } - ] - } - } -} \ No newline at end of file From d56128c176e0dbc54a541d3518ab6bd6104d4980 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Wed, 28 Jan 2026 18:40:53 -0800 Subject: [PATCH 10/15] add new hotreload pipeline --- .pipelines/hotreload-pipelines.yml | 151 ++++++++++++++++++ .pipelines/mssql-pipelines.yml | 6 +- .../HotReload/ConfigurationHotReloadTests.cs | 2 +- 3 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 .pipelines/hotreload-pipelines.yml diff --git a/.pipelines/hotreload-pipelines.yml b/.pipelines/hotreload-pipelines.yml new file mode 100644 index 0000000000..70ba33516e --- /dev/null +++ b/.pipelines/hotreload-pipelines.yml @@ -0,0 +1,151 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +# Hot-Reload Integration Testing Pipeline +# This pipeline runs only hot-reload configuration tests which require longer timeouts +# due to file system watchers and database validation in CI/CD environments. + +trigger: + batch: true + branches: + include: + - main + - gh-readonly-queue/main + - release/* + paths: + exclude: + - docs + +pr: + branches: + include: + - main + - release/* + paths: + exclude: + - samples/** + - docs/** + - '*.md' + - templates/** + +jobs: +- job: windows_hotreload + displayName: 'Windows Hot-Reload Tests' + pool: + vmImage: 'windows-latest' + variables: + solution: '**/*.sln' + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + # The variable setting on the pipeline UI sets the connection string + # for the hot-reload tests. + data-source.connection-string: Server=(localdb)\MSSQLLocalDB;Persist Security Info=False;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=5;TrustServerCertificate=True; + InstallerUrl: https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi + SqlVersionCode: '15.0' + timeoutInMinutes: 90 + + steps: + - task: CmdLine@2 + displayName: 'Set flag to publish received files when previous step fails' + condition: failed() + inputs: + script: 'echo ##vso[task.setvariable variable=publishverify]Yes' + + - task: NuGetAuthenticate@1 + displayName: 'NuGet Authenticate' + + # The .NET CLI commands in proceeding tasks use the .NET SDK version specified ("selected") here. + # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from + # specifying the runtime version a project targets." + - task: UseDotNet@2 + displayName: Setup .NET SDK v8.0.x + inputs: + packageType: sdk + version: 8.0.x + + - task: NuGetToolInstaller@1 + + - task: NuGetCommand@2 + displayName: Restore NuGet packages + inputs: + restoreSolution: '$(solution)' + feedsToUse: config + nugetConfigPath: Nuget.config + + - task: PowerShell@2 + displayName: Install SQL LocalDB + inputs: + targetType: 'inline' + script: | + SqlLocalDb.exe start + SqlLocalDB.exe info "MSSQLLocalDB" + Write-Host "Downloading" + Import-Module BitsTransfer + Start-BitsTransfer -Source $(InstallerUrl) -Destination SqlLocalDB.msi + Write-Host "Installing" + Start-Process -FilePath "SqlLocalDB.msi" -Wait -ArgumentList "/qn", "/norestart", "/l*v SqlLocalDBInstall.log", "IACCEPTSQLLOCALDBLICENSETERMS=YES"; + SqlLocalDB.exe stop MSSQLLocalDB -k + SqlLocalDB.exe delete MSSQLLocalDB + + - task: PowerShell@2 + displayName: 'Start MSSQLLocalDB' + inputs: + targetType: 'inline' + script: | + SqlLocalDb.exe start MSSQLLocalDB + SqlLocalDb.exe info "MSSQLLocalDB" + + - task: DotNetCoreCLI@2 + displayName: Build + inputs: + command: build + projects: | + **/*.csproj + !**/*Tests*.csproj + arguments: '-p:generateConfigFileForDbType=MsSql --configuration $(buildConfiguration)' + + - task: DotNetCoreCLI@2 + displayName: Build Test Projects + inputs: + command: build + projects: '**/*Tests/*.csproj' + arguments: '--configuration $(buildConfiguration)' + + - task: FileTransform@1.206.0 + displayName: 'Generate dab-config.MsSql.json' + inputs: + folderPath: '$(System.DefaultWorkingDirectory)' + fileType: 'json' + targetFiles: 'src/out/tests/*/dab-config.MsSql.json' + + - task: DotNetCoreCLI@2 + displayName: 'Run Hot-Reload Integration Tests' + inputs: + command: test + arguments: '--filter "TestCategory=MsSql&FullyQualifiedName~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=5400000' + projects: '**/*Tests/*.csproj' + timeoutInMinutes: 80 + + - task: PublishCodeCoverageResults@1 + displayName: 'Publish code coverage' + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: '$(Agent.TempDirectory)/**/*cobertura.xml' + + - task: CopyFiles@2 + condition: eq(variables['publishverify'], 'Yes') + displayName: 'Copy received files to Artifact Staging' + inputs: + contents: '**\*.received.*' + targetFolder: '$(Build.ArtifactStagingDirectory)\Verify' + cleanTargetFolder: true + overWrite: true + + - task: PublishBuildArtifacts@1 + displayName: 'Publish received files as Artifacts' + name: 'verifypublish' + condition: eq(variables['publishverify'], 'Yes') + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)\Verify' + ArtifactName: 'Verify' + publishLocation: 'Container' diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index 5b465065a2..77df70358f 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -122,9 +122,8 @@ jobs: displayName: 'Run MsSql Integration Tests' inputs: command: test - arguments: '--filter "TestCategory=MsSql" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=7200000' + arguments: '--filter "TestCategory=MsSql&FullyQualifiedName!~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage"' projects: '**/*Tests/*.csproj' - timeoutInMinutes: 120 - task: CmdLine@2 displayName: 'Set flag to publish Verify *.received files when tests fail' @@ -250,9 +249,8 @@ jobs: displayName: 'Run MsSql Integration Tests' inputs: command: test - arguments: '--filter "TestCategory=MsSql" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=7200000' + arguments: '--filter "TestCategory=MsSql&FullyQualifiedName!~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage"' projects: '**/*Tests/*.csproj' - timeoutInMinutes: 120 - task: PublishCodeCoverageResults@1 displayName: 'Publish code coverage' diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index bfbba8ee8d..917075c52a 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -31,7 +31,7 @@ public class ConfigurationHotReloadTests private const string GQL_QUERY_NAME = "books"; private const string HOT_RELOAD_SUCCESS_MESSAGE = "Validated hot-reloaded configuration file"; private const string HOT_RELOAD_FAILURE_MESSAGE = "Unable to hot reload configuration file due to"; - private const int HOT_RELOAD_TIMEOUT_SECONDS = 120; // Increased from 30 to 120 for CI/CD environments + private const int HOT_RELOAD_TIMEOUT_SECONDS = 120; // Increased timeout for CI/CD environments where file watchers can be slow private const string GQL_QUERY = @"{ books(first: 100) { From f4dc47e1c33e67d3679c955d37bb4732ac1774ba Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Wed, 28 Jan 2026 18:58:19 -0800 Subject: [PATCH 11/15] add new job --- .pipelines/hotreload-pipelines.yml | 151 ----------------------------- .pipelines/mssql-pipelines.yml | 117 ++++++++++++++++++++++ 2 files changed, 117 insertions(+), 151 deletions(-) delete mode 100644 .pipelines/hotreload-pipelines.yml diff --git a/.pipelines/hotreload-pipelines.yml b/.pipelines/hotreload-pipelines.yml deleted file mode 100644 index 70ba33516e..0000000000 --- a/.pipelines/hotreload-pipelines.yml +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -# Hot-Reload Integration Testing Pipeline -# This pipeline runs only hot-reload configuration tests which require longer timeouts -# due to file system watchers and database validation in CI/CD environments. - -trigger: - batch: true - branches: - include: - - main - - gh-readonly-queue/main - - release/* - paths: - exclude: - - docs - -pr: - branches: - include: - - main - - release/* - paths: - exclude: - - samples/** - - docs/** - - '*.md' - - templates/** - -jobs: -- job: windows_hotreload - displayName: 'Windows Hot-Reload Tests' - pool: - vmImage: 'windows-latest' - variables: - solution: '**/*.sln' - buildPlatform: 'Any CPU' - buildConfiguration: 'Release' - # The variable setting on the pipeline UI sets the connection string - # for the hot-reload tests. - data-source.connection-string: Server=(localdb)\MSSQLLocalDB;Persist Security Info=False;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=5;TrustServerCertificate=True; - InstallerUrl: https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi - SqlVersionCode: '15.0' - timeoutInMinutes: 90 - - steps: - - task: CmdLine@2 - displayName: 'Set flag to publish received files when previous step fails' - condition: failed() - inputs: - script: 'echo ##vso[task.setvariable variable=publishverify]Yes' - - - task: NuGetAuthenticate@1 - displayName: 'NuGet Authenticate' - - # The .NET CLI commands in proceeding tasks use the .NET SDK version specified ("selected") here. - # Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from - # specifying the runtime version a project targets." - - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x - inputs: - packageType: sdk - version: 8.0.x - - - task: NuGetToolInstaller@1 - - - task: NuGetCommand@2 - displayName: Restore NuGet packages - inputs: - restoreSolution: '$(solution)' - feedsToUse: config - nugetConfigPath: Nuget.config - - - task: PowerShell@2 - displayName: Install SQL LocalDB - inputs: - targetType: 'inline' - script: | - SqlLocalDb.exe start - SqlLocalDB.exe info "MSSQLLocalDB" - Write-Host "Downloading" - Import-Module BitsTransfer - Start-BitsTransfer -Source $(InstallerUrl) -Destination SqlLocalDB.msi - Write-Host "Installing" - Start-Process -FilePath "SqlLocalDB.msi" -Wait -ArgumentList "/qn", "/norestart", "/l*v SqlLocalDBInstall.log", "IACCEPTSQLLOCALDBLICENSETERMS=YES"; - SqlLocalDB.exe stop MSSQLLocalDB -k - SqlLocalDB.exe delete MSSQLLocalDB - - - task: PowerShell@2 - displayName: 'Start MSSQLLocalDB' - inputs: - targetType: 'inline' - script: | - SqlLocalDb.exe start MSSQLLocalDB - SqlLocalDb.exe info "MSSQLLocalDB" - - - task: DotNetCoreCLI@2 - displayName: Build - inputs: - command: build - projects: | - **/*.csproj - !**/*Tests*.csproj - arguments: '-p:generateConfigFileForDbType=MsSql --configuration $(buildConfiguration)' - - - task: DotNetCoreCLI@2 - displayName: Build Test Projects - inputs: - command: build - projects: '**/*Tests/*.csproj' - arguments: '--configuration $(buildConfiguration)' - - - task: FileTransform@1.206.0 - displayName: 'Generate dab-config.MsSql.json' - inputs: - folderPath: '$(System.DefaultWorkingDirectory)' - fileType: 'json' - targetFiles: 'src/out/tests/*/dab-config.MsSql.json' - - - task: DotNetCoreCLI@2 - displayName: 'Run Hot-Reload Integration Tests' - inputs: - command: test - arguments: '--filter "TestCategory=MsSql&FullyQualifiedName~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=5400000' - projects: '**/*Tests/*.csproj' - timeoutInMinutes: 80 - - - task: PublishCodeCoverageResults@1 - displayName: 'Publish code coverage' - inputs: - codeCoverageTool: Cobertura - summaryFileLocation: '$(Agent.TempDirectory)/**/*cobertura.xml' - - - task: CopyFiles@2 - condition: eq(variables['publishverify'], 'Yes') - displayName: 'Copy received files to Artifact Staging' - inputs: - contents: '**\*.received.*' - targetFolder: '$(Build.ArtifactStagingDirectory)\Verify' - cleanTargetFolder: true - overWrite: true - - - task: PublishBuildArtifacts@1 - displayName: 'Publish received files as Artifacts' - name: 'verifypublish' - condition: eq(variables['publishverify'], 'Yes') - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)\Verify' - ArtifactName: 'Verify' - publishLocation: 'Container' diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index 77df70358f..764b565f98 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -275,3 +275,120 @@ jobs: PathtoPublish: '$(Build.ArtifactStagingDirectory)\Verify' ArtifactName: 'Verify' publishLocation: 'Container' + +- job: windows_hotreload + displayName: 'Windows Hot-Reload Tests' + pool: + vmImage: 'windows-latest' + variables: + solution: '**/*.sln' + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + # Connection string for hot-reload tests + data-source.connection-string: Server=(localdb)\MSSQLLocalDB;Persist Security Info=False;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=5;TrustServerCertificate=True; + InstallerUrl: https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi + SqlVersionCode: '15.0' + timeoutInMinutes: 60 + + steps: + - task: CmdLine@2 + displayName: 'Set flag to publish received files when previous step fails' + condition: failed() + inputs: + script: 'echo ##vso[task.setvariable variable=publishverify]Yes' + + - task: NuGetAuthenticate@1 + displayName: 'NuGet Authenticate' + + - task: UseDotNet@2 + displayName: Setup .NET SDK v8.0.x + inputs: + packageType: sdk + version: 8.0.x + + - task: NuGetToolInstaller@1 + + - task: NuGetCommand@2 + displayName: Restore NuGet packages + inputs: + restoreSolution: '$(solution)' + feedsToUse: config + nugetConfigPath: Nuget.config + + - task: PowerShell@2 + displayName: Install SQL LocalDB + inputs: + targetType: 'inline' + script: | + SqlLocalDb.exe start + SqlLocalDB.exe info "MSSQLLocalDB" + Write-Host "Downloading" + Import-Module BitsTransfer + Start-BitsTransfer -Source $(InstallerUrl) -Destination SqlLocalDB.msi + Write-Host "Installing" + Start-Process -FilePath "SqlLocalDB.msi" -Wait -ArgumentList "/qn", "/norestart", "/l*v SqlLocalDBInstall.log", "IACCEPTSQLLOCALDBLICENSETERMS=YES"; + SqlLocalDB.exe stop MSSQLLocalDB -k + SqlLocalDB.exe delete MSSQLLocalDB + + - task: PowerShell@2 + displayName: 'Start MSSQLLocalDB' + inputs: + targetType: 'inline' + script: | + SqlLocalDb.exe start MSSQLLocalDB + SqlLocalDb.exe info "MSSQLLocalDB" + + - task: DotNetCoreCLI@2 + displayName: Build + inputs: + command: build + projects: | + **/*.csproj + !**/*Tests*.csproj + arguments: '-p:generateConfigFileForDbType=MsSql --configuration $(buildConfiguration)' + + - task: DotNetCoreCLI@2 + displayName: Build Test Projects + inputs: + command: build + projects: '**/*Tests/*.csproj' + arguments: '--configuration $(buildConfiguration)' + + - task: FileTransform@1.206.0 + displayName: 'Generate dab-config.MsSql.json' + inputs: + folderPath: '$(System.DefaultWorkingDirectory)' + fileType: 'json' + targetFiles: 'src/out/tests/*/dab-config.MsSql.json' + + - task: DotNetCoreCLI@2 + displayName: 'Run Hot-Reload Integration Tests' + inputs: + command: test + arguments: '--filter "TestCategory=MsSql&FullyQualifiedName~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=3600000' + projects: '**/*Tests/*.csproj' + timeoutInMinutes: 50 + + - task: PublishCodeCoverageResults@1 + displayName: 'Publish code coverage' + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: '$(Agent.TempDirectory)/**/*cobertura.xml' + + - task: CopyFiles@2 + condition: eq(variables['publishverify'], 'Yes') + displayName: 'Copy received files to Artifact Staging' + inputs: + contents: '**\*.received.*' + targetFolder: '$(Build.ArtifactStagingDirectory)\Verify' + cleanTargetFolder: true + overWrite: true + + - task: PublishBuildArtifacts@1 + displayName: 'Publish received files as Artifacts' + name: 'verifypublish' + condition: eq(variables['publishverify'], 'Yes') + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)\Verify' + ArtifactName: 'Verify' + publishLocation: 'Container' \ No newline at end of file From d8ad3c56bce4479b56a7f4e755fa10aec36493f6 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Wed, 28 Jan 2026 19:44:01 -0800 Subject: [PATCH 12/15] class initialization change --- .pipelines/mssql-pipelines.yml | 2 +- .../HotReload/ConfigurationHotReloadTests.cs | 102 +++++++++++++----- 2 files changed, 78 insertions(+), 26 deletions(-) diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index 764b565f98..adf70e935c 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -277,7 +277,7 @@ jobs: publishLocation: 'Container' - job: windows_hotreload - displayName: 'Windows Hot-Reload Tests' + displayName: 'windows hot-reload tests' pool: vmImage: 'windows-latest' variables: diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index 917075c52a..b655bf53e5 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -194,42 +194,93 @@ public static async Task ClassInitializeAsync(TestContext context) { // Arrange GenerateConfigFile(connectionString: $"{ConfigurationTests.GetConnectionStringFromEnvironmentConfig(TestCategory.MSSQL).Replace("\\", "\\\\")}"); - _testServer = new(Program.CreateWebHostBuilder(new string[] { "--ConfigFileName", CONFIG_FILE_NAME })); - _testClient = _testServer.CreateClient(); - _configProvider = _testServer.Services.GetService(); + + // Add retry logic for test server initialization in CI/CD environments + int maxRetries = 3; + int retryDelayMs = 2000; + Exception lastException = null; - string query = GQL_QUERY; - object payload = - new { query }; - - HttpRequestMessage request = new(HttpMethod.Post, "/graphQL") + for (int attempt = 1; attempt <= maxRetries; attempt++) { - Content = JsonContent.Create(payload) - }; - - HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); - HttpResponseMessage gQLResult = await _testClient.SendAsync(request); + try + { + Console.WriteLine($"Initializing test server (attempt {attempt}/{maxRetries})..."); + _testServer = new(Program.CreateWebHostBuilder(new string[] { "--ConfigFileName", CONFIG_FILE_NAME })); + _testClient = _testServer.CreateClient(); + _configProvider = _testServer.Services.GetService(); + + // Give the server a moment to fully initialize + await Task.Delay(1000); + + string query = GQL_QUERY; + object payload = new { query }; + + HttpRequestMessage request = new(HttpMethod.Post, "/graphQL") + { + Content = JsonContent.Create(payload) + }; + + HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); + HttpResponseMessage gQLResult = await _testClient.SendAsync(request); + + // Assert rest and graphQL requests return status OK. + Assert.AreEqual(HttpStatusCode.OK, restResult.StatusCode, + $"REST request failed on attempt {attempt}. Response: {await restResult.Content.ReadAsStringAsync()}"); + Assert.AreEqual(HttpStatusCode.OK, gQLResult.StatusCode, + $"GraphQL request failed on attempt {attempt}. Response: {await gQLResult.Content.ReadAsStringAsync()}"); + + // Save the contents from request to validate results after hot-reloads. + string restContent = await restResult.Content.ReadAsStringAsync(); + using JsonDocument doc = JsonDocument.Parse(restContent); + _bookDBOContents = doc.RootElement.GetProperty("value").ToString(); + + Console.WriteLine($"Test server initialized successfully on attempt {attempt}"); + return; // Success - exit retry loop + } + catch (Exception ex) + { + lastException = ex; + Console.WriteLine($"Test server initialization attempt {attempt} failed: {ex.Message}"); + + // Clean up failed attempt + try + { + _testClient?.Dispose(); + _testServer?.Dispose(); + } + catch { /* Ignore cleanup errors */ } - // Assert rest and graphQL requests return status OK. - Assert.AreEqual(HttpStatusCode.OK, restResult.StatusCode); - Assert.AreEqual(HttpStatusCode.OK, gQLResult.StatusCode); + if (attempt < maxRetries) + { + Console.WriteLine($"Waiting {retryDelayMs}ms before retry..."); + await Task.Delay(retryDelayMs); + } + } + } - // Save the contents from request to validate results after hot-reloads. - string restContent = await restResult.Content.ReadAsStringAsync(); - using JsonDocument doc = JsonDocument.Parse(restContent); - _bookDBOContents = doc.RootElement.GetProperty("value").ToString(); + // If we got here, all retries failed + throw new Exception($"Failed to initialize test server after {maxRetries} attempts. Last error: {lastException?.Message}", lastException); } [ClassCleanup] public static void ClassCleanup() { - if (File.Exists(CONFIG_FILE_NAME)) + try { - File.Delete(CONFIG_FILE_NAME); - } + if (File.Exists(CONFIG_FILE_NAME)) + { + File.Delete(CONFIG_FILE_NAME); + } - _testServer.Dispose(); - _testClient.Dispose(); + _testClient?.Dispose(); + _testServer?.Dispose(); + + Console.WriteLine("Test cleanup completed successfully"); + } + catch (Exception ex) + { + Console.WriteLine($"Error during test cleanup: {ex.Message}"); + } } /// @@ -902,6 +953,7 @@ private static async Task WaitForConditionAsync(Func condition, TimeSpan t { Console.WriteLine($"Console output captured:\n{_writer.ToString()}"); } + throw new TimeoutException("The condition was not met within the timeout period."); } } From a68257e0e41b44762bacda8dbef617a94ecb045f Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Thu, 29 Jan 2026 01:52:53 -0800 Subject: [PATCH 13/15] move to 2nd task instead of job --- .pipelines/mssql-pipelines.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index adf70e935c..74cd5ba690 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -246,7 +246,15 @@ jobs: targetFiles: 'src/out/tests/*/dab-config.MsSql.json' - task: DotNetCoreCLI@2 - displayName: 'Run MsSql Integration Tests' + displayName: 'Hot-Reload Tests' + inputs: + command: test + arguments: '--filter "TestCategory=MsSql&FullyQualifiedName~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed"' + projects: '**/*Tests/*.csproj' + timeoutInMinutes: 45 + + - task: DotNetCoreCLI@2 + displayName: 'MsSql Integration Tests' inputs: command: test arguments: '--filter "TestCategory=MsSql&FullyQualifiedName!~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage"' @@ -391,4 +399,4 @@ jobs: inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)\Verify' ArtifactName: 'Verify' - publishLocation: 'Container' \ No newline at end of file + publishLocation: 'Container' From 2b7f9a6e2004137a4708f415bcb4e00210544890 Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Thu, 29 Jan 2026 01:58:13 -0800 Subject: [PATCH 14/15] remove unused job --- .pipelines/mssql-pipelines.yml | 117 --------------------------------- 1 file changed, 117 deletions(-) diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index 74cd5ba690..bdb0d4f023 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -283,120 +283,3 @@ jobs: PathtoPublish: '$(Build.ArtifactStagingDirectory)\Verify' ArtifactName: 'Verify' publishLocation: 'Container' - -- job: windows_hotreload - displayName: 'windows hot-reload tests' - pool: - vmImage: 'windows-latest' - variables: - solution: '**/*.sln' - buildPlatform: 'Any CPU' - buildConfiguration: 'Release' - # Connection string for hot-reload tests - data-source.connection-string: Server=(localdb)\MSSQLLocalDB;Persist Security Info=False;Integrated Security=True;MultipleActiveResultSets=False;Connection Timeout=5;TrustServerCertificate=True; - InstallerUrl: https://download.microsoft.com/download/7/c/1/7c14e92e-bdcb-4f89-b7cf-93543e7112d1/SqlLocalDB.msi - SqlVersionCode: '15.0' - timeoutInMinutes: 60 - - steps: - - task: CmdLine@2 - displayName: 'Set flag to publish received files when previous step fails' - condition: failed() - inputs: - script: 'echo ##vso[task.setvariable variable=publishverify]Yes' - - - task: NuGetAuthenticate@1 - displayName: 'NuGet Authenticate' - - - task: UseDotNet@2 - displayName: Setup .NET SDK v8.0.x - inputs: - packageType: sdk - version: 8.0.x - - - task: NuGetToolInstaller@1 - - - task: NuGetCommand@2 - displayName: Restore NuGet packages - inputs: - restoreSolution: '$(solution)' - feedsToUse: config - nugetConfigPath: Nuget.config - - - task: PowerShell@2 - displayName: Install SQL LocalDB - inputs: - targetType: 'inline' - script: | - SqlLocalDb.exe start - SqlLocalDB.exe info "MSSQLLocalDB" - Write-Host "Downloading" - Import-Module BitsTransfer - Start-BitsTransfer -Source $(InstallerUrl) -Destination SqlLocalDB.msi - Write-Host "Installing" - Start-Process -FilePath "SqlLocalDB.msi" -Wait -ArgumentList "/qn", "/norestart", "/l*v SqlLocalDBInstall.log", "IACCEPTSQLLOCALDBLICENSETERMS=YES"; - SqlLocalDB.exe stop MSSQLLocalDB -k - SqlLocalDB.exe delete MSSQLLocalDB - - - task: PowerShell@2 - displayName: 'Start MSSQLLocalDB' - inputs: - targetType: 'inline' - script: | - SqlLocalDb.exe start MSSQLLocalDB - SqlLocalDb.exe info "MSSQLLocalDB" - - - task: DotNetCoreCLI@2 - displayName: Build - inputs: - command: build - projects: | - **/*.csproj - !**/*Tests*.csproj - arguments: '-p:generateConfigFileForDbType=MsSql --configuration $(buildConfiguration)' - - - task: DotNetCoreCLI@2 - displayName: Build Test Projects - inputs: - command: build - projects: '**/*Tests/*.csproj' - arguments: '--configuration $(buildConfiguration)' - - - task: FileTransform@1.206.0 - displayName: 'Generate dab-config.MsSql.json' - inputs: - folderPath: '$(System.DefaultWorkingDirectory)' - fileType: 'json' - targetFiles: 'src/out/tests/*/dab-config.MsSql.json' - - - task: DotNetCoreCLI@2 - displayName: 'Run Hot-Reload Integration Tests' - inputs: - command: test - arguments: '--filter "TestCategory=MsSql&FullyQualifiedName~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed" -- RunConfiguration.TestSessionTimeout=3600000' - projects: '**/*Tests/*.csproj' - timeoutInMinutes: 50 - - - task: PublishCodeCoverageResults@1 - displayName: 'Publish code coverage' - inputs: - codeCoverageTool: Cobertura - summaryFileLocation: '$(Agent.TempDirectory)/**/*cobertura.xml' - - - task: CopyFiles@2 - condition: eq(variables['publishverify'], 'Yes') - displayName: 'Copy received files to Artifact Staging' - inputs: - contents: '**\*.received.*' - targetFolder: '$(Build.ArtifactStagingDirectory)\Verify' - cleanTargetFolder: true - overWrite: true - - - task: PublishBuildArtifacts@1 - displayName: 'Publish received files as Artifacts' - name: 'verifypublish' - condition: eq(variables['publishverify'], 'Yes') - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)\Verify' - ArtifactName: 'Verify' - publishLocation: 'Container' From 9cfeb59e72ad682b2dade311f0a8b694c62f0bca Mon Sep 17 00:00:00 2001 From: aaron burtle Date: Thu, 29 Jan 2026 02:31:24 -0800 Subject: [PATCH 15/15] change task order --- .pipelines/mssql-pipelines.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.pipelines/mssql-pipelines.yml b/.pipelines/mssql-pipelines.yml index bdb0d4f023..af823db200 100644 --- a/.pipelines/mssql-pipelines.yml +++ b/.pipelines/mssql-pipelines.yml @@ -246,19 +246,20 @@ jobs: targetFiles: 'src/out/tests/*/dab-config.MsSql.json' - task: DotNetCoreCLI@2 - displayName: 'Hot-Reload Tests' + displayName: 'MsSql Integration Tests' inputs: command: test - arguments: '--filter "TestCategory=MsSql&FullyQualifiedName~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed"' + arguments: '--filter "TestCategory=MsSql&FullyQualifiedName!~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage"' projects: '**/*Tests/*.csproj' - timeoutInMinutes: 45 + - task: DotNetCoreCLI@2 - displayName: 'MsSql Integration Tests' + displayName: 'Hot-Reload Tests' inputs: command: test - arguments: '--filter "TestCategory=MsSql&FullyQualifiedName!~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage"' + arguments: '--filter "TestCategory=MsSql&FullyQualifiedName~ConfigurationHotReloadTests" --no-build --configuration $(buildConfiguration) --collect "XPlat Code coverage" --logger "console;verbosity=detailed"' projects: '**/*Tests/*.csproj' + timeoutInMinutes: 45 - task: PublishCodeCoverageResults@1 displayName: 'Publish code coverage'