Beispiel #1
0
        public async Task FilesetFiles()
        {
            // Choose a dblock size that is small enough so that more than one volume is needed.
            Dictionary <string, string> options = new Dictionary <string, string>(this.TestOptions)
            {
                ["dblock-size"] = "10mb",

                // This allows us to inspect the dlist files without needing the BackendManager (which is inaccessible here) to decrypt them.
                ["no-encryption"] = "true"
            };

            // Run a full backup.
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null))
            {
                IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER });
                Assert.AreEqual(0, backupResults.Errors.Count());
                Assert.AreEqual(0, backupResults.Warnings.Count());
            }

            // Run a partial backup.
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null))
            {
                IBackupResults backupResults = await this.RunPartialBackup(c).ConfigureAwait(false);

                Assert.AreEqual(0, backupResults.Errors.Count());
                Assert.AreEqual(1, backupResults.Warnings.Count());
            }

            Dictionary <DateTime, int> GetBackupTypesFromRemoteFiles(Controller c, out List <string> filelistFiles)
            {
                Dictionary <DateTime, int> map = new Dictionary <DateTime, int>();

                filelistFiles = new List <string>();

                IListRemoteResults remoteFiles = c.ListRemote();

                foreach (IFileEntry file in remoteFiles.Files)
                {
                    IParsedVolume volume = VolumeBase.ParseFilename(file);
                    if (volume != null && volume.FileType == RemoteVolumeType.Files)
                    {
                        string dlistFile = Path.Combine(this.TARGETFOLDER, volume.File.Name);
                        filelistFiles.Add(dlistFile);
                        VolumeBase.FilesetData filesetData = VolumeReaderBase.GetFilesetData(volume.CompressionModule, dlistFile, new Options(options));
                        map[volume.Time] = filesetData.IsFullBackup ? BackupType.FULL_BACKUP : BackupType.PARTIAL_BACKUP;
                    }
                }

                return(map);
            }

            // Purge a file and verify that the fileset file exists in the new dlist files.
            List <string> dlistFiles;
            Dictionary <DateTime, int> backupTypeMap;

            using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null))
            {
                IPurgeFilesResults purgeResults = c.PurgeFiles(new Library.Utility.FilterExpression($"*{this.fileSizes[0]}*"));
                Assert.AreEqual(0, purgeResults.Errors.Count());
                Assert.AreEqual(0, purgeResults.Warnings.Count());

                List <IListResultFileset> filesets = c.List().Filesets.ToList();
                Assert.AreEqual(2, filesets.Count);
                Assert.AreEqual(BackupType.FULL_BACKUP, filesets.Single(x => x.Version == 1).IsFullBackup);
                Assert.AreEqual(BackupType.PARTIAL_BACKUP, filesets.Single(x => x.Version == 0).IsFullBackup);

                backupTypeMap = GetBackupTypesFromRemoteFiles(c, out dlistFiles);
            }

            int[] backupTypes = backupTypeMap.OrderByDescending(x => x.Key).Select(x => x.Value).ToArray();
            Assert.AreEqual(2, backupTypes.Length);
            Assert.AreEqual(BackupType.FULL_BACKUP, backupTypes[1]);
            Assert.AreEqual(BackupType.PARTIAL_BACKUP, backupTypes[0]);

            // Remove the dlist files.
            foreach (string dlistFile in dlistFiles)
            {
                File.Delete(dlistFile);
            }

            // Run a repair and verify that the fileset file exists in the new dlist files.
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null))
            {
                IRepairResults repairResults = c.Repair();
                Assert.AreEqual(0, repairResults.Errors.Count());
                Assert.AreEqual(0, repairResults.Warnings.Count());

                List <IListResultFileset> filesets = c.List().Filesets.ToList();
                Assert.AreEqual(2, filesets.Count);
                Assert.AreEqual(BackupType.FULL_BACKUP, filesets.Single(x => x.Version == 1).IsFullBackup);
                Assert.AreEqual(BackupType.PARTIAL_BACKUP, filesets.Single(x => x.Version == 0).IsFullBackup);

                backupTypeMap = GetBackupTypesFromRemoteFiles(c, out _);
            }

            backupTypes = backupTypeMap.OrderByDescending(x => x.Key).Select(x => x.Value).ToArray();
            Assert.AreEqual(2, backupTypes.Length);
            Assert.AreEqual(BackupType.FULL_BACKUP, backupTypes[1]);
            Assert.AreEqual(BackupType.PARTIAL_BACKUP, backupTypes[0]);
        }
Beispiel #2
0
        public void DeleteAllRemoteFiles()
        {
            string filePath = Path.Combine(this.DATAFOLDER, "file");

            File.WriteAllBytes(filePath, new byte[] { 0, 1, 2 });

            Dictionary <string, string> firstOptions = new Dictionary <string, string>(this.TestOptions);

            using (Controller c = new Controller("file://" + this.TARGETFOLDER, firstOptions, null))
            {
                IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER });
                Assert.AreEqual(0, backupResults.Errors.Count());
                Assert.AreEqual(0, backupResults.Warnings.Count());
            }

            // Keep track of the backend files from the first backup configuration so that we can
            // check that they remain after we remove the backend files from the second backup
            // configuration.
            string[] firstBackupFiles = Directory.GetFiles(this.TARGETFOLDER);
            Assert.Greater(firstBackupFiles.Length, 0);

            Dictionary <string, string> secondOptions = new Dictionary <string, string>(this.TestOptions)
            {
                ["dbpath"] = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())
            };

            using (Controller c = new Controller("file://" + this.TARGETFOLDER, secondOptions, null))
            {
                // An exception should be thrown due to unrecognized files in the target folder.
                // ReSharper disable once AccessToDisposedClosure
                Assert.That(() => c.Backup(new[] { this.DATAFOLDER }), Throws.Exception);
            }

            // We should be able to safely remove backend files from the second backup by referring
            // to the local database.
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, secondOptions, null))
            {
                IListRemoteResults listResults = c.DeleteAllRemoteFiles();
                Assert.AreEqual(0, listResults.Errors.Count());
                Assert.AreEqual(0, listResults.Warnings.Count());
            }

            // After we delete backend files from the second backup configuration, those from the first
            // configuration should remain (see issues #3845, and #4244).
            foreach (string file in firstBackupFiles)
            {
                Assert.IsTrue(File.Exists(file));
            }

            // Configure and run a second backup with a different prefix.  This should run without error.
            secondOptions["prefix"] = new Options(firstOptions).Prefix + "2";
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, secondOptions, null))
            {
                IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER });
                Assert.AreEqual(0, backupResults.Errors.Count());
                Assert.AreEqual(0, backupResults.Warnings.Count());
            }

            // Even without a local database, we should be able to safely remove backend files from
            // the second backup due to the prefix.
            File.Delete(secondOptions["dbpath"]);
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, secondOptions, null))
            {
                IListRemoteResults listResults = c.DeleteAllRemoteFiles();
                Assert.AreEqual(0, listResults.Errors.Count());
                Assert.AreEqual(0, listResults.Warnings.Count());
            }

            // After we delete backend files from the second backup configuration, those from the first
            // configuration should remain (see issue #2678).
            foreach (string file in firstBackupFiles)
            {
                Assert.IsTrue(File.Exists(file));
            }

            // The first backup configuration should still run normally.
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, firstOptions, null))
            {
                IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER });
                Assert.AreEqual(0, backupResults.Errors.Count());
                Assert.AreEqual(0, backupResults.Warnings.Count());
            }
        }