1#!./parrot
2# Copyright (C) 2006-2014, Parrot Foundation.
3
4=head1 NAME
5
6t/pmc/socket.t - test the Socket PMC
7
8=head1 SYNOPSIS
9
10    % prove t/pmc/socket.t
11
12=head1 DESCRIPTION
13
14Tests the Socket PMC.
15
16The IPv6-related tests are in F<t/pmc/socket_ipv6.t>.
17We sometimes cannot even create an IPv6 family socket without
18HAS_IPV6, see GH #1068.
19
20=cut
21
22.include 'socket.pasm'
23.include 'iglobals.pasm'
24
25.sub main :main
26    .include 'test_more.pir'
27
28    plan(23)
29
30    test_init()
31    test_get_fd()
32    test_read()
33    test_clone()
34    test_bool()
35    test_close()
36    test_is_closed()
37    test_tcp_socket()
38    test_udp_socket()
39    test_getprotobyname()
40    test_server()
41
42.end
43
44.sub test_init
45    new $P0, ['Socket']
46    ok(1, 'Instantiated a Socket PMC')
47
48    $S0 = typeof $P0
49    is($S0, 'Socket', 'PMC has correct type')
50.end
51
52.sub test_get_fd
53    new $P0, ['Socket']
54    $N0 = $P0.'get_fd'()
55    ok(1, "can get_fd a Socket")
56.end
57
58.sub test_read
59    new $P0, ['Socket']
60    $N0 = $P0.'read'(5)
61    is($N0, 0, 'Socket read returns 0 when not connected')
62.end
63
64.sub test_bool
65    new $P0, ['Socket']
66    nok($P0, 'get_bool on closed Socket')
67.end
68
69.sub test_close
70    new $P0, ['Socket']
71    $P0.'close'()
72    ok(1, 'Closed a Socket')
73    nok($P0,'A closed Socket returns False')
74.end
75
76.sub test_is_closed
77    new $P0, ['Socket']
78
79    $N0 = $P0.'is_closed'()
80    is($N0, 1, 'Socket is_closed returned 1 to new socket')
81.end
82
83.sub test_getprotobyname
84    new $P0, ['Socket']
85    $I0 = $P0.'getprotobyname'("icmp")
86    is($I0, 1, 'Socket getprotobyname(icmp) returned 1')
87
88    $I0 = $P0.'getprotobyname'("tcp")
89    is($I0, 6, 'Socket getprotobyname(tcp) returned 6')
90
91    lives_ok(<<'CODE', "empty protocol name does not coredump")
92.sub main
93    new $P0, ['Socket']
94    $I0 = $P0.'getprotobyname'("")
95.end
96CODE
97
98    lives_ok(<<'CODE', "non-existent protocol name does not coredump")
99.sub main
100    new $P0, ['Socket']
101    $I0 = $P0.'getprotobyname'("junk")
102.end
103CODE
104
105.end
106
107.sub test_clone
108    new $P0, ['Socket']
109    $P1 = $P0."sockaddr"("localhost", 1234)
110
111    $P2 = clone $P0
112    ok(1, 'Cloned a Socket PMC')
113
114    $S0 = typeof $P2
115    $S1 = 'Socket'
116
117    $I0 = iseq $S0, $S1
118    ok($I0, 'Cloned PMC has correct type TT#1820')
119.end
120
121.sub test_create_socket
122    .param int pio_pf
123    .param int pio_sock
124    .param int pio_proto
125    .param string msg
126
127    .local pmc sock, ex
128    .local int r
129    r = 0
130    push_eh failed
131    sock = new 'Socket'
132    sock.'socket'(pio_pf, pio_sock, pio_proto)
133    pop_eh
134    r = 1
135    goto check
136  failed:
137    .get_results(ex)
138    finalize ex
139    pop_eh
140    $S0 = ex['message']
141    diag($S0)
142  check:
143    is(r, 1, msg)
144.end
145
146.sub test_tcp_socket
147    test_create_socket(.PIO_PF_INET, .PIO_SOCK_STREAM, .PIO_PROTO_TCP, 'Created a TCP Socket')
148.end
149
150.sub test_udp_socket
151    test_create_socket(.PIO_PF_INET, .PIO_SOCK_DGRAM, .PIO_PROTO_UDP, 'Created a UDP Socket')
152.end
153
154.sub test_server
155    .local pmc interp, conf, server, sock, address, result
156    .local string command, str, part
157    .local int status, port
158
159    interp = getinterp
160    conf = interp[.IGLOBALS_CONFIG_HASH]
161
162  run_tests:
163    command = '"'
164    str = conf['build_dir']
165    command .= str
166    str = conf['slash']
167    command .= str
168    command .= 'parrot'
169    str = conf['exe']
170    command .= str
171    command .= '" t/pmc/testlib/test_server.pir'
172
173    server = new 'FileHandle'
174    server.'open'(command, 'rp')
175    str = server.'readline'()
176    part = substr str, 0, 34
177    is(part, 'Server started, listening on port ', 'Server process started')
178    part = substr str, 34, 4
179    port = part
180
181    sock = new 'Socket'
182    result = sock.'socket'(.PIO_PF_INET, .PIO_SOCK_STREAM, .PIO_PROTO_TCP)
183    ok(result, 'socket')
184    address = sock.'sockaddr'('localhost', port)
185    sock.'connect'(address)
186    status = sock.'send'('test message')
187    is(status, '12', 'send')
188    str = sock.'recv'()
189    is(str, 'test message', 'recv')
190
191    .local int i, len, oldlen, readlen
192    i = 0
193  loop:
194    str = concat str, "a"
195    i = i + 1
196    if i < 2048 goto loop
197    oldlen = length str
198    status = sock.'send'(str)
199    is(status, oldlen, 'send() big')
200    str = ""
201    .local string tmpstr
202  loop1:
203    tmpstr = sock.'read'(1024)
204    readlen = length tmpstr
205    str = concat str, tmpstr
206    len = length str
207    # diag(len)
208    if len == 0 goto bigger
209    if len < oldlen goto loop1
210  bigger:
211    is(len, oldlen, 'read(1024) chunked')
212
213    sock.'close'()
214    server.'close'()
215    status = server.'exit_status'()
216    nok(status, 'Exit status of server process')
217.end
218
219# Local Variables:
220#   mode: pir
221#   fill-column: 100
222# End:
223# vim: expandtab shiftwidth=4 ft=pir:
224