PageRenderTime 124ms CodeModel.GetById 3ms app.highlight 108ms RepoModel.GetById 1ms app.codeStats 1ms

/pypy/module/_socket/test/test_sock_app.py

https://bitbucket.org/pypy/pypy/
Python | 874 lines | 833 code | 26 blank | 15 comment | 34 complexity | b793748f98ef50884185c6a5d243c753 MD5 | raw file
  1import sys, os
  2import pytest
  3from pypy.tool.pytest.objspace import gettestobjspace
  4from pypy.interpreter.gateway import interp2app
  5from pypy.module._file.test.test_file import regex_search
  6from rpython.tool.udir import udir
  7from rpython.rlib import rsocket
  8from rpython.rtyper.lltypesystem import lltype, rffi
  9
 10def setup_module(mod):
 11    mod.space = gettestobjspace(usemodules=['_socket', 'array', 'struct'])
 12    global socket
 13    import socket
 14    mod.w_socket = space.appexec([], "(): import _socket as m; return m")
 15    mod.path = udir.join('fd')
 16    mod.path.write('fo')
 17
 18def test_gethostname():
 19    host = space.appexec([w_socket], "(_socket): return _socket.gethostname()")
 20    assert space.unwrap(host) == socket.gethostname()
 21
 22def test_gethostbyname():
 23    for host in ["localhost", "127.0.0.1"]:
 24        ip = space.appexec([w_socket, space.wrap(host)],
 25                           "(_socket, host): return _socket.gethostbyname(host)")
 26        assert space.unwrap(ip) == socket.gethostbyname(host)
 27
 28def test_gethostbyname_ex():
 29    for host in ["localhost", "127.0.0.1"]:
 30        ip = space.appexec([w_socket, space.wrap(host)],
 31                           "(_socket, host): return _socket.gethostbyname_ex(host)")
 32        assert space.unwrap(ip) == socket.gethostbyname_ex(host)
 33
 34def test_gethostbyaddr():
 35    try:
 36        socket.gethostbyaddr("::1")
 37    except socket.herror:
 38        ipv6 = False
 39    else:
 40        ipv6 = True
 41    for host in ["localhost", "127.0.0.1", "::1"]:
 42        if host == "::1" and not ipv6:
 43            from pypy.interpreter.error import OperationError
 44            with pytest.raises(OperationError):
 45                space.appexec([w_socket, space.wrap(host)],
 46                              "(_socket, host): return _socket.gethostbyaddr(host)")
 47            continue
 48        ip = space.appexec([w_socket, space.wrap(host)],
 49                           "(_socket, host): return _socket.gethostbyaddr(host)")
 50        assert space.unwrap(ip) == socket.gethostbyaddr(host)
 51
 52def test_getservbyname():
 53    name = "smtp"
 54    # 2 args version
 55    port = space.appexec([w_socket, space.wrap(name)],
 56                        "(_socket, name): return _socket.getservbyname(name, 'tcp')")
 57    assert space.unwrap(port) == 25
 58    # 1 arg version
 59    if sys.version_info < (2, 4):
 60        pytest.skip("getservbyname second argument is not optional before python 2.4")
 61    port = space.appexec([w_socket, space.wrap(name)],
 62                        "(_socket, name): return _socket.getservbyname(name)")
 63    assert space.unwrap(port) == 25
 64
 65def test_getservbyport():
 66    if sys.version_info < (2, 4):
 67        pytest.skip("getservbyport does not exist before python 2.4")
 68    port = 25
 69    # 2 args version
 70    name = space.appexec([w_socket, space.wrap(port)],
 71                         "(_socket, port): return _socket.getservbyport(port, 'tcp')")
 72    assert space.unwrap(name) == "smtp"
 73    name = space.appexec([w_socket, space.wrap(port)],
 74                         """(_socket, port):
 75                         try:
 76                             return _socket.getservbyport(port, 42)
 77                         except TypeError:
 78                             return 'OK'
 79                         """)
 80    assert space.unwrap(name) == 'OK'
 81    # 1 arg version
 82    name = space.appexec([w_socket, space.wrap(port)],
 83                         "(_socket, port): return _socket.getservbyport(port)")
 84    assert space.unwrap(name) == "smtp"
 85
 86    from pypy.interpreter.error import OperationError
 87    exc = raises(OperationError, space.appexec,
 88           [w_socket], "(_socket): return _socket.getservbyport(-1)")
 89    assert exc.value.match(space, space.w_ValueError)
 90
 91def test_getprotobyname():
 92    name = "tcp"
 93    w_n = space.appexec([w_socket, space.wrap(name)],
 94                        "(_socket, name): return _socket.getprotobyname(name)")
 95    assert space.unwrap(w_n) == socket.IPPROTO_TCP
 96
 97def test_fromfd():
 98    # XXX review
 99    if not hasattr(socket, 'fromfd'):
