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, &gtests[_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>