Ejemplo n.º 1
0
static void test_long_name(void)
{
    SXE_HTTP_MESSAGE message;
    unsigned         i;
    unsigned         line_len;

    tap_test_case_name("Long Header Name");
    max_buffer_size = 30;

    memset(message_headers, 0, sizeof(message_headers));

    snprintf(message_headers, sizeof(message_headers), "\r\n%s: %s\r\n\r\n", LONG_HEADER(1), VALUE(1));
    sxe_http_message_construct(&message, message_headers, max_buffer_size);
    line_len = strlen(message_headers);
    diag("Long Header Name: The header is %u bytes, the max buffer size is %u bytes", line_len, max_buffer_size);

    is(sxe_http_message_parse_next_line_element(&message, SXE_HTTP_LINE_ELEMENT_TYPE_END_OF_LINE), SXE_RETURN_END_OF_FILE,
                                                                                      "Parsed message request line");

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK,     "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  2,                         "Consuming the request line");

    /* Simulate sxe_buf_consume() */
    memmove(message_headers, &message_headers[2], sizeof(message_headers) - 2);
    diag("Long Header Name: Consumed %u bytes", 2);
    /* Buffer: "LONG-HEADER-1-0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789: VALUE_1\r\n" */
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK,     "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  0,                         "Buffer is full");

    /* Start ignoring current line */
    /* Simulate sxe_buf_clear(), Igore 1st buffer */
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
    diag("Long Header Name: Consumed %u bytes", max_buffer_size);
    /* Buffer: "678901234567890123456789012345678901234567890123456789012345678901234567890123456789: VALUE_1\r\n\r\n" */
    message.ignore_line = 1;
    sxe_http_message_increase_buffer_length(&message, max_buffer_size);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK,     "Get long header");
    is(message.ignore_line, 1, "Ignore buffer flag is set");
    is(message.ignore_length, max_buffer_size, "Ignore length is right");

    for (i = 2; i < 4; i++) { //two more buffers to ignore
        memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
        diag("Long Header Name: Consumed %u bytes", max_buffer_size);
        sxe_http_message_increase_buffer_length(&message, max_buffer_size);
        is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK,     "Get long header");
        is(message.ignore_line, 1, "Ignore buffer flag is set");
        is(message.ignore_length, max_buffer_size, "Ignore length is right");
    }
    /* Buffer: "678901234567890123456789: VALUE_1\r\n\r\n" */
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
    diag("Long Header Name: Consumed %u bytes", max_buffer_size);
    /* Buffer: "E_1\r\n\r\n" */

    sxe_http_message_increase_buffer_length(&message, 7);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_END_OF_FILE, "Get end of line");
    is(message.ignore_line, 0, "Ignore buffer flag is clear");
    is(message.ignore_length, 7, "Ignore length is right");
    is(sxe_http_message_consume_parsed_headers(&message), 7, "Consumed the rest 7 bytes");
}
Ejemplo n.º 2
0
static void test_long_check_two_more_bytes(void)
{
    SXE_HTTP_MESSAGE message;
    unsigned        line_len;

    tap_test_case_name("Check Two More Bytes");
    max_buffer_size = 6;

    memset(message_headers, 0, sizeof(message_headers));

    /* "HEADER: VA" is 6 + 4 bytes */
    snprintf(message_headers, sizeof(message_headers), "\r\nHEADER: VA\r\n\r\n");
    sxe_http_message_construct(&message, message_headers, max_buffer_size);
    line_len = strlen(message_headers);
    diag("Check Two More Bytes: The header is %u bytes, the max buffer size is %u bytes", line_len, max_buffer_size);

    is(sxe_http_message_parse_next_line_element(&message, SXE_HTTP_LINE_ELEMENT_TYPE_END_OF_LINE), SXE_RETURN_END_OF_FILE,
                                                "Parsed message request line");

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  2,                     "Consuming the request line");
    /* Simulate sxe_buf_consume() */
    memmove(message_headers, &message_headers[2], sizeof(message_headers) - 2);
    diag("Check Two More Bytes: Consumed %u bytes", 2);

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  0,                     "Buffer is full");

    /* Start ignoring */
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);

    diag("Check Two More Bytes: Consumed %u bytes", max_buffer_size);
    message.ignore_line = 1;

    /* 6 = strlen(": VA\r\n\r\n") - 2 */
    sxe_http_message_increase_buffer_length(&message, 6);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(message.ignore_line, 1, "Ignore buffer flag is set");
    /* 4 = strlen(":VA") */
    is(message.ignore_length, 4, "Ignore length is right, the ending '\\r\\n' is left for next time");

    memmove(message_headers, &message_headers[4], sizeof(message_headers) - 4);
    diag("Check Two More Bytes: Consumed 4 bytes");

    /* Now buffer is left with "\r\n\r\n" */
    sxe_http_message_increase_buffer_length(&message, 4);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_END_OF_FILE, "Get the end of line");
    is(message.ignore_line, 0, "Ignore buffer flag is clear");
    is(message.ignore_length, 4, "Ignore length is right");
    is(sxe_http_message_consume_parsed_headers(&message), 4, "Consumed the rest of 4 bytes");
}
Ejemplo n.º 3
0
static void test_long_value_with_line_continuations(void)
{
    SXE_HTTP_MESSAGE message;
    unsigned        line_len;

    tap_test_case_name("With Line Continuations");
    max_buffer_size = 60;

    memset(message_headers, 0, sizeof(message_headers));

    snprintf(message_headers, sizeof(message_headers), "\r\n%s: %s\r\n CONTINUE_LINE1\r\n\tCONTINUE_LINE2\r\n\r\n", HEADER(1), LONG_VALUE(1));
    sxe_http_message_construct(&message, message_headers, max_buffer_size);
    line_len = strlen(message_headers);

    diag("With Line Continuations: The header is %u bytes, the max buffer size is %u bytes", line_len, max_buffer_size);

    is(sxe_http_message_parse_next_line_element(&message, SXE_HTTP_LINE_ELEMENT_TYPE_END_OF_LINE), SXE_RETURN_END_OF_FILE,
                                                "Parsed message request line");

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  2,                     "Consuming the request line");
    /* Simulate sxe_buf_consume() */
    memmove(message_headers, &message_headers[2], sizeof(message_headers) - 2);
    diag("With Line Continuations: Consumed %u bytes", 2);

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  0,                     "Buffer is full");
    /* Start ignoring */
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
    diag("With Line Continuations: Consumed %u bytes", max_buffer_size);
    message.ignore_line = 1;

    sxe_http_message_increase_buffer_length(&message, max_buffer_size);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(message.ignore_line, 1, "Ignore buffer flag is set");
    is(message.ignore_length, max_buffer_size, "Ignore length is right");
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
    diag("With Line Continuations: Consumed %u bytes", max_buffer_size);

    sxe_http_message_increase_buffer_length(&message, line_len - 2 - 2 * max_buffer_size);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_END_OF_FILE, "Get the end of line");
    is(message.ignore_line, 0, "Ignore buffer flag is clear");
    is(message.ignore_length, 41, "Ignore length is right");
    is(sxe_http_message_consume_parsed_headers(&message), 41, "Consumed the rest of 41 bytes");
}
Ejemplo n.º 4
0
int
main(void)
{
    TEST_SHA1 sha1_expected;
    TEST_SHA1 sha1_got;
    char      hex_buffer[sizeof(SHA1_HEX)];
    unsigned  val = 0;

    plan_tests(15);
    is(sxe_hex_to_unsigned("0",     2), 0,                                  "'0':2    -> 0");
    is(sxe_hex_to_unsigned("face",  4), 0xface,                             "'face':4 -> 0xface");
    is(sxe_hex_to_unsigned("B00B",  2), 0xb0,                               "'B00B':2 -> 0xb0");
    is(sxe_hex_to_unsigned("XXXX",  4), SXE_UNSIGNED_MAXIMUM,               "'XXXX':4 -> 0x%x (SXE_UNSIGNED_MAXIMUM)",
       sxe_hex_to_unsigned("XXXX",  4));

    is(sxe_valid_hex_to_unsigned("0a", 2, &val), SXE_RETURN_OK,             "0a is valid hex");
    is(val, 10,                                                             "0a hex is 10 decimal");
    is(sxe_valid_hex_to_unsigned("F45C6AC6", 8, &val), SXE_RETURN_OK,       "F45C6AC6 is valid hex");
    is(val, 4099697350,                                                     "F45C6AC6 hex is 4099697350 decimal");
    is(sxe_valid_hex_to_unsigned("ZZ", 2, &val), SXE_RETURN_ERROR_INTERNAL, "ZZ is not valid hex");

    ok(sxe_hex_to_bytes((unsigned char *)&sha1_got, "goofy goober", 12) != SXE_RETURN_OK, "Conversion from hex 'goofy goober' to bytes failed");
    is(sxe_hex_to_bytes((unsigned char *)&sha1_got, SHA1_HEX,       40),   SXE_RETURN_OK, "Conversion from hex '%s' to bytes succeeded", SHA1_HEX);

    memcpy(&sha1_expected, sxe_sha1_expected_bytes, sizeof(sha1_expected));

    if (memcmp(&sha1_got, &sha1_expected, sizeof(TEST_SHA1)) == 0) {
        pass(                                                         "bytes are as expected");
    }
    else {
        SXEL1("Expected:");
        SXED1(&sha1_expected, sizeof(sha1_expected));
        SXEL1("Got:");
        SXED1(&sha1_got,      sizeof(sha1_got));
        fail(                                                         "bytes are not as expected");
    }

    tap_test_case_name("sxe_hex_from_bytes");
    hex_buffer[sizeof(hex_buffer) - 1] = 0xBE;
    is(sxe_hex_from_bytes(hex_buffer, sxe_sha1_expected_bytes, sizeof(sxe_sha1_expected_bytes)), hex_buffer, "Returns hex buffer");
    is_strncmp(hex_buffer, SHA1_HEX, SXE_LITERAL_LENGTH(SHA1_HEX),    "SHA1 converted to hex as expected");
    is((unsigned char)hex_buffer[sizeof(hex_buffer) - 1], 0xBE,       "Guard byte is intact");
    return exit_status();
}
static void
test_case(const char * tapname, const char * request, unsigned count)
{
    SXE  * client;
    tap_ev event;

    tap_test_case_name(tapname);

    SXEA1((client = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close)) != NULL,
            "Failed to allocate client SXE");
    SXEA1(sxe_connect(client, "127.0.0.1", SXE_LOCAL_PORT(listener)) == SXE_RETURN_OK, "Failed to connect to HTTPD");

