1"""develop tests
2"""
3import os
4import types
5
6import pytest
7
8import pkg_resources
9import setuptools.sandbox
10
11
12class TestSandbox:
13    def test_devnull(self, tmpdir):
14        with setuptools.sandbox.DirectorySandbox(str(tmpdir)):
15            self._file_writer(os.devnull)
16
17    @staticmethod
18    def _file_writer(path):
19        def do_write():
20            with open(path, 'w') as f:
21                f.write('xxx')
22
23        return do_write
24
25    def test_setup_py_with_BOM(self):
26        """
27        It should be possible to execute a setup.py with a Byte Order Mark
28        """
29        target = pkg_resources.resource_filename(
30            __name__,
31            'script-with-bom.py')
32        namespace = types.ModuleType('namespace')
33        setuptools.sandbox._execfile(target, vars(namespace))
34        assert namespace.result == 'passed'
35
36    def test_setup_py_with_CRLF(self, tmpdir):
37        setup_py = tmpdir / 'setup.py'
38        with setup_py.open('wb') as stream:
39            stream.write(b'"degenerate script"\r\n')
40        setuptools.sandbox._execfile(str(setup_py), globals())
41
42
43class TestExceptionSaver:
44    def test_exception_trapped(self):
45        with setuptools.sandbox.ExceptionSaver():
46            raise ValueError("details")
47
48    def test_exception_resumed(self):
49        with setuptools.sandbox.ExceptionSaver() as saved_exc:
50            raise ValueError("details")
51
52        with pytest.raises(ValueError) as caught:
53            saved_exc.resume()
54
55        assert isinstance(caught.value, ValueError)
56        assert str(caught.value) == 'details'
57
58    def test_exception_reconstructed(self):
59        orig_exc = ValueError("details")
60
61        with setuptools.sandbox.ExceptionSaver() as saved_exc:
62            raise orig_exc
63
64        with pytest.raises(ValueError) as caught:
65            saved_exc.resume()
66
67        assert isinstance(caught.value, ValueError)
68        assert caught.value is not orig_exc
69
70    def test_no_exception_passes_quietly(self):
71        with setuptools.sandbox.ExceptionSaver() as saved_exc:
72            pass
73
74        saved_exc.resume()
75
76    def test_unpickleable_exception(self):
77        class CantPickleThis(Exception):
78            "This Exception is unpickleable because it's not in globals"
79            def __repr__(self):
80                return 'CantPickleThis%r' % (self.args,)
81
82        with setuptools.sandbox.ExceptionSaver() as saved_exc:
83            raise CantPickleThis('detail')
84
85        with pytest.raises(setuptools.sandbox.UnpickleableException) as caught:
86            saved_exc.resume()
87
88        assert str(caught.value) == "CantPickleThis('detail',)"
89
90    def test_unpickleable_exception_when_hiding_setuptools(self):
91        """
92        As revealed in #440, an infinite recursion can occur if an unpickleable
93        exception while setuptools is hidden. Ensure this doesn't happen.
94        """
95
96        class ExceptionUnderTest(Exception):
97            """
98            An unpickleable exception (not in globals).
99            """
100
101        with pytest.raises(setuptools.sandbox.UnpickleableException) as caught:
102            with setuptools.sandbox.save_modules():
103                setuptools.sandbox.hide_setuptools()
104                raise ExceptionUnderTest()
105
106        msg, = caught.value.args
107        assert msg == 'ExceptionUnderTest()'
108
109    def test_sandbox_violation_raised_hiding_setuptools(self, tmpdir):
110        """
111        When in a sandbox with setuptools hidden, a SandboxViolation
112        should reflect a proper exception and not be wrapped in
113        an UnpickleableException.
114        """
115
116        def write_file():
117            "Trigger a SandboxViolation by writing outside the sandbox"
118            with open('/etc/foo', 'w'):
119                pass
120
121        with pytest.raises(setuptools.sandbox.SandboxViolation) as caught:
122            with setuptools.sandbox.save_modules():
123                setuptools.sandbox.hide_setuptools()
124                with setuptools.sandbox.DirectorySandbox(str(tmpdir)):
125                    write_file()
126
127        cmd, args, kwargs = caught.value.args
128        assert cmd == 'open'
129        assert args == ('/etc/foo', 'w')
130        assert kwargs == {}
131
132        msg = str(caught.value)
133        assert 'open' in msg
134        assert "('/etc/foo', 'w')" in msg
135