1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
3# vi:ts=4:et
4
5from . import util
6import setup as pycurl_setup
7import unittest
8import os, os.path, sys
9import functools
10try:
11    # Python 2
12    from StringIO import StringIO
13except ImportError:
14    # Python 3
15    from io import StringIO
16
17def set_env(key, new_value):
18    old_value = os.environ.get(key)
19    if new_value is not None:
20        os.environ[key] = new_value
21    elif old_value is not None:
22        del os.environ[key]
23    else:
24        # new and old values are None which mean the variable is not set
25        pass
26    return old_value
27
28def reset_env(key, old_value):
29    # empty string means environment variable was empty
30    # None means it was not set
31    if old_value is not None:
32        os.environ[key] = old_value
33    elif key in os.environ:
34        del os.environ[key]
35
36def using_curl_config(path, ssl_library=None):
37    path = os.path.join(os.path.dirname(__file__), 'fake-curl', path)
38    def decorator(fn):
39        @functools.wraps(fn)
40        def decorated(*args, **kwargs):
41            old_path = set_env('PYCURL_CURL_CONFIG', path)
42            old_ssl_library = set_env('PYCURL_SSL_LIBRARY', ssl_library)
43            try:
44                return fn(*args, **kwargs)
45            finally:
46                reset_env('PYCURL_CURL_CONFIG', old_path)
47                reset_env('PYCURL_SSL_LIBRARY', old_ssl_library)
48        return decorated
49    return decorator
50
51def min_python_version(*spec):
52    def decorator(fn):
53        @functools.wraps(fn)
54        def decorated(*args, **kwargs):
55            if sys.version_info < spec:
56                raise unittest.SkipTest('Minimum Python version %s required' % spec.join('.'))
57
58            return fn(*args, **kwargs)
59        return decorated
60    return decorator
61
62class SetupTest(unittest.TestCase):
63
64    @util.only_unix
65    def test_sanity_check(self):
66        config = pycurl_setup.ExtensionConfiguration()
67        # we should link against libcurl, one would expect
68        assert 'curl' in config.libraries
69
70    @util.only_unix
71    def test_valid_option_consumes_argv(self):
72        argv = ['', '--with-nss']
73        pycurl_setup.ExtensionConfiguration(argv)
74        self.assertEqual([''], argv)
75
76    @util.only_unix
77    def test_invalid_option_not_consumed(self):
78        argv = ['', '--bogus']
79        pycurl_setup.ExtensionConfiguration(argv)
80        self.assertEqual(['', '--bogus'], argv)
81
82    @util.only_unix
83    def test_invalid_option_suffix_not_consumed(self):
84        argv = ['', '--with-nss-bogus']
85        pycurl_setup.ExtensionConfiguration(argv)
86        self.assertEqual(['', '--with-nss-bogus'], argv)
87
88    @util.only_unix
89    @using_curl_config('curl-config-empty')
90    def test_no_ssl(self):
91        config = pycurl_setup.ExtensionConfiguration()
92        # do not expect anything to do with ssl
93        assert 'crypto' not in config.libraries
94
95    @util.only_unix
96    @using_curl_config('curl-config-libs-and-static-libs')
97    def test_does_not_use_static_libs(self):
98        config = pycurl_setup.ExtensionConfiguration()
99        # should not link against any libraries from --static-libs if
100        # --libs succeeded
101        assert 'flurby' in config.libraries
102        assert 'kzzert' not in config.libraries
103
104    @util.only_unix
105    @using_curl_config('curl-config-ssl-in-libs')
106    def test_ssl_in_libs(self):
107        config = pycurl_setup.ExtensionConfiguration()
108        # should link against openssl
109        assert 'crypto' in config.libraries
110
111    @util.only_unix
112    @using_curl_config('curl-config-ssl-in-static-libs')
113    def test_ssl_in_static_libs(self):
114        config = pycurl_setup.ExtensionConfiguration()
115        # should link against openssl
116        assert 'crypto' in config.libraries
117
118    @util.only_unix
119    @using_curl_config('curl-config-empty')
120    def test_no_ssl_define(self):
121        config = pycurl_setup.ExtensionConfiguration()
122        # ssl define should be off
123        assert 'HAVE_CURL_SSL' not in config.define_symbols
124
125    @util.only_unix
126    @using_curl_config('curl-config-ssl-in-libs')
127    def test_ssl_in_libs_sets_ssl_define(self):
128        config = pycurl_setup.ExtensionConfiguration()
129        # ssl define should be on
130        assert 'HAVE_CURL_SSL' in config.define_symbols
131
132    @util.only_unix
133    @using_curl_config('curl-config-ssl-in-static-libs')
134    def test_ssl_in_static_libs_sets_ssl_define(self):
135        config = pycurl_setup.ExtensionConfiguration()
136        # ssl define should be on
137        assert 'HAVE_CURL_SSL' in config.define_symbols
138
139    @util.only_unix
140    @using_curl_config('curl-config-ssl-in-libs')
141    def test_ssl_feature_sets_ssl_define(self):
142        config = pycurl_setup.ExtensionConfiguration()
143        # ssl define should be on
144        assert 'HAVE_CURL_SSL' in config.define_symbols
145
146    @util.only_unix
147    @using_curl_config('curl-config-ssl-feature-only')
148    def test_ssl_feature_only(self):
149        saved_stderr = sys.stderr
150        sys.stderr = captured_stderr = StringIO()
151        try:
152            config = pycurl_setup.ExtensionConfiguration()
153        finally:
154            sys.stderr = saved_stderr
155        # ssl define should be on
156        assert 'HAVE_CURL_SSL' in config.define_symbols
157        # and a warning message
158        assert 'Warning: libcurl is configured to use SSL, but we have \
159not been able to determine which SSL backend it is using.' in captured_stderr.getvalue()
160
161    @util.only_unix
162    @using_curl_config('curl-config-ssl-feature-only')
163    def test_libcurl_ssl_openssl(self):
164        config = pycurl_setup.ExtensionConfiguration(['',
165            '--libcurl-dll=tests/fake-curl/libcurl/with_openssl.so'])
166        # openssl should be detected
167        assert 'HAVE_CURL_SSL' in config.define_symbols
168        assert 'HAVE_CURL_OPENSSL' in config.define_symbols
169        assert 'crypto' in config.libraries
170
171        assert 'HAVE_CURL_GNUTLS' not in config.define_symbols
172        assert 'HAVE_CURL_NSS' not in config.define_symbols
173
174    @util.only_unix
175    @using_curl_config('curl-config-ssl-feature-only')
176    def test_libcurl_ssl_gnutls(self):
177        config = pycurl_setup.ExtensionConfiguration(['',
178            '--libcurl-dll=tests/fake-curl/libcurl/with_gnutls.so'])
179        # gnutls should be detected
180        assert 'HAVE_CURL_SSL' in config.define_symbols
181        assert 'HAVE_CURL_GNUTLS' in config.define_symbols
182        assert 'gnutls' in config.libraries
183
184        assert 'HAVE_CURL_OPENSSL' not in config.define_symbols
185        assert 'HAVE_CURL_NSS' not in config.define_symbols
186
187    @util.only_unix
188    @using_curl_config('curl-config-ssl-feature-only')
189    def test_libcurl_ssl_nss(self):
190        config = pycurl_setup.ExtensionConfiguration(['',
191            '--libcurl-dll=tests/fake-curl/libcurl/with_nss.so'])
192        # nss should be detected
193        assert 'HAVE_CURL_SSL' in config.define_symbols
194        assert 'HAVE_CURL_NSS' in config.define_symbols
195        assert 'ssl3' in config.libraries
196
197        assert 'HAVE_CURL_OPENSSL' not in config.define_symbols
198        assert 'HAVE_CURL_GNUTLS' not in config.define_symbols
199
200    @util.only_unix
201    @using_curl_config('curl-config-empty')
202    def test_libcurl_ssl_unrecognized(self):
203        config = pycurl_setup.ExtensionConfiguration(['',
204            '--libcurl-dll=tests/fake-curl/libcurl/with_unknown_ssl.so'])
205        assert 'HAVE_CURL_SSL' not in config.define_symbols
206        assert 'HAVE_CURL_OPENSSL' not in config.define_symbols
207        assert 'HAVE_CURL_GNUTLS' not in config.define_symbols
208        assert 'HAVE_CURL_NSS' not in config.define_symbols
209
210    @util.only_unix
211    @using_curl_config('curl-config-ssl-feature-only')
212    def test_with_ssl_library(self):
213        config = pycurl_setup.ExtensionConfiguration(['',
214            '--with-ssl'])
215        assert 'HAVE_CURL_SSL' in config.define_symbols
216        assert 'HAVE_CURL_OPENSSL' in config.define_symbols
217        assert 'crypto' in config.libraries
218
219        assert 'HAVE_CURL_GNUTLS' not in config.define_symbols
220        assert 'HAVE_CURL_NSS' not in config.define_symbols
221
222    @util.only_unix
223    @using_curl_config('curl-config-ssl-feature-only')
224    def test_with_openssl_library(self):
225        config = pycurl_setup.ExtensionConfiguration(['',
226            '--with-openssl'])
227        assert 'HAVE_CURL_SSL' in config.define_symbols
228        assert 'HAVE_CURL_OPENSSL' in config.define_symbols
229        assert 'crypto' in config.libraries
230
231        assert 'HAVE_CURL_GNUTLS' not in config.define_symbols
232        assert 'HAVE_CURL_NSS' not in config.define_symbols
233
234    @util.only_unix
235    @using_curl_config('curl-config-ssl-feature-only')
236    def test_with_gnutls_library(self):
237        config = pycurl_setup.ExtensionConfiguration(['',
238            '--with-gnutls'])
239        assert 'HAVE_CURL_SSL' in config.define_symbols
240        assert 'HAVE_CURL_GNUTLS' in config.define_symbols
241        assert 'gnutls' in config.libraries
242
243        assert 'HAVE_CURL_OPENSSL' not in config.define_symbols
244        assert 'HAVE_CURL_NSS' not in config.define_symbols
245
246    @util.only_unix
247    @using_curl_config('curl-config-ssl-feature-only')
248    def test_with_nss_library(self):
249        config = pycurl_setup.ExtensionConfiguration(['',
250            '--with-nss'])
251        assert 'HAVE_CURL_SSL' in config.define_symbols
252        assert 'HAVE_CURL_NSS' in config.define_symbols
253        assert 'ssl3' in config.libraries
254
255        assert 'HAVE_CURL_OPENSSL' not in config.define_symbols
256        assert 'HAVE_CURL_GNUTLS' not in config.define_symbols
257
258    @util.only_unix
259    @using_curl_config('curl-config-empty')
260    def test_no_ssl_feature_with_libcurl_dll(self):
261        config = pycurl_setup.ExtensionConfiguration(['',
262            '--libcurl-dll=tests/fake-curl/libcurl/with_openssl.so'])
263        # openssl should not be detected
264        assert 'HAVE_CURL_SSL' not in config.define_symbols
265        assert 'HAVE_CURL_OPENSSL' not in config.define_symbols
266        assert 'crypto' not in config.libraries
267
268    @util.only_unix
269    @using_curl_config('curl-config-empty')
270    def test_no_ssl_feature_with_ssl(self):
271        old_stderr = sys.stderr
272        sys.stderr = captured_stderr = StringIO()
273
274        try:
275            config = pycurl_setup.ExtensionConfiguration(['',
276                '--with-ssl'])
277            # openssl should not be detected
278            assert 'HAVE_CURL_SSL' not in config.define_symbols
279            assert 'HAVE_CURL_OPENSSL' not in config.define_symbols
280            assert 'crypto' not in config.libraries
281        finally:
282            sys.stderr = old_stderr
283
284        self.assertEqual("Warning: SSL backend specified manually but libcurl does not use SSL",
285            captured_stderr.getvalue().strip())
286