def _test_encoding(self, fn): """Test encoding""" fullpath = self.write_file(fn) # Add Unicode paths to encourage a crash. subdir = os.path.join(self.tempdir, 'ɡælɪk.dir') os.mkdir(subdir) subfile = os.path.join(subdir, 'ɡælɪk.file') common.touch_file(subfile) searches = {self.tempdir: []} searches[self.tempdir].append( Search(command='delete', regex='\.[Bb][Aa][Kk]$')) ds = DeepScan(searches) found = False for cmd in ds.scan(): if cmd == True: # True is used to yield to GTK+, but it is not # needed in this test. continue self.assertExists(cmd.path) if cmd.path == fullpath: found = True self.assertTrue(found, "Did not find '%s'" % fullpath) os.unlink(fullpath) self.assertNotExists(fullpath) import shutil shutil.rmtree(subdir)
def test_type(self): """Unit test for type attribute""" dirname = self.mkdtemp(prefix='bleachbit-action-type') filename = os.path.join(dirname, 'file') # this should not delete anything common.touch_file(filename) action_str = u'<action command="delete" search="file" type="d" path="%s" />' % filename self._test_action_str(action_str) self.assertExists(filename) # should delete file action_str = u'<action command="delete" search="file" type="f" path="%s" />' % filename self._test_action_str(action_str) self.assertNotExists(filename) # should delete file common.touch_file(filename) action_str = u'<action command="delete" search="file" path="%s" />' % filename self._test_action_str(action_str) self.assertNotExists(filename) # should not delete anything action_str = u'<action command="delete" search="file" type="f" path="%s" />' % dirname self._test_action_str(action_str) self.assertExists(dirname) # should delete directory action_str = u'<action command="delete" search="file" type="d" path="%s" />' % dirname self._test_action_str(action_str) self.assertNotExists(dirname)
def _test_encoding(self, fn): """Test encoding""" fullpath = self.write_file(fn) # Add Unicode paths to encourage a crash. subdir = os.path.join(self.tempdir, u'ɡælɪk.dir') os.mkdir(subdir) subfile = os.path.join(subdir, u'ɡælɪk.file') common.touch_file(subfile) ds = DeepScan() for use_unicode in (False, True): if use_unicode: search_dir = unicode(self.tempdir) else: search_dir = self.tempdir self.assertIsInstance(search_dir, str) ds.add_search(search_dir, '\.[Bb][Aa][Kk]$') found = False for ret in ds.scan(): if ret == True: # True is used to yield to GTK+, but it is not # needed in this test. continue self.assertExists(ret) if ret == fullpath: found = True self.assertTrue(found, u"Did not find '%s'" % fullpath) os.unlink(fullpath) self.assertNotExists(fullpath) import shutil shutil.rmtree(subdir)
def test_link(self): """Unit test for links with is_link() and get_recycle_bin()""" if not common.destructive_tests('windows link'): return # make a normal directory with a file in it real_dir = os.path.join(self.tempdir, 'real_dir') os.mkdir(real_dir) self.assertExists(real_dir) self.assertEqual(False, is_link(real_dir)) canary_fn = os.path.join(real_dir, 'do_not_delete') common.touch_file(canary_fn) self.assertExists(canary_fn) self.assertEqual(False, is_link(canary_fn)) # link to the normal directory link_dir = os.path.join(self.tempdir, 'link_dir') args = ('cmd', '/c', 'mklink', '/d', link_dir, real_dir) from bleachbit.General import run_external (rc, stdout, stderr) = run_external(args) self.assertEqual(rc, 0, stderr) self.assertExists(link_dir) self.assertEqual(True, is_link(link_dir)) # put the link in the recycle bin move_to_recycle_bin(link_dir) # clear the recycle bin for f in get_recycle_bin(): FileUtilities.delete(f, shred=False) # verify the canary is still there self.assertExists(canary_fn)
def test_walk_all_top(self): """Unit test for walk.all and walk.top""" variants = ('all', 'top') for variant in variants: dirname = self.mkdtemp(prefix='bleachbit-walk-%s' % variant) # this sub-directory should be deleted subdir = os.path.join(dirname, 'sub') os.mkdir(subdir) self.assertExists(subdir) # this file should be deleted too filename = os.path.join(subdir, 'file') common.touch_file(filename) action_str = '<action command="delete" search="walk.%s" path="%s" />' % ( variant, dirname) self._test_action_str(action_str) self.assertNotExists(subdir) if variant == 'all': self.assertExists(dirname) os.rmdir(dirname) elif variant == 'top': self.assertNotExists(dirname) # If the path does not exist, it should be silently ignored. # The top directory no long exists, so just replay it. self._test_action_str(action_str, False)
def benchmark_filter(this_filter): """Measure how fast listing files is with and without filter""" n_files = 100000 print('benchmark of %d files' % n_files) # make a directory with many files dirname = tempfile.mkdtemp(prefix='bleachbit-action-bench') for x in range(0, n_files): common.touch_file(os.path.join(dirname, str(x))) # scan directory import time start = time.time() filter_code = '' if 'regex' == this_filter: # This regex matches everything, so the "no filter" and regex # are comparable filter_code = 'regex="."' action_str = u'<action command="delete" search="glob" path="%s/*" %s />' % \ (dirname, filter_code) results = _action_str_to_results(action_str) end = time.time() elapsed_seconds = end - start rate = n_files / elapsed_seconds print('filter %s: elapsed: %.2f seconds, %.2f files/second' % (this_filter, elapsed_seconds, rate)) # clean up shutil.rmtree(dirname) return rate
def _test_link_helper(self, mklink_option, clear_recycle_bin): """Helper function for testing for links with is_link() and get_recycle_bin() It gets called four times for the combinations of the two parameters. It's called by four unit tests four accounting purposes. In other words, we don't want to count a test as skipped if part of it succeeded. mklink /j = directory junction directory junction does not require administrator privileges mklink /d=directory symbolic link requires administrator privileges """ if mklink_option == '/d': self.skipUnlessAdmin() # make a normal directory with a file in it real_dir = os.path.join(self.tempdir, 'real_dir') os.mkdir(real_dir) self.assertExists(real_dir) self.assertEqual(False, is_link(real_dir)) canary_fn = os.path.join(real_dir, 'do_not_delete') common.touch_file(canary_fn) self.assertExists(canary_fn) self.assertEqual(False, is_link(canary_fn)) # link to the normal directory link_dir = os.path.join(self.tempdir, 'link_dir') args = ('cmd', '/c', 'mklink', mklink_option, link_dir, real_dir) from bleachbit.General import run_external (rc, stdout, stderr) = run_external(args) self.assertEqual(rc, 0, stderr) self.assertExists(link_dir) self.assertEqual(True, is_link(link_dir)) if not clear_recycle_bin: os.rmdir(link_dir) self.assertNotExists(link_dir) shutil.rmtree(real_dir, True) if not common.destructive_tests('windows link'): self.skipTest('destructive tests are disabled') return # put the link in the recycle bin move_to_recycle_bin(link_dir) # clear the recycle bin for f in get_recycle_bin(): FileUtilities.delete(f, shred=False) # verify the canary is still there self.assertExists(canary_fn) # clean up shutil.rmtree(real_dir, True)
def test_delete_read_only(self): """Unit test for delete() with read-only file""" for shred in (False, True): fn = os.path.join(self.tempdir, 'read-only') common.touch_file(fn) import stat os.chmod(fn, stat.S_IREAD) self.assertExists(fn) delete(fn, shred=shred) self.assertNotExists(fn)
def test_delete_not_empty(self): """Test for scenario directory is not empty""" print('hello') fn = os.path.join(self.tempdir, 'make-directory-not-empty') common.touch_file(fn) self.assertExists(fn) self.assertExists(self.tempdir) delete(self.tempdir, allow_shred=False) self.assertExists(fn) self.assertExists(self.tempdir)
def test_delete_hidden(self): """Unit test for delete() with hidden file""" for shred in (False, True): fn = os.path.join(self.tempdir, 'hidden') common.touch_file(fn) import win32api import win32con win32api.SetFileAttributes(fn, win32con.FILE_ATTRIBUTE_HIDDEN) self.assertExists(fn) delete(fn, shred=shred) self.assertNotExists(fn)
def put_files_into_recycle_bin(): """Put a file and a folder into the recycle bin""" # make a file and move it to the recycle bin tests = ('regular', 'unicode-emdash-u\u2014', 'long' + 'x' * 100) for test in tests: (fd, filename) = tempfile.mkstemp( prefix='bleachbit-recycle-file', suffix=test) os.close(fd) move_to_recycle_bin(filename) # make a folder and move it to the recycle bin dirname = tempfile.mkdtemp(prefix='bleachbit-recycle-folder') common.touch_file(os.path.join(dirname, 'file')) move_to_recycle_bin(dirname)
def put_files_into_recycle_bin(): """Put a file and a folder into the recycle bin""" # make a file and move it to the recycle bin tests = ('regular', u'unicode-emdash-u\u2014', 'long' + 'x' * 100) for test in tests: (fd, filename) = tempfile.mkstemp( prefix='bleachbit-recycle-file', suffix=test) os.close(fd) move_to_recycle_bin(filename) # make a folder and move it to the recycle bin dirname = tempfile.mkdtemp(prefix='bleachbit-recycle-folder') common.touch_file(os.path.join(dirname, 'file')) move_to_recycle_bin(dirname)
def test_var(self): """Test the <var> element""" xml_str = r""" <cleaner id="testvar"> <label>cleaner label</label> <description>cleaner description</description> <var name="basepath"> <value>%%LocalAppData%%\FooDoesNotExist</value> <value>~/.config/FooDoesNotExist</value> <value>{tempdir}/a</value> <value>{tempdir}/b</value> </var> <option id="option1"> <label>option1 label</label> <description>option1 description</description> <action search="file" command="delete" path="$$basepath$$/test.log" /> </option> </cleaner> """.format(**{'tempdir': self.tempdir}) # write XML cleaner cml_path = os.path.join(self.tempdir, 'test.xml') self.write_file(cml_path, xml_str) # create two canaries test_log_path_a = os.path.join(self.tempdir, 'a', 'test.log') test_log_path_b = os.path.join(self.tempdir, 'b', 'test.log') common.touch_file(test_log_path_a) common.touch_file(test_log_path_b) self.assertExists(test_log_path_a) self.assertExists(test_log_path_b) # parse XML to XML cleaner instance xmlc = CleanerML(cml_path) self.assertIsInstance(xmlc, CleanerML) self.assertIsInstance(xmlc.cleaner, Cleaner.Cleaner) self.assertTrue(xmlc.cleaner.is_usable()) # run preview self.run_all(xmlc, False) self.assertExists(test_log_path_a) self.assertExists(test_log_path_b) # really delete self.run_all(xmlc, True) self.assertNotExists(test_log_path_a) self.assertNotExists(test_log_path_b)
def test_walk_all(self): """Unit test for walk.all""" dirname = self.mkdtemp(prefix='bleachbit-walk-all') # this sub-directory should be deleted subdir = os.path.join(dirname, 'sub') os.mkdir(subdir) self.assertExists(subdir) # this file should be deleted too filename = os.path.join(subdir, 'file') common.touch_file(filename) action_str = u'<action command="delete" search="walk.all" path="%s" />' % dirname self._test_action_str(action_str) self.assertNotExists(subdir) os.rmdir(dirname)
def test_delete_not_empty(self): """Test for scenario directory is not empty""" dirname = os.path.join(self.tempdir, 'a_dir') os.mkdir(dirname) self.assertTrue(is_dir_empty(dirname)) fn = os.path.join(dirname, 'a_file') common.touch_file(fn) self.assertFalse(is_dir_empty(dirname)) self.assertExists(fn) self.assertExists(dirname) self.assertExists(self.tempdir) # Make sure shredding does not leave a renamed directory like # in https://github.com/bleachbit/bleachbit/issues/783 for allow_shred in (False, True): delete(dirname, allow_shred=allow_shred) self.assertExists(fn) self.assertExists(dirname)
def test_create_simple_cleaner(self): """Unit test for method create_simple_cleaner""" dirname = self.mkdtemp(prefix='bleachbit-test-create-simple-cleaner') filename1 = os.path.join(dirname, '1') common.touch_file(filename1) # test Cyrillic for https://bugs.launchpad.net/bleachbit/+bug/1541808 filename2 = os.path.join(dirname, u'чистый') common.touch_file(filename2) targets = [filename1, filename2, dirname] cleaner = create_simple_cleaner(targets) for cmd in cleaner.get_commands('files'): # preview for result in cmd.execute(False): common.validate_result(self, result) # delete list(cmd.execute(True)) for target in targets: self.assertNotExists(target)
def test_create_simple_cleaner(self): """Unit test for method create_simple_cleaner""" dirname = self.mkdtemp(prefix='bleachbit-test-create-simple-cleaner') filename1 = os.path.join(dirname, '1') common.touch_file(filename1) # test Cyrillic for https://bugs.launchpad.net/bleachbit/+bug/1541808 filename2 = os.path.join(dirname, 'чистый') common.touch_file(filename2) targets = [filename1, filename2, dirname] cleaner = create_simple_cleaner(targets) for cmd in cleaner.get_commands('files'): # preview for result in cmd.execute(False): common.validate_result(self, result) # delete list(cmd.execute(True)) for target in targets: self.assertNotExists(target)
def test_whitelist(self): tests = [ ('/tmp/.truecrypt_aux_mnt1/control', True), ('/tmp/.truecrypt_aux_mnt1/volume', True), ('/tmp/.vbox-foo-ipc/lock', True), ('/tmp/.wine-500/server-806-102400f/lock', True), ('/tmp/gconfd-foo/lock/ior', True), ('/tmp/ksocket-foo/Arts_SoundServerV2', True), ('/tmp/ksocket-foo/secret-cookie', True), ('/tmp/orbit-foo/bonobo-activation-server-ior', True), ('/tmp/orbit-foo/bonobo-activation-register.lock', True), ('/tmp/orbit-foo/bonobo-activation-server-a9cd6cc4973af098918b154c4957a93f-ior', True), ('/tmp/orbit-foo/bonobo-activation-register-a9cd6cc4973af098918b154c4957a93f.lock', True), ('/tmp/pulse-foo/pid', True), ('/tmp/tmpsDOBFd', False), (os.path.expanduser('~/.cache/obexd'), True), (os.path.expanduser('~/.cache/obexd/'), True), (os.path.expanduser('~/.cache/obexd/foo'), True), (os.path.expanduser('~/.cache/obex'), False), (os.path.expanduser('~/.cache/obexd-foo'), False) ] list(register_cleaners()) for test in tests: self.assertEqual( backends['system'].whitelisted(test[0]), test[1], test[0]) # Make sure directory ~/.cache/obexd is ignored # https://github.com/bleachbit/bleachbit/issues/572 obexd_dir = os.path.expanduser('~/.cache/obexd') if not os.path.exists(obexd_dir): os.makedirs(obexd_dir) obexd_fn = os.path.join(obexd_dir, 'bleachbit-test') common.touch_file(obexd_fn) found_canary = False for cmd in backends['system'].get_commands('cache'): for _result in cmd.execute(really_delete=False): self.assertNotEqual(cmd.path, obexd_fn) self.assertFalse('/.cache/obexd/' in cmd.path) from bleachbit.FileUtilities import delete delete(obexd_fn, ignore_missing=True)
def test_touch_file(self): """Unit test for touch_file""" fn = os.path.join(self.tempdir, 'test_touch_file') self.assertNotExists(fn) # Create empty file. common.touch_file(fn) from bleachbit.FileUtilities import getsize self.assertExists(fn) self.assertEqual(0, getsize(fn)) # Increase size of file. fsize = 2**13 with open(fn, "w") as f: f.write(' '*fsize) self.assertEqual(fsize, getsize(fn)) # Do not truncate. common.touch_file(fn) self.assertExists(fn) self.assertEqual(fsize, getsize(fn))
def test_many_patterns(self): """Test a cleaner like Steam Installers and related performance improvement https://github.com/bleachbit/bleachbit/issues/325 """ # set up environment file_count = 1000 dir_count = 10 print('Making %d files in each of %d directories.' % (file_count, dir_count)) tmp_dir = tempfile.mkdtemp() for i_d in range(1, dir_count + 1): sub_dir = os.path.join(tmp_dir, 'dir%d' % i_d) for i_f in range(1, file_count + 1): tmp_fn = os.path.join(sub_dir, 'file%d' % i_f) common.touch_file(tmp_fn) (ini_h, self.ini_fn) = tempfile.mkstemp(suffix='.ini', prefix='winapp2') os.close(ini_h) import string searches = ';'.join( ['*.%s' % letter for letter in string.ascii_letters[0:26]]) cleaner = self.ini2cleaner('FileKey1=%s|%s|RECURSE' % (tmp_dir, searches)) # preview import time t0 = time.time() self.run_all(cleaner, False) t1 = time.time() print('Elapsed time in preview: %.4f seconds ' % (t1 - t0)) # delete self.run_all(cleaner, False) # clean up shutil.rmtree(tmp_dir)
def _test_link_helper(self, mklink_option, clear_recycle_bin): """Helper function for testing for links with is_junction() and get_recycle_bin() It gets called four times for the combinations of the two parameters. It's called by four unit tests for accounting purposes. In other words, we don't want to count a test as skipped if part of it succeeded. mklink /j = directory junction directory junction does not require administrator privileges mklink /d=directory symbolic link requires administrator privileges """ if mklink_option == '/d': self.skipUnlessAdmin() # make a normal directory with a file in it target_dir = os.path.join(self.tempdir, 'target_dir') os.mkdir(target_dir) self.assertExists(target_dir) self.assertFalse(is_junction(target_dir)) from random import randint canary_fn = os.path.join(target_dir, 'do_not_delete%d' % randint(1000, 9999)) common.touch_file(canary_fn) self.assertExists(canary_fn) self.assertFalse(is_junction(canary_fn)) # make a normal directory to hold a link container_dir = os.path.join(self.tempdir, 'container_dir') os.mkdir(container_dir) self.assertExists(container_dir) self.assertFalse(is_junction(container_dir)) # create the link link_pathname = os.path.join(container_dir, 'link') args = ('cmd', '/c', 'mklink', mklink_option, link_pathname, target_dir) from bleachbit.General import run_external (rc, stdout, stderr) = run_external(args) self.assertEqual(rc, 0, stderr) self.assertExists(link_pathname) self.assertTrue(is_junction(link_pathname)) # put the link in the recycle bin move_to_recycle_bin(container_dir) def cleanup_dirs(): shutil.rmtree(container_dir, True) self.assertNotExists(container_dir) shutil.rmtree(target_dir, True) if not clear_recycle_bin: cleanup_dirs() return # clear the recycle bin for f in get_recycle_bin(): FileUtilities.delete(f, shred=False) # verify the canary is still there self.assertExists(canary_fn) # clean up cleanup_dirs()
def test_removeself(self): """Test for the removeself option""" # indexes for test # position 0: FileKey statement # position 1: whether the file `dir_c\subdir\foo.log` should exist after operation is complete # position 2: path of top-folder which should have been deleted tests = ( # Refer to directory directly (i.e., without a glob). (r'FileKey1=%s\dir_c|*.*|REMOVESELF' % self.tempdir, False, r'%s\dir_c' % self.tempdir), # Refer to file that exists. This is invalid, so nothing happens. (r'FileKey1=%s\dir_c\submarine_sandwich.log|*.*|REMOVESELF' % self.tempdir, True, ''), (r'FileKey1=%s\dir_c\submarine*|*.*|REMOVESELF' % self.tempdir, True, ''), # Refer to path that does not exist, so nothing happens. (r'FileKey1=%s\dir_c\doesnotexist.log|*.*|REMOVESELF' % self.tempdir, True, ''), # Refer by glob to both a file and directory (which both start with `sub`). # This should affect only the directory. (r'FileKey1=%s\dir_a\sub*|*.*|REMOVESELF' % self.tempdir, True, r'%s\dir_a\subdir' % self.tempdir), # glob in middle of directory path with whole directory entry (r'FileKey1=%s\*c\subdir|*.*|REMOVESELF' % self.tempdir, False, r'%s\dir_c\subdir' % self.tempdir), (r'FileKey1=%s\*doesnotexist\subdir|*.*|REMOVESELF' % self.tempdir, True, ''), # glob at end of path (r'FileKey1=%s\dir_c\sub*|*.*|REMOVESELF' % self.tempdir, False, r'%s\dir_c\subdir' % self.tempdir), (r'FileKey1=%s\dir_c\doesnotexist*|*.*|REMOVESELF' % self.tempdir, True, '')) (ini_h, self.ini_fn) = tempfile.mkstemp(suffix='.ini', prefix='winapp2') os.close(ini_h) for filekey, c_log_expected, top_log_expected in tests: for letter in ('a', 'b', 'c'): # Make three directories, each with a `foo.log` file. fn = os.path.join(self.tempdir, 'dir_' + letter, 'subdir', 'foo.log') common.touch_file(fn) # In dir_a, place a file one level up from `foo.log`. # Notice the glob `dir_a\sub*` will match both a directory and file. fn2 = os.path.join(self.tempdir, 'dir_a', 'submarine_sandwich.log') common.touch_file(fn2) cleaner = self.ini2cleaner(filekey) self.assertExists(fn, filekey) self.assertExists(fn2, filekey) if top_log_expected: self.assertExists(top_log_expected, filekey) self.run_all(cleaner, True) if c_log_expected: self.assertExists(fn, filekey) else: self.assertNotExists(fn, filekey) if top_log_expected != '': self.assertNotExists(top_log_expected, filekey) self.assertExists(fn2, filekey) if top_log_expected: self.assertNotExists(top_log_expected, filekey)