def test_check_remote_command_fail(self): cmds = [] if tools.checkCommand('nice'): cmds.append('nice') self.cfg.setNiceOnRemote(True) if tools.checkCommand('ionice'): cmds.append('ionice') self.cfg.setIoniceOnRemote(True) if tools.checkCommand('nocache'): cmds.append('nocache') self.cfg.setNocacheOnRemote(True) if tools.checkCommand('screen') and tools.checkCommand('flock'): cmds.extend(('screen', 'flock', 'rmdir', 'mktemp')) self.cfg.setSmartRemoveRunRemoteInBackground(True) # make one after an other command from 'cmds' fail by symlink them # to /bin/false false = tools.which('false') for cmd in cmds: msg = 'current trap: %s' %cmd with self.subTest(cmd = cmd): with TemporaryDirectory() as self.remotePath: self.cfg.setSshSnapshotsPath(self.remotePath) os.symlink(false, os.path.join(self.remotePath, cmd)) self.cfg.setSshPrefix(True, "export PATH=%s:$PATH; " %self.remotePath) ssh = sshtools.SSH(cfg = self.cfg) with self.assertRaisesRegex(MountException, r"Remote host .+ doesn't support '.*?%s.*'" %cmd, msg = msg): ssh.checkRemoteCommands()
def test_checkCommand(self): """ Test the function checkCommand """ self.assertFalse(tools.checkCommand('')) self.assertFalse(tools.checkCommand("notExistedCommand")) self.assertTrue(tools.checkCommand("ls")) self.assertTrue(tools.checkCommand('backintime'))
def test_check_remote_command(self): self.cfg.setNiceOnRemote(tools.checkCommand('nice')) self.cfg.setIoniceOnRemote(tools.checkCommand('ionice')) self.cfg.setNocacheOnRemote(tools.checkCommand('nocache')) self.cfg.setSmartRemoveRunRemoteInBackground(tools.checkCommand('screen') and tools.checkCommand('flock')) os.mkdir(self.remotePath) ssh = sshtools.SSH(cfg = self.cfg) ssh.checkRemoteCommands()
def test_check_remote_command_with_spaces(self): self.cfg.setSmartRemoveRunRemoteInBackground( tools.checkCommand('screen') and tools.checkCommand('flock')) self.remotePath = os.path.join(self.tmpDir.name, 'foo bar') self.cfg.setSshSnapshotsPath(self.remotePath) os.mkdir(self.remotePath) ssh = sshtools.SSH(cfg=self.cfg) ssh.checkRemoteCommands()
def checkFuse(self): """ Check if command in self.mountproc is installed and user is part of group ``fuse``. Raises: exceptions.MountException: if either command is not available or user is not in group fuse """ logger.debug('Check fuse', self) if not tools.checkCommand(self.mountproc): logger.debug('%s is missing' %self.mountproc, self) raise MountException(_('%(proc)s not found. Please install e.g. %(install_command)s') %{'proc': self.mountproc, 'install_command': "'apt-get install %s'" %self.mountproc}) if self.CHECK_FUSE_GROUP: user = self.config.user() try: fuse_grp_members = grp.getgrnam('fuse')[3] except KeyError: #group fuse doesn't exist. So most likely it isn't used by this distribution logger.debug("Group fuse doesn't exist. Skip test", self) return if not user in fuse_grp_members: logger.debug('User %s is not in group fuse' %user, self) raise MountException(_('%(user)s is not member of group \'fuse\'.\n ' 'Run \'sudo adduser %(user)s fuse\'. To apply ' 'changes logout and login again.\nLook at ' '\'man backintime\' for further instructions.') % {'user': user})
def btnDiffClicked(self): sid1 = self.timeLine.currentSnapshotID() sid2 = self.comboDiff.currentSnapshotID() if not sid1 or not sid2: return path1 = sid1.pathBackup(self.path) path2 = sid2.pathBackup(self.path) #check if the 2 paths are different if path1 == path2: messagebox.critical(self, _('You can\'t compare a snapshot to itself')) return diffCmd = self.config.strValue('qt.diff.cmd', DIFF_CMD) diffParams = self.config.strValue('qt.diff.params', DIFF_PARAMS) if not tools.checkCommand(diffCmd): messagebox.critical(self, _('Command not found: %s') % diffCmd) return # prevent backup data from being accidentally overwritten # by create a temporary local copy and only open that one if not isinstance(sid1, snapshots.RootSnapshot): path1 = self.parent.tmpCopy(path1, sid1) if not isinstance(sid2, snapshots.RootSnapshot): path2 = self.parent.tmpCopy(path2, sid2) params = diffParams params = params.replace('%1', '"%s"' %path1) params = params.replace('%2', '"%s"' %path2) cmd = diffCmd + ' ' + params subprocess.Popen(shlex.split(cmd))
def btnDiffClicked(self): sid1 = self.timeLine.currentSnapshotID() sid2 = self.comboDiff.currentSnapshotID() if not sid1 or not sid2: return path1 = sid1.pathBackup(self.path) path2 = sid2.pathBackup(self.path) #check if the 2 paths are different if path1 == path2: messagebox.critical(self, _('You can\'t compare a snapshot to itself')) return diffCmd = self.config.strValue('qt.diff.cmd', DIFF_CMD) diffParams = self.config.strValue('qt.diff.params', DIFF_PARAMS) if not tools.checkCommand(diffCmd): messagebox.critical(self, _('Command not found: %s') % diffCmd) return # prevent backup data from being accidentally overwritten # by create a temporary local copy and only open that one if not isinstance(sid1, snapshots.RootSnapshot): path1 = self.parent.tmpCopy(path1, sid1) if not isinstance(sid2, snapshots.RootSnapshot): path2 = self.parent.tmpCopy(path2, sid2) params = diffParams params = params.replace('%1', '"%s"' % path1) params = params.replace('%2', '"%s"' % path2) cmd = diffCmd + ' ' + params subprocess.Popen(shlex.split(cmd))
def test_check_remote_command_with_spaces(self): self.cfg.setSmartRemoveRunRemoteInBackground(tools.checkCommand('screen') and tools.checkCommand('flock')) self.remotePath = os.path.join(self.tmpDir.name, 'foo bar') self.cfg.setSshSnapshotsPath(self.remotePath) os.mkdir(self.remotePath) ssh = sshtools.SSH(cfg = self.cfg) ssh.checkRemoteCommands()
def checkFuse(self): """ Check if command in self.mountproc is installed and user is part of group ``fuse``. Raises: exceptions.MountException: if either command is not available or user is not in group fuse """ logger.debug('Check fuse', self) if not tools.checkCommand(self.mountproc): logger.debug('%s is missing' % self.mountproc, self) raise MountException( _('%(proc)s not found. Please install e.g. %(install_command)s' ) % { 'proc': self.mountproc, 'install_command': "'apt-get install %s'" % self.mountproc }) if self.CHECK_FUSE_GROUP: user = self.config.user() try: fuse_grp_members = grp.getgrnam('fuse')[3] except KeyError: #group fuse doesn't exist. So most likely it isn't used by this distribution logger.debug("Group fuse doesn't exist. Skip test", self) return if not user in fuse_grp_members: logger.debug('User %s is not in group fuse' % user, self) raise MountException( _('%(user)s is not member of group \'fuse\'.\n ' 'Run \'sudo adduser %(user)s fuse\'. To apply ' 'changes logout and login again.\nLook at ' '\'man backintime\' for further instructions.') % {'user': user})
from time import sleep sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import tools import config import configfile #chroot jails used for building may have no UUID devices (because of tmpfs) #we need to skip tests that require UUIDs DISK_BY_UUID_AVAILABLE = os.path.exists(tools.DISK_BY_UUID) UDEVADM_HAS_UUID = subprocess.Popen(['udevadm', 'info', '-e'], stdout = subprocess.PIPE, stderr = subprocess.DEVNULL ).communicate()[0].find(b'ID_FS_UUID=') > 0 RSYNC_INSTALLED = tools.checkCommand('rsync') RSYNC_307_VERSION = """rsync version 3.0.7 protocol version 30 Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others. Web site: http://rsync.samba.org/ Capabilities: 64-bit files, 64-bit inums, 32-bit timestamps, 64-bit long ints, socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace, append, ACLs, xattrs, iconv, symtimes rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See the GNU General Public Licence for details. """ RSYNC_310_VERSION = """rsync version 3.1.0 protocol version 31 Copyright (C) 1996-2013 by Andrew Tridgell, Wayne Davison, and others.
class TestSshKey(generic.TestCaseCfg): def test_sshKeyGen(self): with TemporaryDirectory() as tmp: secKey = os.path.join(tmp, 'key') pubKey = secKey + '.pub' # create new key self.assertTrue(sshtools.sshKeyGen(secKey)) self.assertTrue(os.path.isfile(secKey)) self.assertTrue(os.path.isfile(pubKey)) # do not overwrite existing keys self.assertFalse(sshtools.sshKeyGen(secKey)) @unittest.skipIf(getpass.getuser() != 'germar', 'Password login does not work on Travis-ci.') @unittest.skipIf(not generic.LOCAL_SSH, 'Skip as this test requires a local ssh server, public and private keys installed') def test_sshCopyId(self): with TemporaryDirectory() as tmp: secKey = os.path.join(tmp, 'key') pubKey = secKey + '.pub' authKeys = os.path.expanduser('~/.ssh/authorized_keys') authKeysSic = os.path.join(tmp, 'sic') if os.path.exists(authKeys): shutil.copyfile(authKeys, authKeysSic) os.remove(authKeys) # create new key sshtools.sshKeyGen(secKey) self.assertTrue(os.path.isfile(pubKey)) with open(pubKey, 'rt') as f: pubKeyValue = f.read() try: # test copy pubKey self.assertTrue(sshtools.sshCopyId(pubKey, self.cfg.user(), 'localhost', askPass = '******')) self.assertTrue(os.path.exists(authKeys)) with open(authKeys, 'rt') as f: self.assertIn(pubKeyValue, f.readlines()) finally: # restore original ~/.ssh/authorized_keys file without test pubKey if os.path.exists(authKeysSic): shutil.copyfile(authKeysSic, authKeys) @unittest.skipIf(not tools.checkCommand('ssh-keygen'), "'ssh-keygen' not found.") def test_sshKeyFingerprint(self): self.assertIsNone(sshtools.sshKeyFingerprint(os.path.abspath(__file__))) with TemporaryDirectory() as d: key = os.path.join(d, 'key') cmd = ['ssh-keygen', '-q', '-N', '', '-f', key] proc = subprocess.Popen(cmd) proc.communicate() fingerprint = sshtools.sshKeyFingerprint(key) self.assertIsInstance(fingerprint, str) if fingerprint.startswith('SHA256'): self.assertEqual(len(fingerprint), 50) self.assertRegex(fingerprint, r'^SHA256:[a-zA-Z0-9/+]+$') else: self.assertEqual(len(fingerprint), 47) self.assertRegex(fingerprint, r'^[a-fA-F0-9:]+$') @unittest.skipIf(not generic.LOCAL_SSH, 'Skip as this test requires a local ssh server, public and private keys installed') def test_sshHostKey(self): fingerprint, keyHash, keyType = sshtools.sshHostKey('localhost') self.assertIsInstance(fingerprint, str) self.assertIsInstance(keyHash, str) self.assertIsInstance(keyType, str) if fingerprint.startswith('SHA256'): self.assertEqual(len(fingerprint), 50) self.assertRegex(fingerprint, r'^SHA256:[a-zA-Z0-9/+]+$') else: self.assertEqual(len(fingerprint), 47) self.assertRegex(fingerprint, r'^[a-fA-F0-9:]+$') self.assertIn(keyType, ('ECDSA', 'RSA')) hostKey = '/etc/ssh/ssh_host_{}_key.pub'.format(keyType.lower()) self.assertTrue(os.path.exists(hostKey)) self.assertEqual(3, len(keyHash.split())) try: with open(hostKey, 'rt') as f: pubKey = f.read().split()[1] self.assertEqual(pubKey, keyHash.split()[2]) except (IOError, IndexError): pass def test_writeKnownHostFile(self): KEY = '|1|abcdefghijklmnopqrstuvwxyz= ecdsa-sha2-nistp256 AAAAABCDEFGHIJKLMNOPQRSTUVWXYZ=' with TemporaryDirectory() as tmp: knownHosts = os.path.expanduser('~/.ssh/known_hosts') knownHostsSic = os.path.join(tmp, 'known_hosts') if os.path.exists(knownHosts): shutil.copyfile(knownHosts, knownHostsSic) try: sshtools.writeKnownHostsFile(KEY) self.assertTrue(os.path.exists(knownHosts)) with open(knownHosts, 'rt') as f: self.assertIn(KEY, [x.strip() for x in f.readlines()]) finally: # restore original known_hosts file if os.path.exists(knownHostsSic): shutil.copyfile(knownHostsSic, knownHosts)
import subprocess import shlex from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * import tools import restoredialog import messagebox import qttools import snapshots _ = gettext.gettext if tools.checkCommand('meld'): DIFF_CMD = 'meld' DIFF_PARAMS = '%1 %2' elif tools.checkCommand('kompare'): DIFF_CMD = 'kompare' DIFF_PARAMS = '%1 %2' else: DIFF_CMD = 'false' DIFF_PARAMS = '%1 %2' class DiffOptionsDialog(QDialog): def __init__(self, parent): super(DiffOptionsDialog, self).__init__(parent) self.config = parent.config
import subprocess import shlex from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * import tools import restoredialog import messagebox import qttools import snapshots _=gettext.gettext if tools.checkCommand('meld'): DIFF_CMD = 'meld' DIFF_PARAMS = '%1 %2' elif tools.checkCommand('kompare'): DIFF_CMD = 'kompare' DIFF_PARAMS = '%1 %2' else: DIFF_CMD = 'false' DIFF_PARAMS = '%1 %2' class DiffOptionsDialog(QDialog): def __init__(self, parent): super(DiffOptionsDialog, self).__init__(parent) self.config = parent.config import icon
class TestTools(generic.TestCase): """ All funtions test here come from tools.py """ def setUp(self): super(TestTools, self).setUp() self.subproc = None def tearDown(self): super(TestTools, self).tearDown() self.killProcess() def createProcess(self, *args): dummyPath = os.path.join(os.path.dirname(__file__), generic.DUMMY) cmd = [dummyPath] cmd.extend(args) self.subproc = subprocess.Popen(cmd) return self.subproc.pid def killProcess(self): if self.subproc: self.subproc.kill() self.subproc.wait() self.subproc = None def test_sharePath(self): share = tools.sharePath() self.assertTrue(share.endswith('share'), 'share = {}'.format(share)) def test_backintimePath(self): path = tools.backintimePath('common') self.assertRegex(path, r'.*/backintime.*/common$') def test_registerBackintimePath(self): path = tools.backintimePath('foo') tools.registerBackintimePath('foo') self.assertIn(path, sys.path) sys.path.remove(path) def test_runningFromSource(self): self.assertTrue(tools.runningFromSource()) def test_addSourceToPathEnviron(self): source = tools.backintimePath('common') path = [x for x in os.getenv('PATH').split(':') if x != source] os.environ['PATH'] = ':'.join(path) tools.addSourceToPathEnviron() self.assertIn(source, os.environ['PATH']) def test_gitRevisionAndHash(self): ref, hashid = tools.gitRevisionAndHash() if isinstance(ref, str): self.assertGreater(len(ref), 0) else: self.assertIsNone(ref) if isinstance(hashid, str): self.assertEqual(len(hashid), 7) else: self.assertIsNone(hashid) def test_readFile(self): """ Test the function readFile """ test_tools_file = os.path.abspath(__file__) test_directory = os.path.dirname(test_tools_file) non_existing_file = os.path.join(test_directory, "nonExistingFile") self.assertIsInstance(tools.readFile(test_tools_file), str) self.assertIsNone(tools.readFile(non_existing_file)) with NamedTemporaryFile('wt') as tmp: tmp.write('foo\nbar') tmp.flush() self.assertIsInstance(tools.readFile(tmp.name), str) self.assertEqual(tools.readFile(tmp.name), 'foo\nbar') tmp_gz = NamedTemporaryFile().name with gzip.open(tmp_gz + '.gz', 'wt') as f: f.write('foo\nbar') f.flush() self.assertIsInstance(tools.readFile(tmp_gz), str) self.assertEqual(tools.readFile(tmp_gz), 'foo\nbar') os.remove(tmp_gz + '.gz') def test_readFileLines(self): """ Test the function readFileLines """ test_tools_file = os.path.abspath(__file__) test_directory = os.path.dirname(test_tools_file) non_existing_file = os.path.join(test_directory, "nonExistingFile") output = tools.readFileLines(test_tools_file) self.assertIsInstance(output, list) self.assertGreaterEqual(len(output), 1) self.assertIsInstance(output[0], str) self.assertIsNone(tools.readFileLines(non_existing_file)) with NamedTemporaryFile('wt') as tmp: tmp.write('foo\nbar') tmp.flush() self.assertIsInstance(tools.readFileLines(tmp.name), list) self.assertListEqual(tools.readFileLines(tmp.name), ['foo', 'bar']) tmp_gz = NamedTemporaryFile().name with gzip.open(tmp_gz + '.gz', 'wt') as f: f.write('foo\nbar') f.flush() self.assertIsInstance(tools.readFileLines(tmp_gz), list) self.assertEqual(tools.readFileLines(tmp_gz), ['foo', 'bar']) os.remove(tmp_gz + '.gz') def test_checkCommand(self): """ Test the function checkCommand """ self.assertFalse(tools.checkCommand('')) self.assertFalse(tools.checkCommand("notExistedCommand")) self.assertTrue(tools.checkCommand("ls")) self.assertTrue(tools.checkCommand('backintime')) def test_which(self): """ Test the function which """ self.assertRegex(tools.which("ls"), r'/.*/ls') self.assertEqual(tools.which('backintime'), os.path.join(os.getcwd(), 'backintime')) self.assertIsNone(tools.which("notExistedCommand")) def test_makeDirs(self): self.assertFalse(tools.makeDirs('/')) self.assertTrue(tools.makeDirs(os.getcwd())) with TemporaryDirectory() as d: path = os.path.join(d, 'foo', 'bar') self.assertTrue(tools.makeDirs(path)) def test_makeDirs_not_writeable(self): with TemporaryDirectory() as d: os.chmod(d, stat.S_IRUSR) path = os.path.join(d, 'foobar{}'.format(random.randrange(100, 999))) self.assertFalse(tools.makeDirs(path)) def test_mkdir(self): self.assertFalse(tools.mkdir('/')) with TemporaryDirectory() as d: path = os.path.join(d, 'foo') self.assertTrue(tools.mkdir(path)) for mode in (0o700, 0o644, 0o777): msg = 'new path should have octal permissions {0:#o}'.format( mode) path = os.path.join(d, '{0:#o}'.format(mode)) self.assertTrue(tools.mkdir(path, mode), msg) self.assertEqual('{0:o}'.format(os.stat(path).st_mode & 0o777), '{0:o}'.format(mode), msg) def test_pids(self): pids = tools.pids() self.assertGreater(len(pids), 0) self.assertIn(os.getpid(), pids) def test_processStat(self): pid = self.createProcess() stat = tools.processStat(pid) self.assertRegex(stat, r'{} \({}\) \w .*'.format(pid, generic.DUMMY[:15])) @patch('builtins.open') def test_processStat_exception(self, mock_open): mock_open.side_effect = OSError() pid = self.createProcess() self.assertEqual(tools.processStat(pid), '') def test_processPaused(self): pid = self.createProcess() self.assertFalse(tools.processPaused(pid)) self.subproc.send_signal(signal.SIGSTOP) sleep(0.01) self.assertTrue(tools.processPaused(pid)) self.subproc.send_signal(signal.SIGCONT) sleep(0.01) self.assertFalse(tools.processPaused(pid)) def test_processName(self): pid = self.createProcess() self.assertEqual(tools.processName(pid), generic.DUMMY[:15]) def test_processCmdline(self): pid = self.createProcess() self.assertRegex(tools.processCmdline(pid), r'.*/sh.*/common/test/dummy_test_process\.sh') self.killProcess() pid = self.createProcess('foo', 'bar') self.assertRegex( tools.processCmdline(pid), r'.*/sh.*/common/test/dummy_test_process\.sh.foo.bar') @patch('builtins.open') def test_processCmdline_exception(self, mock_open): mock_open.side_effect = OSError() pid = self.createProcess() self.assertEqual(tools.processCmdline(pid), '') def test_pidsWithName(self): self.assertEqual(len(tools.pidsWithName('nonExistingProcess')), 0) pid = self.createProcess() pids = tools.pidsWithName(generic.DUMMY) self.assertGreaterEqual(len(pids), 1) self.assertIn(pid, pids) def test_processExists(self): self.assertFalse(tools.processExists('nonExistingProcess')) pid = self.createProcess() self.assertTrue(tools.processExists(generic.DUMMY)) def test_processAlive(self): """ Test the function processAlive """ #TODO: add test (in chroot) running proc as root and kill as non-root self.assertTrue(tools.processAlive(os.getpid())) pid = self.createProcess() self.assertTrue(tools.processAlive(pid)) self.killProcess() self.assertFalse(tools.processAlive(pid)) self.assertFalse(tools.processAlive(999999)) with self.assertRaises(ValueError): tools.processAlive(0) self.assertFalse(tools.processAlive(-1)) def test_checkXServer(self): try: tools.checkXServer() except Exception as e: self.fail('tools.ckeck_x_server() raised exception {}'.format( str(e))) def test_preparePath(self): path_with_slash_at_begin = "/test/path" path_without_slash_at_begin = "test/path" path_with_slash_at_end = "/test/path/" path_without_slash_at_end = "/test/path" self.assertEqual(tools.preparePath(path_with_slash_at_begin), path_with_slash_at_begin) self.assertEqual(tools.preparePath(path_without_slash_at_begin), path_with_slash_at_begin) self.assertEqual(tools.preparePath(path_without_slash_at_end), path_without_slash_at_end) self.assertEqual(tools.preparePath(path_with_slash_at_end), path_without_slash_at_end) def test_powerStatusAvailable(self): if tools.processExists('upowerd') and not generic.ON_TRAVIS: self.assertTrue(tools.powerStatusAvailable()) else: self.assertFalse(tools.powerStatusAvailable()) self.assertIsInstance(tools.onBattery(), bool) def test_rsyncCaps(self): if RSYNC_INSTALLED: caps = tools.rsyncCaps() self.assertIsInstance(caps, list) self.assertGreaterEqual(len(caps), 1) self.assertListEqual(tools.rsyncCaps(data=RSYNC_307_VERSION), [ '64-bit files', '64-bit inums', '32-bit timestamps', '64-bit long ints', 'socketpairs', 'hardlinks', 'symlinks', 'IPv6', 'batchfiles', 'inplace', 'append', 'ACLs', 'xattrs', 'iconv', 'symtimes' ]) self.assertListEqual(tools.rsyncCaps(data=RSYNC_310_VERSION), [ 'progress2', '64-bit files', '64-bit inums', '64-bit timestamps', '64-bit long ints', 'socketpairs', 'hardlinks', 'symlinks', 'IPv6', 'batchfiles', 'inplace', 'append', 'ACLs', 'xattrs', 'iconv', 'symtimes', 'prealloc' ]) @unittest.skip('Not yet implemented') def test_rsyncPrefix(self): pass @unittest.skip('Not yet implemented') def test_tempFailureRetry(self): pass def test_md5sum(self): with NamedTemporaryFile() as f: f.write(b'foo') f.flush() self.assertEqual(tools.md5sum(f.name), 'acbd18db4cc2f85cedef654fccc4a4d8') def test_checkCronPattern(self): self.assertTrue(tools.checkCronPattern('0')) self.assertTrue(tools.checkCronPattern('0,10,13,15,17,20,23')) self.assertTrue(tools.checkCronPattern('*/6')) self.assertFalse(tools.checkCronPattern('a')) self.assertFalse(tools.checkCronPattern(' 1')) self.assertFalse(tools.checkCronPattern('0,10,13,1a,17,20,23')) self.assertFalse(tools.checkCronPattern('0,10,13, 15,17,20,23')) self.assertFalse(tools.checkCronPattern('*/6,8')) self.assertFalse(tools.checkCronPattern('*/6 a')) @unittest.skip('Not yet implemented') def test_checkHomeEncrypt(self): pass #envLoad and envSave tests are in TestToolsEnviron below @unittest.skip('Not yet implemented') def test_keyringSupported(self): pass @unittest.skip('Not yet implemented') def test_password(self): pass @unittest.skip('Not yet implemented') def test_setPassword(self): pass def test_mountpoint(self): self.assertEqual(tools.mountpoint('/nonExistingFolder/foo/bar'), '/') proc = os.path.join('/proc', str(os.getpid()), 'fd') self.assertEqual(tools.mountpoint(proc), '/proc') def test_decodeOctalEscape(self): self.assertEqual(tools.decodeOctalEscape('/mnt/normalPath'), '/mnt/normalPath') self.assertEqual( tools.decodeOctalEscape('/mnt/path\\040with\\040space'), '/mnt/path with space') def test_mountArgs(self): rootArgs = tools.mountArgs('/') self.assertIsInstance(rootArgs, list) self.assertGreaterEqual(len(rootArgs), 3) self.assertEqual(rootArgs[1], '/') procArgs = tools.mountArgs('/proc') self.assertGreaterEqual(len(procArgs), 3) self.assertEqual(procArgs[0], 'proc') self.assertEqual(procArgs[1], '/proc') self.assertEqual(procArgs[2], 'proc') def test_device(self): self.assertEqual(tools.device('/proc'), 'proc') self.assertRegex(tools.device('/sys'), r'sys.*') self.assertRegex(tools.device('/nonExistingFolder/foo/bar'), r'/dev/.*') def test_filesystem(self): self.assertEqual(tools.filesystem('/proc'), 'proc') self.assertRegex(tools.filesystem('/sys'), r'sys.*') self.assertRegex( tools.filesystem('/nonExistingFolder/foo/bar').lower(), r'(:?ext[2-4]|xfs|zfs|jfs|raiserfs|btrfs)') # tools.uuidFromDev() get called from tools.uuidFromPath. # So we skip an extra unittest as it's hard to find a dev on all systems @unittest.skipIf(not DISK_BY_UUID_AVAILABLE and not UDEVADM_HAS_UUID, 'No UUIDs available on this system.') def test_uuidFromPath(self): uuid = tools.uuidFromPath('/nonExistingFolder/foo/bar') self.assertIsInstance(uuid, str) self.assertRegex(uuid.lower(), r'^[a-f0-9\-]+$') self.assertEqual(len(uuid.replace('-', '')), 32) @unittest.skipIf(not DISK_BY_UUID_AVAILABLE and not UDEVADM_HAS_UUID, 'No UUIDs available on this system.') def test_filesystemMountInfo(self): """ Basic sanity checks on returned structure """ mounts = tools.filesystemMountInfo() self.assertIsInstance(mounts, dict) self.assertGreater(len(mounts.items()), 0) self.assertIn('/', mounts) self.assertIn('original_uuid', mounts.get('/')) @unittest.skip('Not yet implemented') def test_wrapLine(self): pass def test_syncfs(self): self.assertTrue(tools.syncfs()) def test_isRoot(self): self.assertIsInstance(tools.isRoot(), bool) def test_usingSudo(self): self.assertIsInstance(tools.usingSudo(), bool) def test_patternHasNotEncryptableWildcard(self): self.assertFalse(tools.patternHasNotEncryptableWildcard('foo')) self.assertFalse(tools.patternHasNotEncryptableWildcard('/foo')) self.assertFalse(tools.patternHasNotEncryptableWildcard('foo/*/bar')) self.assertFalse(tools.patternHasNotEncryptableWildcard('foo/**/bar')) self.assertFalse(tools.patternHasNotEncryptableWildcard('*/foo')) self.assertFalse(tools.patternHasNotEncryptableWildcard('**/foo')) self.assertFalse(tools.patternHasNotEncryptableWildcard('foo/*')) self.assertFalse(tools.patternHasNotEncryptableWildcard('foo/**')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo?')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo[1-2]')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo*')) self.assertTrue(tools.patternHasNotEncryptableWildcard('*foo')) self.assertTrue(tools.patternHasNotEncryptableWildcard('**foo')) self.assertTrue(tools.patternHasNotEncryptableWildcard('*.foo')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo*bar')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo**bar')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo*/bar')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo**/bar')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo/*bar')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo/**bar')) self.assertTrue(tools.patternHasNotEncryptableWildcard('foo/*/bar*')) self.assertTrue(tools.patternHasNotEncryptableWildcard('*foo/*/bar')) def test_readTimeStamp(self): with NamedTemporaryFile('wt') as f: f.write('20160127 0124') f.flush() self.assertEqual(tools.readTimeStamp(f.name), datetime(2016, 1, 27, 1, 24)) with NamedTemporaryFile('wt') as f: f.write('20160127') f.flush() self.assertEqual(tools.readTimeStamp(f.name), datetime(2016, 1, 27, 0, 0)) def test_writeTimeStamp(self): with NamedTemporaryFile('rt') as f: tools.writeTimeStamp(f.name) s = f.read().strip('\n') self.assertTrue(s.replace(' ', '').isdigit()) self.assertEqual(len(s), 13) @unittest.skip('Not yet implemented') def test_inhibitSuspend(self): pass @unittest.skip('Not yet implemented') def test_unInhibitSuspend(self): pass @unittest.skipIf(not tools.checkCommand('crontab'), "'crontab' not found.") def test_readWriteCrontab(self): now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') oldCrontab = tools.readCrontab() self.assertIsInstance(oldCrontab, list) testLine = '#BackInTime Unittest from {}. Test probably failed. You can remove this line.'.format( now) self.assertTrue(tools.writeCrontab(oldCrontab + [ testLine, ])) newCrontab = tools.readCrontab() self.assertIn(testLine, newCrontab) self.assertEqual(len(newCrontab), len(oldCrontab) + 1) self.assertTrue(tools.writeCrontab(oldCrontab)) if oldCrontab: self.assertListEqual(oldCrontab, tools.readCrontab()) def test_splitCommands(self): ret = list( tools.splitCommands(['echo foo;'], head='echo start;', tail='echo end', maxLength=40)) self.assertEqual(len(ret), 1) self.assertEqual(ret[0], 'echo start;echo foo;echo end') ret = list( tools.splitCommands(['echo foo;'] * 3, head='echo start;', tail='echo end', maxLength=40)) self.assertEqual(len(ret), 2) self.assertEqual(ret[0], 'echo start;echo foo;echo foo;echo end') self.assertEqual(ret[1], 'echo start;echo foo;echo end') ret = list( tools.splitCommands(['echo foo;'] * 3, head='echo start;', tail='echo end', maxLength=0)) self.assertEqual(len(ret), 1) self.assertEqual(ret[0], 'echo start;echo foo;echo foo;echo foo;echo end') ret = list( tools.splitCommands(['echo foo;'] * 3, head='echo start;', tail='echo end', maxLength=-10)) self.assertEqual(len(ret), 1) self.assertEqual(ret[0], 'echo start;echo foo;echo foo;echo foo;echo end') def test_isIPv6Address(self): self.assertTrue(tools.isIPv6Address('fd00:0::5')) self.assertTrue(tools.isIPv6Address('2001:db8:0:8d3:0:8a2e:70:7344')) self.assertFalse(tools.isIPv6Address('foo.bar')) self.assertFalse(tools.isIPv6Address('192.168.1.1')) self.assertFalse(tools.isIPv6Address('fd00')) def test_excapeIPv6Address(self): self.assertEqual(tools.escapeIPv6Address('fd00:0::5'), '[fd00:0::5]') self.assertEqual( tools.escapeIPv6Address('2001:db8:0:8d3:0:8a2e:70:7344'), '[2001:db8:0:8d3:0:8a2e:70:7344]') self.assertEqual(tools.escapeIPv6Address('foo.bar'), 'foo.bar') self.assertEqual(tools.escapeIPv6Address('192.168.1.1'), '192.168.1.1') self.assertEqual(tools.escapeIPv6Address('fd00'), 'fd00') def test_camelCase(self): self.assertEqual(tools.camelCase('foo'), 'Foo') self.assertEqual(tools.camelCase('Foo'), 'Foo') self.assertEqual(tools.camelCase('foo_bar'), 'FooBar') self.assertEqual(tools.camelCase('foo_Bar'), 'FooBar')
from time import sleep sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import tools import config import configfile #chroot jails used for building may have no UUID devices (because of tmpfs) #we need to skip tests that require UUIDs DISK_BY_UUID_AVAILABLE = os.path.exists(tools.DISK_BY_UUID) UDEVADM_HAS_UUID = subprocess.Popen( ['udevadm', 'info', '-e'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).communicate()[0].find(b'ID_FS_UUID=') > 0 RSYNC_INSTALLED = tools.checkCommand('rsync') RSYNC_307_VERSION = """rsync version 3.0.7 protocol version 30 Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others. Web site: http://rsync.samba.org/ Capabilities: 64-bit files, 64-bit inums, 32-bit timestamps, 64-bit long ints, socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace, append, ACLs, xattrs, iconv, symtimes rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See the GNU General Public Licence for details. """ RSYNC_310_VERSION = """rsync version 3.1.0 protocol version 31 Copyright (C) 1996-2013 by Andrew Tridgell, Wayne Davison, and others.