diff options
author | Jon Bernard <jbernard@tuxion.com> | 2014-07-07 13:48:35 -0400 |
---|---|---|
committer | Jon Bernard <jbernard@tuxion.com> | 2014-07-07 13:48:35 -0400 |
commit | 5abf9f05cecc6395fe928c80cdb551daf23bd248 (patch) | |
tree | 90ff8df2e2d2cd9b8c7c13b163801823138f06d2 /tests/test_basic.py | |
parent | cb64f40c1bd63527655ba8b52355a0550194e11e (diff) | |
download | dotfiles-5abf9f05cecc6395fe928c80cdb551daf23bd248.tar.gz dotfiles-5abf9f05cecc6395fe928c80cdb551daf23bd248.tar.bz2 dotfiles-5abf9f05cecc6395fe928c80cdb551daf23bd248.zip |
Move tests into a directory
I'm hoping to add more tests for specific features and break then into
separate files so things are a bit easier to manage.
Diffstat (limited to 'tests/test_basic.py')
-rwxr-xr-x | tests/test_basic.py | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100755 index 0000000..5c48a82 --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,390 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import with_statement + +import os +import shutil +import tempfile +import unittest + +from dotfiles import core +from dotfiles import cli +from dotfiles.utils import is_link_to + + +def touch(fname, times=None): + with open(fname, 'a'): + os.utime(fname, times) + + +class DotfilesTestCase(unittest.TestCase): + + def setUp(self): + """Create a temporary home directory.""" + + self.homedir = tempfile.mkdtemp() + + # Create a repository for the tests to use. + self.repository = os.path.join(self.homedir, 'Dotfiles') + os.mkdir(self.repository) + + def tearDown(self): + """Delete the temporary home directory and its contents.""" + + shutil.rmtree(self.homedir) + + def assertPathEqual(self, path1, path2): + self.assertEqual( + os.path.realpath(path1), + os.path.realpath(path2)) + + def test_force_sync_directory(self): + """Test forced sync when the dotfile is a directory. + + I installed the lastpass chrome extension which stores a socket in + ~/.lastpass. So I added that directory as an external to /tmp and + attempted a forced sync. An error occurred because sync() calls + os.remove() as it mistakenly assumes the dotfile is a file and not + a directory. + """ + + os.mkdir(os.path.join(self.homedir, '.lastpass')) + externals = {'.lastpass': '/tmp'} + + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], externals=externals, packages=[], + dry_run=False) + + dotfiles.sync(force=True) + + self.assertPathEqual( + os.path.join(self.homedir, '.lastpass'), + '/tmp') + + def test_dispatch(self): + """Test that the force option is handed on to the sync method.""" + class MockDotfiles(object): + def sync(self, files=None, force=False): + assert bool(force) + dotfiles = MockDotfiles() + cli.dispatch(dotfiles, 'sync', True, []) + + def test_move_repository(self): + """Test the move() method for a Dotfiles repository.""" + + touch(os.path.join(self.repository, 'bashrc')) + + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], force=True, externals={}, packages=[], + dry_run=False) + + dotfiles.sync() + + # Make sure sync() did the right thing. + self.assertPathEqual( + os.path.join(self.homedir, '.bashrc'), + os.path.join(self.repository, 'bashrc')) + + target = os.path.join(self.homedir, 'MyDotfiles') + + dotfiles.move(target) + + self.assertTrue(os.path.exists(os.path.join(target, 'bashrc'))) + self.assertPathEqual( + os.path.join(self.homedir, '.bashrc'), + os.path.join(target, 'bashrc')) + + def test_force_sync_directory_symlink(self): + """Test a forced sync on a directory symlink. + + A bug was reported where a user wanted to replace a dotfile repository + with an other one. They had a .vim directory in their home directory + which was obviously also a symbolic link. This caused: + + OSError: Cannot call rmtree on a symbolic link + """ + + # Create a dotfile symlink to some directory + os.mkdir(os.path.join(self.homedir, 'vim')) + os.symlink(os.path.join(self.homedir, 'vim'), + os.path.join(self.homedir, '.vim')) + + # Create a vim directory in the repository. This will cause the above + # symlink to be overwritten on sync. + os.mkdir(os.path.join(self.repository, 'vim')) + + # Make sure the symlink points to the correct location. + self.assertPathEqual( + os.path.join(self.homedir, '.vim'), + os.path.join(self.homedir, 'vim')) + + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], externals={}, packages=[], dry_run=False) + + dotfiles.sync(force=True) + + # The symlink should now point to the directory in the repository. + self.assertPathEqual( + os.path.join(self.homedir, '.vim'), + os.path.join(self.repository, 'vim')) + + def test_glob_ignore_pattern(self): + """ Test that the use of glob pattern matching works in the ignores list. + + The following repo dir exists: + + myscript.py + myscript.pyc + myscript.pyo + bashrc + bashrc.swp + vimrc + vimrc.swp + install.sh + + Using the glob pattern dotfiles should have the following sync result in home: + + .myscript.py -> Dotfiles/myscript.py + .bashrc -> Dotfiles/bashrc + .vimrc -> Dotfiles/vimrc + + """ + ignore = ['*.swp', '*.py?', 'install.sh'] + + all_repo_files = ( + ('myscript.py', '.myscript.py'), + ('myscript.pyc', None), + ('myscript.pyo', None), + ('bashrc', '.bashrc'), + ('bashrc.swp', None), + ('vimrc', '.vimrc'), + ('vimrc.swp', None), + ('install.sh', None) + ) + + all_dotfiles = [f for f in all_repo_files if f[1] is not None] + + for original, symlink in all_repo_files: + touch(os.path.join(self.repository, original)) + + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=ignore, externals={}, packages=[], + dry_run=False) + + dotfiles.sync() + + # Now check that the files that should have a symlink + # point to the correct file and are the only files that + # exist in the home dir. + self.assertEqual( + sorted(os.listdir(self.homedir)), + sorted([f[1] for f in all_dotfiles] + ['Dotfiles'])) + + for original, symlink in all_dotfiles: + self.assertPathEqual( + os.path.join(self.repository, original), + os.path.join(self.homedir, symlink)) + + def test_packages(self): + """ + Test packages. + """ + files = ['foo', 'package/bar'] + symlinks = ['.foo', '.package/bar'] + join = os.path.join + + # Create files + for filename in files: + path = join(self.repository, filename) + dirname = os.path.dirname(path) + if not os.path.exists(dirname): + os.makedirs(dirname) + touch(path) + + # Create Dotfiles object + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], externals={}, packages=['package'], + dry_run=False) + + # Create symlinks in homedir + dotfiles.sync() + + # Verify it created what we expect + def check_all(files, symlinks): + self.assertTrue(os.path.isdir(join(self.homedir, '.package'))) + for src, dst in zip(files, symlinks): + self.assertTrue(is_link_to(join(self.homedir, dst), + join(self.repository, src))) + check_all(files, symlinks) + + # Add files to the repository + new_files = [join(self.homedir, f) for f in ['.bar', '.package/foo']] + for filename in new_files: + path = join(self.homedir, filename) + touch(path) + new_repo_files = ['bar', 'package/foo'] + dotfiles.add(new_files) + check_all(files + new_repo_files, symlinks + new_files) + + # Remove them from the repository + dotfiles.remove(new_files) + check_all(files, symlinks) + + # Move the repository + self.repository = join(self.homedir, 'Dotfiles2') + dotfiles.move(self.repository) + check_all(files, symlinks) + + def test_missing_package(self): + """ + Test a non-existent package. + """ + + package_file = '.package/bar' + + # Create Dotfiles object + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], externals={}, packages=['package'], + dry_run=False) + + path = os.path.join(self.homedir, package_file) + dirname = os.path.dirname(path) + if not os.path.exists(dirname): + os.makedirs(dirname) + touch(path) + + dotfiles.add([os.path.join(self.homedir, package_file)]) + + + def test_single_sync(self): + """ + Test syncing a single file in the repo + + The following repo dir exists: + + bashrc + netrc + vimrc + + Syncing only vimrc should have the folowing sync result in home: + + .vimrc -> Dotfiles/vimrc + + """ + + # define the repository contents + repo_files = ( + ('bashrc', False), + ('netrc', False), + ('vimrc', True)) + + # populate the repository + for dotfile, _ in repo_files: + touch(os.path.join(self.repository, dotfile)) + + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], externals={}, packages=[], + dry_run=False) + + # sync only certain dotfiles + for dotfile, should_sync in repo_files: + if should_sync: + dotfiles.sync(files=['.%s' % dotfile]) + + # verify home directory contents + for dotfile, should_sync in repo_files: + if should_sync: + self.assertPathEqual( + os.path.join(self.repository, dotfile), + os.path.join(self.homedir, '.%s' % dotfile)) + else: + self.assertFalse(os.path.exists( + os.path.join(self.homedir, dotfile))) + + + def test_missing_remove(self): + """Test removing a dotfile that's been removed from the repository.""" + + repo_file = os.path.join(self.repository, 'testdotfile') + + touch(repo_file) + + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], externals={}, packages=[], + dry_run=False) + + dotfiles.sync() + + # remove the dotfile from the repository, homedir symlink is now broken + os.remove(repo_file) + + # remove the broken symlink + dotfiles.remove(['.testdotfile']) + + # verify symlink was removed + self.assertFalse(os.path.exists( + os.path.join(self.homedir, '.testdotfile'))) + + + def test_add_package(self): + """ + Test adding a package that isn't already in the repository + + """ + + package_dir = os.path.join(self.homedir, + '.%s/%s' % ('config', 'gtk-3.0')) + + os.makedirs(package_dir) + touch('%s/testfile' % package_dir) + + dotfiles = core.Dotfiles( + homedir=self.homedir, repository=self.repository, + prefix='', ignore=[], externals={}, packages=['config'], + dry_run=False, quiet=True) + + # This should fail, you should not be able to add dotfiles that are + # defined to be packages. + dotfiles.add(['.config']) + self.assertFalse(os.path.islink(os.path.join(self.homedir, '.config'))) + + + def test_package_and_prefix(self): + """Test syncing a package when using a non-default prefix.""" + + package_dir = os.path.join(self.repository, '.config/awesome') + os.makedirs(package_dir) + touch('%s/testfile' % package_dir) + + dotfiles = core.Dotfiles(homedir=self.homedir, + repository=self.repository, + prefix='.', + ignore=[], + externals={}, + packages=['.config'], + dry_run=False, + quiet=True) + + dotfiles.sync() + + expected = os.path.join(self.homedir, ".config") + self.assertTrue(os.path.isdir(expected)) + + expected = os.path.join(expected, "awesome") + self.assertTrue(os.path.islink(expected)) + + expected = os.path.join(expected, "testfile") + self.assertTrue(os.path.isfile(expected)) + + +if __name__ == '__main__': + unittest.main() |