From f1aa22e9e30cc22fa1046dfc4b7b897d4b470fc1 Mon Sep 17 00:00:00 2001 From: Paul Johnson Date: Sat, 19 Dec 2020 11:49:37 +0000 Subject: [PATCH] test duration on CI pipeline with more databases --- .../Testing/BaseTestDatabase.cs | 1 - .../Testing/LocalDbTestDatabase.cs | 24 ++++++++++-------- .../Testing/SqlDeveloperTestDatabase.cs | 25 +++++++++++-------- .../Testing/TestDatabaseFactory.cs | 14 +++++------ .../Testing/TestDatabaseSettings.cs | 12 +++++++++ .../Testing/UmbracoIntegrationTest.cs | 10 +++++++- 6 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/Testing/TestDatabaseSettings.cs diff --git a/src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs index 25fbc6ef59..9b874c9999 100644 --- a/src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/BaseTestDatabase.cs @@ -22,7 +22,6 @@ namespace Umbraco.Tests.Integration.Testing protected IUmbracoDatabaseFactory _databaseFactory; protected IList _testDatabases; - protected const int ThreadCount = 2; protected UmbracoDatabase.CommandInfo[] _cachedDatabaseInitCommands = new UmbracoDatabase.CommandInfo[0]; diff --git a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs index 5ae889d8fb..b208a72c2f 100644 --- a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.IO; +using System.Linq; using System.Threading; using Microsoft.Extensions.Logging; using Umbraco.Core.Persistence; @@ -18,6 +19,7 @@ namespace Umbraco.Tests.Integration.Testing public const string InstanceName = "UmbracoTests"; public const string DatabaseName = "UmbracoTests"; + private readonly TestDatabaseSettings _settings; private readonly LocalDb _localDb; private static LocalDb.Instance s_localDbInstance; private static string s_filesPath; @@ -25,26 +27,26 @@ namespace Umbraco.Tests.Integration.Testing public static LocalDbTestDatabase Instance { get; private set; } // It's internal because `Umbraco.Core.Persistence.LocalDb` is internal - internal LocalDbTestDatabase(ILoggerFactory loggerFactory, LocalDb localDb, string filesPath, IUmbracoDatabaseFactory dbFactory) + internal LocalDbTestDatabase(TestDatabaseSettings settings, ILoggerFactory loggerFactory, LocalDb localDb, string filesPath, IUmbracoDatabaseFactory dbFactory) { _loggerFactory = loggerFactory; _databaseFactory = dbFactory; + _settings = settings; _localDb = localDb; s_filesPath = filesPath; Instance = this; // For GlobalSetupTeardown.cs - _testDatabases = new[] - { - // With Schema - TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-1", false), - TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-2", false), + var counter = 0; - // Empty (for migration testing etc) - TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-3", true), - TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-4", true), - }; + var schema = Enumerable.Range(0, _settings.SchemaDatabaseCount) + .Select(x => TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-{++counter}", false)); + + var empty = Enumerable.Range(0, _settings.EmptyDatabasesCount) + .Select(x => TestDbMeta.CreateWithoutConnectionString($"{DatabaseName}-{++counter}", true)); + + _testDatabases = schema.Concat(empty).ToList(); s_localDbInstance = _localDb.GetInstance(InstanceName); if (s_localDbInstance != null) @@ -80,7 +82,7 @@ namespace Umbraco.Tests.Integration.Testing _prepareQueue.Add(meta); } - for (int i = 0; i < ThreadCount; i++) + for (int i = 0; i < _settings.PrepareThreadCount; i++) { var thread = new Thread(PrepareDatabase); thread.Start(); diff --git a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs index 7ab65c1e74..80cf3c654c 100644 --- a/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/SqlDeveloperTestDatabase.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Data.SqlClient; +using System.Linq; using System.Threading; using Microsoft.Extensions.Logging; using Umbraco.Core.Persistence; @@ -16,28 +18,29 @@ namespace Umbraco.Tests.Integration.Testing /// public class SqlDeveloperTestDatabase : BaseTestDatabase, ITestDatabase { + private readonly TestDatabaseSettings _settings; private readonly string _masterConnectionString; public const string DatabaseName = "UmbracoTests"; public static SqlDeveloperTestDatabase Instance { get; private set; } - public SqlDeveloperTestDatabase(ILoggerFactory loggerFactory, IUmbracoDatabaseFactory databaseFactory, string masterConnectionString) + public SqlDeveloperTestDatabase(TestDatabaseSettings settings, ILoggerFactory loggerFactory, IUmbracoDatabaseFactory databaseFactory, string masterConnectionString) { _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _databaseFactory = databaseFactory ?? throw new ArgumentNullException(nameof(databaseFactory)); + _settings = settings; _masterConnectionString = masterConnectionString; - _testDatabases = new[] - { - // With Schema - TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-1", false, masterConnectionString), - TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-2", false, masterConnectionString), + var counter = 0; - // Empty (for migration testing etc) - TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-3", true, masterConnectionString), - TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-4", true, masterConnectionString), - }; + var schema = Enumerable.Range(0, _settings.SchemaDatabaseCount) + .Select(x => TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-{++counter}", false, masterConnectionString)); + + var empty = Enumerable.Range(0, _settings.EmptyDatabasesCount) + .Select(x => TestDbMeta.CreateWithMasterConnectionString($"{DatabaseName}-{++counter}", true, masterConnectionString)); + + _testDatabases = schema.Concat(empty).ToList(); Instance = this; // For GlobalSetupTeardown.cs } @@ -54,7 +57,7 @@ namespace Umbraco.Tests.Integration.Testing _prepareQueue.Add(meta); } - for (int i = 0; i < ThreadCount; i++) + for (int i = 0; i < _settings.PrepareThreadCount; i++) { var thread = new Thread(PrepareDatabase); thread.Start(); diff --git a/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs index 6d7e88b5b0..9ca463c69a 100644 --- a/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs +++ b/src/Umbraco.Tests.Integration/Testing/TestDatabaseFactory.cs @@ -10,16 +10,16 @@ namespace Umbraco.Tests.Integration.Testing { public class TestDatabaseFactory { - public static ITestDatabase Create(string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory) + public static ITestDatabase Create(TestDatabaseSettings settings, string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory) { string connectionString = Environment.GetEnvironmentVariable("UmbracoIntegrationTestConnectionString"); return string.IsNullOrEmpty(connectionString) - ? CreateLocalDb(filesPath, loggerFactory, dbFactory) - : CreateSqlDeveloper(loggerFactory, dbFactory, connectionString); + ? CreateLocalDb(settings, filesPath, loggerFactory, dbFactory) + : CreateSqlDeveloper(settings, loggerFactory, dbFactory, connectionString); } - private static ITestDatabase CreateLocalDb(string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory) + private static ITestDatabase CreateLocalDb(TestDatabaseSettings settings, string filesPath, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory) { if (!Directory.Exists(filesPath)) { @@ -33,10 +33,10 @@ namespace Umbraco.Tests.Integration.Testing throw new InvalidOperationException("LocalDB is not available."); } - return new LocalDbTestDatabase(loggerFactory, localDb, filesPath, dbFactory.Create()); + return new LocalDbTestDatabase(settings, loggerFactory, localDb, filesPath, dbFactory.Create()); } - private static ITestDatabase CreateSqlDeveloper(ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory, string connectionString) + private static ITestDatabase CreateSqlDeveloper(TestDatabaseSettings settings, ILoggerFactory loggerFactory, TestUmbracoDatabaseFactoryProvider dbFactory, string connectionString) { // NOTE: Example setup for Linux box. // $ export SA_PASSWORD=Foobar123! @@ -47,7 +47,7 @@ namespace Umbraco.Tests.Integration.Testing throw new InvalidOperationException("ENV: UmbracoIntegrationTestConnectionString is not set"); } - return new SqlDeveloperTestDatabase(loggerFactory, dbFactory.Create(), connectionString); + return new SqlDeveloperTestDatabase(settings, loggerFactory, dbFactory.Create(), connectionString); } } } diff --git a/src/Umbraco.Tests.Integration/Testing/TestDatabaseSettings.cs b/src/Umbraco.Tests.Integration/Testing/TestDatabaseSettings.cs new file mode 100644 index 0000000000..9d9e305bc9 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/TestDatabaseSettings.cs @@ -0,0 +1,12 @@ + +namespace Umbraco.Tests.Integration.Testing +{ + public class TestDatabaseSettings + { + public int PrepareThreadCount { get; set; } + + public int SchemaDatabaseCount { get; set; } + + public int EmptyDatabasesCount { get; set; } + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index ca62668493..2a1e9a9298 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -282,7 +282,15 @@ namespace Umbraco.Tests.Integration.Testing return s_dbInstance; } - s_dbInstance = TestDatabaseFactory.Create(filesPath, loggerFactory, dbFactory); + // TODO: pull from IConfiguration + var settings = new TestDatabaseSettings + { + PrepareThreadCount = 4, + EmptyDatabasesCount = 2, + SchemaDatabaseCount = 4 + }; + + s_dbInstance = TestDatabaseFactory.Create(settings, filesPath, loggerFactory, dbFactory); return s_dbInstance; }