From db70f421ae92dac4eb1af63dd4cc03d605782dda Mon Sep 17 00:00:00 2001 From: udeeshagautam <46980425+udeeshagautam@users.noreply.github.com> Date: Tue, 14 May 2019 17:00:21 -0700 Subject: [PATCH] Fix for Full/Log/Differential backup #5370 (#811) * fixing the order of setting backup properties so that they are correctly propogated to actual action * Adding a backup type specific test and enabling 'few' old ones which seem to work consistentenly * Adding finally block, close connection and name change as per PR comments --- .../BackupOperation/BackupOperation.cs | 3 +- .../DisasterRecovery/BackupServiceTests.cs | 329 ++++++++++++------ 2 files changed, 219 insertions(+), 113 deletions(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/BackupOperation/BackupOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/BackupOperation/BackupOperation.cs index f41d24ba..8b689c8a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/BackupOperation/BackupOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/BackupOperation/BackupOperation.cs @@ -172,11 +172,12 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery /// public override void Execute() { + // set the operation properties before using them to create backup obejct + this.SetBackupProps(); this.backup = new Backup(); this.backup.Database = this.backupInfo.DatabaseName; this.backup.Action = this.backupActionType; this.backup.Incremental = this.isBackupIncremental; - this.SetBackupProps(); try { diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs index ebb2979a..4d4053b2 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs @@ -71,165 +71,239 @@ CREATE CERTIFICATE {1} WITH SUBJECT = 'Backup Encryption Certificate'; "; /// /// Create simple backup test /// - //[Fact] + [Fact] public void CreateBackupTest() { DisasterRecoveryService service = new DisasterRecoveryService(); - string databaseName = "testbackup_" + new Random().Next(10000000, 99999999); - SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); - DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); - SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); + string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); + SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName); - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); + try + { + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); + SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List() { backupPath }, - new Dictionary() { { backupPath, (int)DeviceType.File } }); - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - // Backup the database - service.PerformBackup(backupOperation); + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - VerifyAndCleanBackup(backupPath); - testDb.Cleanup(); + // Backup the database + service.PerformBackup(backupOperation); + + VerifyAndCleanBackup(backupPath); + sqlConn.Close(); + } + finally + { + testDb.Cleanup(); + } } - //[Fact] + [Fact] public void ScriptBackupTest() { DisasterRecoveryService service = new DisasterRecoveryService(); - string databaseName = "testbackup_" + new Random().Next(10000000, 99999999); + string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); - DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); - SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List() { backupPath }, - new Dictionary() { { backupPath, (int)DeviceType.File } }); - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); + try + { + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); + SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - // Generate script for backup - service.ScriptBackup(backupOperation); - string script = backupOperation.ScriptContent; - Assert.True(!string.IsNullOrEmpty(script)); - // Execute the script - testDb.RunQuery(script); + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - VerifyAndCleanBackup(backupPath); - testDb.Cleanup(); + // Generate script for backup + service.ScriptBackup(backupOperation); + string script = backupOperation.ScriptContent; + Assert.True(!string.IsNullOrEmpty(script)); + + // Execute the script + testDb.RunQuery(script); + + VerifyAndCleanBackup(backupPath); + sqlConn.Close(); + } + finally + { + testDb.Cleanup(); + } } - - + /// /// Test creating backup with advanced options set. /// - //[Fact] + [Fact] public void CreateBackupWithAdvancedOptionsTest() { DisasterRecoveryService service = new DisasterRecoveryService(); - string databaseName = "testbackup_" + new Random().Next(10000000, 99999999); + string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); - DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); - SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - string certificateName = CreateCertificate(testDb); - string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); + try + { + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); + SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List(){ backupPath }, - new Dictionary(){{ backupPath, (int)DeviceType.File }}); - backupInfo.ContinueAfterError = true; - backupInfo.FormatMedia = true; - backupInfo.SkipTapeHeader = true; - backupInfo.Initialize = true; - backupInfo.MediaName = "backup test media"; - backupInfo.MediaDescription = "backup test"; - backupInfo.RetainDays = 90; - backupInfo.CompressionOption = (int)BackupCompressionOptions.On; - backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; - backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; - backupInfo.EncryptorName = certificateName; + string certificateName = CreateCertificate(testDb); + string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - - // Backup the database - Console.WriteLine("Perform backup operation.."); - service.PerformBackup(backupOperation); + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + backupInfo.ContinueAfterError = true; + backupInfo.FormatMedia = true; + backupInfo.SkipTapeHeader = true; + backupInfo.Initialize = true; + backupInfo.MediaName = "backup test media"; + backupInfo.MediaDescription = "backup test"; + backupInfo.RetainDays = 90; + backupInfo.CompressionOption = (int)BackupCompressionOptions.On; + backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; + backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; + backupInfo.EncryptorName = certificateName; - // Remove the backup file - Console.WriteLine("Verify the backup file exists and remove.."); - VerifyAndCleanBackup(backupPath); + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - // Delete certificate and master key - Console.WriteLine("Remove certificate and master key.."); - testDb.RunQuery(cleanupCertificateQuery); - - // Clean up the database - Console.WriteLine("Clean up database.."); - testDb.Cleanup(); + // Backup the database + Console.WriteLine("Perform backup operation.."); + service.PerformBackup(backupOperation); + + // Remove the backup file + Console.WriteLine("Verify the backup file exists and remove.."); + VerifyAndCleanBackup(backupPath); + + // Delete certificate and master key + Console.WriteLine("Remove certificate and master key.."); + testDb.RunQuery(cleanupCertificateQuery); + + sqlConn.Close(); + } + finally + { + // Clean up the database + Console.WriteLine("Clean up database.."); + testDb.Cleanup(); + } } /// /// Test creating backup with advanced options set. /// - //[Fact] + [Fact] public void ScriptBackupWithAdvancedOptionsTest() { DisasterRecoveryService service = new DisasterRecoveryService(); - string databaseName = "testbackup_" + new Random().Next(10000000, 99999999); + string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); - DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); - SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - string certificateName = CreateCertificate(testDb); - string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); + try + { + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); + SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List() { backupPath }, - new Dictionary() { { backupPath, (int)DeviceType.File } }); - backupInfo.FormatMedia = true; - backupInfo.SkipTapeHeader = true; - backupInfo.Initialize = true; - backupInfo.MediaName = "backup test media"; - backupInfo.MediaDescription = "backup test"; - backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; - backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; - backupInfo.EncryptorName = certificateName; + string certificateName = CreateCertificate(testDb); + string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + backupInfo.FormatMedia = true; + backupInfo.SkipTapeHeader = true; + backupInfo.Initialize = true; + backupInfo.MediaName = "backup test media"; + backupInfo.MediaDescription = "backup test"; + backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; + backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; + backupInfo.EncryptorName = certificateName; - // Backup the database - Console.WriteLine("Generate script for backup operation.."); - service.ScriptBackup(backupOperation); - string script = backupOperation.ScriptContent; + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - // Run the script - Console.WriteLine("Execute the script.."); - testDb.RunQuery(script); + // Backup the database + Console.WriteLine("Generate script for backup operation.."); + service.ScriptBackup(backupOperation); + string script = backupOperation.ScriptContent; - // Remove the backup file - Console.WriteLine("Verify the backup file exists and remove.."); - VerifyAndCleanBackup(backupPath); + // Run the script + Console.WriteLine("Execute the script.."); + testDb.RunQuery(script); - // Delete certificate and master key - Console.WriteLine("Remove certificate and master key.."); - testDb.RunQuery(cleanupCertificateQuery); + // Remove the backup file + Console.WriteLine("Verify the backup file exists and remove.."); + VerifyAndCleanBackup(backupPath); - // Clean up the database - Console.WriteLine("Clean up database.."); - testDb.Cleanup(); + // Delete certificate and master key + Console.WriteLine("Remove certificate and master key.."); + testDb.RunQuery(cleanupCertificateQuery); + sqlConn.Close(); + } + finally + { + // Clean up the database + Console.WriteLine("Clean up database.."); + testDb.Cleanup(); + } + } + + /// + /// Test the correct script generation for different backup action types + /// + [Fact] + public void ScriptBackupWithDifferentActionTypesTest() + { + string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); + SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName); + + try + { + // Create Full backup script + string script = GenerateScriptForBackupType(BackupType.Full, databaseName); + + // Validate Full backup script + Assert.Contains("BACKUP DATABASE", script, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("BACKUP LOG", script, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("DIFFERENTIAL", script, StringComparison.OrdinalIgnoreCase); + + // Create log backup script + script = GenerateScriptForBackupType(BackupType.TransactionLog, databaseName); + + // Validate Log backup script + Assert.Contains("BACKUP LOG", script, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("BACKUP DATABASE", script, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("DIFFERENTIAL", script, StringComparison.OrdinalIgnoreCase); + + // Create differential backup script + script = GenerateScriptForBackupType(BackupType.Differential, databaseName); + + // Validate differential backup script + Assert.Contains("BACKUP DATABASE", script, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("BACKUP LOG", script, StringComparison.OrdinalIgnoreCase); + Assert.Contains("WITH DIFFERENTIAL", script, StringComparison.OrdinalIgnoreCase); + } + finally + { + // Clean up the database + Console.WriteLine("Clean up database.."); + testDb.Cleanup(); + } } //[Fact] @@ -393,6 +467,37 @@ CREATE CERTIFICATE {1} WITH SUBJECT = 'Backup Encryption Certificate'; "; } return false; } + + private string GenerateScriptForBackupType(BackupType backupType, string databaseName) + { + DisasterRecoveryService service = new DisasterRecoveryService(); + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true); + SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo); + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); + + BackupInfo backupInfoLog = CreateDefaultBackupInfo(databaseName, + backupType, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + backupInfoLog.FormatMedia = true; + backupInfoLog.SkipTapeHeader = true; + backupInfoLog.Initialize = true; + backupInfoLog.MediaName = "backup test media"; + backupInfoLog.MediaDescription = "backup test"; + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfoLog, helper.DataContainer, sqlConn); + + // Generate Script + Console.WriteLine("Generate script for backup operation.."); + service.ScriptBackup(backupOperation); + string script = backupOperation.ScriptContent; + + // There shouldnt be any backup file created + Assert.True(!File.Exists(backupPath), "Backup file is not expected to be created"); + + sqlConn.Close(); + return script; + } #endregion } } \ No newline at end of file