unit-tests: Don't assert failures for unreadable settings files as root
[strongswan.git] / src / libstrongswan / tests / suites / test_fetch_http.c
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "test_suite.h"
17
18 #include <unistd.h>
19 #include <time.h>
20
21 /**
22 * HTTP test definition
23 */
24 typedef struct {
25 /* HTTP Method */
26 char *meth;
27 /* HTTP 1.x minor version */
28 int minor;
29 /* host to connect to */
30 char *host;
31 /* HTTP service port */
32 int port;
33 /* path on host to fetch from */
34 char *path;
35 /* request Content-Type, if any */
36 char *type;
37 /* request data, if any */
38 void *req;
39 /* length of request data */
40 int req_len;
41 /* response data, if any */
42 void *res;
43 /* length of response data */
44 int res_len;
45 } test_service_t;
46
47 static char large[] = {
48 0x88,0x3e,0xa3,0xe3,0x95,0x67,0x53,0x93,0xc8,0xce,0x5c,0xcd,0x8c,0x03,0x0c,0xa8,
49 0x94,0xaf,0x49,0xf6,0xc6,0x50,0xad,0xb8,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
50 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
51 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
52 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
53 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
54 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
55 0xb4,0xa3,0x15,0x08,0xbe,0xff,0x4d,0x31,0x81,0x39,0x62,0x29,0xf0,0x90,0x79,0x02,
56 0x4d,0x0c,0xf4,0x9e,0xe5,0xd4,0xdc,0xca,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
57 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
58 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
59 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
60 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
61 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
62 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
63 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
64 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
65 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
66 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
67 0xb4,0xa3,0x15,0x08,0xbe,0xff,0x4d,0x31,0x81,0x39,0x62,0x29,0xf0,0x90,0x79,0x02,
68 0x4d,0x0c,0xf4,0x9e,0xe5,0xd4,0xdc,0xca,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
69 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
70 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
71 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
72 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
73 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
74 0xb4,0xa3,0x15,0x08,0xbe,0xff,0x4d,0x31,0x81,0x39,0x62,0x29,0xf0,0x90,0x79,0x02,
75 0x4d,0x0c,0xf4,0x9e,0xe5,0xd4,0xdc,0xca,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
76 };
77
78 static bool servicing(void *data, stream_t *stream)
79 {
80 test_service_t *test = (test_service_t*)data;
81 char buf[1024], hdr[256], *start, *end = NULL, *body = NULL, *type = NULL;
82 struct tm tm;
83 time_t t;
84 ssize_t len, tot = 0;
85 int nr = 0;
86
87 start = buf;
88
89 /* parse method and headers */
90 while (end != start)
91 {
92 len = stream->read(stream, buf + tot, sizeof(buf) - tot, TRUE);
93 ck_assert(len > 0);
94 tot += len;
95
96 while (TRUE)
97 {
98 end = memchr(start, '\n', tot);
99 if (!end)
100 {
101 break;
102 }
103 *end = '\0';
104 ck_assert(end > buf);
105 ck_assert(*(--end) == '\r');
106 *end = '\0';
107 if (end == start)
108 {
109 body = end + strlen("\r\n");
110 break;
111 }
112 switch (nr++)
113 {
114 case 0:
115 snprintf(hdr, sizeof(hdr), "%s %s HTTP/1.%u",
116 test->meth, test->path, test->minor);
117 ck_assert_str_eq(hdr, start);
118 break;
119 default:
120 if (strcasepfx(start, "Content-Length: "))
121 {
122 ck_assert_int_eq(
123 atoi(start + strlen("Content-Length: ")),
124 test->req_len);
125 }
126 if (strcasepfx(start, "Content-Type: "))
127 {
128 type = start + strlen("Content-Type: ");
129 }
130 break;
131 }
132 start = end + strlen("\r\n");
133 }
134 }
135
136 if (test->type)
137 {
138 ck_assert(type);
139 ck_assert_str_eq(type, test->type);
140 }
141
142 /* request body */
143 if (test->req_len)
144 {
145 ck_assert(stream->read_all(stream, buf + tot,
146 test->req_len - (tot - (body - buf))));
147 ck_assert(memeq(body, test->req, test->req_len));
148 }
149
150 /* response headers */
151 snprintf(buf, sizeof(buf), "HTTP/1.%u 200 OK\r\n", test->minor);
152 ck_assert(stream->write_all(stream, buf, strlen(buf)));
153 t = time(NULL);
154 gmtime_r(&t, &tm);
155 strftime(buf, sizeof(buf), "%a, %d %b %Y %T %z", &tm);
156 ck_assert(stream->write_all(stream, buf, strlen(buf)));
157 snprintf(buf, sizeof(buf), "Server: strongSwan unit test\r\n");
158 ck_assert(stream->write_all(stream, buf, strlen(buf)));
159
160 /* rest of response headers */
161 snprintf(buf, sizeof(buf), "Content-Type: text/plain\r\n");
162 ck_assert(stream->write_all(stream, buf, strlen(buf)));
163 snprintf(buf, sizeof(buf), "Content-Length: %u\r\n", test->res_len);
164 ck_assert(stream->write_all(stream, buf, strlen(buf)));
165 snprintf(buf, sizeof(buf), "Connection: close\r\n");
166 ck_assert(stream->write_all(stream, buf, strlen(buf)));
167 snprintf(buf, sizeof(buf), "\r\n");
168 ck_assert(stream->write_all(stream, buf, strlen(buf)));
169
170 /* response body */
171 ck_assert(stream->write_all(stream, test->res, test->res_len));
172 return FALSE;
173 }
174
175 static test_service_t gtests[] = {
176 { "GET", 1, "127.0.0.1", 6543, "/a/test/?b=c", NULL,
177 NULL, 0, "\x12\x34", 2 },
178 { "GET", 0, "localhost", 6543, "/", NULL,
179 NULL, 0, NULL, 0 },
180 { "GET", 0, "127.0.0.1", 6543, "/largefile", NULL,
181 NULL, 0, large, sizeof(large) },
182 { "GET", 1, "[::1]", 6543, "/ipv6-url", NULL,
183 NULL, 0, "\x00\r\n\r\x00testdatablabla", 20 },
184 };
185
186 START_TEST(test_get)
187 {
188 stream_service_t *service;
189 status_t status;
190 chunk_t data, expected;
191 char uri[256];
192
193 lib->processor->set_threads(lib->processor, 8);
194
195 snprintf(uri, sizeof(uri), "tcp://%s:%u", gtests[_i].host, gtests[_i].port);
196 service = lib->streams->create_service(lib->streams, uri, 1);
197 ck_assert(service != NULL);
198 service->on_accept(service, servicing, &gtests[_i], JOB_PRIO_HIGH, 0);
199
200 snprintf(uri, sizeof(uri), "http://%s:%u%s",
201 gtests[_i].host, gtests[_i].port, gtests[_i].path);
202 status = lib->fetcher->fetch(lib->fetcher, uri, &data,
203 !gtests[_i].minor ? FETCH_HTTP_VERSION_1_0 : FETCH_END,
204 FETCH_END);
205 ck_assert_int_eq(status, SUCCESS);
206 expected = chunk_create(gtests[_i].res, gtests[_i].res_len);
207 ck_assert_msg(chunk_compare(expected, data) == 0,
208 "exp %B\ngot %B\n", &expected, &data);
209 free(data.ptr);
210
211 service->destroy(service);
212 }
213 END_TEST
214
215
216 static test_service_t ptests[] = {
217 { "POST", 1, "127.0.0.1", 6543, "/a/test/?b=c", "application/binary",
218 "\x23\x45", 2, "\x12\x34", 2 },
219 { "POST", 0, "localhost", 6543, "/largefile", "application/x-large",
220 large, sizeof(large), large, sizeof(large) },
221 { "POST", 1, "[::1]", 6543, "/ipv6-url", "text/plain",
222 "\x00\r\n\r\x00testdatablabla", 20, "\x00\r\n\r\x00testdatablabla", 20 },
223 };
224
225 START_TEST(test_post)
226 {
227 stream_service_t *service;
228 status_t status;
229 chunk_t data, expected;
230 char uri[256];
231
232 lib->processor->set_threads(lib->processor, 8);
233
234 snprintf(uri, sizeof(uri), "tcp://%s:%u", ptests[_i].host, ptests[_i].port);
235 service = lib->streams->create_service(lib->streams, uri, 1);
236 ck_assert(service != NULL);
237 service->on_accept(service, servicing, &ptests[_i], JOB_PRIO_HIGH, 0);
238
239 snprintf(uri, sizeof(uri), "http://%s:%u%s",
240 ptests[_i].host, ptests[_i].port, ptests[_i].path);
241 status = lib->fetcher->fetch(lib->fetcher, uri, &data,
242 FETCH_REQUEST_TYPE, ptests[_i].type,
243 FETCH_REQUEST_DATA,
244 chunk_create(ptests[_i].req, ptests[_i].req_len),
245 !ptests[_i].minor ? FETCH_HTTP_VERSION_1_0 : FETCH_END,
246 FETCH_END);
247 ck_assert_int_eq(status, SUCCESS);
248 expected = chunk_create(ptests[_i].res, ptests[_i].res_len);
249 ck_assert_msg(chunk_compare(expected, data) == 0,
250 "exp %B\ngot %B\n", &expected, &data);
251 free(data.ptr);
252
253 service->destroy(service);
254 }
255 END_TEST
256
257 Suite *fetch_http_suite_create()
258 {
259 Suite *s;
260 TCase *tc;
261
262 s = suite_create("http fetcher");
263
264 tc = tcase_create("GET");
265 tcase_add_loop_test(tc, test_get, 0, countof(gtests));
266 suite_add_tcase(s, tc);
267
268 tc = tcase_create("POST");
269 tcase_add_loop_test(tc, test_post, 0, countof(ptests));
270 suite_add_tcase(s, tc);
271
272 return s;
273 }