diff --git a/Duplicati/UnitTest/ImportExportTests.cs b/Duplicati/UnitTest/ImportExportTests.cs index 9663d5ec1..26062445c 100644 --- a/Duplicati/UnitTest/ImportExportTests.cs +++ b/Duplicati/UnitTest/ImportExportTests.cs @@ -1,28 +1,29 @@ -// Copyright (C) 2025, The Duplicati Team -// https://duplicati.com, hello@duplicati.com -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// Copyright (C) 2025, The Duplicati Team +// https://duplicati.com, hello@duplicati.com +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; using System.IO; using Duplicati.Library.RestAPI; +using Duplicati.Library.SQLiteHelper; using Duplicati.Server; using Duplicati.Server.Database; using Duplicati.Server.Serializable; @@ -126,46 +127,57 @@ namespace Duplicati.UnitTest [Category("ImportExport")] public void RoundTrip() { - Dictionary metadata = new Dictionary { { "SourceFilesCount", "1" } }; - Dictionary advancedOptions = new Dictionary { { "server-datafolder", this.serverDatafolder } }; + var metadata = new Dictionary { { "SourceFilesCount", "1" } }; + var advancedOptions = new Dictionary { { "server-datafolder", this.serverDatafolder } }; + + // Mock the setup enough to get the import/export working var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(new EventPollNotify()); FIXMEGlobal.Provider = new DefaultServiceProviderFactory().CreateServiceProvider(serviceCollection); + FIXMEGlobal.DataFolder = this.serverDatafolder; - using (Program.DataConnection = Program.GetDatabaseConnection(advancedOptions, true)) + var dbpath = Path.Combine(this.serverDatafolder, Library.AutoUpdater.DataFolderManager.SERVER_DATABASE_FILENAME); + if (File.Exists(dbpath)) + File.Delete(dbpath); + + var con = SQLiteLoader.LoadConnection(); + SQLiteLoader.OpenDatabase(con, dbpath, null); + DatabaseUpgrader.UpgradeDatabase(con, dbpath, typeof(Duplicati.Library.RestAPI.Database.DatabaseConnectionSchemaMarker)); + + using (var connection = new Connection(con, true, null)) { // Unencrypted file, don't import metadata. string unencryptedWithoutMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName()); - File.WriteAllBytes(unencryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("unencrypted without metadata", "user", "password", metadata), null)); - BackupImportExportHandler.ImportBackup(Program.DataConnection, unencryptedWithoutMetadata, false, () => null); - Assert.AreEqual(1, Program.DataConnection.Backups.Length); - Assert.AreEqual(0, Program.DataConnection.Backups[0].Metadata.Count); + File.WriteAllBytes(unencryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(connection, this.CreateBackup("unencrypted without metadata", "user", "password", metadata), null)); + BackupImportExportHandler.ImportBackup(connection, unencryptedWithoutMetadata, false, () => null); + Assert.AreEqual(1, connection.Backups.Length); + Assert.AreEqual(0, connection.Backups[0].Metadata.Count); // Unencrypted file, import metadata. string unencryptedWithMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName()); - File.WriteAllBytes(unencryptedWithMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("unencrypted with metadata", "user", "password", metadata), null)); - BackupImportExportHandler.ImportBackup(Program.DataConnection, unencryptedWithMetadata, true, () => null); - Assert.AreEqual(2, Program.DataConnection.Backups.Length); - Assert.AreEqual(metadata.Count, Program.DataConnection.Backups[1].Metadata.Count); + File.WriteAllBytes(unencryptedWithMetadata, BackupImportExportHandler.ExportToJSON(connection, this.CreateBackup("unencrypted with metadata", "user", "password", metadata), null)); + BackupImportExportHandler.ImportBackup(connection, unencryptedWithMetadata, true, () => null); + Assert.AreEqual(2, connection.Backups.Length); + Assert.AreEqual(metadata.Count, connection.Backups[1].Metadata.Count); // Encrypted file, don't import metadata. string encryptedWithoutMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName()); string passphrase = "abcde"; - File.WriteAllBytes(encryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("encrypted without metadata", "user", "password", metadata), passphrase)); - BackupImportExportHandler.ImportBackup(Program.DataConnection, encryptedWithoutMetadata, false, () => passphrase); - Assert.AreEqual(3, Program.DataConnection.Backups.Length); - Assert.AreEqual(0, Program.DataConnection.Backups[2].Metadata.Count); + File.WriteAllBytes(encryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(connection, this.CreateBackup("encrypted without metadata", "user", "password", metadata), passphrase)); + BackupImportExportHandler.ImportBackup(connection, encryptedWithoutMetadata, false, () => passphrase); + Assert.AreEqual(3, connection.Backups.Length); + Assert.AreEqual(0, connection.Backups[2].Metadata.Count); // Encrypted file, import metadata. string encryptedWithMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName()); - File.WriteAllBytes(encryptedWithMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("encrypted with metadata", "user", "password", metadata), passphrase)); - BackupImportExportHandler.ImportBackup(Program.DataConnection, encryptedWithMetadata, true, () => passphrase); - Assert.AreEqual(4, Program.DataConnection.Backups.Length); - Assert.AreEqual(metadata.Count, Program.DataConnection.Backups[3].Metadata.Count); + File.WriteAllBytes(encryptedWithMetadata, BackupImportExportHandler.ExportToJSON(connection, this.CreateBackup("encrypted with metadata", "user", "password", metadata), passphrase)); + BackupImportExportHandler.ImportBackup(connection, encryptedWithMetadata, true, () => passphrase); + Assert.AreEqual(4, connection.Backups.Length); + Assert.AreEqual(metadata.Count, connection.Backups[3].Metadata.Count); // Encrypted file, incorrect passphrase. - Assert.Throws(Is.InstanceOf(), () => BackupImportExportHandler.ImportBackup(Program.DataConnection, encryptedWithMetadata, true, () => passphrase + " ")); + Assert.Throws(Is.InstanceOf(), () => BackupImportExportHandler.ImportBackup(connection, encryptedWithMetadata, true, () => passphrase + " ")); } } }