From 561f9216bad6e561c846f2f791d9ab973a2090bb Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Tue, 14 Jul 2020 12:50:13 -0400 Subject: [PATCH] Add down migration tests --- .../20200511012117_SLAddHeartbeat.cs | 43 +++++++++++++-- .../20200616180742_SLTopicTimeout.cs | 39 ++++++++++++- .../20200705163700_SLAllowNullDMApi.cs | 34 +++++++++++- .../Tgstation.Server.Tests/IntegrationTest.cs | 55 +++++++++++++++++++ 4 files changed, 161 insertions(+), 10 deletions(-) diff --git a/src/Tgstation.Server.Host/Database/Migrations/20200511012117_SLAddHeartbeat.cs b/src/Tgstation.Server.Host/Database/Migrations/20200511012117_SLAddHeartbeat.cs index 6e4a97ffef..77fc1f8ad4 100644 --- a/src/Tgstation.Server.Host/Database/Migrations/20200511012117_SLAddHeartbeat.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/20200511012117_SLAddHeartbeat.cs @@ -18,7 +18,7 @@ namespace Tgstation.Server.Host.Database.Migrations name: "HeartbeatSeconds", table: "DreamDaemonSettings", nullable: false, - defaultValue: 0u); + defaultValue: 0U); } /// @@ -27,9 +27,44 @@ namespace Tgstation.Server.Host.Database.Migrations if (migrationBuilder == null) throw new ArgumentNullException(nameof(migrationBuilder)); - migrationBuilder.DropColumn( - name: "HeartbeatSeconds", - table: "DreamDaemonSettings"); + migrationBuilder.RenameTable( + name: "DreamDaemonSettings", + newName: "DreamDaemonSettings_down"); + + migrationBuilder.CreateTable( + name: "DreamDaemonSettings", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + AllowWebClient = table.Column(nullable: false), + SecurityLevel = table.Column(nullable: false), + PrimaryPort = table.Column(nullable: false), + SecondaryPort = table.Column(nullable: false), + StartupTimeout = table.Column(nullable: false), + AutoStart = table.Column(nullable: false), + SoftRestart = table.Column(nullable: false), + SoftShutdown = table.Column(nullable: false), + ProcessId = table.Column(nullable: true), + AccessToken = table.Column(nullable: true), + InstanceId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DreamDaemonSettings", x => x.Id); + table.ForeignKey( + name: "FK_DreamDaemonSettings_Instances_InstanceId", + column: x => x.InstanceId, + principalTable: "Instances", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.Sql( + $"INSERT INTO DreamDaemonSettings SELECT Id,AllowWebClient,SecurityLevel,PrimaryPort,SecondaryPort,StartupTimeout,AutoStart,SoftRestart,SoftShutdown,ProcessId,AccessToken,InstanceId FROM DreamDaemonSettings_down"); + + migrationBuilder.DropTable( + name: "DreamDaemonSettings_down"); } } } diff --git a/src/Tgstation.Server.Host/Database/Migrations/20200616180742_SLTopicTimeout.cs b/src/Tgstation.Server.Host/Database/Migrations/20200616180742_SLTopicTimeout.cs index bca299417f..fcdcdf9500 100644 --- a/src/Tgstation.Server.Host/Database/Migrations/20200616180742_SLTopicTimeout.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/20200616180742_SLTopicTimeout.cs @@ -25,9 +25,42 @@ namespace Tgstation.Server.Host.Database.Migrations { if (migrationBuilder == null) throw new ArgumentNullException(nameof(migrationBuilder)); - migrationBuilder.DropColumn( - name: "TopicRequestTimeout", - table: "DreamDaemonSettings"); + + migrationBuilder.RenameTable( + name: "DreamDaemonSettings", + newName: "DreamDaemonSettings_down"); + + migrationBuilder.CreateTable( + name: "DreamDaemonSettings", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + AllowWebClient = table.Column(nullable: false), + SecurityLevel = table.Column(nullable: false), + PrimaryPort = table.Column(nullable: false), + SecondaryPort = table.Column(nullable: false), + StartupTimeout = table.Column(nullable: false), + AutoStart = table.Column(nullable: false), + InstanceId = table.Column(nullable: false), + HeartbeatSeconds = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DreamDaemonSettings", x => x.Id); + table.ForeignKey( + name: "FK_DreamDaemonSettings_Instances_InstanceId", + column: x => x.InstanceId, + principalTable: "Instances", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.Sql( + $"INSERT INTO DreamDaemonSettings SELECT Id,AllowWebClient,SecurityLevel,PrimaryPort,SecondaryPort,StartupTimeout,AutoStart,InstanceId,HeartbeatSeconds FROM DreamDaemonSettings_down"); + + migrationBuilder.DropTable( + name: "DreamDaemonSettings_down"); } } } diff --git a/src/Tgstation.Server.Host/Database/Migrations/20200705163700_SLAllowNullDMApi.cs b/src/Tgstation.Server.Host/Database/Migrations/20200705163700_SLAllowNullDMApi.cs index 422cdcc5c5..e001cc523f 100644 --- a/src/Tgstation.Server.Host/Database/Migrations/20200705163700_SLAllowNullDMApi.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/20200705163700_SLAllowNullDMApi.cs @@ -131,9 +131,37 @@ namespace Tgstation.Server.Host.Database.Migrations name: "CompileJobs_down", newName: "CompileJobs"); - migrationBuilder.DropColumn( - name: "RequireDMApiValidation", - table: "DreamMakerSettings"); + migrationBuilder.RenameTable( + name: "DreamMakerSettings", + newName: "DreamMakerSettings_down"); + + migrationBuilder.CreateTable( + name: "DreamMakerSettings", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ProjectName = table.Column(maxLength: 10000, nullable: true), + ApiValidationPort = table.Column(nullable: false), + ApiValidationSecurityLevel = table.Column(nullable: false), + InstanceId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DreamMakerSettings", x => x.Id); + table.ForeignKey( + name: "FK_DreamMakerSettings_Instances_InstanceId", + column: x => x.InstanceId, + principalTable: "Instances", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.Sql( + $"INSERT INTO DreamMakerSettings SELECT Id,ProjectName,ApiValidationPort,ApiValidationSecurityLevel,InstanceId FROM DreamMakerSettings_down"); + + migrationBuilder.DropTable( + name: "DreamMakerSettings_down"); } } } diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs index 3f02965eca..f2669bcfc9 100644 --- a/tests/Tgstation.Server.Tests/IntegrationTest.cs +++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs @@ -1,3 +1,7 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -15,6 +19,9 @@ using System.Threading.Tasks; using Tgstation.Server.Api; using Tgstation.Server.Api.Models; using Tgstation.Server.Client; +using Tgstation.Server.Host.Configuration; +using Tgstation.Server.Host.Database; +using Tgstation.Server.Host.Database.Migrations; using Tgstation.Server.Host.Extensions; using Tgstation.Server.Host.System; using Tgstation.Server.Tests.Instance; @@ -107,6 +114,54 @@ namespace Tgstation.Server.Tests } while (true); } +#if DEBUG + [TestMethod] + public async Task TestDownMigrations() + { + var connectionString = Environment.GetEnvironmentVariable("TGS4_TEST_CONNECTION_STRING"); + + if (String.IsNullOrEmpty(connectionString)) + Assert.Inconclusive("No connection string configured in env var TGS4_TEST_CONNECTION_STRING!"); + + var databaseTypeString = Environment.GetEnvironmentVariable("TGS4_TEST_DATABASE_TYPE"); + if (!Enum.TryParse(databaseTypeString, out var databaseType)) + Assert.Inconclusive("No/invalid database type configured in env var TGS4_TEST_DATABASE_TYPE!"); + + string migrationName = null; + DbContext CreateContext() + { + switch (databaseType) + { + case DatabaseType.MySql: + case DatabaseType.MariaDB: + migrationName = nameof(MYInitialCreate); + return new MySqlDatabaseContext(Host.Database.Design.DesignTimeDbContextFactoryHelpers.CreateDatabaseContextOptions(databaseType, connectionString)); + case DatabaseType.PostgresSql: + migrationName = nameof(PGCreate); + return new PostgresSqlDatabaseContext(Host.Database.Design.DesignTimeDbContextFactoryHelpers.CreateDatabaseContextOptions(databaseType, connectionString)); + case DatabaseType.SqlServer: + migrationName = nameof(MSInitialCreate); + return new SqlServerDatabaseContext(Host.Database.Design.DesignTimeDbContextFactoryHelpers.CreateDatabaseContextOptions(databaseType, connectionString)); + case DatabaseType.Sqlite: + migrationName = nameof(SLRebuild); + return new SqliteDatabaseContext(Host.Database.Design.DesignTimeDbContextFactoryHelpers.CreateDatabaseContextOptions(databaseType, connectionString)); + } + + return null; + } + + Task Delete(DbContext context) => databaseType == DatabaseType.Sqlite ? Task.CompletedTask : context.Database.EnsureCreatedAsync(); + + using var context = CreateContext(); + await Delete(context); + await context.Database.MigrateAsync(default); + var dbServiceProvider = ((IInfrastructure)context.Database).Instance; + var migrator = dbServiceProvider.GetRequiredService(); + await migrator.MigrateAsync(migrationName, default); + await Delete(context); + } +#endif + [TestMethod] public async Task TestServer() {