diff --git a/.travis.yml b/.travis.yml index 2795dfa1f..b89e9bfed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ jobs: directories: - $BUILD_DIR script: - - ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories SVNDataLong,SVNData + - ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories SVNDataLong,SVNData,RecoveryTool - stage: tests cache: directories: diff --git a/Duplicati/CommandLine/RecoveryTool/Program.cs b/Duplicati/CommandLine/RecoveryTool/Program.cs index 0d6361330..90fdb93c5 100644 --- a/Duplicati/CommandLine/RecoveryTool/Program.cs +++ b/Duplicati/CommandLine/RecoveryTool/Program.cs @@ -20,7 +20,7 @@ using System.Collections.Generic; namespace Duplicati.CommandLine.RecoveryTool { - static class Program + public static class Program { /// /// The main entry point for the application. diff --git a/Duplicati/UnitTest/Duplicati.UnitTest.csproj b/Duplicati/UnitTest/Duplicati.UnitTest.csproj index aa596353a..02ce5464f 100644 --- a/Duplicati/UnitTest/Duplicati.UnitTest.csproj +++ b/Duplicati/UnitTest/Duplicati.UnitTest.csproj @@ -44,6 +44,7 @@ + @@ -80,6 +81,10 @@ {2AF960C0-357D-4D44-A3D5-8B6E89DB0F11} Duplicati.CommandLine.BackendTool + + {4a010589-76e6-4f05-a5c4-4598d5df11f8} + Duplicati.CommandLine.RecoveryTool + {17566860-3D98-4604-AA5B-47661F75609F} Duplicati.GUI.TrayIcon diff --git a/Duplicati/UnitTest/RecoveryToolTests.cs b/Duplicati/UnitTest/RecoveryToolTests.cs new file mode 100644 index 000000000..f6b3ecb60 --- /dev/null +++ b/Duplicati/UnitTest/RecoveryToolTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Duplicati.Library.Main; +using NUnit.Framework; + +namespace Duplicati.UnitTest +{ + [TestFixture] + public class RecoveryToolTests : BasicSetupHelper + { + [Test] + [Category("RecoveryTool")] + public void Recover() + { + // Files to create in MB. + int[] fileSizes = {10, 20, 30}; + foreach (int size in fileSizes) + { + byte[] data = new byte[size * 1024 * 1024]; + Random rng = new Random(); + rng.NextBytes(data); + File.WriteAllBytes(Path.Combine(this.DATAFOLDER, size + "MB"), data); + } + + const string subdirectoryName = "subdirectory"; + string subdirectoryPath = Path.Combine(this.DATAFOLDER, subdirectoryName); + Directory.CreateDirectory(subdirectoryPath); + foreach (int size in fileSizes) + { + byte[] data = new byte[size * 1024 * 1024]; + Random rng = new Random(); + rng.NextBytes(data); + File.WriteAllBytes(Path.Combine(subdirectoryPath, size + "MB"), data); + } + + // Run a backup. + Dictionary options = new Dictionary(this.TestOptions); + string backendURL = "file://" + this.TARGETFOLDER; + using (Controller c = new Controller(backendURL, options, null)) + { + c.Backup(new[] {this.DATAFOLDER}); + } + + // Download the backend files. + string downloadFolder = Path.Combine(this.RESTOREFOLDER, "downloadedFiles"); + Directory.CreateDirectory(downloadFolder); + int status = CommandLine.RecoveryTool.Program.RealMain(new[] {"download", $"{backendURL}", $"{downloadFolder}", $"--passphrase={options["passphrase"]}"}); + Assert.AreEqual(0, status); + + // Create the index. + status = CommandLine.RecoveryTool.Program.RealMain(new[] {"index", $"{downloadFolder}"}); + Assert.AreEqual(0, status); + + // Restore to a different folder. + string restoreFolder = Path.Combine(this.RESTOREFOLDER, "restoredFiles"); + Directory.CreateDirectory(restoreFolder); + status = CommandLine.RecoveryTool.Program.RealMain(new[] {"restore", $"{downloadFolder}", $"--targetpath={restoreFolder}"}); + Assert.AreEqual(0, status); + + // Since this.DATAFOLDER is a folder, Path.GetFileName will return the name of the + // last folder in the path. + string baseFolder = Path.GetFileName(this.DATAFOLDER); + + foreach (string filepath in Directory.EnumerateFiles(this.DATAFOLDER)) + { + string filename = Path.GetFileName(filepath); + Assert.IsTrue(TestUtils.CompareFiles(filepath, Path.Combine(restoreFolder, baseFolder, filename ?? String.Empty), filename, false)); + } + + foreach (string filepath in Directory.EnumerateFiles(subdirectoryPath)) + { + string filename = Path.GetFileName(filepath); + Assert.IsTrue(TestUtils.CompareFiles(filepath, Path.Combine(restoreFolder, baseFolder, subdirectoryName, filename ?? String.Empty), filename, false)); + } + } + } +} \ No newline at end of file diff --git a/pipeline/start.sh b/pipeline/start.sh index 9ff9ca6b2..801148791 100755 --- a/pipeline/start.sh +++ b/pipeline/start.sh @@ -6,7 +6,7 @@ SCRIPT_DIR="$( cd "$(dirname "$0")" ; pwd -P )" ${ROOT_DIR}/pipeline/jobs/build_job.sh ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories BulkNormal ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories BulkNoSize -${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories SVNDataLong,SVNData +${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories SVNDataLong,SVNData,RecoveryTool ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories Border ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories Filter,Targeted,Purge,Serialization,WebApi,Utility,UriUtility,IO,ImportExport,Disruption,RestoreHandler