1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
import logging
from unittest.mock import (
patch, call, Mock
)
from pytest import (
raises, fixture
)
import os
import pytest
from kiwi.path import Path
from kiwi.exceptions import KiwiFileAccessError
class TestPath:
@fixture(autouse=True)
def inject_fixtures(self, caplog):
self._caplog = caplog
def test_sort_by_hierarchy(self):
ordered = Path.sort_by_hierarchy(
['usr', 'usr/bin', 'etc', 'usr/lib']
)
assert ordered == ['usr', 'etc', 'usr/bin', 'usr/lib']
@patch('pathlib.Path')
def test_create(self, mock_Path):
path = Mock()
mock_Path.return_value = path
Path.create('foo')
path.mkdir.assert_called_once_with(
parents=True, exist_ok=True
)
mock_Path.return_value = Exception
with raises(KiwiFileAccessError):
Path.create('foo')
@patch('kiwi.command.os.path.exists')
@patch('kiwi.command.Command.run')
def test_wipe(self, mock_command, mock_exists):
mock_exists.return_value = True
Path.wipe('foo')
mock_command.assert_called_once_with(
['rm', '-r', '-f', 'foo']
)
mock_exists.return_value = False
mock_command.reset_mock()
Path.wipe('foo')
assert not mock_command.called
@patch('kiwi.command.Command.run')
def test_remove_hierarchy(self, mock_command):
Path.remove_hierarchy('/my_root', '/tmp/foo/bar')
with self._caplog.at_level(logging.WARNING):
assert mock_command.call_args_list == [
call(
[
'rmdir', '--ignore-fail-on-non-empty',
'/my_root/tmp/foo/bar'
]
),
call(
[
'rmdir', '--ignore-fail-on-non-empty',
'/my_root/tmp/foo'
]
)
]
assert 'remove_hierarchy: path /my_root/tmp is protected' in \
self._caplog.text
mock_command.reset_mock()
Path.remove_hierarchy('/home/kiwi/my_root', 'foo')
mock_command.assert_called_once_with(
['rmdir', '--ignore-fail-on-non-empty', '/home/kiwi/my_root/foo']
)
def test_move_to_root(self):
assert [
'/usr/bin', '/sbin'
] == Path.move_to_root('/root_dir', ['/root_dir/usr/bin', '/sbin'])
def test_rebase_to_root(self):
assert [
'/root_dir/usr/bin', '/root_dir/sbin'
] == Path.rebase_to_root('/root_dir', ['usr/bin', '/sbin'])
@patch('os.access')
@patch('os.environ.get')
@patch('os.path.exists')
def test_which(self, mock_exists, mock_env, mock_access):
mock_env.return_value = '/usr/local/bin:/usr/bin:/bin'
mock_exists.return_value = True
assert Path.which('some-file') == '/usr/local/bin/some-file'
mock_exists.return_value = False
assert Path.which('some-file') is None
mock_access.return_value = False
mock_env.return_value = '/usr/local/bin:/usr/bin:/bin'
assert Path.which('some-file', access_mode=os.X_OK) is None
def test_which_with_real_data(self, pytestconfig: pytest.Config):
assert Path.which(
'pyproject.toml',
custom_env={'PATH': str(pytestconfig.rootpath)},
access_mode=os.F_OK
) == str(pytestconfig.rootpath / "pyproject.toml")
assert Path.which(
'__init__.py',
custom_env={'PATH': "/kiwi/"},
access_mode=os.F_OK,
root_dir=str(pytestconfig.rootpath)
) == str(pytestconfig.rootpath / "kiwi" / "__init__.py")
@patch('os.access')
@patch('os.environ.get')
@patch('os.path.exists')
def test_which_not_found_log(
self, mock_exists, mock_env, mock_access
):
PATH = '/usr/local/bin:/usr/bin:/bin'
mock_env.return_value = PATH
mock_exists.return_value = False
with self._caplog.at_level(logging.DEBUG):
assert Path.which('file') is None
assert ('Looking for file in ' + PATH) in self._caplog.text
def test_access_invalid_mode(self):
with raises(ValueError) as issue:
Path.access("/some/non-existent-file/", 128)
assert '0x80' in format(issue.value)
def test_access_with_non_existent_file(self):
non_existent = "/some/file/that/should/not/exist"
with raises(KiwiFileAccessError) as issue:
Path.access(non_existent, os.F_OK)
assert non_existent in issue.value.message
@patch('os.stat')
@patch('os.access')
def test_access_with_args(self, mock_access, mock_stat):
mock_access.return_value = True
fname = "arbitrary"
mode = os.R_OK
assert Path.access(fname, mode, effective_ids=True)
mock_stat.assert_called_once_with(fname)
mock_access.assert_called_once_with(fname, mode, effective_ids=True)
def test_first_exists(self):
assert Path.first_exists('/') == '/'
assert Path.first_exists('/etc/foo/bar') == '/etc'
assert Path.first_exists('artificial') == '.'
assert Path.first_exists('foo/bar') == '.'
assert Path.first_exists('/x/y/z') == '/'
|