100        pytest.skip("No socket.fromfd on this platform")
101    orig_fd = path.open()
102    fd = space.appexec([w_socket, space.wrap(orig_fd.fileno()),
103            space.wrap(socket.AF_INET), space.wrap(socket.SOCK_STREAM),
104            space.wrap(0)],
105           """(_socket, fd, family, type, proto):
106                 return _socket.fromfd(fd, family, type, proto)""")
107
108    assert space.unwrap(space.call_method(fd, 'fileno'))
109    fd = space.appexec([w_socket, space.wrap(orig_fd.fileno()),
110            space.wrap(socket.AF_INET), space.wrap(socket.SOCK_STREAM)],
111                """(_socket, fd, family, type):
112                    return _socket.fromfd(fd, family, type)""")
113
114    assert space.unwrap(space.call_method(fd, 'fileno'))
115
116def test_ntohs():
117    w_n = space.appexec([w_socket, space.wrap(125)],
118                        "(_socket, x): return _socket.ntohs(x)")
119    assert space.unwrap(w_n) == socket.ntohs(125)
120
121def test_ntohl():
122    w_n = space.appexec([w_socket, space.wrap(125)],
123                        "(_socket, x): return _socket.ntohl(x)")
124    assert space.unwrap(w_n) == socket.ntohl(125)
125    w_n = space.appexec([w_socket, space.wrap(0x89abcdef)],
126                        "(_socket, x): return _socket.ntohl(x)")
127    assert space.unwrap(w_n) in (0x89abcdef, 0xefcdab89)
128    space.raises_w(space.w_OverflowError, space.appexec,
129                   [w_socket, space.wrap(1<<32)],
130                   "(_socket, x): return _socket.ntohl(x)")
131
132def test_htons():
133    w_n = space.appexec([w_socket, space.wrap(125)],
134                        "(_socket, x): return _socket.htons(x)")
135    assert space.unwrap(w_n) == socket.htons(125)
136
137def test_htonl():
138    w_n = space.appexec([w_socket, space.wrap(125)],
139                        "(_socket, x): return _socket.htonl(x)")
140    assert space.unwrap(w_n) == socket.htonl(125)
141    w_n = space.appexec([w_socket, space.wrap(0x89abcdef)],
142                        "(_socket, x): return _socket.htonl(x)")
143    assert space.unwrap(w_n) in (0x89abcdef, 0xefcdab89)
144    space.raises_w(space.w_OverflowError, space.appexec,
145                   [w_socket, space.wrap(1<<32)],
146                   "(_socket, x): return _socket.htonl(x)")
147
148def test_aton_ntoa():
149    ip = '123.45.67.89'
150    packed = socket.inet_aton(ip)
151    w_p = space.appexec([w_socket, space.wrap(ip)],
152                        "(_socket, ip): return _socket.inet_aton(ip)")
153    assert space.unwrap(w_p) == packed
154    w_ip = space.appexec([w_socket, space.wrap(packed)],
155                         "(_socket, p): return _socket.inet_ntoa(p)")
156    assert space.unwrap(w_ip) == ip
157
158def test_pton_ntop_ipv4():
159    if not hasattr(socket, 'inet_pton'):
160        pytest.skip('No socket.inet_pton on this platform')
161    tests = [
162        ("123.45.67.89", "\x7b\x2d\x43\x59"),
163        ("0.0.0.0", "\x00" * 4),
164        ("255.255.255.255", "\xff" * 4),
165    ]
166    for ip, packed in tests:
167        w_p = space.appexec([w_socket, space.wrap(ip)],
168                            "(_socket, ip): return _socket.inet_pton(_socket.AF_INET, ip)")
169        assert space.unwrap(w_p) == packed
170        w_ip = space.appexec([w_socket, w_p],
171                             "(_socket, p): return _socket.inet_ntop(_socket.AF_INET, p)")
172        assert space.unwrap(w_ip) == ip
173
174def test_ntop_ipv6():
175    if not hasattr(socket, 'inet_pton'):
176        pytest.skip('No socket.inet_pton on this platform')
177    if not socket.has_ipv6:
178        pytest.skip("No IPv6 on this platform")
179    tests = [
180        ("\x00" * 16, "::"),
181        ("\x01" * 16, ":".join(["101"] * 8)),
182        ("\x00\x00\x10\x10" * 4, None), #"::1010:" + ":".join(["0:1010"] * 3)),
183        ("\x00" * 12 + "\x01\x02\x03\x04", "::1.2.3.4"),
184        ("\x00" * 10 + "\xff\xff\x01\x02\x03\x04", "::ffff:1.2.3.4"),
185    ]
186    for packed, ip in tests:
187        w_ip = space.appexec([w_socket, space.wrap(packed)],
188            "(_socket, packed): return _socket.inet_ntop(_socket.AF_INET6, packed)")
189        if ip is not None:   # else don't check for the precise representation
190            assert space.unwrap(w_ip) == ip
191        w_packed = space.appexec([w_socket, w_ip],
192            "(_socket, ip): return _socket.inet_pton(_socket.AF_INET6, ip)")
193        assert space.unwrap(w_packed) == packed
194
195def test_pton_ipv6():
196    if not hasattr(socket, 'inet_pton'):
197        pytest.skip('No socket.inet_pton on this platform')
198    if not socket.has_ipv6:
199        pytest.skip("No IPv6 on this platform")
200    tests = [
201        ("\x00" * 16, "::"),
202        ("\x01" * 16, ":".join(["101"] * 8)),
203        ("\x00\x01" + "\x00" * 12 + "\x00\x02", "1::2"),
204        ("\x00" * 4 + "\x00\x01" * 6, "::1:1:1:1:1:1"),
205        ("\x00\x01" * 6 + "\x00" * 4, "1:1:1:1:1:1::"),
206        ("\xab\xcd\xef\00" + "\x00" * 12, "ABCD:EF00::"),
207        ("\xab\xcd\xef\00" + "\x00" * 12, "abcd:ef00::"),
208        ("\x00\x00\x10\x10" * 4, "::1010:" + ":".join(["0:1010"] * 3)),
209        ("\x00" * 12 + "\x01\x02\x03\x04", "::1.2.3.4"),
210        ("\x00" * 10 + "\xff\xff\x01\x02\x03\x04", "::ffff:1.2.3.4"),
211    ]
212    for packed, ip in tests:
213        w_packed = space.appexec([w_socket, space.wrap(ip)],
214            "(_socket, ip): return _socket.inet_pton(_socket.AF_INET6, ip)")
215        assert space.unwrap(w_packed) == packed
216
217def test_has_ipv6():
218    pytest.skip("has_ipv6 is always True on PyPy for now")
219    res = space.appexec([w_socket], "(_socket): return _socket.has_ipv6")
220    assert space.unwrap(res) == socket.has_ipv6
221
222def test_getaddrinfo():
223    host = "localhost"
224    port = 25
225    info = socket.getaddrinfo(host, port)
226    w_l = space.appexec([w_socket, space.wrap(host), space.wrap(port)],
227                        "(_socket, host, port): return _socket.getaddrinfo(host, port)")
228    assert space.unwrap(w_l) == info
229    w_l = space.appexec([w_socket, space.wrap(host), space.wrap(port)],
230                        "(_socket, host, port): return _socket.getaddrinfo(host, long(port))")
231    assert space.unwrap(w_l) == info
232    pytest.skip("Unicode conversion is too slow")
233    w_l = space.appexec([w_socket, space.wrap(unicode(host)), space.wrap(port)],
234                        "(_socket, host, port): return _socket.getaddrinfo(host, port)")
235    assert space.unwrap(w_l) == info
236
237def test_unknown_addr_as_object():
238    from pypy.module._socket.interp_socket import addr_as_object
239    c_addr = lltype.malloc(rsocket._c.sockaddr, flavor='raw', track_allocation=False)
240    c_addr.c_sa_data[0] = 'c'
241    rffi.setintfield(c_addr, 'c_sa_family', 15)
242    # XXX what size to pass here? for the purpose of this test it has
243    #     to be short enough so we have some data, 1 sounds good enough
244    #     + sizeof USHORT
245    w_obj = addr_as_object(rsocket.Address(c_addr, 1 + 2), -1, space)
246    assert space.isinstance_w(w_obj, space.w_tuple)
247    assert space.int_w(space.getitem(w_obj, space.wrap(0))) == 15
248    assert space.str_w(space.getitem(w_obj, space.wrap(1))) == 'c'
249
250def test_addr_raw_packet():
251    from pypy.module._socket.interp_socket import addr_as_object
252    if not hasattr(rsocket._c, 'sockaddr_ll'):
253        pytest.skip("posix specific test")
254    # HACK: To get the correct interface number of lo, which in most cases is 1,
255    # but can be anything (i.e. 39), we need to call the libc function
256    # if_nametoindex to get the correct index
257    import ctypes
258    libc = ctypes.CDLL(ctypes.util.find_library('c'))
259    ifnum = libc.if_nametoindex('lo')
260
261    c_addr_ll = lltype.malloc(rsocket._c.sockaddr_ll, flavor='raw')
262    addrlen = rffi.sizeof(rsocket._c.sockaddr_ll)
263    c_addr = rffi.cast(lltype.Ptr(rsocket._c.sockaddr), c_addr_ll)
264    rffi.setintfield(c_addr_ll, 'c_sll_ifindex', ifnum)
265    rffi.setintfield(c_addr_ll, 'c_sll_protocol', 8)
266    rffi.setintfield(c_addr_ll, 'c_sll_pkttype', 13)
267    rffi.setintfield(c_addr_ll, 'c_sll_hatype', 0)
268    rffi.setintfield(c_addr_ll, 'c_sll_halen', 3)
269    c_addr_ll.c_sll_addr[0] = 'a'
270    c_addr_ll.c_sll_addr[1] = 'b'
271    c_addr_ll.c_sll_addr[2] = 'c'
272    rffi.setintfield(c_addr, 'c_sa_family', socket.AF_PACKET)
273    # fd needs to be somehow valid
274    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
275    fd = s.fileno()
276    w_obj = addr_as_object(rsocket.make_address(c_addr, addrlen), fd, space)
277    lltype.free(c_addr_ll, flavor='raw')
278    assert space.is_true(space.eq(w_obj, space.newtuple([
279        space.wrap('lo'),
280        space.wrap(socket.ntohs(8)),
281        space.wrap(13),
282        space.wrap(False),
283        space.wrap("abc"),
284        ])))
285
286def test_getnameinfo():
287    host = "127.0.0.1"
288    port = 25
289    info = socket.getnameinfo((host, port), 0)
290    w_l = space.appexec([w_socket, space.wrap(host), space.wrap(port)],
291                        "(_socket, host, port): return _socket.getnameinfo((host, port), 0)")
292    assert space.unwrap(w_l) == info
293
294def test_timeout():
295    space.appexec([w_socket, space.wrap(25.4)],
296                  "(_socket, timeout): _socket.setdefaulttimeout(timeout)")
297    w_t = space.appexec([w_socket],
298                  "(_socket): return _socket.getdefaulttimeout()")
299    assert space.unwrap(w_t) == 25.4
300
301    space.appexec([w_socket, space.w_None],
302                  "(_socket, timeout): _socket.setdefaulttimeout(timeout)")
303    w_t = space.appexec([w_socket],
304                  "(_socket): return _socket.getdefaulttimeout()")
305    assert space.unwrap(w_t) is None
306
307
308# XXX also need tests for other connection and timeout errors
309
310
311class AppTestSocket:
312    spaceconfig = dict(usemodules=['_socket', '_weakref', 'struct'])
313
314    def setup_class(cls):
315        cls.space = space
316        cls.w_udir = space.wrap(str(udir))
317        cls.w_regex_search = space.wrap(interp2app(regex_search))
318
319    def teardown_class(cls):
320        if not cls.runappdirect:
321            cls.space.sys.getmodule('_socket').shutdown(cls.space)
322
323    def test_module(self):
324        import _socket
325        assert _socket.socket.__name__ == 'socket'
326        assert _socket.socket.__module__ == '_socket'
327
328    def test_ntoa_exception(self):
329        import _socket
330        raises(_socket.error, _socket.inet_ntoa, b"ab")
331
332    def test_aton_exceptions(self):
333        import _socket
334        tests = ["127.0.0.256", "127.0.0.255555555555555555", "127.2b.0.0",
335            "127.2.0.0.1", "127.2.0."]
336        for ip in tests:
337            raises(_socket.error, _socket.inet_aton, ip)
338
339    def test_ntop_exceptions(self):
340        import _socket
341        if not hasattr(_socket, 'inet_ntop'):
342            skip('No socket.inet_pton on this platform')
343        for family, packed, exception in \
344                    [(_socket.AF_INET + _socket.AF_INET6, "", _socket.error),
345                     (_socket.AF_INET, "a", ValueError),
346                     (_socket.AF_INET6, "a", ValueError),
347                     (_socket.AF_INET, u"aa\u2222a", UnicodeEncodeError)]:
348            raises(exception, _socket.inet_ntop, family, packed)
349
350    def test_pton_exceptions(self):
351        import _socket
352        if not hasattr(_socket, 'inet_pton'):
353            skip('No socket.inet_pton on this platform')
354        tests = [
355            (_socket.AF_INET + _socket.AF_INET6, ""),
356            (_socket.AF_INET, "127.0.0.256"),
357            (_socket.AF_INET, "127.0.0.255555555555555555"),
358            (_socket.AF_INET, "127.2b.0.0"),
359            (_socket.AF_INET, "127.2.0.0.1"),
360            (_socket.AF_INET, "127.2..0"),
361            (_socket.AF_INET6, "127.0.0.1"),
362            (_socket.AF_INET6, "1::2::3"),
363            (_socket.AF_INET6, "1:1:1:1:1:1:1:1:1"),
364            (_socket.AF_INET6, "1:1:1:1:1:1:1:1::"),
365            (_socket.AF_INET6, "1:1:1::1:1:1:1:1"),
366            (_socket.AF_INET6, "1::22222:1"),
367            (_socket.AF_INET6, "1::eg"),
368        ]
369        for family, ip in tests:
370            raises(_socket.error, _socket.inet_pton, family, ip)
371
372    def test_newsocket_error(self):
373        import _socket
374        raises(_socket.error, _socket.socket, 10001, _socket.SOCK_STREAM, 0)
375
376    def test_socket_fileno(self):
377        import _socket
378        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
379        assert s.fileno() > -1
380        assert isinstance(s.fileno(), int)
381
382    def test_socket_repr(self):
383        import _socket
384        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
385        try:
386            expected = ('<socket object, fd=%s, family=%s, type=%s, protocol=%s>'
387                        % (s.fileno(), s.family, s.type, s.proto))
388            assert repr(s) == expected
389        finally:
390            s.close()
391        expected = ('<socket object, fd=-1, family=%s, type=%s, protocol=%s>'
392                    % (s.family, s.type, s.proto))
393        assert repr(s) == expected
394
395    def test_socket_close(self):
396        import _socket, os
397        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
398        fileno = s.fileno()
399        assert s.fileno() >= 0
400        s.close()
401        assert s.fileno() < 0
402        s.close()
403        if os.name != 'nt':
404            raises(OSError, os.close, fileno)
405
406    def test_socket_track_resources(self):
407        import _socket, os, gc, sys, cStringIO
408        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
409        fileno = s.fileno()
410        assert s.fileno() >= 0
411        s.close()
412        assert s.fileno() < 0
413        s.close()
414        if os.name != 'nt':
415            raises(OSError, os.close, fileno)
416
417    @pytest.mark.skipif("config.option.runappdirect")
418    def test_track_resources(self):
419        import os, gc, sys, cStringIO
420        import _socket
421        if '__pypy__' not in sys.builtin_module_names:
422            skip("pypy specific test")
423        #
424        def fn(flag1, flag2, do_close=False):
425            sys.pypy_set_track_resources(flag1)
426            mysock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
427            sys.pypy_set_track_resources(flag2)
428            buf = cStringIO.StringIO()
429            preverr = sys.stderr
430            try:
431                sys.stderr = buf
432                if do_close:
433                    mysock.close()
434                del mysock
435                gc.collect() # force __del__ to be called
436            finally:
437                sys.stderr = preverr
438                sys.pypy_set_track_resources(False)
439            return buf.getvalue()
440
441        # check with track_resources disabled
442        assert fn(False, False) == ""
443        #
444        # check that we don't get the warning if we actually closed the socket
445        msg = fn(True, True, do_close=True)
446        assert msg == ''
447        #
448        # check with track_resources enabled
449        msg = fn(True, True)
450        assert self.regex_search(r"""
451        WARNING: unclosed <socket object, .*>
452        Created at \(most recent call last\):
453          File ".*", line .*, in test_track_resources
454          File ".*", line .*, in fn
455        """, msg)
456        #
457        # track_resources is enabled after the construction of the socket. in
458        # this case, the socket is not registered for finalization at all, so
459        # we don't see a message
460        msg = fn(False, True)
461        assert msg == ''
462
463
464    def test_socket_close_error(self):
465        import _socket, os
466        if os.name == 'nt':
467            skip("Windows sockets are not files")
468        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
469        os.close(s.fileno())
470        s.close()
471
472    def test_socket_connect(self):
473        import _socket, os
474        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
475        # it would be nice to have a test which works even if there is no
476        # network connection. However, this one is "good enough" for now. Skip
477        # it if there is no connection.
478        try:
479            s.connect(("www.python.org", 80))
480        except _socket.gaierror as ex:
481            skip("GAIError - probably no connection: %s" % str(ex.args))
482        name = s.getpeername() # Will raise socket.error if not connected
483        assert name[1] == 80
484        s.close()
485
486    def test_socket_connect_ex(self):
487        import _socket
488        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
489        # The following might fail if the DNS redirects failed requests to a
490        # catch-all address (i.e. opendns).
491        # Make sure we get an app-level error, not an interp one.
492        raises(_socket.gaierror, s.connect_ex, ("wrong.invalid", 80))
493        s.close()
494
495    def test_socket_connect_typeerrors(self):
496        tests = [
497            "",
498            ("80"),
499            ("80", "80"),
500            (80, 80),
501        ]
502        import _socket
503        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
504        for args in tests:
505            raises((TypeError, ValueError), s.connect, args)
506        s.close()
507
508    def test_bigport(self):
509        import _socket
510        s = _socket.socket()
511        exc = raises(OverflowError, s.connect, ("localhost", -1))
512        assert "port must be 0-65535." in str(exc.value)
513        exc = raises(OverflowError, s.connect, ("localhost", 1000000))
514        assert "port must be 0-65535." in str(exc.value)
515        s = _socket.socket(_socket.AF_INET6)
516        exc = raises(OverflowError, s.connect, ("::1", 1234, 1048576))
517        assert "flowinfo must be 0-1048575." in str(exc.value)
518
519    def test_NtoH(self):
520        import sys
521        import _socket as socket
522        # This just checks that htons etc. are their own inverse,
523        # when looking at the lower 16 or 32 bits.
524        sizes = {socket.htonl: 32, socket.ntohl: 32,
525                 socket.htons: 16, socket.ntohs: 16}
526        for func, size in sizes.items():
527            mask = (1 << size) - 1
528            for i in (0, 1, 0xffff, ~0xffff, 2, 0x01234567, 0x76543210):
529                assert i & mask == func(func(i&mask)) & mask
530
531            swapped = func(mask)
532            assert swapped & mask == mask
533            try:
534                func(-1)
535            except (OverflowError, ValueError):
536                pass
537            else:
538                assert False
539            try:
540                func(sys.maxint*2+2)
541            except OverflowError:
542                pass
543            else:
544                assert False
545
546    def test_NtoH_overflow(self):
547        skip("we are not checking for overflowing values yet")
548        import _socket as socket
549        # Checks that we cannot give too large values to htons etc.
550        # Skipped for now; CPython 2.6 is also not consistent.
551        sizes = {socket.htonl: 32, socket.ntohl: 32,
552                 socket.htons: 16, socket.ntohs: 16}
553        for func, size in sizes.items():
554            try:
555                func(1 << size)
556            except OverflowError:
557                pass
558            else:
559                assert False
560
561    def test_newsocket(self):
562        import socket
563        s = socket.socket()
564
565    def test_subclass(self):
566        from _socket import socket
567        class MySock(socket):
568            blah = 123
569        s = MySock()
570        assert s.blah == 123
571
572    def test_getsetsockopt(self):
573        import _socket as socket
574        import struct
575        # A socket should start with reuse == 0
576        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
577        reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
578        assert reuse == 0
579        #
580        raises(TypeError, s.setsockopt, socket.SOL_SOCKET,
581                          socket.SO_REUSEADDR, 2 ** 31)
582        raises(TypeError, s.setsockopt, socket.SOL_SOCKET,
583                          socket.SO_REUSEADDR, 2 ** 32 + 1)
584        assert s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 0
585        #
586        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
587        reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
588        assert reuse != 0
589        # String case
590        intsize = struct.calcsize('i')
591        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
592        reusestr = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
593                                intsize)
594        (reuse,) = struct.unpack('i', reusestr)
595        assert reuse == 0
596        reusestr = struct.pack('i', 1)
597        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, reusestr)
598        reusestr = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
599                                intsize)
600        (reuse,) = struct.unpack('i', reusestr)
601        assert reuse != 0
602
603    def test_socket_ioctl(self):
604        import _socket, sys
605        if sys.platform != 'win32':
606            skip("win32 only")
607        assert hasattr(_socket.socket, 'ioctl')
608        assert hasattr(_socket, 'SIO_RCVALL')
609        assert hasattr(_socket, 'RCVALL_ON')
610        assert hasattr(_socket, 'RCVALL_OFF')
611        assert hasattr(_socket, 'SIO_KEEPALIVE_VALS')
612        s = _socket.socket()
613        raises(ValueError, s.ioctl, -1, None)
614        s.ioctl(_socket.SIO_KEEPALIVE_VALS, (1, 100, 100))
615
616    def test_dup(self):
617        import _socket as socket
618        if not hasattr(socket.socket, 'dup'):
619            skip('No dup() on this platform')
620        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
621        s.bind(('localhost', 0))
622        s2 = s.dup()
623        assert s.fileno() != s2.fileno()
624        assert s.getsockname() == s2.getsockname()
625
626    def test_buffer_or_unicode(self):
627        # Test that send/sendall/sendto accept a buffer or a unicode as arg
628        import _socket, os
629        s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
630        # XXX temporarily we use python.org to test, will have more robust tests
631        # in the absence of a network connection later when more parts of the
632        # socket API are implemented.  Currently skip the test if there is no
633        # connection.
634        try:
635            s.connect(("www.python.org", 80))
636        except _socket.gaierror as ex:
637            skip("GAIError - probably no connection: %s" % str(ex.args))
638        exc = raises(TypeError, s.send, None)
639        assert str(exc.value) == "must be string or buffer, not None"
640        assert s.send(buffer('')) == 0
641        assert s.sendall(buffer('')) is None
642        assert s.send(memoryview('')) == 0
643        assert s.sendall(memoryview('')) is None
644        assert s.send(u'') == 0
645        assert s.sendall(u'') is None
646        raises(UnicodeEncodeError, s.send, u'\xe9')
647        s.close()
648        s = _socket.socket(_socket.AF_INET, _socket.SOCK_DGRAM, 0)
649        s.sendto(buffer(''), ('localhost', 9)) # Send to discard port.
650        s.close()
651
652    def test_unix_socket_connect(self):
653        import _socket, os
654        if not hasattr(_socket, 'AF_UNIX'):
655            skip('AF_UNIX not supported.')
656        oldcwd = os.getcwd()
657        os.chdir(self.udir)
658        try:
659            sockpath = 'app_test_unix_socket_connect'
660
661            serversock = _socket.socket(_socket.AF_UNIX)
662            serversock.bind(sockpath)
663            serversock.listen(1)
664
665            clientsock = _socket.socket(_socket.AF_UNIX)
666            clientsock.connect(sockpath)
667            s, addr = serversock.accept()
668            assert not addr
669
670            s.send(b'X')
671            data = clientsock.recv(100)
672            assert data == b'X'
673            clientsock.send(b'Y')
674            data = s.recv(100)
675            assert data == b'Y'
676
677            clientsock.close()
678            s.close()
679        finally:
680            os.chdir(oldcwd)
681
682    def test_automatic_shutdown(self):
683        # doesn't really test anything, but at least should not explode
684        # in close_all_sockets()
685        import _socket
686        self.foo = _socket.socket()
687
688
689class AppTestNetlink:
690    def setup_class(cls):
691        if not hasattr(os, 'getpid'):
692            pytest.skip("AF_NETLINK needs os.getpid()")
693        w_ok = space.appexec([], "(): import _socket; " +
694                                 "return hasattr(_socket, 'AF_NETLINK')")
695        if not space.is_true(w_ok):
696            pytest.skip("no AF_NETLINK on this platform")
697        cls.space = space
698
699    def test_connect_to_kernel_netlink_routing_socket(self):
700        import _socket, os
701        s = _socket.socket(_socket.AF_NETLINK, _socket.SOCK_DGRAM, _socket.NETLINK_ROUTE)
702        assert s.getsockname() == (0, 0)
703        s.bind((0, 0))
704        a, b = s.getsockname()
705        assert a == os.getpid()
706        assert b == 0
707
708
709class AppTestPacket:
710    def setup_class(cls):
711        if not hasattr(os, 'getuid') or os.getuid() != 0:
712            pytest.skip("AF_PACKET needs to be root for testing")
713        w_ok = space.appexec([], "(): import _socket; " +
714                                 "return hasattr(_socket, 'AF_PACKET')")
715        if not space.is_true(w_ok):
716            pytest.skip("no AF_PACKET on this platform")
717        cls.space = space
718
719    def test_convert_between_tuple_and_sockaddr_ll(self):
720        import _socket
721        s = _socket.socket(_socket.AF_PACKET, _socket.SOCK_RAW)
722        assert s.getsockname() == ('', 0, 0, 0, '')
723        s.bind(('lo', 123))
724        a, b, c, d, e = s.getsockname()
725        assert (a, b, c) == ('lo', 123, 0)
726        assert isinstance(d, int)
727        assert isinstance(e, str)
728        assert 0 <= len(e) <= 8
729
730
731class AppTestSocketTCP:
732    HOST = 'localhost'
733    spaceconfig = {'usemodules': ['_socket', 'array']}
734
735    def setup_method(self, method):
736        w_HOST = self.space.wrap(self.HOST)
737        self.w_serv =self.space.appexec([w_socket, w_HOST],
738            '''(_socket, HOST):
739            serv = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
740            serv.bind((HOST, 0))
741            serv.listen(1)
742            return serv
743            ''')
744
745    def teardown_method(self, method):
746        if hasattr(self, 'w_serv'):
747            self.space.appexec([self.w_serv], '(serv): serv.close()')
748            self.w_serv = None
749
750    def test_timeout(self):
751        from _socket import timeout
752        def raise_timeout():
753            self.serv.settimeout(1.0)
754            self.serv.accept()
755        raises(timeout, raise_timeout)
756
757    def test_timeout_zero(self):
758        from _socket import error
759        def raise_error():
760            self.serv.settimeout(0.0)
761            foo = self.serv.accept()
762        raises(error, raise_error)
763
764    def test_recv_send_timeout(self):
765        from _socket import socket, timeout, SOL_SOCKET, SO_RCVBUF, SO_SNDBUF
766        cli = socket()
767        cli.connect(self.serv.getsockname())
768        t, addr = self.serv.accept()
769        cli.settimeout(1.0)
770        # test recv() timeout
771        t.send(b'*')
772        buf = cli.recv(100)
773        assert buf == b'*'
774        raises(timeout, cli.recv, 100)
775        # test that send() works
776        count = cli.send(b'!')
777        assert count == 1
778        buf = t.recv(1)
779        assert buf == b'!'
780        # test that sendall() works
781        count = cli.sendall(b'?')
782        assert count is None
783        buf = t.recv(1)
784        assert buf == b'?'
785        # speed up filling the buffers
786        t.setsockopt(SOL_SOCKET, SO_RCVBUF, 4096)
787        cli.setsockopt(SOL_SOCKET, SO_SNDBUF, 4096)
788        # test send() timeout
789        count = 0
790        try:
791            while 1:
792                count += cli.send(b'foobar' * 70)
793                assert count < 100000
794        except timeout:
795            pass
796        t.recv(count)
797        # test sendall() timeout
798        try:
799            while 1:
800                cli.sendall(b'foobar' * 70)
801        except timeout:
802            pass
803        # done
804        cli.close()
805        t.close()
806
807    def test_recv_into(self):
808        import socket
809        import array
810        MSG = b'dupa was here\n'
811        cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
812        cli.connect(self.serv.getsockname())
813        conn, addr = self.serv.accept()
814        buf = buffer(MSG)
815        conn.send(buf)
816        buf = array.array('b', b' ' * 1024)
817        nbytes = cli.recv_into(buf)
818        assert nbytes == len(MSG)
819        msg = buf.tostring()[:len(MSG)]
820        assert msg == MSG
821
822        conn.send(MSG)
823        buf = bytearray(1024)
824        nbytes = cli.recv_into(memoryview(buf))
825        assert nbytes == len(MSG)
826        msg = buf[:len(MSG)]
827        assert msg == MSG
828
829    def test_recvfrom_into(self):
830        import socket
831        import array
832        MSG = b'dupa was here\n'
833        cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
834        cli.connect(self.serv.getsockname())
835        conn, addr = self.serv.accept()
836        buf = buffer(MSG)
837        conn.send(buf)
838        buf = array.array('b', b' ' * 1024)
839        nbytes, addr = cli.recvfrom_into(buf)
840        assert nbytes == len(MSG)
841        msg = buf.tostring()[:len(MSG)]
842        assert msg == MSG
843
844        conn.send(MSG)
845        buf = bytearray(1024)
846        nbytes, addr = cli.recvfrom_into(memoryview(buf))
847        assert nbytes == len(MSG)
848        msg = buf[:len(MSG)]
849        assert msg == MSG
850
851        conn.send(MSG)
852        buf = bytearray(8)
853        exc = raises(ValueError, cli.recvfrom_into, buf, 1024)
854        assert str(exc.value) == "nbytes is greater than the length of the buffer"
855
856    def test_family(self):
857        import socket
858        cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
859        assert cli.family == socket.AF_INET
860
861
862class AppTestErrno:
863    spaceconfig = {'usemodules': ['_socket']}
864
865    def test_errno(self):
866        from socket import socket, AF_INET, SOCK_STREAM, error
867        import errno
868        s = socket(AF_INET, SOCK_STREAM)
869        exc = raises(error, s.accept)
870        assert isinstance(exc.value, error)
871        assert isinstance(exc.value, IOError)
872        # error is EINVAL, or WSAEINVAL on Windows
873        assert exc.value.errno == getattr(errno, 'WSAEINVAL', errno.EINVAL)
874        assert isinstance(exc.value.message, str)