CCL: split-list deals with multiple use attr YAZ-844
[yaz-moved-to-github.git] / test / test_comstack.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 #if HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdio.h>
12
13 #include <yaz/test.h>
14 #include <yaz/comstack.h>
15 #include <yaz/tcpip.h>
16
17 static void tst_http_request(void)
18 {
19     {
20         /* no content, no headers */
21         const char *http_buf =
22             /*123456789012345678 */
23             "GET / HTTP/1.1\r\n"
24             "\r\n"
25             "GET / HTTP/1.0\r\n";
26
27         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
28         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
29         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 16), 0);
30         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 17), 0);
31         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 18), 18);
32         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 19), 18);
33     }
34     {
35         /* one header, no content */
36         const char *http_buf =
37             /*123456789012345678 */
38             "GET / HTTP/1.1\r\n"
39             "Content-Type: x\r\n"
40             "\r\n"
41             "GET / HTTP/1.0\r\n";
42
43         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
44         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
45         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 34), 0);
46         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 35), 35);
47         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 36), 35);
48     }
49     {
50         /* one content-length header, length 0 */
51         const char *http_buf =
52             /*123456789012345678 */
53             "GET / HTTP/1.1\r\n"
54             "Content-Length: 0\r\n"
55             "\r\n"
56             "GET / HTTP/1.0\r\n";
57
58         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
59         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
60         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 35), 0);
61         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 37), 37);
62         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 38), 37);
63     }
64     {
65         /* one content-length header, length 5 */
66         const char *http_buf =
67             /*123456789012345678 */
68             "GET / HTTP/1.1\r\n"
69             "Content-Length: 5\r\n"
70             "\r\n"
71             "ABCDE"
72             "GET / HTTP/1.0\r\n";
73
74         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
75         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
76         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 41), 0);
77         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 42), 42);
78         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 43), 42);
79     }
80     {
81         /* LF only in GET, one content-length header, length 5 */
82         const char *http_buf =
83             /*123456789012345678 */
84             "GET / HTTP/1.1\n"
85             "Content-Length: 5\r\n"
86             "\r\n"
87             "ABCDE"
88             "GET / HTTP/1.0\r\n";
89
90         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
91         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
92         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 40), 0);
93         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 41), 41);
94         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 42), 41);
95     }
96     {
97         /* LF only in all places, one content-length header, length 5 */
98         const char *http_buf =
99             /*123456789012345678 */
100             "GET / HTTP/1.1\n"
101             "Content-Length: 5\n"
102             "\n"
103             "ABCDE"
104             "GET / HTTP/1.0\r\n";
105
106         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
107         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
108         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 38), 0);
109         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 39), 39);
110         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 40), 39);
111     }
112
113     {
114         /* one header, unknown transfer-encoding (no content) */
115         const char *http_buf =
116             /*12345678901234567890123456789 */
117             "GET / HTTP/1.1\r\n"
118             "Transfer-Encoding: chunke_\r\n"
119             "\r\n"
120             "GET / HTTP/1.0\r\n";
121
122         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 45), 0);
123         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 46), 46);
124     }
125
126     {
127         /* one header, one chunk */
128         const char *http_buf =
129             /*12345678901234567890123456789 */
130             "GET / HTTP/1.1\r\n"
131             "Transfer-Encoding: chunked\r\n"
132             "\r\n"
133             "3\r\n"
134             "123\r\n"
135             "0\r\n\r\n"
136             "GET / HTTP/1.0\r\n";
137
138         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 58), 0);
139         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 59), 59);
140     }
141
142     {
143         /* one header, two chunks */
144         const char *http_buf =
145             /*12345678901234567890123456789 */
146             "GET / HTTP/1.1\r\n"
147             "Transfer-Encoding: chunked\r\n"
148             "\r\n"
149             "3\r\n"
150             "123\r\n"
151             "2\r\n"
152             "12\n"
153             "0\r\n\r\n"
154             "GET / HTTP/1.0\r\n";
155
156         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 64), 0);
157         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 65), 65);
158     }
159 }
160
161 static void tst_http_response(void)
162 {
163     {
164         /* unlimited content, no headers */
165         const char *http_buf =
166             /*123456789012345678 */
167             "HTTP/1.1 200 OK\r\n"
168             "\r\n"
169             "HTTP/1.1 200 OK\r\n";
170
171         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
172         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
173         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 24), 0);
174     }
175     {
176         /* no content, no headers */
177         const char *http_buf =
178             /*123456789012345678 */
179             "HTTP/1.1 204 OK\r\n"
180             "\r\n"
181             "HTTP/1.1 200 OK\r\n";
182
183         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
184         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
185         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 18), 0);
186         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 19), 19);
187         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 24), 19);
188     }
189     {
190         /* response, content  */
191         const char *http_buf =
192             /*123456789012345678 */
193             "HTTP/1.1 200 OK\r\n"
194             "Content-Length: 2\r\n"
195             "\r\n"
196             "12"
197             "HTTP/1.1 200 OK\r\n";
198
199         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 1), 0);
200         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 2), 0);
201         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 39), 0);
202         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 40), 40);
203         YAZ_CHECK_EQ(cs_complete_auto(http_buf, 41), 40);
204     }
205 }
206
207 /** \brief COMSTACK synopsis from manual, doc/comstack.xml */
208 static int comstack_example(const char *server_address_str)
209 {
210     COMSTACK stack;
211     char *buf = 0;
212     int size = 0, length_incoming;
213     void *server_address_ip;
214     int status;
215
216     char *protocol_package = "GET / HTTP/1.0\r\n\r\n";
217     int protocol_package_length = strlen(protocol_package);
218
219     stack = cs_create(tcpip_type, 1, PROTO_HTTP);
220     if (!stack) {
221         perror("cs_create");  /* use perror() here since we have no stack yet */
222         return -1;
223     }
224
225     server_address_ip = cs_straddr(stack, server_address_str);
226     if (!server_address_ip) {
227         fprintf(stderr, "cs_straddr: address could not be resolved\n");
228         return -1;
229     }
230
231     status = cs_connect(stack, server_address_ip);
232     if (status) {
233         fprintf(stderr, "cs_connect: %s\n", cs_strerror(stack));
234         return -1;
235     }
236
237     status = cs_rcvconnect(stack);
238     if (status) {
239         fprintf(stderr, "cs_rcvconnect: %s\n", cs_strerror(stack));
240         return -1;
241     }
242
243     status = cs_put(stack, protocol_package, protocol_package_length);
244     if (status) {
245         fprintf(stderr, "cs_put: %s\n", cs_strerror(stack));
246         return -1;
247     }
248
249     /* Now get a response */
250     length_incoming = cs_get(stack, &buf, &size);
251     if (!length_incoming) {
252         fprintf(stderr, "Connection closed\n");
253         return -1;
254     } else if (length_incoming < 0) {
255         fprintf(stderr, "cs_get: %s\n", cs_strerror(stack));
256         return -1;
257     }
258
259     /* Print result */
260     fwrite(buf, length_incoming, 1, stdout);
261
262     /* clean up */
263     cs_close(stack);
264     if (buf)
265         xfree(buf);
266     return 0;
267 }
268
269 static void tst_cs_get_host_args(void)
270 {
271     const char *arg = 0;
272
273     cs_get_host_args("http://localhost:9999", &arg);
274     YAZ_CHECK(arg && !strcmp(arg, ""));
275     cs_get_host_args("http://localhost:9999/x", &arg);
276     YAZ_CHECK(arg && !strcmp(arg, "x"));
277     cs_get_host_args("http://localhost:9999?x", &arg);
278     YAZ_CHECK(arg && !strcmp(arg, ""));
279     cs_get_host_args("localhost:9999", &arg);
280     YAZ_CHECK(arg && !strcmp(arg, ""));
281     cs_get_host_args("localhost:9999/", &arg);
282     YAZ_CHECK(arg && !strcmp(arg, ""));
283     cs_get_host_args("localhost:9999/x&url=http://some.host", &arg);
284     YAZ_CHECK(arg && !strcmp(arg, "x&url=http://some.host"));
285     cs_get_host_args("http://localhost:9999/x&url=http://some.host", &arg);
286     YAZ_CHECK(arg && !strcmp(arg, "x&url=http://some.host"));
287     cs_get_host_args("http:/localhost:9999/x", &arg);
288     YAZ_CHECK(arg && !strcmp(arg, "localhost:9999/x"));
289     cs_get_host_args("http//localhost:9999/x", &arg);
290     YAZ_CHECK(arg && !strcmp(arg, "/localhost:9999/x"));
291     cs_get_host_args("http://y/x", &arg);
292     YAZ_CHECK(arg && !strcmp(arg, "x"));
293     cs_get_host_args("http:///x", &arg);
294     YAZ_CHECK(arg && !strcmp(arg, "x"));
295 }
296
297 int main (int argc, char **argv)
298 {
299     YAZ_CHECK_INIT(argc, argv);
300     YAZ_CHECK_LOG();
301     if (argc == 2)
302        comstack_example(argv[1]);
303     tst_http_request();
304     tst_http_response();
305     tst_cs_get_host_args();
306     YAZ_CHECK_TERM;
307 }
308
309 /*
310  * Local variables:
311  * c-basic-offset: 4
312  * c-file-style: "Stroustrup"
313  * indent-tabs-mode: nil
314  * End:
315  * vim: shiftwidth=4 tabstop=8 expandtab
316  */
317