Beispiel #1
0
        public void ExcludeProblematicPaths()
        {
            // A normal path that will be backed up.
            string normalFilePath = Path.Combine(this.DATAFOLDER, "normal");

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

            // A long path to exclude.
            string longFile = SystemIO.IO_OS.PathCombine(this.DATAFOLDER, new string('y', 255));

            TestUtils.WriteFile(longFile, new byte[] { 0, 1 });

            // A folder that ends with a dot to exclude.
            string folderWithDot = Path.Combine(this.DATAFOLDER, "folder_with_dot.");

            SystemIO.IO_OS.DirectoryCreate(folderWithDot);

            // A folder that ends with a space to exclude.
            string folderWithSpace = Path.Combine(this.DATAFOLDER, "folder_with_space ");

            SystemIO.IO_OS.DirectoryCreate(folderWithSpace);

            // A file that ends with a dot to exclude.
            string fileWithDot = Path.Combine(this.DATAFOLDER, "file_with_dot.");

            TestUtils.WriteFile(fileWithDot, new byte[] { 0, 1 });

            // A file that ends with a space to exclude.
            string fileWithSpace = Path.Combine(this.DATAFOLDER, "file_with_space ");

            TestUtils.WriteFile(fileWithSpace, new byte[] { 0, 1 });

            FilterExpression filter = new FilterExpression(longFile, false);

            filter = FilterExpression.Combine(filter, new FilterExpression(Util.AppendDirSeparator(folderWithDot), false));
            filter = FilterExpression.Combine(filter, new FilterExpression(Util.AppendDirSeparator(folderWithSpace), false));
            filter = FilterExpression.Combine(filter, new FilterExpression(fileWithDot, false));
            filter = FilterExpression.Combine(filter, new FilterExpression(fileWithSpace, false));

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

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

            using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null))
            {
                IListResults listResults = c.List("*");
                Assert.AreEqual(0, listResults.Errors.Count());
                Assert.AreEqual(0, listResults.Warnings.Count());

                string[] backedUpPaths = listResults.Files.Select(x => x.Path).ToArray();
                Assert.AreEqual(2, backedUpPaths.Length);
                Assert.Contains(Util.AppendDirSeparator(this.DATAFOLDER), backedUpPaths);
                Assert.Contains(normalFilePath, backedUpPaths);
            }
        }
        public void ProblematicSuffixes(string pathComponent, bool skipOnWindows)
        {
            if (Platform.IsClientWindows && skipOnWindows)
            {
                return;
            }

            string folderPath = SystemIO.IO_OS.PathCombine(this.DATAFOLDER, pathComponent);

            SystemIO.IO_OS.DirectoryCreate(folderPath);

            string filePath = SystemIO.IO_OS.PathCombine(folderPath, pathComponent);

            byte[] fileBytes = { 0, 1, 2 };
            TestUtils.WriteFile(filePath, fileBytes);

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

            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());
            }

            Dictionary <string, string> restoreOptions = new Dictionary <string, string>(this.TestOptions)
            {
                ["restore-path"] = this.RESTOREFOLDER
            };

            // Restore just the file.
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, restoreOptions, null))
            {
                IRestoreResults restoreResults = c.Restore(new[] { filePath });
                Assert.AreEqual(0, restoreResults.Errors.Count());
                Assert.AreEqual(0, restoreResults.Warnings.Count());
            }

            string restoreFilePath = SystemIO.IO_OS.PathCombine(this.RESTOREFOLDER, pathComponent);

            TestUtils.AssertFilesAreEqual(filePath, restoreFilePath, true, pathComponent);
            SystemIO.IO_OS.FileDelete(restoreFilePath);

            // Restore the entire directory.
            string pathSpec = $"[{Regex.Escape(Util.AppendDirSeparator(this.DATAFOLDER))}.*]";

            using (Controller c = new Controller("file://" + this.TARGETFOLDER, restoreOptions, null))
            {
                IRestoreResults restoreResults = c.Restore(new[] { pathSpec });
                Assert.AreEqual(0, restoreResults.Errors.Count());
                Assert.AreEqual(0, restoreResults.Warnings.Count());
            }

            TestUtils.AssertDirectoryTreesAreEquivalent(this.DATAFOLDER, this.RESTOREFOLDER, true, pathComponent);
        }
Beispiel #3
0
        public void LongPath()
        {
            string folderPath = Path.Combine(this.DATAFOLDER, new string('x', 10));

            SystemIO.IO_OS.DirectoryCreate(folderPath);

            string fileName = new string('y', 255);
            string filePath = SystemIO.IO_OS.PathCombine(folderPath, fileName);

            byte[] fileBytes = { 0, 1, 2 };
            TestUtils.WriteFile(filePath, fileBytes);

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

            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());
            }

            Dictionary <string, string> restoreOptions = new Dictionary <string, string>(this.TestOptions)
            {
                ["restore-path"] = this.RESTOREFOLDER
            };

            using (Controller c = new Controller("file://" + this.TARGETFOLDER, restoreOptions, null))
            {
                IRestoreResults restoreResults = c.Restore(new[] { filePath });
                Assert.AreEqual(0, restoreResults.Errors.Count());
                Assert.AreEqual(0, restoreResults.Warnings.Count());
            }

            string restoreFilePath = SystemIO.IO_OS.PathCombine(this.RESTOREFOLDER, fileName);

            Assert.IsTrue(SystemIO.IO_OS.FileExists(restoreFilePath));

            MemoryStream restoredStream = new MemoryStream();

            using (FileStream fileStream = SystemIO.IO_OS.FileOpenRead(restoreFilePath))
            {
                Utility.CopyStream(fileStream, restoredStream);
            }

            Assert.AreEqual(fileBytes, restoredStream.ToArray());
        }
