diff options
Diffstat (limited to 'bzrlib/tests/blackbox/test_filesystem_cicp.py')
-rw-r--r-- | bzrlib/tests/blackbox/test_filesystem_cicp.py | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/bzrlib/tests/blackbox/test_filesystem_cicp.py b/bzrlib/tests/blackbox/test_filesystem_cicp.py new file mode 100644 index 0000000..3956692 --- /dev/null +++ b/bzrlib/tests/blackbox/test_filesystem_cicp.py @@ -0,0 +1,282 @@ +# Copyright (C) 2008, 2009, 2010 Canonical Ltd +# +# This program 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + +"""Tests variations of case-insensitive and case-preserving file-systems.""" + +import os + +from bzrlib import ( + osutils, + tests, + ) +from bzrlib.tests import KnownFailure +from bzrlib.osutils import canonical_relpath, pathjoin +from bzrlib.tests.script import run_script +from bzrlib.tests.features import ( + CaseInsCasePresFilenameFeature, + ) + + + +class TestCICPBase(tests.TestCaseWithTransport): + """Base class for tests on a case-insensitive, case-preserving filesystem. + """ + + _test_needs_features = [CaseInsCasePresFilenameFeature] + + def _make_mixed_case_tree(self): + """Make a working tree with mixed-case filenames.""" + wt = self.make_branch_and_tree('.') + # create a file on disk with the mixed-case parent and base name + self.build_tree(['CamelCaseParent/', 'lowercaseparent/']) + self.build_tree_contents([('CamelCaseParent/CamelCase', 'camel case'), + ('lowercaseparent/lowercase', 'lower case'), + ('lowercaseparent/mixedCase', 'mixedCasecase'), + ]) + return wt + + +class TestAdd(TestCICPBase): + + def test_add_simple(self): + """Test add always uses the case of the filename reported by the os.""" + wt = self.make_branch_and_tree('.') + # create a file on disk with the mixed-case name + self.build_tree(['CamelCase']) + run_script(self, """ + $ bzr add camelcase + adding CamelCase + """) + + def test_add_subdir(self): + """test_add_simple but with subdirectories tested too.""" + wt = self.make_branch_and_tree('.') + # create a file on disk with the mixed-case parent and base name + self.build_tree(['CamelCaseParent/', 'CamelCaseParent/CamelCase']) + run_script(self, """ + $ bzr add camelcaseparent/camelcase + adding CamelCaseParent + adding CamelCaseParent/CamelCase + """) + + def test_add_implied(self): + """test add with no args sees the correct names.""" + wt = self.make_branch_and_tree('.') + # create a file on disk with the mixed-case parent and base name + self.build_tree(['CamelCaseParent/', 'CamelCaseParent/CamelCase']) + run_script(self, """ + $ bzr add + adding CamelCaseParent + adding CamelCaseParent/CamelCase + """) + + def test_re_add(self): + """Test than when a file has 'unintentionally' changed case, we can't + add a new entry using the new case.""" + wt = self.make_branch_and_tree('.') + # create a file on disk with the mixed-case name + self.build_tree(['MixedCase']) + run_script(self, """ + $ bzr add MixedCase + adding MixedCase + """) + # 'accidently' rename the file on disk + osutils.rename('MixedCase', 'mixedcase') + run_script(self, """ + $ bzr add mixedcase + """) + + def test_re_add_dir(self): + # like re-add, but tests when the operation is on a directory. + """Test than when a file has 'unintentionally' changed case, we can't + add a new entry using the new case.""" + wt = self.make_branch_and_tree('.') + # create a file on disk with the mixed-case name + self.build_tree(['MixedCaseParent/', 'MixedCaseParent/MixedCase']) + run_script(self, """ + $ bzr add MixedCaseParent + adding MixedCaseParent + adding MixedCaseParent/MixedCase + """) + # 'accidently' rename the directory on disk + osutils.rename('MixedCaseParent', 'mixedcaseparent') + run_script(self, """ + $ bzr add mixedcaseparent + """) + + def test_add_not_found(self): + """Test add when the input file doesn't exist.""" + wt = self.make_branch_and_tree('.') + # create a file on disk with the mixed-case name + self.build_tree(['MixedCaseParent/', 'MixedCaseParent/MixedCase']) + expected_fname = pathjoin(wt.basedir, "MixedCaseParent", "notfound") + run_script(self, """ + $ bzr add mixedcaseparent/notfound + 2>bzr: ERROR: No such file: %s + """ % (repr(expected_fname),)) + + +class TestMove(TestCICPBase): + + def test_mv_newname(self): + wt = self._make_mixed_case_tree() + run_script(self, """ + $ bzr add -q + $ bzr ci -qm message + $ bzr mv camelcaseparent/camelcase camelcaseparent/NewCamelCase + CamelCaseParent/CamelCase => CamelCaseParent/NewCamelCase + """) + + def test_mv_newname_after(self): + wt = self._make_mixed_case_tree() + # In this case we can specify the incorrect case for the destination, + # as we use --after, so the file-system is sniffed. + run_script(self, """ + $ bzr add -q + $ bzr ci -qm message + $ mv CamelCaseParent/CamelCase CamelCaseParent/NewCamelCase + $ bzr mv --after camelcaseparent/camelcase camelcaseparent/newcamelcase + CamelCaseParent/CamelCase => CamelCaseParent/NewCamelCase + """) + + def test_mv_newname_exists(self): + # test a mv, but when the target already exists with a name that + # differs only by case. + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + run_script(self, """ + $ bzr mv camelcaseparent/camelcase LOWERCASEPARENT/LOWERCASE + 2>bzr: ERROR: Could not move CamelCase => lowercase: \ +lowercaseparent/lowercase is already versioned. + """) + + def test_mv_newname_exists_after(self): + # test a 'mv --after', but when the target already exists with a name + # that differs only by case. Note that this is somewhat unlikely + # but still reasonable. + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + # Remove the source and create a destination file on disk with a different case. + # bzr should report that the filename is already versioned. + os.unlink('CamelCaseParent/CamelCase') + osutils.rename('lowercaseparent/lowercase', 'lowercaseparent/LOWERCASE') + run_script(self, """ + $ bzr mv --after camelcaseparent/camelcase LOWERCASEPARENT/LOWERCASE + 2>bzr: ERROR: Could not move CamelCase => lowercase: \ +lowercaseparent/lowercase is already versioned. + """) + + def test_mv_newname_root(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + run_script(self, """ + $ bzr mv camelcaseparent NewCamelCaseParent + CamelCaseParent => NewCamelCaseParent + """) + + def test_mv_newname_root_after(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + # In this case we can specify the incorrect case for the destination, + # as we use --after, so the file-system is sniffed. + run_script(self, """ + $ mv CamelCaseParent NewCamelCaseParent + $ bzr mv --after camelcaseparent NewCamelCaseParent + CamelCaseParent => NewCamelCaseParent + """) + + def test_mv_newcase(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + + # perform a mv to the new case - we expect bzr to accept the new + # name, as specified, and rename the file on the file-system too. + run_script(self, """ + $ bzr mv camelcaseparent/camelcase camelcaseparent/camelCase + CamelCaseParent/CamelCase => CamelCaseParent/camelCase + """) + self.failUnlessEqual(canonical_relpath(wt.basedir, 'camelcaseparent/camelcase'), + 'CamelCaseParent/camelCase') + + def test_mv_newcase_after(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + + # perform a mv to the new case - we must ensure the file-system has the + # new case first. + osutils.rename('CamelCaseParent/CamelCase', 'CamelCaseParent/camelCase') + run_script(self, """ + $ bzr mv --after camelcaseparent/camelcase camelcaseparent/camelCase + CamelCaseParent/CamelCase => CamelCaseParent/camelCase + """) + # bzr should not have renamed the file to a different case + self.failUnlessEqual(canonical_relpath(wt.basedir, 'camelcaseparent/camelcase'), + 'CamelCaseParent/camelCase') + + def test_mv_multiple(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + run_script(self, """ + $ bzr mv LOWercaseparent/LOWercase LOWercaseparent/MIXEDCase camelcaseparent + lowercaseparent/lowercase => CamelCaseParent/lowercase + lowercaseparent/mixedCase => CamelCaseParent/mixedCase + """) + + +class TestMisc(TestCICPBase): + + def test_status(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + run_script(self, """ + $ bzr status camelcaseparent/camelcase LOWERCASEPARENT/LOWERCASE + added: + CamelCaseParent/ + CamelCaseParent/CamelCase + lowercaseparent/ + lowercaseparent/lowercase + """) + + def test_ci(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + + got = self.run_bzr('ci -m message camelcaseparent LOWERCASEPARENT')[1] + for expected in ['CamelCaseParent', 'lowercaseparent', + 'CamelCaseParent/CamelCase', 'lowercaseparent/lowercase']: + self.assertContainsRe(got, 'added ' + expected + '\n') + + def test_rm(self): + wt = self._make_mixed_case_tree() + self.run_bzr('add') + self.run_bzr('ci -m message') + + got = self.run_bzr('rm camelcaseparent LOWERCASEPARENT')[1] + for expected in ['lowercaseparent/lowercase', 'CamelCaseParent/CamelCase']: + self.assertContainsRe(got, 'deleted ' + expected + '\n') + + + # The following commands need tests and/or cicp lovin': + # update, remove, file_id, file_path, diff, log, touching_revisions, ls, + # ignore, cat, revert, resolve. |