#ifdef _WIN32
    usleep(10000);    /* Copied from test-errors.c and which is a TODO item */
#endif

    is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &event), "client_connect", "Got a client connected event");
    is(tap_ev_arg(event, "this"), client, "It's the client");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_connect", "Got a server connected event");

    test_sxe_send(client, request, strlen(request), client_sent, "client_sent", q_client, TEST_WAIT, &event);

    if (count == 2) {
        is_eq(test_tap_ev_queue_identifier_wait(q_httpd , TEST_WAIT, &event), "h_header", "HTTPD: header event (a)"         );
        is_strncmp(tap_ev_arg(event, "key"  ), "Good"   , SXE_LITERAL_LENGTH( "Good"   ), "HTTPD: header was 'Good'"        );
        is_strncmp(tap_ev_arg(event, "value"), "Header" , SXE_LITERAL_LENGTH( "Header" ), "HTTPD: header value was 'Header'");

        is_eq(test_tap_ev_queue_identifier_wait(q_httpd , TEST_WAIT, &event), "h_header", "HTTPD: header event (b)"         );
        is_strncmp(tap_ev_arg(event, "key"  ), "Another", SXE_LITERAL_LENGTH( "Another"), "HTTPD: header was 'Another'"     );
        is_strncmp(tap_ev_arg(event, "value"), "Foo"    , SXE_LITERAL_LENGTH( "Foo"    ), "HTTPD: header value was 'Foo'"   );
    }

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_respond", "HTTPD: respond event");

    sxe_close(client);
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_close", "HTTPD: close event");
}
Ejemplo n.º 6
0
static void test_five_headers(void)
{
    SXE_HTTP_MESSAGE message;
    unsigned        line_len;

    tap_test_case_name("Five Headers - Normal Long Normal Long-With-Continuations Normal");
    max_buffer_size = 70;

    memset(message_headers, 0, sizeof(message_headers));

    snprintf(message_headers, sizeof(message_headers), "\r\n%s: %s\r\n%s: %s\r\n%s: %s\r\n%s: %s\r\n CONTINUE_LINE1\r\n\tCONTINUE_LINE2\r\n%s: %s\r\n\r\n",
                                                        HEADER(1), VALUE(1),
                                                        HEADER(2), LONG_VALUE(2),
                                                        HEADER(333), VALUE(3333),
                                                        LONG_HEADER(4), VALUE(4),
                                                        HEADER(55), VALUE(5));
    sxe_http_message_construct(&message, message_headers, max_buffer_size);
    line_len = strlen(message_headers);

    diag("Five Headers: The header is %u bytes, the max buffer size is %u bytes", line_len, max_buffer_size);

    is(sxe_http_message_parse_next_line_element(&message, SXE_HTTP_LINE_ELEMENT_TYPE_END_OF_LINE), SXE_RETURN_END_OF_FILE,
                                                "Parsed message request line");

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_OK, "Get header 1");
    is(message.ignore_length, 0, "No ignore");
    is(message.ignore_length, 0, "Ignore length is 0");
    is_strncmp(sxe_http_message_get_header_name(&message), HEADER(1), strlen(HEADER(1)), "Name is " HEADER(1));
    is(sxe_http_message_get_header_name_length(&message), strlen(HEADER(1)), "Name length is %u",   (unsigned)strlen(HEADER(1)));
    is_strncmp(sxe_http_message_get_header_value(&message), VALUE(1), strlen(VALUE(1)), "Value is " VALUE(1));
    is(sxe_http_message_get_header_value_length(&message), strlen(VALUE(1)), "Value length is %u",  (unsigned)strlen(VALUE(1)));

    /* Don't do any consume since last sxe_http_message_parse_next_header() returns OK */

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(message.ignore_length, 0, "No ignore");
    /* 21 == 2 + strlen(HEADER(1)) + 2 + strlen(VALUE(1)) + 2 */
    is(sxe_http_message_consume_parsed_headers(&message),  21, "Consuming the request line and header 1");
    /* Simulate sxe_buf_consume() */
    memmove(message_headers, &message_headers[21], sizeof(message_headers) - 21);
    diag("Five Headers: Consumed 21 bytes");

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  0,                     "Buffer is full");
    /* Start ignoring */
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
    diag("Five Headers: Consumed %u bytes", max_buffer_size);
    message.ignore_line = 1;

    sxe_http_message_increase_buffer_length(&message, max_buffer_size);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(message.ignore_line, 0, "Ignore buffer flag is clear, since found the end of long header 2");
    /* 55 = strlen(HEADER(2)) + 2 + strlen(LONG_VALUE(2)) + 2 - 70 */
    is(message.ignore_length, 55, "Ignore length is right");
    memmove(message_headers, &message_headers[55], sizeof(message_headers) - 55);
    diag("Five Headers: Consumed 55 bytes");

    sxe_http_message_increase_buffer_length(&message, max_buffer_size);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_OK, "Get normal header 3");
    is(message.ignore_length, 0, "No ignore");
    is_strncmp(sxe_http_message_get_header_name(&message), HEADER(333), strlen(HEADER(333)), "Name is " HEADER(333));
    is(sxe_http_message_get_header_name_length(&message), strlen(HEADER(333)), "Name length is %u", (unsigned)strlen(HEADER(333)));
    is_strncmp(sxe_http_message_get_header_value(&message), VALUE(3333), strlen(VALUE(3333)), "Value is " VALUE(3333));
    is(sxe_http_message_get_header_value_length(&message), strlen(VALUE(3333)), "Value length is %u", (unsigned)strlen(VALUE(3333)));

    /* Don't do any consume since last sxe_http_message_parse_next_header() returns OK */

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(message.ignore_length, 0, "No ignore");
    /* 24 == strlen(HEADER(333)) + 2 + strlen(VALUE(3333)) + 2 */
    is(sxe_http_message_consume_parsed_headers(&message),  24, "Consuming the header 3");
    /* Simulate sxe_buf_consume() */
    memmove(message_headers, &message_headers[24], sizeof(message_headers) - 24);
    diag("Five Headers: Consumed 24 bytes");

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header");
    is(sxe_http_message_consume_parsed_headers(&message),  0,                     "Buffer is full");
    /* Start ignoring */
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
    diag("Five Headers: Consumed %u bytes", max_buffer_size);
    message.ignore_line = 1;

    sxe_http_message_increase_buffer_length(&message, max_buffer_size);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header 4");
    is(message.ignore_line, 1, "Ignore buffer flag is set, the end of long header 4 not found yet");
    /* 55 = strlen(HEADER(2)) + 2 + strlen(LONG_VALUE(2)) + 2 - 70 */
    is(message.ignore_length, max_buffer_size, "Ignore length is right");
    memmove(message_headers, &message_headers[max_buffer_size], sizeof(message_headers) - max_buffer_size);
    diag("Five Headers: Consumed %u bytes", max_buffer_size);

    /* 41 = 351(line_len) - 21 - 55 - 24 - 3 * 210 */
    sxe_http_message_increase_buffer_length(&message, 41);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_WARN_WOULD_BLOCK, "Get long header 4");
    is(message.ignore_line, 0, "Ignore buffer flag is set, the end of long header 4 not found yet");
    /* 19 = strlen("\r\n\tCONTINUE_LINE2\r\n") */
    is(message.ignore_length, 19, "Ignore length is right");
    memmove(message_headers, &message_headers[19], sizeof(message_headers) - 19);
    diag("Five Headers: Consumed 19 bytes, the left part of long header 4");

    /* 22 = 41 - 19 */
    sxe_http_message_increase_buffer_length(&message, 22);
    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_OK, "Get the header 5");
    is(message.ignore_line, 0, "Ignore buffer flag is clear");
    is(message.ignore_length, 0, "Ignore length is 0");
    is_strncmp(sxe_http_message_get_header_name(&message), HEADER(55), strlen(HEADER(55)), "Name is " HEADER(55));
    is(sxe_http_message_get_header_name_length(&message), strlen(HEADER(55)), "Name length is %u",    (unsigned)strlen(HEADER(55)));
    is_strncmp(sxe_http_message_get_header_value(&message), VALUE(5), strlen(VALUE(5)), "Value is "   VALUE(5));
    is(sxe_http_message_get_header_value_length(&message), strlen(VALUE(5)), "Value length is %u",    (unsigned)strlen(VALUE(5)));

    /* Don't do any consume since last sxe_http_message_parse_next_header() returns OK */

    is(sxe_http_message_parse_next_header(&message), SXE_RETURN_END_OF_FILE, "Get long header");
    /* 22 = strlen("HEADER-55: VALUE_5\r\n\r\n") */
    is(sxe_http_message_consume_parsed_headers(&message), 22, "Consumed the rest of 22 bytes which are header 5 and eof");
}
Ejemplo n.º 7
0
int
main(void)
{
    SXE_HTTPD_REQUEST      * request[TEST_BUFFER_COUNT];
    SXE                    * client[TEST_BUFFER_COUNT];
    tap_ev                   ev;
    SXE                    * listener;
    char                   * send_buffer;
    int                      i;

    SXEA1(send_buffer = malloc(TEST_SEND_BYTES), "Failed to allocate %u KB", TEST_SEND_BYTES);

    for (i = 0; i < TEST_SEND_BYTES; i++) {
        send_buffer[i] = 'A';
    }

    tap_plan(33, TAP_FLAG_ON_FAILURE_EXIT, NULL);
    test_sxe_register_and_init(TEST_BUFFER_COUNT * 2 + 1);

    sxe_httpd_construct(&httpd, TEST_BUFFER_COUNT + 1, TEST_BUFFER_COUNT, TEST_BUFFER_SIZE, 0);
    SXE_HTTPD_SET_HANDLER(&httpd, respond, h_respond);

    SXEA1((listener = test_httpd_listen(&httpd, "0.0.0.0", 0)) != NULL,                         "sxe_httpd_listen failed");

    tap_test_case_name("connecting 10 clients");
    for (i = 0; i < TEST_BUFFER_COUNT; i++) {
        SXEA1((client[i] = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, NULL)) != NULL, "sxe_new_tcp failed");
        sxe_connect(client[i], "127.0.0.1", SXE_LOCAL_PORT(listener));

#define TEST_GET "GET / HTTP/1.1\r\n\r\n"

        is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &ev), "client_connect",      "client[%d] connected to HTTPD", i);
        TEST_SXE_SEND_LITERAL(client[i], TEST_GET, client_sent, q_client, TEST_WAIT, &ev);

        is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev),            "h_respond", "HTTPD[%d] respond event", i);
        request[i] = SXE_CAST_NOCONST(SXE_HTTPD_REQUEST *, tap_ev_arg(ev, "request"));
    }

    tap_test_case_name("response_copy_body_data() runs out");
    {
        SXE_RETURN ret = SXE_RETURN_OK;

        sxe_httpd_response_start(request[0], 200, "OK");

        /* When we copy body data, we try to immediately send each buffer. If
         * it succeeds, we may not actually run out of buffers, because as the
         * buffers are depleted they are freed again. Eventually, though,
         * we'll fill the kernel's TCP output buffers.
         */
        for (i = 0; i < TEST_SEND_COUNT && ret == SXE_RETURN_OK; i++) {
            ret = sxe_httpd_response_copy_body_data(request[0], send_buffer, TEST_SEND_BYTES);
        }
        is(ret, SXE_RETURN_NO_UNUSED_ELEMENTS, "HTTPD: response ran out of buffers after sending %d bytes %d times", TEST_SEND_BYTES, i);

        /* NOTE: you get an assertion if you call sxe_httpd_response_end() after
         * we've run out of buffers, because the last valid buffer has been send,
         * and no other buffers are available, so request->out_buffer == NULL. Not
         * sure what to do in this case... I guess we could queue a zero-length
         * buffer? Although we're out of buffers...
         */
#if NOT_SURE_WHAT_TO_DO_HERE
        sxe_httpd_response_end(request[0], h_sent, NULL);
#endif
    }

    tap_test_case_name("response_start() runs out of buffers");
    {
        is(sxe_httpd_response_start(request[1], 200, "OK"), SXE_RETURN_NO_UNUSED_ELEMENTS, "response_start() ran out of buffers");
        sxe_httpd_close(request[1]);
        sxe_close(client[1]);
    }

    tap_test_case_name("response_simple() runs out of buffers during response_start()");
    {
        is(sxe_httpd_response_simple(request[2], NULL, NULL, 200, "OK", "", NULL), SXE_RETURN_NO_UNUSED_ELEMENTS, "response_simple() ran out of buffers");
        sxe_httpd_close(request[2]);
        sxe_close(client[2]);
    }

    /* TODO: because there are as many buffers as there are clients, we should
     * be able to test all combinations of places where we can run out of
     * buffers. We just need to ensure that all clients now call
     * response_start(), so that all have a buffer allocated. Then we can do
     * things like call sxe_httpd_response_header() with enough headers to
     * fill up the buffer and grab another one, which will fail because there
     * are no more buffers free... as long as the send does not complete
     * immediately. Perhaps it's worth mocking send() so that it always
     * returns a blocking answer?
     */

    sxe_httpd_close(request[0]);
    sxe_close(client[0]);

    return exit_status();
}
Ejemplo n.º 8
0
int
main(int argc, char ** argv)
{
    const char * line;
    unsigned     i;

    if (argc > 1) {
        test_program_arg = argv[1];
        sxe_log_hook_line_out(test_log_line_out_to_stdout);
        SXEA10(sxe_log_hook_line_out(test_log_line_out_to_stdout) == test_log_line_out_to_stdout,
               "sxe_log_hook_line_out failed to hook test_log_line_out_to_stdout");

        if (strcmp(argv[1], "1") == 0) {
            if (getenv("SXE_LOG_LEVEL") != NULL) {
                SXED80("should not see this (level too high)", strlen("should not see this (level too high)"));    /* Cover early out in dump */
            }

            SXEL40("BOO");
        }
        else if (strcmp(argv[1], "2") == 0) {
#ifndef LOCAL_SXE_DEBUG
            sxe_log_set_indent_maximum(~0U);
#endif
            sxe_log_set_level(SXE_LOG_LEVEL_WARNING);
            SXEE50("level_five()");
            test_level_six(SXE_LOG_LEVEL_LIBRARY_DUMP);
            SXER50("return // five");
            SXEE50("level_five()");
            test_level_six(SXE_LOG_LEVEL_WARNING);
            SXER50("return // five");
            SXEL20("that's all, folks");
        }

        exit(0);
    }

    test_program_name = argv[0];
    plan_tests(3 * TEST_LINES_EXPECTED + 3);

    /* Tests for different log level settings */

    tap_test_case_name("Level settings");
    ok((line = test_log_first("1")) != NULL,                        "Test log at default level wrote a line");
    diag("line = %s", line);

    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL=2") >= 0,        "%s: Failed to putenv: %s", test_program_name, strerror(errno));
    ok(test_log_first("1") == NULL,                                 "Test log with SXE_LOG_LEVEL=2 failed to write a line");

    /* TODO: Replace putenvs with calls to the TBD function that allows setting fine grained levels programmatically. */

    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE=5") >= 0, "%s: Failed to putenv: %s", test_program_name, strerror(errno));
    ok((line = test_log_first("1")) != NULL,                        "Test log with SXE_LOG_LEVEL_LIBSXE=5 wrote a line");
    diag("line = %s", line);
    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG=2") >= 0, "%s: Failed to setenv: %s", test_program_name, strerror(errno));
    ok(test_log_first("1") == NULL,                                 "Test log with SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG=2 failed to write a line");
    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS=7") >= 0, "%s: Failed to putenv: %s", test_program_name, strerror(errno));
    ok((line = test_log_first("1")) != NULL,                        "Test log with SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS=7 wrote a line");
    diag("line = %s", line);

    /* Remove the more specific environment variables
     */
    SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE") == 0,                                      "%s: unsetenv failed: %s", test_program_name, strerror(errno));
    SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG") == 0,                          "%s: unsetenv failed: %s", test_program_name, strerror(errno));
    SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS") == 0, "%s: unsetenv failed: %s", test_program_name, strerror(errno));

    /* Tests for indentation interacting with log level */

    tap_test_case_name("Indentation");
    line = test_log_first("2");

    for (i = 0; i < TEST_LINES_EXPECTED; i++) {
        ok(line != NULL,                                            "Got line %u", 2 * i + 1);
        ok(strstr(line, test_expected[i]) != NULL,                  "Found '%s' in '%.*s'", test_expected[i], (int)strlen(line) - 1, line);

        if (i > 2) {
            ok(test_log_next() != NULL,                             "Got line %u", 2 * i + 2);
        }

        line = test_log_next();
    }

    ok(line == NULL,                                                "Got EOF");
    return exit_status();
}
Ejemplo n.º 9
0
int
main(void)
{
    SXE_HTTPD    httpd;
    SXE        * client;
    SXE        * client2;
    SXE        * server;
    SXE        * server2;
    tap_ev       event;

    plan_tests(14);

    test_sxe_register_and_init(1000);

    sxe_httpd_construct(&httpd, 2, 10, 512, 0);
    SXE_HTTPD_SET_HANDLER(&httpd, connect, h_connect);
    SXE_HTTPD_SET_HANDLER(&httpd, request, h_request);
    SXE_HTTPD_SET_HANDLER(&httpd, close,   h_close);
    ok((listener = test_httpd_listen(&httpd, "0.0.0.0", 0)) != NULL,                              "HTTPD listening");

    /* Starts two connections, then make a new connection, the oldest will be reaped by the server */
    tap_test_case_name("reap connections");

    /* 1st connection */
    SXEA1((client = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close)) != NULL,
           "Failed to allocate client SXE");
    SXEA1(sxe_connect(client, "127.0.0.1", SXE_LOCAL_PORT(listener)) == SXE_RETURN_OK,          "Failed to connect to HTTPD");
    is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &event), "client_connect", "Got 1st client connected event");
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_connect",     "Got 1st server connect event");
    server = SXE_CAST(SXE *, tap_ev_arg(event, "this"));

    /* 1st client: send a complete request line */
    TEST_SXE_SEND_LITERAL(client, "GET /good HTTP/1.1\r\n", client_sent, q_client, TEST_WAIT, &event);

    /* Waiting for 1st client request state "stable" on "STATE_HEADER" to make
     * sure there is no more state updates on this request object, then the following
     * usleep will guarantee the 1st connection is older than the 2nd one.
     */
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_request",     "Got 1st server request event");
    is(tap_ev_arg(event, "this"), server,                                                        "It's the 1st server");
    usleep(300000);

    /* 2nd connection, reaping happens, the 1st one got reaped */
    SXEA1((client2 = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close)) != NULL,
           "Failed to allocate client SXE");
    SXEA1(sxe_connect(client2, "127.0.0.1", SXE_LOCAL_PORT(listener)) == SXE_RETURN_OK,         "Failed to connect to HTTPD");

    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_connect",     "Got 2nd server connect event");
    server2 = SXE_CAST(SXE *, tap_ev_arg(event, "this"));
    is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &event), "h_close",       "Got a server close event");
    is(tap_ev_arg(event, "this"), server,                                                        "It's the 1st server");

    /* Pull these two arguments off in any order */
    test_process_all_libev_events();
    ok((event = tap_ev_queue_shift_next(q_client, "client_connect")) != NULL, "Got 2nd client connected event");
    ok((event = tap_ev_queue_shift_next(q_client, "client_close")) != NULL, "Got a client close event");
    is(tap_ev_arg(event, "this"), client,                                                        "It's the 1st client");

    is(tap_ev_queue_length(q_httpd),                                         0,                "No server events lurking");
    is(tap_ev_queue_length(q_client),                                         0,                "No client events lurking");

    sxe_close(listener);
    return exit_status();
}