Completed
Pull Request — master (#669)
by
unknown
01:04
created

tests.fail_if_readonly()   A

Complexity

Conditions 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 2
dl 0
loc 4
rs 10
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
"""
5
test_utils
6
------------
7
8
Tests for `cookiecutter.utils` module.
9
"""
10
11
import os
12
import pytest
13
import stat
14
import sys
15
16
from cookiecutter import utils
17
18
19
def make_readonly(path):
20
    """Helper function that is called in the tests to change the access
21
    permissions of the given file.
22
    """
23
    mode = os.stat(path).st_mode
24
    os.chmod(path, mode & ~stat.S_IWRITE)
25
26
27
def test_rmtree():
28
    os.mkdir('foo')
29
    with open('foo/bar', "w") as f:
30
        f.write("Test data")
31
    make_readonly('foo/bar')
32
    utils.rmtree('foo')
33
    assert not os.path.exists('foo')
34
35
36
def test_rmtree_error_uses_callback(mocker):
37
    """
38
    Test that on system who fails deleting files when those files
39
    are read only, the workaround that sets them to writable first
40
    works.
41
    """
42
43
    # Setting up mocks to check if callbacks were really called
44
    real_force_delete = utils.force_delete
45
    force_delete = mocker.patch("cookiecutter.utils.force_delete")
46
    force_delete.side_effect = real_force_delete
47
48
    real_unlink = os.unlink
49
    # python 2.7 uses os.remove, python3.+ uses os.unlink
50
    unlink = mocker.patch("os.unlink")
51
    mocker.patch("os.remove", new=unlink)
52
53
    def fail_if_readonly(*args, **kwargs):
54
        if not os.stat("foo/bar").st_mode & stat.S_IWRITE:
55
            raise OSError
56
        real_unlink(*args, **kwargs)
57
58
    unlink.side_effect = fail_if_readonly
59
60
    # Doing the same as in test_rmtree
61
    os.mkdir('foo')
62
    with open('foo/bar', "w") as f:
63
        f.write("Test data")
64
    make_readonly('foo/bar')
65
    utils.rmtree('foo')
66
    assert not os.path.exists('foo')
67
68
    # Validating that it's really the callback that helped
69
    # having the desired behaviour
70
    assert len(unlink.mock_calls) == 2
71
    assert len(force_delete.mock_calls) == 1
72
73
74
def test_make_sure_path_exists():
75
    if sys.platform.startswith('win'):
76
        existing_directory = os.path.abspath(os.curdir)
77
        uncreatable_directory = 'a*b'
78
    else:
79
        existing_directory = '/usr/'
80
        uncreatable_directory = '/this-doesnt-exist-and-cant-be-created/'
81
82
    assert utils.make_sure_path_exists(existing_directory)
83
    assert utils.make_sure_path_exists('tests/blah')
84
    assert utils.make_sure_path_exists('tests/trailingslash/')
85
    assert not utils.make_sure_path_exists(uncreatable_directory)
86
    utils.rmtree('tests/blah/')
87
    utils.rmtree('tests/trailingslash/')
88
89
90
def test_workin():
91
    cwd = os.getcwd()
92
    ch_to = 'tests/files'
93
94
    class TestException(Exception):
95
        pass
96
97
    def test_work_in():
98
        with utils.work_in(ch_to):
99
            test_dir = os.path.join(cwd, ch_to).replace("/", os.sep)
100
            assert test_dir == os.getcwd()
101
            raise TestException()
102
103
    # Make sure we return to the correct folder
104
    assert cwd == os.getcwd()
105
106
    # Make sure that exceptions are still bubbled up
107
    with pytest.raises(TestException):
108
        test_work_in()
109