Beispiel #4
0
        public void DirectoriesWithWildcards()
        {
            const string  file        = "file";
            List <string> directories = new List <string>();

            // Keep expected match counts since they'll differ between
            // Linux and Windows.
            var questionMarkWildcardShouldMatchCount = 0;
            var verbatimAsteriskShouldMatchCount     = 0;

            const string asterisk        = "*";
            string       dirWithAsterisk = Path.Combine(this.DATAFOLDER, asterisk);

            // Windows does not support literal asterisks in paths.
            if (!Platform.IsClientWindows)
            {
                SystemIO.IO_OS.DirectoryCreate(dirWithAsterisk);
                TestUtils.WriteFile(SystemIO.IO_OS.PathCombine(dirWithAsterisk, file), new byte[] { 0 });
                directories.Add(dirWithAsterisk);
                questionMarkWildcardShouldMatchCount++;
                verbatimAsteriskShouldMatchCount++;
            }

            const string questionMark        = "?";
            string       dirWithQuestionMark = Path.Combine(this.DATAFOLDER, questionMark);

            // Windows does not support literal question marks in paths.
            if (!Platform.IsClientWindows)
            {
                SystemIO.IO_OS.DirectoryCreate(dirWithQuestionMark);
                TestUtils.WriteFile(SystemIO.IO_OS.PathCombine(dirWithQuestionMark, file), new byte[] { 1 });
                directories.Add(dirWithQuestionMark);
                questionMarkWildcardShouldMatchCount++;
            }

            // Include at least one single character directory in Windows
            // for a '?' wildcard can match on
            const string singleCharacterDir     = "X";
            string       dirWithSingleCharacter = Path.Combine(this.DATAFOLDER, singleCharacterDir);

            SystemIO.IO_OS.DirectoryCreate(dirWithSingleCharacter);
            TestUtils.WriteFile(SystemIO.IO_OS.PathCombine(dirWithSingleCharacter, file), new byte[] { 2 });
            directories.Add(dirWithSingleCharacter);
            questionMarkWildcardShouldMatchCount++;

            const string dir       = "dir";
            string       normalDir = Path.Combine(this.DATAFOLDER, dir);

            SystemIO.IO_OS.DirectoryCreate(normalDir);
            TestUtils.WriteFile(SystemIO.IO_OS.PathCombine(normalDir, file), new byte[] { 3 });
            directories.Add(normalDir);

            // Backup all files.
            Dictionary <string, string> options = new Dictionary <string, string>(this.TestOptions);

            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());
            }

            // Restore all files.
            Dictionary <string, string> restoreOptions = new Dictionary <string, string>(options)
            {
                ["restore-path"] = this.RESTOREFOLDER
            };

            using (Controller c = new Controller("file://" + this.TARGETFOLDER, restoreOptions, null))
            {
                IRestoreResults restoreResults = c.Restore(null);
                Assert.AreEqual(0, restoreResults.Errors.Count());
                Assert.AreEqual(0, restoreResults.Warnings.Count());

                TestUtils.AssertDirectoryTreesAreEquivalent(this.DATAFOLDER, this.RESTOREFOLDER, true, "Restore");

                // List results using * should return a match for each directory.
                IListResults listResults = c.List(SystemIO.IO_OS.PathCombine(dirWithAsterisk, file));
                Assert.AreEqual(0, listResults.Errors.Count());
                Assert.AreEqual(0, listResults.Warnings.Count());
                Assert.AreEqual(directories.Count, listResults.Files.Count());

                listResults = c.List(SystemIO.IO_OS.PathCombine(dirWithQuestionMark, file));
                Assert.AreEqual(0, listResults.Errors.Count());
                Assert.AreEqual(0, listResults.Warnings.Count());
                // List results using ? should return 3 matches in Linux,
                // one for the directory with '*' and one for the directory
                // with '?', plus one for directory 'X'; but should return
                // 1 matches in Windows just for directory 'X'.
                Assert.AreEqual(questionMarkWildcardShouldMatchCount, listResults.Files.Count());
            }

            SystemIO.IO_OS.DirectoryDelete(this.RESTOREFOLDER, true);

            // Restore one file at a time using the verbatim identifier.
            foreach (string directory in directories)
            {
                foreach (string expectedFilePath in SystemIO.IO_OS.EnumerateFiles(directory))
                {
                    using (Controller c = new Controller("file://" + this.TARGETFOLDER, restoreOptions, null))
                    {
                        string verbatimFilePath = "@" + expectedFilePath;

                        // Verify that list result using verbatim identifier contains only one file.
                        IListResults listResults = c.List(verbatimFilePath);
                        Assert.AreEqual(0, listResults.Errors.Count());
                        Assert.AreEqual(0, listResults.Warnings.Count());
                        Assert.AreEqual(1, listResults.Files.Count());
                        Assert.AreEqual(expectedFilePath, listResults.Files.Single().Path);

                        IRestoreResults restoreResults = c.Restore(new[] { verbatimFilePath });
                        Assert.AreEqual(0, restoreResults.Errors.Count());
                        Assert.AreEqual(0, restoreResults.Warnings.Count());

                        string fileName         = SystemIO.IO_OS.PathGetFileName(expectedFilePath);
                        string restoredFilePath = SystemIO.IO_OS.PathCombine(this.RESTOREFOLDER, fileName);
                        TestUtils.AssertFilesAreEqual(expectedFilePath, restoredFilePath, false, expectedFilePath);

                        SystemIO.IO_OS.FileDelete(restoredFilePath);
                    }
                }
            }

            // Backup with asterisk in include filter should include all directories.
            FilterExpression filter = new FilterExpression(dirWithAsterisk);

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

            // Backup with verbatim asterisk in include filter should include
            // one directory in Linux and zero directories in Windows.
            filter = new FilterExpression("@" + SystemIO.IO_OS.PathCombine(dirWithAsterisk, file));
            using (Controller c = new Controller("file://" + this.TARGETFOLDER, options, null))
            {
                IBackupResults backupResults = c.Backup(new[] { this.DATAFOLDER }, filter);
                Assert.AreEqual(0, backupResults.Errors.Count());
                Assert.AreEqual(0, backupResults.Warnings.Count());
                Assert.AreEqual(verbatimAsteriskShouldMatchCount, backupResults.ExaminedFiles);
            }
        }
