summaryrefslogtreecommitdiff
path: root/tests/unit/test_locations.py
blob: 01e6f7585daab72ac74c960fd6dbac6e82cc015e (plain)
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""
locations.py tests

"""
import os
import sys
import shutil
import tempfile
import getpass

import pytest

from mock import Mock
import pip

from pip.locations import distutils_scheme

if sys.platform == 'win32':
   pwd = Mock()
else:
   import pwd


class TestLocations:
    def setup(self):
        self.tempdir = tempfile.mkdtemp()
        self.st_uid = 9999
        self.username = "example"
        self.patch()

    def tearDown(self):
        self.revert_patch()
        shutil.rmtree(self.tempdir, ignore_errors=True)

    def patch(self):
        """ first store and then patch python methods pythons """
        self.tempfile_gettempdir = tempfile.gettempdir
        self.old_os_fstat = os.fstat
        if sys.platform != 'win32':
            # os.geteuid and pwd.getpwuid are not implemented on windows
            self.old_os_geteuid = os.geteuid
            self.old_pwd_getpwuid = pwd.getpwuid
        self.old_getpass_getuser = getpass.getuser

        # now patch
        tempfile.gettempdir = lambda : self.tempdir
        getpass.getuser = lambda : self.username
        os.geteuid = lambda : self.st_uid
        os.fstat = lambda fd : self.get_mock_fstat(fd)

        if sys.platform != 'win32':
            pwd.getpwuid = lambda uid: self.get_mock_getpwuid(uid)

    def revert_patch(self):
        """ revert the patches to python methods """
        tempfile.gettempdir = self.tempfile_gettempdir
        getpass.getuser = self.old_getpass_getuser
        if sys.platform != 'win32':
            # os.geteuid and pwd.getpwuid are not implemented on windows
            os.geteuid = self.old_os_geteuid
            pwd.getpwuid = self.old_pwd_getpwuid
        os.fstat = self.old_os_fstat

    def get_mock_fstat(self, fd):
        """ returns a basic mock fstat call result.
            Currently only the st_uid attribute has been set.
        """
        result = Mock()
        result.st_uid = self.st_uid
        return result

    def get_mock_getpwuid(self, uid):
        """ returns a basic mock pwd.getpwuid call result.
            Currently only the pw_name attribute has been set.
        """
        result = Mock()
        result.pw_name = self.username
        return result

    def get_build_dir_location(self):
        """ returns a string pointing to the
            current build_prefix.
        """
        return os.path.join(self.tempdir, 'pip_build_%s' % self.username)

    def test_dir_path(self):
        """ test the path name for the build_prefix
        """
        from pip import locations
        assert locations._get_build_prefix() == self.get_build_dir_location()

    #skip on windows, build dir is not created
    @pytest.mark.skipif("sys.platform == 'win32'")
    @pytest.mark.skipif("not hasattr(os, 'O_NOFOLLOW')")
    def test_dir_created(self):
        """ test that the build_prefix directory is generated when
            _get_build_prefix is called.
        """
        assert not os.path.exists(self.get_build_dir_location() ), \
            "the build_prefix directory should not exist yet!"
        from pip import locations
        locations._get_build_prefix()
        assert os.path.exists(self.get_build_dir_location() ), \
            "the build_prefix directory should now exist!"


    #skip on windows, build dir is not created
    @pytest.mark.skipif("sys.platform == 'win32'")
    def test_dir_created_without_NOFOLLOW(self, monkeypatch):
        """ test that the build_prefix directory is generated when
            os.O_NOFOLLOW doen't exist
        """
        if hasattr(os, 'O_NOFOLLOW'):
           monkeypatch.delattr("os.O_NOFOLLOW")
        assert not os.path.exists(self.get_build_dir_location() ), \
            "the build_prefix directory should not exist yet!"
        from pip import locations
        locations._get_build_prefix()
        assert os.path.exists(self.get_build_dir_location() ), \
            "the build_prefix directory should now exist!"

    #skip on windows; this exception logic only runs on linux
    @pytest.mark.skipif("sys.platform == 'win32'")
    @pytest.mark.skipif("not hasattr(os, 'O_NOFOLLOW')")
    def test_error_raised_when_owned_by_another(self):
        """ test calling _get_build_prefix when there is a temporary
            directory owned by another user raises an InstallationError.
        """
        from pip import locations
        os.geteuid = lambda : 1111
        os.mkdir(self.get_build_dir_location() )

        with pytest.raises(pip.exceptions.InstallationError):
            locations._get_build_prefix()

    #skip on windows; this exception logic only runs on linux
    @pytest.mark.skipif("sys.platform == 'win32'")
    def test_error_raised_when_owned_by_another_without_NOFOLLOW(self, monkeypatch):
        """ test calling _get_build_prefix when there is a temporary
            directory owned by another user raises an InstallationError.
            (when os.O_NOFOLLOW doesn't exist
        """
        if hasattr(os, 'O_NOFOLLOW'):
           monkeypatch.delattr("os.O_NOFOLLOW")
        from pip import locations
        os.geteuid = lambda : 1111
        os.mkdir(self.get_build_dir_location() )

        with pytest.raises(pip.exceptions.InstallationError):
            locations._get_build_prefix()


    def test_no_error_raised_when_owned_by_you(self):
        """ test calling _get_build_prefix when there is a temporary
            directory owned by you raise no InstallationError.
        """
        from pip import locations
        os.mkdir(self.get_build_dir_location())
        locations._get_build_prefix()


class TestDisutilsScheme:

    def test_root_modifies_appropiately(self):
        norm_scheme = distutils_scheme("example")
        root_scheme = distutils_scheme("example", root="/test/root/")

        for key, value in norm_scheme.items():
            expected = os.path.join("/test/root/", os.path.abspath(value)[1:])
            assert root_scheme[key] == expected

    def test_distutils_config_file_read(self, tmpdir, monkeypatch):
       f = tmpdir.mkdir("config").join("setup.cfg")
       f.write("[install]\ninstall-scripts=/somewhere/else")
       from distutils.dist import Distribution
       # patch the function that returns what config files are present
       monkeypatch.setattr(Distribution, 'find_config_files', lambda self: [f])
       scheme = distutils_scheme('example')
       assert scheme['scripts'] == '/somewhere/else'