int main() { tap_plan(18); //is/isn't tap_is('a','a', "'a' is 'a'"); tap_is(1, 1, "1 is 1"); tap_is(4.0, 4.0, "4.0 is 4.0"); tap_isnt('a', 'b', "'a' isn't 'b'"); tap_isnt(0, 1, "0 isn't 1"); tap_isnt(2.0, 4.0, "2.0 isn't 4.0"); //todo tap_todo(4, "strings"); tap_is_str("foo", "foo", "\"foo\" is \"foo\""); tap_is_str("1", "1", "\"1\" is \"1\""); tap_isnt_str("foo", "bar", "\"foo\" isn't \"bar\""); tap_isnt_str("0", "1", "\"0\" isn't \"1\""); //like/unlike tap_like("foobar", "foo*", REG_EXTENDED, "\"foobar\" is like \"foo*\""); tap_like("foobar", "^foo", REG_EXTENDED, "\"foobar\" is like \"^foo\""); tap_like("foobar", "bar$", REG_EXTENDED, "\"foobar\" is like \"bar$\""); tap_todo(2, "don't care"); tap_like("foobar", "fooba[rz]", REG_EXTENDED, "\"foobar\" is like \"fooba[rz]\""); tap_unlike("foobar", "foobaz", REG_EXTENDED, "\"foobar\" is unlike \"foobaz\""); tap_unlike("foobar", "baz$", REG_EXTENDED, "\"foobar\" is unlike \"baz$\""); tap_unlike("foobar", "foo$", REG_EXTENDED, "\"foobar\" is unlike \"foo$\""); tap_unlike("foobar", "^foo$", REG_EXTENDED, "\"foobar\" is unlike \"^foo$\""); return tap_status(); }
static void test(void) { tap_plan(0); tap_plan(1); tap_plan(2); tap_skip_all(NULL); tap_skip_all("foo %s", "bar"); tap_skip(0, NULL); tap_skip(1, "foo %s", "bar"); tap_skip(2, NULL); tap_diag("foo"); tap_diag("foo %s", "bar"); tap_bail(NULL); tap_bail("foo %s", "bar"); tap_ok(0, NULL); tap_ok(1, NULL); tap_ok(0, "%s", "foo"); tap_ok(1, "%s", "foo"); tap_is_str("foo", "foo", NULL); tap_is_str("foo", "bar", NULL); tap_is_str("foo", "foo", "foo %s", "bar"); tap_is_str("foo", "bar", "foo %s", "bar"); tap_is_str(NULL, NULL, NULL); tap_is_str(NULL, "bar", NULL); tap_is_int(1, 1, NULL); tap_is_int(1, 0, NULL); tap_is_int(1, 1, "foo %s", "bar"); tap_is_int(1, 0, "foo %s", "bar"); tap_is_float(1.0, 1.0, 0.1, NULL); tap_is_float(1.0, 2.0, 0.1, NULL); tap_is_float(1.0, 1.0, 0.1, "foo %s", "bar"); tap_is_float(1.0, 2.0, 0.1, "foo %s", "bar"); tap_done_testing(); }
int main(void) { tap_plan(8); CHECK("foobarbaz", "bar", "qux", "fooquxbaz", "equal length"); CHECK("foobarbaz", "bar", "quux", "fooquuxbaz", "longer replacement"); CHECK("foobarbaz", "bar", "qx", "fooqxbaz", "shorter replacement"); CHECK("foobarbaz", "foo", "qux", "quxbarbaz", "startswith target"); CHECK("foobarbaz", "baz", "qux", "foobarqux", "endswith target"); CHECK("foobarbaz", "a", "x", "foobxrbxz", "multiple instances"); CHECK("barbarbar", "barbar", "foo", "foobar", "overlapping instances"); CHECK("foo", "foo", "bar", "bar", "equals target"); return tap_finish(); }
int main(void) { pu_log_action_t *a; tap_plan(31); tap_ok((a = pu_log_action_parse("installed pacutils (1.0.0)")) != NULL, "install"); tap_is_int(a->operation, PU_LOG_OPERATION_INSTALL, "operation"); tap_is_str(a->target, "pacutils", "package"); tap_is_str(a->new_version, "1.0.0", "new_version"); tap_is_str(a->old_version, NULL, "old_version"); pu_log_action_free(a); tap_ok((a = pu_log_action_parse("upgraded pacutils (1.0.0 -> 2.0.0)")) != NULL, "upgrade"); tap_is_int(a->operation, PU_LOG_OPERATION_UPGRADE, "operation"); tap_is_str(a->target, "pacutils", "package"); tap_is_str(a->new_version, "2.0.0", "new_version"); tap_is_str(a->old_version, "1.0.0", "old_version"); pu_log_action_free(a); tap_ok((a = pu_log_action_parse("downgraded pacutils (2.0.0 -> 1.0.0)")) != NULL, "downgrade"); tap_is_int(a->operation, PU_LOG_OPERATION_DOWNGRADE, "operation"); tap_is_str(a->target, "pacutils", "package"); tap_is_str(a->new_version, "1.0.0", "new_version"); tap_is_str(a->old_version, "2.0.0", "old_version"); pu_log_action_free(a); tap_ok((a = pu_log_action_parse("reinstalled pacutils (1.0.0)")) != NULL, "reinstall"); tap_is_int(a->operation, PU_LOG_OPERATION_REINSTALL, "operation"); tap_is_str(a->target, "pacutils", "package"); tap_is_str(a->new_version, "1.0.0", "new_version"); tap_is_str(a->old_version, "1.0.0", "old_version"); pu_log_action_free(a); tap_ok((a = pu_log_action_parse("removed pacutils (1.0.0)")) != NULL, "removed"); tap_is_int(a->operation, PU_LOG_OPERATION_REMOVE, "operation"); tap_is_str(a->target, "pacutils", "package"); tap_is_str(a->new_version, NULL, "new_version"); tap_is_str(a->old_version, "1.0.0", "old_version"); pu_log_action_free(a); tap_ok(pu_log_action_parse("") == NULL, "empty input"); tap_is_int(errno, EINVAL, "errno"); tap_ok(pu_log_action_parse(NULL) == NULL, "NULL input"); tap_is_int(errno, EINVAL, "errno"); tap_ok(pu_log_action_parse("not a valid action") == NULL, "invalid input"); tap_is_int(errno, EINVAL, "errno"); return tap_finish(); }
int main(void) { tap_plan(8); is(sign(pathcmp("/foo", "/foo")), 0); is(sign(pathcmp("/foo", "/foo/")), 0); is(sign(pathcmp("/foo//", "//foo/")), 0); is(sign(pathcmp("//foo//bar//", "/foo/bar")), 0); is(sign(pathcmp("/foo", "foo/")), -1); is(sign(pathcmp("/foo", "/fo/o")), 1); is(sign(pathcmp("/foo", "/bar")), 1); is(sign(pathcmp("/bar", "/foo")), -1); return tap_finish(); }
int main(void) { tap_plan(12); tap_is_str(strcasechr("aBcDeF", 'd'), "DeF", NULL); tap_is_str(strcasechr("aBcDeF", 'D'), "DeF", NULL); tap_is_str(strcasechr("aBcDeF", 'e'), "eF", NULL); tap_is_str(strcasechr("aBcDeF", 'E'), "eF", NULL); tap_is_str(strfuzzy("abcdefg", "adg"), "g", NULL); tap_is_str(strfuzzy("abcdefg", "cdg"), "g", NULL); tap_is_str(strfuzzy("abcdefg", "ace"), "efg", NULL); tap_is_str(strfuzzy("abcdefg", "cb"), NULL, NULL); tap_is_str(strcasefuzzy("abcdefg", "aDg"), "g", NULL); tap_is_str(strcasefuzzy("abcdefg", "cDg"), "g", NULL); tap_is_str(strcasefuzzy("abcdefg", "aCe"), "efg", NULL); tap_is_str(strcasefuzzy("abcdefg", "cB"), NULL, NULL); return tap_finish(); }
int main() { tap_plan(11); tap_ok(1==1, "1==1"); tap_not_ok(1==2, "1==2"); tap_is(1, 1, "1 is 1"); tap_is('a', 'a', "'a' is 'a'"); tap_is(4.0, 4.0, "4.0 is 4.0"); tap_isnt(1, 2, "1 isn't 2"); tap_isnt('a', 'b', "'a' isn't 'b'"); tap_isnt(2.0, 4.0, "2.0 isn't 4.0"); tap_like("foobar", "^foo", REG_EXTENDED, "\"foobar\" is like \"^foo\""); tap_unlike("foobar", "foo$", REG_EXTENDED, "\"foobar\" is unlike \"foo$\""); tap_pass("just passing"); return tap_status(); }
/* * Note the number of tests that will be run. */ void plan_tests(unsigned int tests) { tap_plan(tests, 0, NULL); }
int main() { fgraph_heap_t *heap = 0; fgraph_return_t res = 0; unsigned long ulval = 0, *pulval = 0; tap_plan(48); res = fgraph_heap_init(&heap, 10); tap_ok(res == FGRAPH_SUCCESS, "heap inited ok"); tap_ok(heap != 0, "heap not null"); res = fgraph_heap_init(&heap, 20); tap_ok(res == FGRAPH_EINITED, "heap already inited"); res = fgraph_heap_max(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "max returned ok"); tap_ok(ulval == 9, "max-key is 9"); res = fgraph_heap_insert(&heap, 0, 10); tap_ok(res == FGRAPH_SUCCESS, "value added ok"); res = fgraph_heap_insert(&heap, 20, 3); tap_ok(res == FGRAPH_EBOUNDS, "value not added, out of bounds"); res = fgraph_heap_size(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "heap size returned ok"); tap_ok(ulval == 1, "heap size is 1"); res = fgraph_heap_insert(&heap, 1, 8); tap_ok(res == FGRAPH_SUCCESS, "value added ok"); res = fgraph_heap_insert(&heap, 2, 6); tap_ok(res == FGRAPH_SUCCESS, "value added ok"); res = fgraph_heap_insert(&heap, 2, 20); tap_ok(res == FGRAPH_EEXISTS, "key exists"); res = fgraph_heap_insert(&heap, 3, 20); tap_ok(res == FGRAPH_SUCCESS, "value added ok"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "value removed ok"); tap_ok(ulval == 2, "min-key is 2"); res = fgraph_heap_decrease(&heap, 3, 4); tap_ok(res == FGRAPH_SUCCESS, "key decreased ok"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "value removed ok"); tap_ok(ulval == 3, "min-key is 3"); res = fgraph_heap_size(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "size returned ok"); tap_ok(ulval == 2, "size is 2"); res = fgraph_heap_clear(&heap); tap_ok(res == FGRAPH_SUCCESS, "heap cleared ok"); tap_ok(heap == 0, "heap is null"); res = fgraph_heap_insert(&heap, 2, 2); tap_ok(res == FGRAPH_ENULL, "heap is null"); res = fgraph_heap_decrease(&heap, 2, 10); tap_ok(res == FGRAPH_ENULL, "heap is null"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_ENULL, "heap is null"); res = fgraph_heap_size(&heap, &ulval); tap_ok(res == FGRAPH_ENULL, "heap is null"); res = fgraph_heap_max(&heap, &ulval); tap_ok(res == FGRAPH_ENULL, "heap is null"); res = fgraph_heap_init(&heap, 4); tap_ok(res == FGRAPH_SUCCESS, "heap inited ok"); tap_ok(heap != 0, "heap not null"); res = fgraph_heap_insert(&heap, 0, 32); tap_ok(res == FGRAPH_SUCCESS, "inserted (0,32) ok"); res = fgraph_heap_insert(&heap, 1, 4); tap_ok(res == FGRAPH_SUCCESS, "inserted (1,4) ok"); res = fgraph_heap_insert(&heap, 2, 10); tap_ok(res == FGRAPH_SUCCESS, "inserted (2,10) ok"); res = fgraph_heap_insert(&heap, 3, 25); tap_ok(res == FGRAPH_SUCCESS, "inserted (3,25) ok"); res = fgraph_heap_insert(&heap, 4, 36); tap_ok(res == FGRAPH_EBOUNDS, "out of bounds"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "removed ok"); tap_ok(ulval == 1, "min-key is 1"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "removed ok"); tap_ok(ulval == 2, "min-key is 2"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "removed ok"); tap_ok(ulval == 3, "min-key is 3"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_SUCCESS, "removed ok"); tap_ok(ulval == 0, "min-key is 0"); res = fgraph_heap_remove(&heap, &ulval); tap_ok(res == FGRAPH_EEMPTY, "heap is empty"); res = fgraph_heap_max(&heap, pulval); tap_ok(res == FGRAPH_ENULL, "pulval is null"); res = fgraph_heap_remove(&heap, pulval); tap_ok(res == FGRAPH_ENULL, "pulval is null"); res = fgraph_heap_size(&heap, pulval); tap_ok(res == FGRAPH_ENULL, "pulval is null"); res = fgraph_heap_clear(&heap); tap_ok(res == FGRAPH_SUCCESS, "cleared ok"); tap_ok(heap == 0, "heap is null"); return tap_status(); }
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(); }
int main() { fgraph_t *graph = 0; fgraph_return_t res = 0; fgraph_edge_weight_t wval = 0, *pwval = 0; fgraph_option_t oval = 0, *poval = 0; unsigned long ulval = 0, *pulval = 0; int ival = 0, *pival = 0; tap_plan(52); res = fgraph_init(&graph, 8, FGRAPH_ODIRECTED); tap_ok(res == FGRAPH_SUCCESS, "inited ok"); tap_ok(graph != 0, "graph not null"); res = fgraph_size(&graph, &ulval); tap_ok(res == FGRAPH_SUCCESS, "got graph size ok"); tap_ok(ulval == 8, "graph size is 8"); res = fgraph_size(&graph, pulval); tap_ok(res == FGRAPH_ENULL, "pulval is null"); res = fgraph_options(&graph, &oval); tap_ok(res == FGRAPH_SUCCESS, "got graph options ok"); tap_ok(oval == FGRAPH_ODIRECTED, "options ok"); res = fgraph_options(&graph, poval); tap_ok(res == FGRAPH_ENULL, "poval is null"); res = fgraph_edge_add(&graph, 0, 1, 8); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 0, 2, 2); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 1, 5, 7); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 1, 2, 3); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 2, 4, 1); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 2, 3, 5); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 3, 6, 3); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 3, 7, 1); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 4, 5, 2); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 4, 6, 6); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 5, 7, 4); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_add(&graph, 6, 7, 2); tap_ok(res == FGRAPH_SUCCESS, "edge added ok"); res = fgraph_edge_count_all(&graph, &ulval); tap_ok(res == FGRAPH_SUCCESS, "got count ok"); tap_ok(ulval == 12, "edge count is 12"); res = fgraph_edge_count_all(&graph, pulval); tap_ok(res == FGRAPH_ENULL, "pulval is null"); res = fgraph_edge_count(&graph, 0, &ulval); tap_ok(res == FGRAPH_SUCCESS, "got count ok"); tap_ok(ulval == 2, "edge count is 2"); res = fgraph_edge_count(&graph, 0, pulval); tap_ok(res == FGRAPH_ENULL, "pulval is null"); res = fgraph_edge_count(&graph, 5, &ulval); tap_ok(res == FGRAPH_SUCCESS, "got count ok"); tap_ok(ulval == 1, "edge count is 1"); res = fgraph_edge_count(&graph, 20, &ulval); tap_ok(res == FGRAPH_ENOVTX, "no such vertex"); res = fgraph_edge_get_weight(&graph, 5, 7, &wval); tap_ok(res == FGRAPH_SUCCESS, "got weight ok"); tap_ok(wval == 4, "weight is 4"); res = fgraph_edge_get_weight(&graph, 5, 7, pwval); tap_ok(res == FGRAPH_ENULL, "pwval is null"); res = fgraph_edge_get_weight(&graph, 7, 5, &wval); tap_ok(res == FGRAPH_ENOEDGE, "no such edge"); res = fgraph_edge_get_weight(&graph, 4, 6, &wval); tap_ok(res == FGRAPH_SUCCESS, "got weight ok"); tap_ok(wval == 6, "weight is 6"); res = fgraph_edge_set_weight(&graph, 4, 6, 10); tap_ok(res == FGRAPH_SUCCESS, "set weight ok"); res = fgraph_edge_set_weight(&graph, 6, 4, 10); tap_ok(res == FGRAPH_ENOEDGE, "no such edge"); res = fgraph_edge_get_weight(&graph, 4, 6, &wval); tap_ok(res == FGRAPH_SUCCESS, "got weight ok"); tap_ok(wval == 10, "weight is 10"); res = fgraph_edge_exists(&graph, 2, 4, &ival); tap_ok(res == FGRAPH_SUCCESS, "checked for edge ok"); tap_ok(ival, "edge exists"); res = fgraph_edge_exists(&graph, 2, 4, pival); tap_ok(res == FGRAPH_ENULL, "pival is null"); res = fgraph_edge_exists(&graph, 4, 2, &ival); tap_ok(res == FGRAPH_SUCCESS, "checked for edge ok"); tap_ok(!ival, "no such edge"); res = fgraph_edge_remove(&graph, 2, 4); tap_ok(res == FGRAPH_SUCCESS, "removed edge ok"); res = fgraph_edge_remove(&graph, 4, 2); tap_ok(res == FGRAPH_ENOEDGE, "no such edge"); res = fgraph_edge_get_weight(&graph, 2, 4, &wval); tap_ok(res == FGRAPH_ENOEDGE, "no such edge"); res = fgraph_edge_set_weight(&graph, 2, 4, 10); tap_ok(res == FGRAPH_ENOEDGE, "no such edge"); res = fgraph_edge_exists(&graph, 2, 4, &ival); tap_ok(res == FGRAPH_SUCCESS, "checked for edge ok"); tap_ok(!ival, "edge does not exist"); res = fgraph_clear(&graph); tap_ok(res == FGRAPH_SUCCESS, "cleared graph ok"); tap_ok(graph == 0, "graph is null"); return tap_status(); }
int main(void) { SXE_HTTPD httpd; SXE_HTTPD_REQUEST * request; tap_ev ev; SXE * listener; SXE * c; SXE * c2; char buffer[1024]; tap_plan(24, TAP_FLAG_ON_FAILURE_EXIT, NULL); test_sxe_register_and_init(12); sxe_httpd_construct(&httpd, 3, 10, 512, 0); SXE_HTTPD_SET_HANDLER(&httpd, connect, h_connect); SXE_HTTPD_SET_HANDLER(&httpd, request, h_request); SXE_HTTPD_SET_HANDLER(&httpd, header, h_header); SXE_HTTPD_SET_HANDLER(&httpd, eoh, h_eoh); SXE_HTTPD_SET_HANDLER(&httpd, body, h_body); SXE_HTTPD_SET_HANDLER(&httpd, respond, h_respond); SXE_HTTPD_SET_HANDLER(&httpd, close, h_close); listener = test_httpd_listen(&httpd, "0.0.0.0", 0); c = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, NULL); sxe_connect(c, "127.0.0.1", SXE_LOCAL_PORT(listener)); is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &ev), "client_connect", "1st Client connected to HTTPD"); TEST_SXE_SEND_LITERAL(c, "POST /this/is/a/URL HTTP/1.1\r\nContent-Length: 10\r\n\r\n12345678\r\n", client_sent, q_client, TEST_WAIT, &ev); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_connect", "HTTPD: connected"); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_request", "HTTPD: new request"); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_header", "HTTPD: header event"); is_strncmp(tap_ev_arg(ev, "key"), "Content-Length", SXE_LITERAL_LENGTH("Content-Length"), "HTTPD: header was 'Connect'"); is_strncmp(tap_ev_arg(ev, "value"), "10", SXE_LITERAL_LENGTH("10"), "HTTPD: header value was 'whatever'"); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_eoh", "HTTPD: eoh (end of headers) event"); test_ev_queue_wait_read(q_httpd, TEST_WAIT, &ev, NULL, "h_body", buffer, 10, "HTTPD body handler"); is_strncmp(buffer, "12345678\r\n", SXE_LITERAL_LENGTH("12345678\r\n"), "HTTPD: read correct body"); /* httpd is still in "req_response" state */ is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_respond", "HTTPD: respond event"); /* Extra data from client, e.g., "content-length" is wrong and shorter than real packet */ TEST_SXE_SEND_LITERAL(c, "AB", client_sent, q_client, TEST_WAIT, &ev); /* Send another valid request again, the connection is in "sink" mode now, data will get ignored */ TEST_SXE_SEND_LITERAL(c, "POST /this/is/a/URL HTTP/1.1\r\nContent-Length: 10\r\n\r\n12345678\r\n", client_sent, q_client, TEST_WAIT, &ev); test_process_all_libev_events(); /* In sink mode, no more httpd events */ is(tap_ev_queue_length(q_httpd), 0, "No lurking httpd events"); /* New client connection should not be affected */ c2 = test_new_tcp(NULL, "0.0.0.0", 0, client_connect, client_read, client_close); sxe_connect(c2, "127.0.0.1", SXE_LOCAL_PORT(listener)); is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &ev), "client_connect", "2nd Client connected to HTTPD"); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_connect", "HTTPD: connected"); TEST_SXE_SEND_LITERAL(c2, "GET /simple HTTP/1.1\r\n\r\n", client_sent, q_client, TEST_WAIT, &ev); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_request", "HTTPD: new request"); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_eoh", "HTTPD: eoh (end of headers) event"); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_respond", "HTTPD: respond event"); request = (SXE_HTTPD_REQUEST *)(long)tap_ev_arg(ev, "request"); sxe_httpd_response_simple(request, h_sent, NULL, 200, "OK", NULL, "Connection", "close", NULL); is_eq(test_tap_ev_queue_identifier_wait(q_httpd, TEST_WAIT, &ev), "h_sent", "HTTPD: finished responding"); sxe_close(request->sxe); #define TEST_200_CLOSE_RESPONSE "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 0\r\n\r\n" test_ev_queue_wait_read(q_client, TEST_WAIT, &ev, c2, "client_read", buffer, SXE_LITERAL_LENGTH(TEST_200_CLOSE_RESPONSE), "client"); is_strncmp(buffer, TEST_200_CLOSE_RESPONSE, SXE_LITERAL_LENGTH(TEST_200_CLOSE_RESPONSE), "GET response is a 200 OK with close"); is_eq(test_tap_ev_queue_identifier_wait(q_client, TEST_WAIT, &ev), "client_close", "Got a client close event"); return exit_status(); }