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(__name__,
30            'script-with-bom.py')
31        namespace = types.ModuleType('namespace')
32        setuptools.sandbox._execfile(target, vars(namespace))
33        assert namespace.result == 'passed'
34
35    def test_setup_py_with_CRLF(self, tmpdir):
36        setup_py = tmpdir / 'setup.py'
37        with setup_py.open('wb') as stream:
38            stream.write(b'"degenerate script"\r\n')
39        setuptools.sandbox._execfile(str(setup_py), globals())
40
41
42class TestExceptionSaver:
43    def test_exception_trapped(self):
44        with setuptools.sandbox.ExceptionSaver():
45            raise ValueError("details")
46
47    def test_exception_resumed(self):
48        with setuptools.sandbox.ExceptionSaver() as saved_exc:
49            raise ValueError("details")
50
51        with pytest.raises(ValueError) as caught:
52            saved_exc.resume()
53
54        assert isinstance(caught.value, ValueError)
55        assert str(caught.value) == 'details'
56
57    def test_exception_reconstructed(self):
58        orig_exc = ValueError("details")
59
60        with setuptools.sandbox.ExceptionSaver() as saved_exc:
61            raise orig_exc
62
63        with pytest.raises(ValueError) as caught:
64            saved_exc.resume()
65
66        assert isinstance(caught.value, ValueError)
67        assert caught.value is not orig_exc
68
69    def test_no_exception_passes_quietly(self):
70        with setuptools.sandbox.ExceptionSaver() as saved_exc:
71            pass
72
73        saved_exc.resume()
74
75    def test_unpickleable_exception(self):
76        class CantPickleThis(Exception):
77            "This Exception is unpickleable because it's not in globals"
78            def __repr__(self):
79                return 'CantPickleThis%r' % (self.args,)
80
81        with setuptools.sandbox.ExceptionSaver() as saved_exc:
82            raise CantPickleThis('detail')
83
84        with pytest.raises(setuptools.sandbox.UnpickleableException) as caught:
85            saved_exc.resume()
86
87        assert str(caught.value) == "CantPickleThis('detail',)"
88
89    def test_unpickleable_exception_when_hiding_setuptools(self):
90        """
91        As revealed in #440, an infinite recursion can occur if an unpickleable
92        exception while setuptools is hidden. Ensure this doesn't happen.
93        """
94
95        class ExceptionUnderTest(Exception):
96            """
97            An unpickleable exception (not in globals).
98            """
99
100        with pytest.raises(setuptools.sandbox.UnpickleableException) as caught:
101            with setuptools.sandbox.save_modules():
102                setuptools.sandbox.hide_setuptools()
103                raise ExceptionUnderTest()
104
105        msg, = caught.value.args
106        assert msg == 'ExceptionUnderTest()'
107
108    def test_sandbox_violation_raised_hiding_setuptools(self, tmpdir):
109        """
110        When in a sandbox with setuptools hidden, a SandboxViolation
111        should reflect a proper exception and not be wrapped in
112        an UnpickleableException.
113        """
114
115        def write_file():
116            "Trigger a SandboxViolation by writing outside the sandbox"
117            with open('/etc/foo', 'w'):
118                pass
119
120        with pytest.raises(setuptools.sandbox.SandboxViolation) as caught:
121            with setuptools.sandbox.save_modules():
122                setuptools.sandbox.hide_setuptools()
123                with setuptools.sandbox.DirectorySandbox(str(tmpdir)):
124                    write_file()
125
126        cmd, args, kwargs = caught.value.args
127        assert cmd == 'open'
128        assert args == ('/etc/foo', 'w')
129        assert kwargs == {}
130
131        msg = str(caught.value)
132        assert 'open' in msg
133        assert "('/etc/foo', 'w')" in msg
134