| 449 CX_TEST_ASSERT(client->req_buffer_pos > 0); |
449 CX_TEST_ASSERT(client->req_buffer_pos > 0); |
| 450 CX_TEST_ASSERT(client->req_buffer_pos < len); |
450 CX_TEST_ASSERT(client->req_buffer_pos < len); |
| 451 |
451 |
| 452 // read the request buffer from sock and continue with client_send_request |
452 // read the request buffer from sock and continue with client_send_request |
| 453 CxBuffer buf; |
453 CxBuffer buf; |
| 454 cxBufferInit(&buf, cxDefaultAllocator, NULL, len, CX_BUFFER_AUTO_EXTEND); |
454 cxBufferInit(&buf, cxDefaultAllocator, NULL, len, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
| 455 char tmpbuf[1024]; |
455 char tmpbuf[1024]; |
| 456 int writes = 1; |
456 int writes = 1; |
| 457 while(client->req_buffer_pos < client->req_buffer_len && writes < 2000000) { |
457 while(client->req_buffer_pos < client->req_buffer_len && writes < 2000000) { |
| 458 ssize_t r = read(sock, tmpbuf, 1024); |
458 ssize_t r = read(sock, tmpbuf, 1024); |
| 459 CX_TEST_ASSERT(r >= 0); |
459 CX_TEST_ASSERT(r >= 0); |
| 477 |
477 |
| 478 // cleanup |
478 // cleanup |
| 479 close(fds[0]); |
479 close(fds[0]); |
| 480 close(fds[1]); |
480 close(fds[1]); |
| 481 http_client_free(client); |
481 http_client_free(client); |
| |
482 cxBufferDestroy(&buf); |
| |
483 } |
| |
484 } |
| |
485 |
| |
486 typedef struct TestResponse { |
| |
487 int status; |
| |
488 char *msg; |
| |
489 CxBuffer *response; |
| |
490 } TestResponse; |
| |
491 |
| |
492 static int test_response_start(HttpClient *client, int status, char *msg, void *userdata) { |
| |
493 TestResponse *test = userdata; |
| |
494 test->status = status; |
| |
495 test->msg = strdup(msg); |
| |
496 return 0; |
| |
497 } |
| |
498 |
| |
499 static ssize_t test_response_body_write(HttpClient *client, void *buf, size_t size, void *userdata) { |
| |
500 TestResponse *test = userdata; |
| |
501 cxBufferWrite(buf, 1, size, test->response); |
| |
502 return size; |
| |
503 } |
| |
504 |
| |
505 static CX_TEST(test_http_client_io_simple) { |
| |
506 CX_TEST_DO { |
| |
507 EventHandler dummy; |
| |
508 HttpClient *client = http_client_new(&dummy); |
| |
509 |
| |
510 int fds[2]; |
| |
511 util_socketpair(fds); |
| |
512 util_socket_setnonblock(fds[0], 1); |
| |
513 util_socket_setnonblock(fds[1], 1); |
| |
514 client->socketfd = fds[0]; |
| |
515 int sock = fds[1]; |
| |
516 |
| |
517 // setup client |
| |
518 http_client_set_uri(client, "/test/uri/"); |
| |
519 http_client_set_method(client, "GET"); |
| |
520 http_client_add_request_header(client, cx_mutstr("Host"), cx_mutstr("localhost")); |
| |
521 http_client_add_request_header(client, cx_mutstr("Test1"), cx_mutstr("value1")); |
| |
522 http_client_add_request_header(client, cx_mutstr("Test2"), cx_mutstr("value2")); |
| |
523 create_req_buffer(client); |
| |
524 |
| |
525 size_t req_header_len = client->req_buffer_len; |
| |
526 |
| |
527 // response buffer |
| |
528 CxBuffer buf; |
| |
529 cxBufferInit(&buf, cxDefaultAllocator, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
| |
530 |
| |
531 TestResponse testr = { 0 }; |
| |
532 testr.response = &buf; |
| |
533 client->response_start = test_response_start; |
| |
534 client->response_start_userdata = &testr; |
| |
535 client->response_body_write = test_response_body_write; |
| |
536 client->response_body_write_userdata = &testr; |
| |
537 |
| |
538 // test IO |
| |
539 Event event; |
| |
540 event.cookie = client; |
| |
541 int ret = client_io(&dummy, &event); |
| |
542 CX_TEST_ASSERT(!client->error); |
| |
543 CX_TEST_ASSERT(ret == 1); |
| |
544 |
| |
545 // do IO and read request until the header is processed |
| |
546 size_t req_header_pos = 0; |
| |
547 char req_buf[4]; |
| |
548 while(req_header_pos < req_header_len) { |
| |
549 ssize_t r = read(sock, req_buf, 4); |
| |
550 if(r == 0) { |
| |
551 break; |
| |
552 } |
| |
553 CX_TEST_ASSERT(r > 0); |
| |
554 req_header_pos += r; |
| |
555 ret = client_io(&dummy, &event); |
| |
556 CX_TEST_ASSERT(!client->error); |
| |
557 CX_TEST_ASSERT(ret == 1); |
| |
558 } |
| |
559 CX_TEST_ASSERT(req_header_pos == req_header_len); |
| |
560 |
| |
561 char *response_str = |
| |
562 "HTTP/1.1 200 OK\r\n" |
| |
563 "Host: localhost\r\n" |
| |
564 "Content-length: 13\r\n" |
| |
565 "\r\n" |
| |
566 "Hello World!\n"; |
| |
567 size_t response_str_len = strlen(response_str); |
| |
568 size_t response_str_pos = 0; |
| |
569 |
| |
570 // send response and do IO |
| |
571 while(response_str_pos < response_str_len) { |
| |
572 size_t len = response_str_len - response_str_pos; |
| |
573 if(len > 3) { |
| |
574 //len = 3; |
| |
575 } |
| |
576 ssize_t w = write(sock, response_str + response_str_pos, len); |
| |
577 if(w == 0) { |
| |
578 break; |
| |
579 } |
| |
580 CX_TEST_ASSERT(w > 0); |
| |
581 response_str_pos += w; |
| |
582 |
| |
583 ret = client_io(&dummy, &event); |
| |
584 |
| |
585 CX_TEST_ASSERT(!client->error); |
| |
586 CX_TEST_ASSERT(ret == 1); |
| |
587 } |
| |
588 CX_TEST_ASSERT(response_str_pos == response_str_len); |
| |
589 CX_TEST_ASSERT(testr.status == 200); |
| |
590 CX_TEST_ASSERT(testr.msg); |
| |
591 CX_TEST_ASSERT(!strcmp(testr.msg, "OK")); |
| |
592 CX_TEST_ASSERT(testr.response->size == 13); |
| |
593 CX_TEST_ASSERT(!cx_strcmp(cx_strn(testr.response->space, testr.response->size), "Hello World!\n")); |
| |
594 |
| |
595 // cleanup |
| |
596 free(testr.msg); |
| |
597 close(fds[0]); |
| |
598 close(fds[1]); |
| |
599 http_client_free(client); |
| |
600 cxBufferDestroy(&buf); |
| 482 } |
601 } |
| 483 } |
602 } |
| 484 |
603 |
| 485 void http_client_add_tests(CxTestSuite *suite) { |
604 void http_client_add_tests(CxTestSuite *suite) { |
| 486 cx_test_register(suite, test_http_client_send_request); |
605 cx_test_register(suite, test_http_client_send_request); |
| 487 } |
606 cx_test_register(suite, test_http_client_io_simple); |
| |
607 } |