Beispiel #5
0
        public void SymLinkPolicy(Options.SymlinkStrategy symlinkPolicy)
        {
            // Create symlink target directory
            const string targetDirName = "target";
            var          targetDir     = systemIO.PathCombine(this.DATAFOLDER, targetDirName);

            systemIO.DirectoryCreate(targetDir);
            // Create files in symlink target directory
            var fileNames = new[] { "a.txt", "b.txt", "c.txt" };

            foreach (var file in fileNames)
            {
                var targetFile = systemIO.PathCombine(targetDir, file);
                TestUtils.WriteFile(targetFile, Encoding.Default.GetBytes(file));
            }

            // Create actual symlink directory linking to the target directory
            const string symlinkDirName = "symlink";
            var          symlinkDir     = systemIO.PathCombine(this.DATAFOLDER, symlinkDirName);

            try
            {
                systemIO.CreateSymlink(symlinkDir, targetDir, asDir: true);
            }
            catch (Exception e)
            {
                // If client cannot create symlinks, mark test as ignored
                Assert.Ignore($"Client could not create a symbolic link.  Error reported: {e.Message}");
            }

            // Backup all files with given symlink policy
            Dictionary <string, string> restoreOptions = new Dictionary <string, string>(this.TestOptions)
            {
                ["restore-path"] = this.RESTOREFOLDER
            };
            Dictionary <string, string> backupOptions = new Dictionary <string, string>(this.TestOptions)
            {
                ["symlink-policy"] = symlinkPolicy.ToString()
            };

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

                // Verify that symlink policy was followed
                var restoreSymlinkDir = systemIO.PathCombine(this.RESTOREFOLDER, symlinkDirName);
                switch (symlinkPolicy)
                {
                case Options.SymlinkStrategy.Store:
                    // Restore should contain an actual symlink to the original target
                    Assert.That(systemIO.IsSymlink(restoreSymlinkDir), Is.True);
                    var restoredSymlinkFullPath = systemIO.PathGetFullPath(systemIO.GetSymlinkTarget(restoreSymlinkDir));
                    var symlinkTargetFullPath   = systemIO.PathGetFullPath(targetDir);
                    Assert.That(restoredSymlinkFullPath, Is.EqualTo(symlinkTargetFullPath));
                    break;

                case Options.SymlinkStrategy.Follow:
                    // Restore should contain a regular directory with copies of the files in the symlink target
                    Assert.That(systemIO.IsSymlink(restoreSymlinkDir), Is.False);
                    TestUtils.AssertDirectoryTreesAreEquivalent(targetDir, restoreSymlinkDir, true, "Restore");
                    break;

                case Options.SymlinkStrategy.Ignore:
                    // Restore should not contain the symlink or directory at all
                    Assert.That(systemIO.DirectoryExists(restoreSymlinkDir), Is.False);
                    Assert.That(systemIO.FileExists(restoreSymlinkDir), Is.False);
                    break;

                default:
                    Assert.Fail($"Unexpected symlink policy");
                    break;
                }
            }
        }