/integration_tests/describe_trash_list.py
Python | 301 lines | 291 code | 9 blank | 1 comment | 0 complexity | 06ddb8632a567eb13053f20f9900a430 MD5 | raw file
- # Copyright (C) 2011 Andrea Francia Trivolzio(PV) Italy
- import os
- from trashcli.trash import ListCmd
- from files import (write_file, require_empty_dir, make_sticky_dir,
- make_unsticky_dir, make_unreadable_file, make_empty_file,
- make_parent_for)
- from nose.tools import istest
- from .output_collector import OutputCollector
- from trashinfo import (
- a_trashinfo,
- a_trashinfo_without_date,
- a_trashinfo_without_path,
- a_trashinfo_with_invalid_date)
- from textwrap import dedent
- class Setup(object):
- def setUp(self):
- require_empty_dir('XDG_DATA_HOME')
- require_empty_dir('topdir')
- self.user = TrashListUser(
- environ = {'XDG_DATA_HOME': 'XDG_DATA_HOME'})
- self.home_trashcan = FakeTrashDir('XDG_DATA_HOME/Trash')
- self.add_trashinfo = self.home_trashcan.add_trashinfo
- def when_dir_is_sticky(self, path):
- make_sticky_dir(path)
- def when_dir_exists_unsticky(self, path):
- make_unsticky_dir(path)
- @istest
- class describe_trash_list(Setup):
- @istest
- def should_output_the_help_message(self):
- self.user.run('trash-list', '--help')
- self.user.should_read_output(dedent("""\
- Usage: trash-list [OPTIONS...]
- List trashed files
- Options:
- --version show program's version number and exit
- -h, --help show this help message and exit
- Report bugs to http://code.google.com/p/trash-cli/issues
- """))
- @istest
- def should_output_nothing_when_trashcan_is_empty(self):
- self.user.run_trash_list()
- self.user.should_read_output('')
- @istest
- def should_output_deletion_date_and_path(self):
- self.add_trashinfo('/aboslute/path', '2001-02-03T23:55:59')
- self.user.run_trash_list()
- self.user.should_read_output( "2001-02-03 23:55:59 /aboslute/path\n")
- @istest
- def should_output_info_for_multiple_files(self):
- self.add_trashinfo("/file1", "2000-01-01T00:00:01")
- self.add_trashinfo("/file2", "2000-01-01T00:00:02")
- self.add_trashinfo("/file3", "2000-01-01T00:00:03")
- self.user.run_trash_list()
- self.user.should_read_output( "2000-01-01 00:00:01 /file1\n"
- "2000-01-01 00:00:02 /file2\n"
- "2000-01-01 00:00:03 /file3\n")
- @istest
- def should_output_unknown_dates_with_question_marks(self):
- self.home_trashcan.having_file(a_trashinfo_without_date())
- self.user.run_trash_list()
- self.user.should_read_output("????-??-?? ??:??:?? /path\n")
- @istest
- def should_output_invalid_dates_using_question_marks(self):
- self.home_trashcan.having_file(a_trashinfo_with_invalid_date())
- self.user.run_trash_list()
- self.user.should_read_output("????-??-?? ??:??:?? /path\n")
- @istest
- def should_warn_about_empty_trashinfos(self):
- self.home_trashcan.touch('empty.trashinfo')
- self.user.run_trash_list()
- self.user.should_read_error(
- "Parse Error: XDG_DATA_HOME/Trash/info/empty.trashinfo: "
- "Unable to parse Path.\n")
- @istest
- def should_warn_about_unreadable_trashinfo(self):
- self.home_trashcan.having_unreadable('unreadable.trashinfo')
- self.user.run_trash_list()
- self.user.should_read_error(
- "[Errno 13] Permission denied: "
- "'XDG_DATA_HOME/Trash/info/unreadable.trashinfo'\n")
- @istest
- def should_warn_about_unexistent_path_entry(self):
- self.home_trashcan.having_file(a_trashinfo_without_path())
- self.user.run_trash_list()
- self.user.should_read_error(
- "Parse Error: XDG_DATA_HOME/Trash/info/1.trashinfo: "
- "Unable to parse Path.\n")
- self.user.should_read_output('')
- @istest
- class with_a_top_trash_dir(Setup):
- def setUp(self):
- super(type(self),self).setUp()
- self.top_trashdir1 = FakeTrashDir('topdir/.Trash/123')
- self.user.set_fake_uid(123)
- self.user.add_volume('topdir')
- @istest
- def should_list_its_contents_if_parent_is_sticky(self):
- self.when_dir_is_sticky('topdir/.Trash')
- self.and_contains_a_valid_trashinfo()
- self.user.run_trash_list()
- self.user.should_read_output("2000-01-01 00:00:00 topdir/file1\n")
- @istest
- def and_should_warn_if_parent_is_not_sticky(self):
- self.when_dir_exists_unsticky('topdir/.Trash')
- self.and_dir_exists('topdir/.Trash/123')
- self.user.run_trash_list()
- self.user.should_read_error("TrashDir skipped because parent not sticky: topdir/.Trash/123\n")
- @istest
- def but_it_should_not_warn_when_the_parent_is_unsticky_but_there_is_no_trashdir(self):
- self.when_dir_exists_unsticky('topdir/.Trash')
- self.but_does_not_exists_any('topdir/.Trash/123')
- self.user.run_trash_list()
- self.user.should_read_error("")
- @istest
- def should_ignore_trash_from_a_unsticky_topdir(self):
- self.when_dir_exists_unsticky('topdir/.Trash')
- self.and_contains_a_valid_trashinfo()
- self.user.run_trash_list()
- self.user.should_read_output("")
- @istest
- def it_should_ignore_Trash_is_a_symlink(self):
- self.when_is_a_symlink_to_a_dir('topdir/.Trash')
- self.and_contains_a_valid_trashinfo()
- self.user.run_trash_list()
- self.user.should_read_output('')
- @istest
- def and_should_warn_about_it(self):
- self.when_is_a_symlink_to_a_dir('topdir/.Trash')
- self.and_contains_a_valid_trashinfo()
- self.user.run_trash_list()
- self.user.should_read_error('TrashDir skipped because parent not sticky: topdir/.Trash/123\n')
- def but_does_not_exists_any(self, path):
- assert not os.path.exists(path)
- def and_dir_exists(self, path):
- os.mkdir(path)
- assert os.path.isdir(path)
- def and_contains_a_valid_trashinfo(self):
- self.top_trashdir1.add_trashinfo('file1', '2000-01-01T00:00:00')
- def when_is_a_symlink_to_a_dir(self, path):
- dest = "%s-dest" % path
- os.mkdir(dest)
- rel_dest = os.path.basename(dest)
- os.symlink(rel_dest, path)
- @istest
- class describe_when_a_file_is_in_alternate_top_trashdir(Setup):
- @istest
- def should_list_contents_of_alternate_trashdir(self):
- self.user.set_fake_uid(123)
- self.user.add_volume('topdir')
- self.top_trashdir2 = FakeTrashDir('topdir/.Trash-123')
- self.top_trashdir2.add_trashinfo('file', '2000-01-01T00:00:00')
- self.user.run_trash_list()
- self.user.should_read_output("2000-01-01 00:00:00 topdir/file\n")
- @istest
- class describe_trash_list_with_raw_option:
- def setup(self):
- self.having_XDG_DATA_HOME('XDG_DATA_HOME')
- self.running('trash-list', '--raw')
- @istest
- def output_should_contains_trashinfo_paths(self):
- from nose import SkipTest; raise SkipTest()
- self.having_trashinfo('foo.trashinfo')
- self.output_should_contain_line(
- 'XDG_DATA_HOME/Trash/info/foo.trashinfo')
- @istest
- def output_should_contains_backup_copy_paths(self):
- from nose import SkipTest; raise SkipTest()
- self.having_trashinfo('foo.trashinfo')
- self.output_should_contain_line(
- 'XDG_DATA_HOME/Trash/files/foo')
- def having_XDG_DATA_HOME(self, value):
- self.XDG_DATA_HOME = value
- def running(self, *argv):
- user = TrashListUser( environ = {'XDG_DATA_HOME': self.XDG_DATA_HOME})
- user.run(argv)
- self.output = user.output()
- def output_should_contain_line(self, line):
- assert line in self.output_lines()
- def output_lines(self):
- return [line.rstrip('\n') for line in self.output.splitlines()]
- class FakeTrashDir:
- def __init__(self, path):
- self.path = path + '/info'
- self.number = 1
- def touch(self, path_relative_to_info_dir):
- make_empty_file(self.join(path_relative_to_info_dir))
- def having_unreadable(self, path_relative_to_info_dir):
- path = self.join(path_relative_to_info_dir)
- make_unreadable_file(path)
- def join(self, path_relative_to_info_dir):
- import os
- return os.path.join(self.path, path_relative_to_info_dir)
- def having_file(self, contents):
- path = '%(info_dir)s/%(name)s.trashinfo' % { 'info_dir' : self.path,
- 'name' : str(self.number)}
- make_parent_for(path)
- write_file(path, contents)
- self.number += 1
- self.path_of_last_file_added = path
- def add_trashinfo(self, escaped_path_entry, formatted_deletion_date):
- self.having_file(a_trashinfo(escaped_path_entry, formatted_deletion_date))
- class TrashListUser:
- def __init__(self, environ={}):
- self.stdout = OutputCollector()
- self.stderr = OutputCollector()
- self.environ = environ
- self.fake_getuid = self.error
- self.volumes = []
- def run_trash_list(self):
- self.run('trash-list')
- def run(self,*argv):
- from trashcli.trash import FileSystemReader
- file_reader = FileSystemReader()
- file_reader.list_volumes = lambda: self.volumes
- ListCmd(
- out = self.stdout,
- err = self.stderr,
- environ = self.environ,
- getuid = self.fake_getuid,
- file_reader = file_reader,
- list_volumes = lambda: self.volumes,
- ).run(*argv)
- def set_fake_uid(self, uid):
- self.fake_getuid = lambda: uid
- def add_volume(self, mount_point):
- self.volumes.append(mount_point)
- def error(self):
- raise ValueError()
- def should_read_output(self, expected_value):
- self.stdout.assert_equal_to(expected_value)
- def should_read_error(self, expected_value):
- self.stderr.assert_equal_to(expected_value)
- def output(self):
- return self.stdout.getvalue()