Source code for testing.functional.test_selection

# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2014 Aaron Whitehouse <aaron@whitehouse.kiwi.nz>
#
# This file is part of duplicity.
#
# Duplicity is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# Duplicity is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with duplicity; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

import os
import sys
import platform

import unittest

from . import FunctionalTestCase


[docs]class IncludeExcludeFunctionalTest(FunctionalTestCase): """ This contains methods used in the tests below for testing the include, exclude and various filelist features. """ # These tests assume the following files and logic, with: # "is" meaning that the file is included specifically # "ia" meaning that the file should be included automatically because its parent is included # "ic" meaning that the folder is included because its contents are included # "es" meaning that the file is excluded specifically # "ea" meaning that the file should be excluded automatically because its parent is included # select2 (es) # --- 1.doc (ea) # --- 1.py (is) # --- 1 (is) # ------ 1sub1 (ia) # --------- 1sub1sub1 (ia) # ------------ 1sub1sub1_file.txt (ia) # --------- 1sub1sub2 (es) # ------------ 1sub1sub2_file.txt (ea) # --------- 1sub1sub3 (ia) # ------------ 1sub1sub3_file.txt (es) # ------ 1sub2 (ic) # --------- 1sub2sub1 (is) # --------- 1sub2sub2 (ea) # --------- 1sub2sub3 (es) # Not necessary as also ea, but to ensure there are no issues doing so # ------ 1sub3 (ia) # --------- 1sub3sub1 (es) # --------- 1sub3sub2 (es) # --------- 1sub3sub3 (ia) # --- 2 (ic) # ------ 2sub1 (is) # --------- 2sub1sub1 (ia) # ------------ 2sub1sub1_file.txt (ia) # --------- 2sub1sub2 (es) # --------- 2sub1sub3 (es) # ------ 2sub2 (ea) # --------- 2sub2sub1 (ea) # --------- 2sub2sub2 (ea) # --------- 2sub2sub3 (ea) # ------ 2sub3 (ea) # --------- 2sub3sub1 (ea) # --------- 2sub3sub3 (ea) # --------- 2sub3sub2 (ea) # --- 3 (is) # ------ 3sub1 (es) # --------- 3sub1sub1 (ea) # --------- 3sub1sub2 (ea) # --------- 3sub1sub3 (ea) # ------ 3sub2 (ia) # --------- 3sub2sub1 (ia) # --------- 3sub2sub2 (ia) # --------- 3sub2sub3 (ia) # ------ 3sub3 (is) # Not necessary as also ia, but to ensure there are no issues doing so # --------- 3sub3sub1 (ia) # --------- 3sub3sub2 (es, ic) # ------------ 3sub3sub2_file.txt (is) # --------- 3sub3sub3 (ia) # --- trailing_space (ea) # Note this is "trailing_space ". Excluded until trailing_space test, when (is) # ------ trailing_space sub1 (ea) # Excluded until trailing_space test, when (ia) # ------ trailing_space sub2 (ea) # Excluded until trailing_space test, when (es, ic) # --------- trailing_space sub2_file.txt (ea) # Excluded until trailing_space test, when (is) complete_directory_tree = [ ['1', '2', '3', 'trailing_space ', '1.doc', '1.py'], ['1sub1', '1sub2', '1sub3'], ['1sub1sub1', '1sub1sub2', '1sub1sub3'], ['1sub1sub1_file.txt'], ['1sub1sub2_file.txt'], ['1sub1sub3_file.txt'], ['1sub2sub1', '1sub2sub2', '1sub2sub3'], ['1sub3sub1', '1sub3sub2', '1sub3sub3'], ['2sub1', '2sub2', '2sub3'], ['2sub1sub1', '2sub1sub2', '2sub1sub3'], ['2sub1sub1_file.txt'], ['2sub2sub1', '2sub2sub2', '2sub2sub3'], ['2sub3sub1', '2sub3sub2', '2sub3sub3'], ['3sub1', '3sub2', '3sub3'], ['3sub1sub1', '3sub1sub2', '3sub1sub3'], ['3sub2sub1', '3sub2sub2', '3sub2sub3'], ['3sub3sub1', '3sub3sub2', '3sub3sub3'], ['3sub3sub2_file.txt'], ['trailing_space sub1', 'trailing_space sub2'], ['trailing_space sub2_file.txt'] ] expected_restored_tree = [['1', '2', '3', '1.py'], ['1sub1', '1sub2', '1sub3'], ['1sub1sub1', '1sub1sub3'], ['1sub1sub1_file.txt'], ['1sub2sub1'], ['1sub3sub3'], ['2sub1'], ['2sub1sub1'], ['2sub1sub1_file.txt'], ['3sub2', '3sub3'], ['3sub2sub1', '3sub2sub2', '3sub2sub3'], ['3sub3sub1', '3sub3sub2', '3sub3sub3'], ['3sub3sub2_file.txt']] expected_restored_tree_with_trailing_space = [['1', '2', '3', 'trailing_space ', '1.py'], ['1sub1', '1sub2', '1sub3'], ['1sub1sub1', '1sub1sub3'], ['1sub1sub1_file.txt'], ['1sub2sub1'], ['1sub3sub3'], ['2sub1'], ['2sub1sub1'], ['2sub1sub1_file.txt'], ['3sub2', '3sub3'], ['3sub2sub1', '3sub2sub2', '3sub2sub3'], ['3sub3sub1', '3sub3sub2', '3sub3sub3'], ['3sub3sub2_file.txt'], ['trailing_space sub1', 'trailing_space sub2'], ['trailing_space sub2_file.txt']]
[docs] def directory_tree_to_list_of_lists(self, parent_directory): """ This takes a folder as an input and returns a list with its contents. If the directory has subdirectories, it returns a list of lists with the contents of those subdirectories. """ directory_list = [] for root, dirs, files in os.walk(parent_directory): to_add = [] if dirs: dirs.sort() # So that we can easily compare to what we expect to_add = dirs if files: files.sort() # So that we can easily compare to what we expect to_add += files if to_add: directory_list.append(to_add) return directory_list
[docs]class TestCheckTestFiles(IncludeExcludeFunctionalTest): """ Tests the testfiles required by the exclude/include tests are as expected. """
[docs] def test_files_are_as_expected(self): """Test that the contents of testfiles/select are as expected.""" testfiles = self.directory_tree_to_list_of_lists('testfiles/select2') # print(testfiles) self.assertEqual(testfiles, self.complete_directory_tree)
[docs]class TestIncludeExcludeOptions(IncludeExcludeFunctionalTest): """ This tests the behaviour of the duplicity binary when the include/exclude options are passed directly """
[docs] def test_include_exclude_basic(self): """ Test --include and --exclude work in the basic case """ self.backup("full", "testfiles/select2", options=["--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt", "--exclude", "testfiles/select2/3/3sub3/3sub3sub2", "--include", "testfiles/select2/3/3sub2/3sub2sub2", "--include", "testfiles/select2/3/3sub3", "--exclude", "testfiles/select2/3/3sub1", "--exclude", "testfiles/select2/2/2sub1/2sub1sub3", "--exclude", "testfiles/select2/2/2sub1/2sub1sub2", "--include", "testfiles/select2/2/2sub1", "--exclude", "testfiles/select2/1/1sub3/1sub3sub2", "--exclude", "testfiles/select2/1/1sub3/1sub3sub1", "--exclude", "testfiles/select2/1/1sub2/1sub2sub3", "--include", "testfiles/select2/1/1sub2/1sub2sub1", "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt", "--exclude", "testfiles/select2/1/1sub1/1sub1sub2", "--exclude", "testfiles/select2/1/1sub2", "--include", "testfiles/select2/1.py", "--include", "testfiles/select2/3", "--include", "testfiles/select2/1", "--exclude", "testfiles/select2/**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs] def test_include_exclude_trailing_whitespace(self): """Test that folders with trailing whitespace in the names work correctly when passing as include/exclude""" # Note that, because this only passes items in as a list of options, this test does not test whether duplicity # would correctly interpret commandline options with spaces. However, bin/duplicity uses sys.argv[1:], which # should return a list of strings after having correctly processed quotes etc. self.backup("full", "testfiles/select2", options=["--include", "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt", "--exclude", "testfiles/select2/trailing_space /trailing_space sub2", "--include", "testfiles/select2/trailing_space ", "--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt", "--exclude", "testfiles/select2/3/3sub3/3sub3sub2", "--include", "testfiles/select2/3/3sub2/3sub2sub2", "--include", "testfiles/select2/3/3sub3", "--exclude", "testfiles/select2/3/3sub1", "--exclude", "testfiles/select2/2/2sub1/2sub1sub3", "--exclude", "testfiles/select2/2/2sub1/2sub1sub2", "--include", "testfiles/select2/2/2sub1", "--exclude", "testfiles/select2/1/1sub3/1sub3sub2", "--exclude", "testfiles/select2/1/1sub3/1sub3sub1", "--exclude", "testfiles/select2/1/1sub2/1sub2sub3", "--include", "testfiles/select2/1/1sub2/1sub2sub1", "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt", "--exclude", "testfiles/select2/1/1sub1/1sub1sub2", "--exclude", "testfiles/select2/1/1sub2", "--include", "testfiles/select2/1.py", "--include", "testfiles/select2/3", "--include", "testfiles/select2/1", "--exclude", "testfiles/select2/**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)
[docs]class TestExcludeFilelistTest(IncludeExcludeFunctionalTest): """ Test --exclude-filelist using duplicity binary. """
[docs] def test_exclude_filelist(self): """Test that exclude filelist works in the basic case """ # As this is an exclude filelist any lines with no +/- modifier should be treated as if they have a -. # Create a filelist with open('testfiles/exclude.txt', 'w') as f: f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' 'testfiles/select2/3/3sub3/3sub3sub2\n' '+ testfiles/select2/3/3sub2/3sub2sub2\n' '+ testfiles/select2/3/3sub3\n' '- testfiles/select2/3/3sub1\n' # - added to ensure it makes no difference 'testfiles/select2/2/2sub1/2sub1sub3\n' 'testfiles/select2/2/2sub1/2sub1sub2\n' '+ testfiles/select2/2/2sub1\n' 'testfiles/select2/1/1sub3/1sub3sub2\n' 'testfiles/select2/1/1sub3/1sub3sub1\n' 'testfiles/select2/1/1sub2/1sub2sub3\n' '+ testfiles/select2/1/1sub2/1sub2sub1\n' 'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' 'testfiles/select2/1/1sub1/1sub1sub2\n' '- testfiles/select2/1/1sub2\n' # - added to ensure it makes no difference '+ testfiles/select2/1.py\n' '+ testfiles/select2/3\n' '+ testfiles/select2/1\n' 'testfiles/select2/**') self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs] def test_exclude_filelist_combined_imperfections(self): """Test that exclude filelist works with imperfections in the input file""" # This is a combined test for speed reasons. The individual imperfections are tested as unittests in # unit/test_selection. # Imperfections tested are; # * Leading space/spaces before the modifier # * Trailing space/spaces after the filename (but before the newline) # * Blank lines (newline character only) # * Line only containing spaces # * Full-line comments with # as the first character and with leading/trailing spaces # * Unnecessarily quoted filenames with/without modifier (both " and ') # Create a filelist with open('testfiles/exclude.txt', 'w') as f: f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' 'testfiles/select2/3/3sub3/3sub3sub2\n' '+ testfiles/select2/3/3sub2/3sub2sub2\n' ' + testfiles/select2/3/3sub3\n' # Note leading space added here '- testfiles/select2/3/3sub1\n' ' testfiles/select2/2/2sub1/2sub1sub3\n' # Note leading spaces added here '\n' 'testfiles/select2/2/2sub1/2sub1sub2\n' ' + testfiles/select2/2/2sub1 \n' # Note added trailing/leading space here '- "testfiles/select2/1/1sub3/1sub3sub2"\n' # Unnecessary quotes '# Testing a full-line comment\n' "'testfiles/select2/1/1sub3/1sub3sub1' \n" # Note added spaces and quotes here 'testfiles/select2/1/1sub2/1sub2sub3\n' ' \n' '+ testfiles/select2/1/1sub2/1sub2sub1\n' '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' 'testfiles/select2/1/1sub1/1sub1sub2\n' ' # Testing a full-line comment with leading and trailing spaces \n' 'testfiles/select2/1/1sub2 \n' # Note added spaces here '+ testfiles/select2/1.py\n' '+ testfiles/select2/3 \n' # Note added space here '+ testfiles/select2/1\n' '- testfiles/select2/**') self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs] def test_exclude_globbing_filelist_combined_imperfections(self): """Test that exclude globbing filelist works with imperfections in the input file""" # Identical to test_exclude_filelist_combined_imperfections and included to ensure that # the deprecated --exclude-globbing-filelist function works as expected until it is deliberately removed. # This is a combined test for speed reasons. The individual imperfections are tested as unittests in # unit/test_selection. # Imperfections tested are; # * Leading space/spaces before the modifier # * Trailing space/spaces after the filename (but before the newline) # * Blank lines (newline character only) # * Line only containing spaces # * Full-line comments with # as the first character and with leading/trailing spaces # * Unnecessarily quoted filenames with/without modifier (both " and ') # Create a filelist with open('testfiles/exclude.txt', 'w') as f: f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' 'testfiles/select2/3/3sub3/3sub3sub2\n' '+ testfiles/select2/3/3sub2/3sub2sub2\n' ' + testfiles/select2/3/3sub3\n' # Note leading space added here '- testfiles/select2/3/3sub1\n' ' testfiles/select2/2/2sub1/2sub1sub3\n' # Note leading spaces added here '\n' 'testfiles/select2/2/2sub1/2sub1sub2\n' ' + testfiles/select2/2/2sub1 \n' # Note added trailing/leading space here '- "testfiles/select2/1/1sub3/1sub3sub2"\n' # Unnecessary quotes '# Testing a full-line comment\n' "'testfiles/select2/1/1sub3/1sub3sub1' \n" # Note added spaces and quotes here 'testfiles/select2/1/1sub2/1sub2sub3\n' ' \n' '+ testfiles/select2/1/1sub2/1sub2sub1\n' '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' 'testfiles/select2/1/1sub1/1sub1sub2\n' ' # Testing a full-line comment with leading and trailing spaces \n' 'testfiles/select2/1/1sub2 \n' # Note added spaces here '+ testfiles/select2/1.py\n' '+ testfiles/select2/3 \n' # Note added space here '+ testfiles/select2/1\n' '- testfiles/select2/**') self.backup("full", "testfiles/select2", options=["--exclude-globbing-filelist=testfiles/exclude.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs] def test_exclude_filelist_trailing_whitespace_folders_work_with_quotes(self): """Test that folders with trailing whitespace in the names work correctly if they are enclosed in quotes""" # Create a filelist with open('testfiles/exclude.txt', 'w') as f: f.write('+ "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt"\n' # New '- "testfiles/select2/trailing_space /trailing_space sub2"\n' # New '+ "testfiles/select2/trailing_space "\n' # New '+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' 'testfiles/select2/3/3sub3/3sub3sub2\n' '+ testfiles/select2/3/3sub2/3sub2sub2\n' '+ testfiles/select2/3/3sub3\n' '- testfiles/select2/3/3sub1\n' 'testfiles/select2/2/2sub1/2sub1sub3\n' 'testfiles/select2/2/2sub1/2sub1sub2\n' '+ testfiles/select2/2/2sub1\n' 'testfiles/select2/1/1sub3/1sub3sub2\n' 'testfiles/select2/1/1sub3/1sub3sub1\n' 'testfiles/select2/1/1sub2/1sub2sub3\n' '+ testfiles/select2/1/1sub2/1sub2sub1\n' 'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' 'testfiles/select2/1/1sub1/1sub1sub2\n' '- testfiles/select2/1/1sub2\n' '+ testfiles/select2/1.py\n' '+ testfiles/select2/3\n' '+ testfiles/select2/1\n' 'testfiles/select2/**') self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)
[docs] def test_exclude_filelist_progress_option(self): """Test that exclude filelist is unaffected by the --progress option""" # Regression test for Bug #1264744 (https://bugs.launchpad.net/duplicity/+bug/1264744) # Create a filelist identical to that used in test_exclude_filelist with open('testfiles/exclude.txt', 'w') as f: f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' 'testfiles/select2/3/3sub3/3sub3sub2\n' '+ testfiles/select2/3/3sub2/3sub2sub2\n' '+ testfiles/select2/3/3sub3\n' '- testfiles/select2/3/3sub1\n' # - added to ensure it makes no difference 'testfiles/select2/2/2sub1/2sub1sub3\n' 'testfiles/select2/2/2sub1/2sub1sub2\n' '+ testfiles/select2/2/2sub1\n' 'testfiles/select2/1/1sub3/1sub3sub2\n' 'testfiles/select2/1/1sub3/1sub3sub1\n' 'testfiles/select2/1/1sub2/1sub2sub3\n' '+ testfiles/select2/1/1sub2/1sub2sub1\n' 'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' 'testfiles/select2/1/1sub1/1sub1sub2\n' '- testfiles/select2/1/1sub2\n' # - added to ensure it makes no difference '+ testfiles/select2/1.py\n' '+ testfiles/select2/3\n' '+ testfiles/select2/1\n' 'testfiles/select2/**') # Backup the files exactly as in test_exclude_filelist, but with the --progress option self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt", "--progress"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) # The restored files should match those restored in test_exclude_filelist self.assertEqual(restored, self.expected_restored_tree)
[docs]class TestIncludeFilelistTest(IncludeExcludeFunctionalTest): """ Test --include-filelist using duplicity binary. """
[docs] def test_include_filelist(self): """Test that include filelist works in the basic case""" # See test_exclude_filelist above for explanation of what is expected. As this is an include filelist # any lines with no +/- modifier should be treated as if they have a +. # Create a filelist with open('testfiles/include.txt', 'w') as f: f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' '- testfiles/select2/3/3sub3/3sub3sub2\n' 'testfiles/select2/3/3sub2/3sub2sub2\n' '+ testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference '- testfiles/select2/3/3sub1\n' '- testfiles/select2/2/2sub1/2sub1sub3\n' '- testfiles/select2/2/2sub1/2sub1sub2\n' 'testfiles/select2/2/2sub1\n' '- testfiles/select2/1/1sub3/1sub3sub2\n' '- testfiles/select2/1/1sub3/1sub3sub1\n' '- testfiles/select2/1/1sub2/1sub2sub3\n' '+ testfiles/select2/1/1sub2/1sub2sub1\n' # + added to ensure it makes no difference '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' '- testfiles/select2/1/1sub1/1sub1sub2\n' '- testfiles/select2/1/1sub2\n' 'testfiles/select2/1.py\n' 'testfiles/select2/3\n' 'testfiles/select2/1\n' '- testfiles/select2/**') self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs] def test_include_filelist_combined_imperfections(self): """Test that include filelist works with imperfections in the input file""" # This is a combined test for speed reasons. The individual imperfections are tested as unittests in # unit/test_selection. # Imperfections tested are; # * Leading space/spaces before the modifier # * Trailing space/spaces after the filename (but before the newline) # * Blank lines (newline character only) # * Line only containing spaces # * Full-line comments with # as the first character and with leading/trailing spaces # * Unnecessarily quoted filenames with/without modifier (both " and ') # Create a filelist with open('testfiles/include.txt', 'w') as f: f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' '- testfiles/select2/3/3sub3/3sub3sub2\n' '"testfiles/select2/3/3sub2/3sub2sub2"\n' ' + testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference '- testfiles/select2/3/3sub1\n' '- testfiles/select2/2/2sub1/2sub1sub3\n' ' - "testfiles/select2/2/2sub1/2sub1sub2"\n' 'testfiles/select2/2/2sub1 \n' '\n' '- testfiles/select2/1/1sub3/1sub3sub2\n' '- testfiles/select2/1/1sub3/1sub3sub1 \n' "- 'testfiles/select2/1/1sub2/1sub2sub3'\n" ' \n' ' + testfiles/select2/1/1sub2/1sub2sub1 \n' # + added to ensure it makes no difference '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' ' - testfiles/select2/1/1sub1/1sub1sub2 \n' '# Testing full-line comment\n' '- testfiles/select2/1/1sub2\n' "'testfiles/select2/1.py'\n" 'testfiles/select2/3\n' ' # Testing another full-line comment \n' 'testfiles/select2/1\n' '- testfiles/select2/**') self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs] def test_include_filelist_workaround_combined_imperfections_no_wildcards(self): """Test that include filelist works with imperfections in the input file""" # This is a modified version of test_include_filelist that passes, despite Bug #1408411 # It is still a valid test, it just does not test as many selection features as the above. # This is a combined test for speed reasons. The individual imperfections are tested as unittests in # unit/test_selection. # Imperfections tested are; # * Leading space/spaces before the modifier # * Trailing space/spaces after the filename (but before the newline) # * Blank lines (newline character only) # * Line only containing spaces # * Full-line comments with # as the first character and with leading/trailing spaces # * Unnecessarily quoted filenames with/without modifier (both " and ') # Create a filelist with open('testfiles/include.txt', 'w') as f: f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' 'testfiles/select2/3/3sub2/3sub2sub2 \n' ' + testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference ' - testfiles/select2/3/3sub1 \n' '- testfiles/select2/2/2sub1/2sub1sub3\n' '- testfiles/select2/2/2sub1/2sub1sub2\n' '"testfiles/select2/2/2sub1"\n' ' - testfiles/select2/2/2sub3 \n' # Added because of Bug #1408411 '- testfiles/select2/2/2sub2\n' # Added because of Bug #1408411 "- 'testfiles/select2/1/1sub3/1sub3sub2'\n" '\n' '- testfiles/select2/1/1sub3/1sub3sub1\n' '- testfiles/select2/1/1sub2/1sub2sub3\n' '- "testfiles/select2/1/1sub2/1sub2sub2"\n' # Added because of Bug #1408411 '# This is a full-line comment\n' '+ testfiles/select2/1/1sub2/1sub2sub1 \n' # + added to ensure it makes no difference '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' ' \n' '- testfiles/select2/1/1sub1/1sub1sub2\n' # '- testfiles/select2/1/1sub2\n' # Commented out because of Bug #1408411 "'testfiles/select2/1.py'\n" ' # This is another full-line comment, with spaces \n' 'testfiles/select2/3\n' # '- testfiles/select2/2\n' # Commented out because of Bug #1408411 'testfiles/select2/1\n' '- "testfiles/select2/trailing_space "\n' # es instead of ea as no wildcard - ** '- testfiles/select2/1.doc') # es instead of ea as no wildcard - ** self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs] def test_include_globbing_filelist_combined_imperfections(self): """Test that include globbing filelist works with imperfections in the input file""" # Identical to test_include_filelist_combined_imperfections and included to ensure that # the deprecated --include-globbing-filelist function works as expected until it is deliberately removed. # This is a combined test for speed reasons. The individual imperfections are tested as unittests in # unit/test_selection. # Imperfections tested are; # * Leading space/spaces before the modifier # * Trailing space/spaces after the filename (but before the newline) # * Blank lines (newline character only) # * Line only containing spaces # * Full-line comments with # as the first character and with leading/trailing spaces # * Unnecessarily quoted filenames with/without modifier (both " and ') # Create a filelist with open('testfiles/include.txt', 'w') as f: f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n' '- testfiles/select2/3/3sub3/3sub3sub2\n' '"testfiles/select2/3/3sub2/3sub2sub2"\n' ' + testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference '- testfiles/select2/3/3sub1\n' '- testfiles/select2/2/2sub1/2sub1sub3\n' ' - "testfiles/select2/2/2sub1/2sub1sub2"\n' 'testfiles/select2/2/2sub1 \n' '\n' '- testfiles/select2/1/1sub3/1sub3sub2\n' '- testfiles/select2/1/1sub3/1sub3sub1 \n' "- 'testfiles/select2/1/1sub2/1sub2sub3'\n" ' \n' ' + testfiles/select2/1/1sub2/1sub2sub1 \n' # + added to ensure it makes no difference '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n' ' - testfiles/select2/1/1sub1/1sub1sub2 \n' '# Testing full-line comment\n' '- testfiles/select2/1/1sub2\n' "'testfiles/select2/1.py'\n" 'testfiles/select2/3\n' ' # Testing another full-line comment \n' 'testfiles/select2/1\n' '- testfiles/select2/**') self.backup("full", "testfiles/select2", options=["--include-globbing-filelist=testfiles/include.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs]class TestIncludeExcludedForContents(IncludeExcludeFunctionalTest): """ Test to check that folders that are excluded are included if they contain includes of higher priority. Exhibits the issue reported in Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411). """
[docs] def write_filelist(self, filelist_name): """Used by the below tests to write the filelist""" assert filelist_name is not None with open(filelist_name, 'w') as f: f.write("+ testfiles/select/1/2/1\n" "- testfiles/select/1/2\n" "- testfiles/select/1/1\n" "- testfiles/select/1/3")
[docs] def restore_and_check(self): """Restores the backup and compares to what was expected (based on the filelist in write_filelist)""" self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['2'], ['1']])
[docs] def test_commandline_include_exclude(self): """test an excluded folder is included for included contents when using commandline includes and excludes""" self.backup("full", "testfiles/select/1", options=["--include", "testfiles/select/1/2/1", "--exclude", "testfiles/select/1/2", "--exclude", "testfiles/select/1/1", "--exclude", "testfiles/select/1/3"]) self.restore_and_check()
[docs] def test_include_globbing_filelist(self): """test an excluded folder is included for included contents with an include-globbing-filelist """ # Deprecated, but include for now to ensure it keeps working until it is deliberately removed. self.write_filelist("testfiles/include.txt") self.backup("full", "testfiles/select/1", options=["--include-globbing-filelist=testfiles/include.txt"]) self.restore_and_check()
[docs] def test_exclude_globbing_filelist(self): """test an excluded folder is included for included contents with an exclude-globbing-filelist """ # Deprecated, but include for now to ensure it keeps working until it is deliberately removed. self.write_filelist("testfiles/exclude.txt") self.backup("full", "testfiles/select/1", options=["--exclude-globbing-filelist=testfiles/exclude.txt"]) self.restore_and_check()
[docs] def test_include_filelist(self): """test an excluded folder is included for included contents with an include-filelist (non-globbing) """ # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411) self.write_filelist("testfiles/include.txt") self.backup("full", "testfiles/select/1", options=["--include-filelist=testfiles/include.txt"]) self.restore_and_check()
[docs] def test_exclude_filelist(self): """test an excluded folder is included for included contents with an exclude-filelist (non-globbing) """ # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411) self.write_filelist("testfiles/exclude.txt") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/exclude.txt"]) self.restore_and_check()
[docs]class TestAsterisks(IncludeExcludeFunctionalTest): """ Test to check that asterisks work as expected Exhibits the issue reported in Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371). See the unit tests for more granularity on the issue."""
[docs] def restore_and_check(self): """Restores the backup and compares to what is expected.""" self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['2'], ['1']])
[docs] def test_exclude_filelist_asterisks_none(self): """Basic exclude filelist.""" with open("testfiles/filelist.txt", 'w') as f: f.write("+ testfiles/select/1/2/1\n" "- testfiles/select/1/2\n" "- testfiles/select/1/1\n" "- testfiles/select/1/3") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"]) self.restore_and_check()
[docs] def test_exclude_filelist_asterisks_single(self): """Exclude filelist with asterisks replacing folders.""" # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371) with open("testfiles/filelist.txt", 'w') as f: f.write("+ */select/1/2/1\n" "- */select/1/2\n" "- testfiles/*/1/1\n" "- */*/1/3") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"]) self.restore_and_check()
[docs] def test_exclude_filelist_asterisks_double_asterisks(self): """Exclude filelist with double asterisks replacing folders.""" # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371) with open("testfiles/filelist.txt", 'w') as f: f.write("+ **/1/2/1\n" "- **/1/2\n" "- **/select/1/1\n" "- testfiles/select/1/3") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"]) self.restore_and_check()
[docs] def test_commandline_asterisks_single_excludes_only(self): """test_commandline_include_exclude with single asterisks on exclude lines.""" self.backup("full", "testfiles/select/1", options=["--include", "testfiles/select/1/2/1", "--exclude", "testfiles/*/1/2", "--exclude", "*/select/1/1", "--exclude", "*/select/1/3"]) self.restore_and_check()
[docs] def test_commandline_asterisks_single_both(self): """test_commandline_include_exclude with single asterisks on both exclude and include lines.""" # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371) self.backup("full", "testfiles/select/1", options=["--include", "*/select/1/2/1", "--exclude", "testfiles/*/1/2", "--exclude", "*/select/1/1", "--exclude", "*/select/1/3"]) self.restore_and_check()
[docs] def test_commandline_asterisks_double_exclude_only(self): """test_commandline_include_exclude with double asterisks on exclude lines.""" self.backup("full", "testfiles/select/1", options=["--include", "testfiles/select/1/2/1", "--exclude", "**/1/2", "--exclude", "**/1/1", "--exclude", "**/1/3"]) self.restore_and_check()
[docs] def test_commandline_asterisks_double_both(self): """test_commandline_include_exclude with double asterisks on both exclude and include lines.""" # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371) self.backup("full", "testfiles/select/1", options=["--include", "**/1/2/1", "--exclude", "**/1/2", "--exclude", "**/1/1", "--exclude", "**/1/3"]) self.restore_and_check()
[docs] def test_single_and_double_asterisks(self): """This compares a backup using --include-globbing-filelist with a single and double *.""" with open("testfiles/filelist.txt", 'w') as f: f.write("+ testfiles/select2/*\n" "- testfiles/select") self.backup("full", "testfiles/", options=["--include-globbing-filelist=testfiles/filelist.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir + "/select2") with open("testfiles/filelist2.txt", 'w') as f: f.write("+ testfiles/select2/**\n" "- testfiles/select") self.backup("full", "testfiles/", options=["--include-globbing-filelist=testfiles/filelist2.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored2 = self.directory_tree_to_list_of_lists(restore_dir + "/select2") self.assertEqual(restored, restored2)
[docs] def test_single_and_double_asterisks_includes_excludes(self): """This compares a backup using --includes/--excludes with a single and double *.""" self.backup("full", "testfiles/", options=["--include", "testfiles/select2/*", "--exclude", "testfiles/select"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir + "/select2") self.backup("full", "testfiles/", options=["--include", "testfiles/select2/**", "--exclude", "testfiles/select"]) self.restore() restore_dir = 'testfiles/restore_out' restored2 = self.directory_tree_to_list_of_lists(restore_dir + "/select2") self.assertEqual(restored, restored2)
[docs]class TestTrailingSlash(IncludeExcludeFunctionalTest): """ Test to check that a trailing slash works as expected Exhibits the issue reported in Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)."""
[docs] def restore_and_check(self): """Restores the backup and compares to what is expected.""" self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['2'], ['1']])
[docs] def test_exclude_filelist_trailing_slashes(self): """test_exclude_filelist_asterisks_none with trailing slashes.""" with open("testfiles/filelist.txt", 'w') as f: f.write("+ testfiles/select/1/2/1/\n" "- testfiles/select/1/2/\n" "- testfiles/select/1/1/\n" "- testfiles/select/1/3/") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"]) self.restore_and_check()
[docs] def test_exclude_filelist_trailing_slashes_single_wildcards_excludes(self): """test_exclude_filelist_trailing_slashes with single wildcards in excludes.""" # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482) with open("testfiles/filelist.txt", 'w') as f: f.write("+ testfiles/select/1/2/1/\n" "- */select/1/2/\n" "- testfiles/*/1/1/\n" "- */*/1/3/") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"]) self.restore_and_check()
[docs] def test_exclude_filelist_trailing_slashes_double_wildcards_excludes(self): """test_exclude_filelist_trailing_slashes with double wildcards in excludes.""" # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482) with open("testfiles/filelist.txt", 'w') as f: f.write("+ testfiles/select/1/2/1/\n" "- **/1/2/\n" "- **/1/1/\n" "- **/1/3/") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"]) self.restore_and_check()
[docs] def test_exclude_filelist_trailing_slashes_double_wildcards_excludes_2(self): """second test_exclude_filelist_trailing_slashes with double wildcards in excludes.""" # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482) and # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371) with open("testfiles/filelist.txt", 'w') as f: f.write("+ **/1/2/1/\n" "- **/1/2/\n" "- **/1/1/\n" "- **/1/3/") self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"]) self.restore_and_check()
[docs] def test_exclude_filelist_trailing_slashes_wildcards(self): """test_commandline_asterisks_single_excludes_only with trailing slashes.""" # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482) self.backup("full", "testfiles/select/1", options=["--include", "testfiles/select/1/2/1/", "--exclude", "testfiles/*/1/2/", "--exclude", "*/select/1/1/", "--exclude", "*/select/1/3/"]) self.restore_and_check()
[docs]class TestTrailingSlash2(IncludeExcludeFunctionalTest): """ This tests the behaviour of globbing strings with a trailing slash""" # See Bug #1479545 (https://bugs.launchpad.net/duplicity/+bug/1479545)
[docs] def test_no_trailing_slash(self): """ Test that including 1.py works as expected""" self.backup("full", "testfiles/select2", options=["--include", "testfiles/select2/1.py", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1.py']])
[docs] def test_trailing_slash(self): """ Test that globs with a trailing slash only match directories""" # Regression test for Bug #1479545 # (https://bugs.launchpad.net/duplicity/+bug/1479545) self.backup("full", "testfiles/select2", options=["--include", "testfiles/select2/1.py/", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [])
[docs] def test_include_files_not_subdirectories(self): """ Test that a trailing slash glob followed by a * glob only matches files and not subdirectories""" self.backup("full", "testfiles/select2", options=["--exclude", "testfiles/select2/*/", "--include", "testfiles/select2/*", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1.doc', '1.py']])
[docs] def test_include_subdirectories_not_files(self): """ Test that a trailing slash glob only matches directories""" self.backup("full", "testfiles/select2", options=["--include", "testfiles/select2/1/1sub1/**/", "--exclude", "testfiles/select2/1/1sub1/**", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1'], ['1sub1'], ['1sub1sub1', '1sub1sub2', '1sub1sub3']])
[docs]class TestGlobbingReplacement(IncludeExcludeFunctionalTest): """ This tests the behaviour of the extended shell globbing pattern replacement functions.""" # See the manual for a description of behaviours, but in summary: # * can be expanded to any string of characters not containing "/" # ? expands to any character except "/" and # [...] expands to a single character of those characters specified (ranges are acceptable). # The new special pattern, **, expands to any string of characters whether or not it contains "/". # Furthermore, if the pattern starts with "ignorecase:" (case insensitive), then this prefix will be # removed and any character in the string can be replaced with an upper- or lowercase version of itself.
[docs] def test_globbing_replacement_in_includes(self): """ Test behaviour of the extended shell globbing pattern replacement functions in both include and exclude""" # Identical to test_include_exclude_basic with globbing characters added to both include and exclude lines # Exhibits the issue reported in Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371). # See above and the unit tests for more granularity on the issue. self.backup("full", "testfiles/select2", options=["--include", "testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt", # Note ** and ? added "--exclude", "testfiles/select2/*/3s*1", # Note * added in both directory and filename "--exclude", "testfiles/select2/**/2sub1sub3", # Note ** added "--exclude", "ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2", # Note ignorecase added "--include", "ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1", # Note ignorecase, [] and # ? added "--exclude", "testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2", # Note [] added "--exclude", "testfiles/select2/1/1sub[1-4]/1sub3sub1", # Note [range] added "--include", "testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1", # Note * and [] added "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt", # Note ? added "--exclude", "testfiles/select2/1/1*1/1sub1sub2", # Note * added "--exclude", "testfiles/select2/1/1sub2", "--include", "testfiles/select[2-4]/*.py", # Note * and [range] added "--include", "testfiles/*2/3", # Note * added "--include", "**/select2/1", # Note ** added "--exclude", "testfiles/select2/**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
[docs]class TestExcludeIfPresent(IncludeExcludeFunctionalTest): """ This tests the behaviour of duplicity's --exclude-if-present option"""
[docs] def test_exclude_if_present_baseline(self): """ Test that duplicity normally backs up files""" with open("testfiles/select2/1/1sub1/1sub1sub1/.nobackup", "w") as tag: tag.write("Files in this folder should not be backed up.") self.backup("full", "testfiles/select2/1/1sub1", options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/*", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1sub1sub1'], ['.nobackup', '1sub1sub1_file.txt']])
[docs] def test_exclude_if_present_excludes(self): """ Test that duplicity excludes files with relevant tag""" with open("testfiles/select2/1/1sub1/1sub1sub1/.nobackup", "w") as tag: tag.write("Files in this folder should not be backed up.") self.backup("full", "testfiles/select2/1/1sub1", options=["--exclude-if-present", ".nobackup", "--include", "testfiles/select2/1/1sub1/1sub1sub1/*", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [])
[docs] def test_exclude_if_present_excludes_2(self): """ Test that duplicity excludes files with relevant tag""" with open("testfiles/select2/1/1sub1/1sub1sub1/EXCLUDE.tag", "w") as tag: tag.write("Files in this folder should also not be backed up.") self.backup("full", "testfiles/select2/1/1sub1", options=["--exclude-if-present", "EXCLUDE.tag", "--include", "testfiles/select2/1/1sub1/1sub1sub1/*", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [])
[docs]class TestLockedFoldersNoError(IncludeExcludeFunctionalTest): """ This tests that inaccessible folders do not cause an error""" @unittest.skipUnless(platform.platform().startswith('Linux'), 'Skip on non-Linux systems')
[docs] def test_locked_baseline(self): """ Test no error if locked in path but excluded""" folder_to_lock = "testfiles/select2/1/1sub1/1sub1sub3" initial_mode = os.stat(folder_to_lock).st_mode os.chmod(folder_to_lock, 0o0000) self.backup("full", "testfiles/select2/1/1sub1", options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/*", "--exclude", "**"]) os.chmod(folder_to_lock, initial_mode) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1sub1sub1'], ['1sub1sub1_file.txt']])
@unittest.skipUnless(platform.platform().startswith('Linux'), 'Skip on non-Linux systems')
[docs] def test_locked_excl_if_present(self): """ Test no error if excluded locked with --exclude-if-present""" # Regression test for Bug #1620085 # https://bugs.launchpad.net/duplicity/+bug/1620085 folder_to_lock = "testfiles/select2/1/1sub1/1sub1sub3" initial_mode = os.stat(folder_to_lock).st_mode os.chmod(folder_to_lock, 0o0000) self.backup("full", "testfiles/select2/1/1sub1", options=["--exclude-if-present", "EXCLUDE.tag", "--include", "testfiles/select2/1/1sub1/1sub1sub1/*", "--exclude", "**"]) os.chmod(folder_to_lock, initial_mode) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1sub1sub1'], ['1sub1sub1_file.txt']])
[docs]class TestFolderIncludesFiles(IncludeExcludeFunctionalTest): """ This tests that including a folder includes the files within it""" # https://bugs.launchpad.net/duplicity/+bug/1624725
[docs] def test_includes_files(self): """This tests that including a folder includes the files within it""" self.backup("full", "testfiles/select2/1/1sub1", options=["--include", "testfiles/select2/1/1sub1/1sub1sub1", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1sub1sub1'], ['1sub1sub1_file.txt']])
[docs] def test_includes_files_trailing_slash(self): """This tests that including a folder includes the files within it""" self.backup("full", "testfiles/select2/1/1sub1", options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1sub1sub1'], ['1sub1sub1_file.txt']])
[docs] def test_includes_files_trailing_slash_globbing_chars(self): """Tests folder includes with globbing char and /""" self.backup("full", "testfiles/select2/1/1sub1", options=["--include", "testfiles/s?lect2/1/1sub1/1sub1sub1/", "--exclude", "**"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [['1sub1sub1'], ['1sub1sub1_file.txt']])
[docs] def test_excludes_files_no_trailing_slash(self): """This tests that excluding a folder excludes the files within it""" self.backup("full", "testfiles/select2/1/1sub1", options=["--exclude", "testfiles/select2/1/1sub1/1sub1sub1", "--exclude", "testfiles/select2/1/1sub1/1sub1sub2", "--exclude", "testfiles/select2/1/1sub1/1sub1sub3", "--include", "testfiles/select2/1/1sub1/1sub1**", "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [])
[docs] def test_excludes_files_trailing_slash(self): """Excluding a folder excludes the files within it, if ends with /""" self.backup("full", "testfiles/select2/1/1sub1", options=["--exclude", "testfiles/select2/1/1sub1/1sub1sub1/", "--exclude", "testfiles/select2/1/1sub1/1sub1sub2/", "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/", "--include", "testfiles/select2/1/1sub1/1sub1**", "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [])
[docs] def test_excludes_files_trailing_slash_globbing_chars(self): """Tests folder excludes with globbing char and /""" self.backup("full", "testfiles/select2/1/1sub1", options=["--exclude", "testfiles/sel?ct2/1/1sub1/1sub1sub1/", "--exclude", "testfiles/sel[e,f]ct2/1/1sub1/1sub1sub2/", "--exclude", "testfiles/sel*t2/1/1sub1/1sub1sub3/", "--include", "testfiles/select2/1/1sub1/1sub1**", "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, [])
[docs]class TestAbsolutePaths(IncludeExcludeFunctionalTest): """ Tests include/exclude options with absolute paths"""
[docs] def test_absolute_paths_non_globbing(self): """ Test --include and --exclude work with absolute paths""" self.backup("full", os.path.abspath("testfiles/select2"), options=["--include", os.path.abspath("testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"), "--exclude", os.path.abspath("testfiles/select2/3/3sub3/3sub3sub2"), "--include", os.path.abspath("testfiles/select2/3/3sub2/3sub2sub2"), "--include", os.path.abspath("testfiles/select2/3/3sub3"), "--exclude", os.path.abspath("testfiles/select2/3/3sub1"), "--exclude", os.path.abspath("testfiles/select2/2/2sub1/2sub1sub3"), "--exclude", os.path.abspath("testfiles/select2/2/2sub1/2sub1sub2"), "--include", os.path.abspath("testfiles/select2/2/2sub1"), "--exclude", os.path.abspath("testfiles/select2/1/1sub3/1sub3sub2"), "--exclude", os.path.abspath("testfiles/select2/1/1sub3/1sub3sub1"), "--exclude", os.path.abspath("testfiles/select2/1/1sub2/1sub2sub3"), "--include", os.path.abspath("testfiles/select2/1/1sub2/1sub2sub1"), "--exclude", os.path.abspath("testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"), "--exclude", os.path.abspath("testfiles/select2/1/1sub1/1sub1sub2"), "--exclude", os.path.abspath("testfiles/select2/1/1sub2"), "--include", os.path.abspath("testfiles/select2/1.py"), "--include", os.path.abspath("testfiles/select2/3"), "--include", os.path.abspath("testfiles/select2/1"), "--exclude", os.path.abspath("testfiles/select2/**")]) self.restore() restore_dir = 'testfiles/restore_out' restored = self.directory_tree_to_list_of_lists(restore_dir) self.assertEqual(restored, self.expected_restored_tree)
if __name__ == "__main__": unittest.main()