diff --git a/Duplicati/Library/Main/Properties/AssemblyInfo.cs b/Duplicati/Library/Main/Properties/AssemblyInfo.cs index e7934bf6c..58e66c4db 100644 --- a/Duplicati/Library/Main/Properties/AssemblyInfo.cs +++ b/Duplicati/Library/Main/Properties/AssemblyInfo.cs @@ -52,3 +52,6 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: [assembly: AssemblyVersion("2.0.0.7")] [assembly: AssemblyFileVersion("2.0.0.7")] + +// Expose internal classes to UnitTests, so that Database classes can be tested +[assembly: InternalsVisibleTo("Duplicati.UnitTest")] diff --git a/Duplicati/UnitTest/RepairHandlerTests.cs b/Duplicati/UnitTest/RepairHandlerTests.cs index fcaf7348d..419ce0546 100644 --- a/Duplicati/UnitTest/RepairHandlerTests.cs +++ b/Duplicati/UnitTest/RepairHandlerTests.cs @@ -17,7 +17,7 @@ namespace Duplicati.UnitTest public override void SetUp() { base.SetUp(); - File.WriteAllBytes(Path.Combine(this.DATAFOLDER, "file"), new byte[] {0}); + File.WriteAllBytes(Path.Combine(this.DATAFOLDER, "file"), new byte[] { 0 }); } [Test] @@ -35,7 +35,7 @@ namespace Duplicati.UnitTest Dictionary options = new Dictionary(this.TestOptions); using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null)) { - IBackupResults backupResults = c.Backup(new[] {this.DATAFOLDER}); + IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }); Assert.AreEqual(0, backupResults.Errors.Count()); Assert.AreEqual(0, backupResults.Warnings.Count()); } @@ -105,7 +105,7 @@ namespace Duplicati.UnitTest // A subsequent backup should run without errors. using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null)) { - IBackupResults backupResults = c.Backup(new[] {this.DATAFOLDER}); + IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }); Assert.AreEqual(0, backupResults.Errors.Count()); Assert.AreEqual(0, backupResults.Warnings.Count()); } @@ -117,10 +117,10 @@ namespace Duplicati.UnitTest [TestCase("false")] public void RepairMissingIndexFiles(string noEncryption) { - Dictionary options = new Dictionary(this.TestOptions) {["no-encryption"] = noEncryption}; + Dictionary options = new Dictionary(this.TestOptions) { ["no-encryption"] = noEncryption }; using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null)) { - IBackupResults backupResults = c.Backup(new[] {this.DATAFOLDER}); + IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }); Assert.AreEqual(0, backupResults.Errors.Count()); Assert.AreEqual(0, backupResults.Warnings.Count()); } @@ -144,5 +144,50 @@ namespace Duplicati.UnitTest Assert.IsTrue(File.Exists(Path.Combine(this.TARGETFOLDER, file))); } } + + [Test] + [Category("RepairHandler")] + [TestCase("true")] + [TestCase("false")] + public void RepairExtraIndexFiles(string noEncryption) + { + // Extra index files will be added to the database and should have a correct link established + Dictionary options = new Dictionary(this.TestOptions) { ["no-encryption"] = noEncryption }; + using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null)) + { + IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }); + TestUtils.AssertResults(backupResults); + } + + string[] dindexFiles = Directory.EnumerateFiles(this.TARGETFOLDER, "*dindex*").ToArray(); + Assert.Greater(dindexFiles.Length, 0); + string origFile = dindexFiles.First(); + // Duplicate index file + string dupFile = Path.Combine(TARGETFOLDER, Path.GetFileName(origFile).Replace(".dindex", "1.dindex")); + File.Copy(origFile, dupFile); + + using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null)) + { + IRepairResults repairResults = c.Repair(); + TestUtils.AssertResults(repairResults); + } + + // Check database block link + using (LocalDatabase db = new LocalDatabase(DBFILE, "Test", true)) + { + long indexVolumeId = db.GetRemoteVolumeID(Path.GetFileName(origFile)); + long duplicateVolumeId = db.GetRemoteVolumeID(Path.GetFileName(dupFile)); + Assert.AreNotEqual(-1, indexVolumeId); + Assert.AreNotEqual(-1, duplicateVolumeId); + + using (var cmd = db.Connection.CreateCommand()) + { + string sql = @"SELECT ""BlockVolumeID"" FROM ""IndexBlockLink"" WHERE ""IndexVolumeID"" = ?"; + long linkedIndexId = cmd.ExecuteScalarInt64(sql, -1, indexVolumeId); + long linkedDuplicateId = cmd.ExecuteScalarInt64(sql, -1, duplicateVolumeId); + Assert.AreEqual(linkedIndexId, linkedDuplicateId); + } + } + } } } \ No newline at end of file