1 /* testsock.i
2  * Tests of socket API.
3  */
4 /* Copyright (c) 2015, David H. Munro.
5  * All rights reserved.
6  * This file is part of yorick (http://yorick.sourceforge.net).
7  * Read the accompanying LICENSE file for details.
8  */
9 
testsock(port)10 func testsock(port)
11 {
12   listener = socket((port?port:0), accept_cb);
13   write, format="%s\n", "listening - now start client yorick, then type:";
14   write, format="%s\n", "#include \"testsock.i\"";
15   write, format="testclient, %ld;\n", listener.port;
16 }
17 
testclient(port,host)18 func testclient(port, host)
19 {
20   sock = socket((host?host:noop(-)), port);
21   n = test_data(*);
22   for (i=1,fail=0 ; i<=n ; ++i) {
23     s = test_data(noop(i));
24     if (i & 1) {
25       write, format="socket client send %ld...", i;
26       if (socksend(sock, s) != sizeof(s)) {
27         close, sock;
28         error, "socket test client died on test "+totxt(i);
29       }
30       write, format="%s\n", "";
31     } else {
32       r = s;
33       r(..) *= 0;
34       write, format="socket client recv %ld...", i;
35       if (sockrecv(sock, r) != sizeof(r)) {
36         close, sock;
37         error, "socket test client died on test "+totxt(i);
38       }
39       write, format="%s\n", "";
40       if (anyof(r != s)) {
41         write, format="WARNING - socket client recv failed on test %ld\n", i;
42         fail += 1;
43       }
44     }
45   }
46   write, format="socket client recv %s...", "final";
47   r = array(0, 10);
48   if (sockrecv(sock, r)!=sizeof(r)/2 || anyof(r(1:5)!=indgen(5))) {
49     write, format="%s\n", "WARNING - socket client recv failed on final test";
50     fail += 1;
51   }
52   write, format="%s\n", "";
53   close, sock;
54   if (fail) error, "socket test client recv failure count: "+totxt(fail);
55   write, format="%s\n", "SUCCESS - socket test client side passed all tests";
56 }
57 
58 test_state = save(reset, recv, step, sock, req, irep, imax, fail);
recv(sock)59 func recv(sock)   /* recv callback, do as little as possible */
60 {
61   if (catch(-1)) {
62     write, "FATAL - socket server recv callback closing sock";
63     close, sock;
64     return;
65   }
66   sockrecv, sock, use(req);
67   after, 0., test_state, "step";  /* defer most work */
68 }
reset(s)69 func reset(s)
70 {
71   use, sock, req, irep, imax, fail;
72   sock = s
73   req = test_data(1);
74   req(..) = 0;
75   irep = 2;
76   imax = test_data(*);
77   fail = 0;
78   write, format="\n%s\n", "connection established, listener shut down";
79 }
80 func step
81 {
82   use, sock, req, irep, imax, fail;
83   write, format="socket server recv %ld\n", irep-1;
84   if (anyof(test_data(irep-1) != req)) {
85     write, format="WARNING - socket server recv failed on test %ld\n", irep-1;
86     fail += 1;
87   }
88   if (irep <= imax) {
89     write, format="socket server send %ld...", irep;
90     socksend, sock, test_data(noop(irep));
91     write, format="%s\n", "";
92   }
93   if (irep < imax) {  /* at least one more recv to wait for */
94     req = test_data(irep+1);
95     irep += 2;
96     return;
97   }
98   /* send final partial message to client */
99   write, format="socket server send %s...", "final";
100   socksend, sock, indgen(5);
101   write, format="%s\n", "";
102   close, sock;
103   req = [];
104   if (fail) error, "socket test server recv failure count: "+totxt(fail);
105   write, format="%s\n", "SUCCESS - socket test server side passed all tests";
106   maybe_prompt;  /* why doesn't this work? */
107   write, format="%s", "> ";
108 }
109 sock = req = irep = imax = fail = [];
110 test_state = restore(test_state);
111 
112 recv_cb = closure(test_state, "recv");
accept_cb(sock)113 func accept_cb(sock) {
114   test_state, reset, sock(recv_cb);
115   close, sock;
116 }
117 
118 x = indgen(0:1738);
119 test_data = save(,x, ,char(x), ,short(x(::-1)+x(-,)), ,int(x-x(-,)),
120                  ,float(x-31), ,double(x*x(-,)), ,(x-51)-1i*(x-432));
121