Annotation of embedaddon/strongswan/src/libstrongswan/tests/suites/test_fetch_http.c, revision 1.1
1.1 ! misho 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: #define HTTP_SUCCESS(status) ((status) >= 200 && (status) < 300)
! 22:
! 23: /**
! 24: * HTTP test definition
! 25: */
! 26: typedef struct {
! 27: /* HTTP Method */
! 28: char *meth;
! 29: /* HTTP 1.x minor version */
! 30: int minor;
! 31: /* host to connect to */
! 32: char *host;
! 33: /* HTTP service port */
! 34: int port;
! 35: /* path on host to fetch from */
! 36: char *path;
! 37: /* request Content-Type, if any */
! 38: char *type;
! 39: /* request data, if any */
! 40: void *req;
! 41: /* length of request data */
! 42: int req_len;
! 43: /* response data, if any */
! 44: void *res;
! 45: /* length of response data */
! 46: int res_len;
! 47: /* status code, defaults to 200 */
! 48: u_int code;
! 49: } test_service_t;
! 50:
! 51: static char large[] = {
! 52: 0x88,0x3e,0xa3,0xe3,0x95,0x67,0x53,0x93,0xc8,0xce,0x5c,0xcd,0x8c,0x03,0x0c,0xa8,
! 53: 0x94,0xaf,0x49,0xf6,0xc6,0x50,0xad,0xb8,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
! 54: 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
! 55: 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
! 56: 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
! 57: 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
! 58: 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
! 59: 0xb4,0xa3,0x15,0x08,0xbe,0xff,0x4d,0x31,0x81,0x39,0x62,0x29,0xf0,0x90,0x79,0x02,
! 60: 0x4d,0x0c,0xf4,0x9e,0xe5,0xd4,0xdc,0xca,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
! 61: 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
! 62: 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
! 63: 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
! 64: 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
! 65: 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
! 66: 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
! 67: 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
! 68: 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
! 69: 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
! 70: 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
! 71: 0xb4,0xa3,0x15,0x08,0xbe,0xff,0x4d,0x31,0x81,0x39,0x62,0x29,0xf0,0x90,0x79,0x02,
! 72: 0x4d,0x0c,0xf4,0x9e,0xe5,0xd4,0xdc,0xca,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
! 73: 0xf3,0x15,0xbb,0x5b,0xb8,0x35,0xd8,0x17,0xad,0xcf,0x6b,0x07,0x63,0x61,0x2e,0x2f,
! 74: 0xa5,0xc9,0x1d,0xa7,0xac,0xaa,0x4d,0xde,0x71,0x65,0x95,0x87,0x66,0x50,0xa2,0xa6,
! 75: 0x28,0xef,0x49,0x5c,0x53,0xa3,0x87,0xad,0x42,0xc3,0x41,0xd8,0xfa,0x92,0xd8,0x32,
! 76: 0xce,0x7c,0xf2,0x72,0x2f,0x51,0x27,0x71,0xe3,0x78,0x59,0xf9,0x46,0x23,0xf3,0xa7,
! 77: 0x38,0x12,0x05,0xbb,0x1a,0xb0,0xe0,0x12,0xae,0x97,0xa1,0x0f,0xd4,0x34,0xe0,0x15,
! 78: 0xb4,0xa3,0x15,0x08,0xbe,0xff,0x4d,0x31,0x81,0x39,0x62,0x29,0xf0,0x90,0x79,0x02,
! 79: 0x4d,0x0c,0xf4,0x9e,0xe5,0xd4,0xdc,0xca,0xea,0xb8,0x85,0x8a,0xde,0x92,0xe1,0xbc,
! 80: };
! 81:
! 82: static bool servicing(void *data, stream_t *stream)
! 83: {
! 84: test_service_t *test = (test_service_t*)data;
! 85: char buf[1024], hdr[256], *start, *end = NULL, *body = NULL, *type = NULL;
! 86: struct tm tm;
! 87: time_t t;
! 88: ssize_t len, tot = 0;
! 89: int nr = 0;
! 90:
! 91: start = buf;
! 92:
! 93: /* parse method and headers */
! 94: while (end != start)
! 95: {
! 96: len = stream->read(stream, buf + tot, sizeof(buf) - tot, TRUE);
! 97: ck_assert(len > 0);
! 98: tot += len;
! 99:
! 100: while (TRUE)
! 101: {
! 102: end = memchr(start, '\n', tot);
! 103: if (!end)
! 104: {
! 105: break;
! 106: }
! 107: *end = '\0';
! 108: ck_assert(end > buf);
! 109: ck_assert(*(--end) == '\r');
! 110: *end = '\0';
! 111: if (end == start)
! 112: {
! 113: body = end + strlen("\r\n");
! 114: break;
! 115: }
! 116: switch (nr++)
! 117: {
! 118: case 0:
! 119: snprintf(hdr, sizeof(hdr), "%s %s HTTP/1.%u",
! 120: test->meth, test->path, test->minor);
! 121: ck_assert_str_eq(hdr, start);
! 122: break;
! 123: default:
! 124: if (strcasepfx(start, "Content-Length: "))
! 125: {
! 126: ck_assert_int_eq(
! 127: atoi(start + strlen("Content-Length: ")),
! 128: test->req_len);
! 129: }
! 130: if (strcasepfx(start, "Content-Type: "))
! 131: {
! 132: type = start + strlen("Content-Type: ");
! 133: }
! 134: break;
! 135: }
! 136: start = end + strlen("\r\n");
! 137: }
! 138: }
! 139:
! 140: if (test->type)
! 141: {
! 142: ck_assert(type);
! 143: ck_assert_str_eq(type, test->type);
! 144: }
! 145:
! 146: /* request body */
! 147: if (test->req_len)
! 148: {
! 149: ck_assert(stream->read_all(stream, buf + tot,
! 150: test->req_len - (tot - (body - buf))));
! 151: ck_assert(memeq(body, test->req, test->req_len));
! 152: }
! 153:
! 154: if (!test->code)
! 155: {
! 156: test->code = 200;
! 157: }
! 158:
! 159: /* response headers */
! 160: snprintf(buf, sizeof(buf), "HTTP/1.%u %u OK\r\n", test->minor, test->code);
! 161: ck_assert(stream->write_all(stream, buf, strlen(buf)));
! 162:
! 163: /* if the response code indicates an error the following write operations
! 164: * might fail because the client already terminated the TCP connection */
! 165: #define may_fail(test, op) ck_assert(op || !HTTP_SUCCESS(test->code))
! 166:
! 167: t = time(NULL);
! 168: gmtime_r(&t, &tm);
! 169: strftime(buf, sizeof(buf), "%a, %d %b %Y %T %z", &tm);
! 170: may_fail(test, stream->write_all(stream, buf, strlen(buf)));
! 171: snprintf(buf, sizeof(buf), "Server: strongSwan unit test\r\n");
! 172: may_fail(test, stream->write_all(stream, buf, strlen(buf)));
! 173:
! 174: /* rest of response headers */
! 175: snprintf(buf, sizeof(buf), "Content-Type: text/plain\r\n");
! 176: may_fail(test, stream->write_all(stream, buf, strlen(buf)));
! 177: snprintf(buf, sizeof(buf), "Content-Length: %u\r\n", test->res_len);
! 178: may_fail(test, stream->write_all(stream, buf, strlen(buf)));
! 179: snprintf(buf, sizeof(buf), "Connection: close\r\n");
! 180: may_fail(test, stream->write_all(stream, buf, strlen(buf)));
! 181: snprintf(buf, sizeof(buf), "\r\n");
! 182: may_fail(test, stream->write_all(stream, buf, strlen(buf)));
! 183:
! 184: /* response body */
! 185: may_fail(test, stream->write_all(stream, test->res, test->res_len));
! 186: return FALSE;
! 187: }
! 188:
! 189: static test_service_t gtests[] = {
! 190: { "GET", 1, "127.0.0.1", 6543, "/a/test/?b=c", NULL,
! 191: NULL, 0, "\x12\x34", 2, 0 },
! 192: { "GET", 0, "localhost", 6543, "/", NULL,
! 193: NULL, 0, NULL, 0, 0 },
! 194: { "GET", 0, "127.0.0.1", 6543, "/largefile", NULL,
! 195: NULL, 0, large, sizeof(large), 0 },
! 196: { "GET", 1, "[::1]", 6543, "/ipv6-url", NULL,
! 197: NULL, 0, "\x00\r\n\r\x00testdatablabla", 20, 0 },
! 198: };
! 199:
! 200: START_TEST(test_get)
! 201: {
! 202: stream_service_t *service;
! 203: status_t status;
! 204: chunk_t data, expected;
! 205: char uri[256];
! 206:
! 207: lib->processor->set_threads(lib->processor, 8);
! 208:
! 209: snprintf(uri, sizeof(uri), "tcp://%s:%u", gtests[_i].host, gtests[_i].port);
! 210: service = lib->streams->create_service(lib->streams, uri, 1);
! 211: ck_assert(service != NULL);
! 212: service->on_accept(service, servicing, >ests[_i], JOB_PRIO_HIGH, 0);
! 213:
! 214: snprintf(uri, sizeof(uri), "http://%s:%u%s",
! 215: gtests[_i].host, gtests[_i].port, gtests[_i].path);
! 216: status = lib->fetcher->fetch(lib->fetcher, uri, &data,
! 217: !gtests[_i].minor ? FETCH_HTTP_VERSION_1_0 : FETCH_END,
! 218: FETCH_END);
! 219: ck_assert_int_eq(status, SUCCESS);
! 220: expected = chunk_create(gtests[_i].res, gtests[_i].res_len);
! 221: ck_assert_msg(chunk_compare(expected, data) == 0,
! 222: "exp %B\ngot %B\n", &expected, &data);
! 223: free(data.ptr);
! 224:
! 225: service->destroy(service);
! 226: }
! 227: END_TEST
! 228:
! 229:
! 230: static test_service_t ptests[] = {
! 231: { "POST", 1, "127.0.0.1", 6543, "/a/test/?b=c", "application/binary",
! 232: "\x23\x45", 2, "\x12\x34", 2, 0 },
! 233: { "POST", 0, "localhost", 6543, "/largefile", "application/x-large",
! 234: large, sizeof(large), large, sizeof(large), 0 },
! 235: { "POST", 1, "[::1]", 6543, "/ipv6-url", "text/plain",
! 236: "\x00\r\n\r\x00testdatablabla", 20, "\x00\r\n\r\x00testdatablabla", 20, 0 },
! 237: };
! 238:
! 239: START_TEST(test_post)
! 240: {
! 241: stream_service_t *service;
! 242: status_t status;
! 243: chunk_t data, expected;
! 244: char uri[256];
! 245:
! 246: lib->processor->set_threads(lib->processor, 8);
! 247:
! 248: snprintf(uri, sizeof(uri), "tcp://%s:%u", ptests[_i].host, ptests[_i].port);
! 249: service = lib->streams->create_service(lib->streams, uri, 1);
! 250: ck_assert(service != NULL);
! 251: service->on_accept(service, servicing, &ptests[_i], JOB_PRIO_HIGH, 0);
! 252:
! 253: snprintf(uri, sizeof(uri), "http://%s:%u%s",
! 254: ptests[_i].host, ptests[_i].port, ptests[_i].path);
! 255: status = lib->fetcher->fetch(lib->fetcher, uri, &data,
! 256: FETCH_REQUEST_TYPE, ptests[_i].type,
! 257: FETCH_REQUEST_DATA,
! 258: chunk_create(ptests[_i].req, ptests[_i].req_len),
! 259: !ptests[_i].minor ? FETCH_HTTP_VERSION_1_0 : FETCH_END,
! 260: FETCH_END);
! 261: ck_assert_int_eq(status, SUCCESS);
! 262: expected = chunk_create(ptests[_i].res, ptests[_i].res_len);
! 263: ck_assert_msg(chunk_compare(expected, data) == 0,
! 264: "exp %B\ngot %B\n", &expected, &data);
! 265: free(data.ptr);
! 266:
! 267: service->destroy(service);
! 268: }
! 269: END_TEST
! 270:
! 271:
! 272: static test_service_t rtests[] = {
! 273: { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 200 },
! 274: { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 204 },
! 275: { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 400 },
! 276: { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 404 },
! 277: { "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 500 },
! 278: };
! 279:
! 280: START_TEST(test_response_code)
! 281: {
! 282: stream_service_t *service;
! 283: status_t status;
! 284: chunk_t data = chunk_empty;
! 285: char uri[256];
! 286: u_int code;
! 287:
! 288: lib->processor->set_threads(lib->processor, 8);
! 289:
! 290: snprintf(uri, sizeof(uri), "tcp://%s:%u", rtests[_i].host, rtests[_i].port);
! 291: service = lib->streams->create_service(lib->streams, uri, 1);
! 292: ck_assert(service != NULL);
! 293: service->on_accept(service, servicing, &rtests[_i], JOB_PRIO_HIGH, 0);
! 294:
! 295: snprintf(uri, sizeof(uri), "http://%s:%u%s",
! 296: rtests[_i].host, rtests[_i].port, rtests[_i].path);
! 297: status = lib->fetcher->fetch(lib->fetcher, uri, &data,
! 298: FETCH_RESPONSE_CODE, &code, FETCH_END);
! 299: ck_assert_int_eq(status, HTTP_SUCCESS(rtests[_i].code) ? SUCCESS : FAILED);
! 300: ck_assert_int_eq(code, rtests[_i].code);
! 301: free(data.ptr);
! 302:
! 303: service->destroy(service);
! 304: }
! 305: END_TEST
! 306:
! 307: Suite *fetch_http_suite_create()
! 308: {
! 309: Suite *s;
! 310: TCase *tc;
! 311:
! 312: s = suite_create("http fetcher");
! 313:
! 314: tc = tcase_create("GET");
! 315: tcase_add_loop_test(tc, test_get, 0, countof(gtests));
! 316: test_case_set_timeout(tc, 10);
! 317: suite_add_tcase(s, tc);
! 318:
! 319: tc = tcase_create("POST");
! 320: tcase_add_loop_test(tc, test_post, 0, countof(ptests));
! 321: test_case_set_timeout(tc, 10);
! 322: suite_add_tcase(s, tc);
! 323:
! 324: tc = tcase_create("response code");
! 325: tcase_add_loop_test(tc, test_response_code, 0, countof(rtests));
! 326: test_case_set_timeout(tc, 10);
! 327: suite_add_tcase(s, tc);
! 328:
! 329: return s;
! 330: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>