#include "easy_file.h" #include "easy_io.h" #include #include #include #include #include #include #include /** * 测试easy_request */ /////////////////////////////////////////////////////////////////////////////////////////////////// #define TEST_ROOT_DIR "/tmp" static char test_thread_7_server_text[400]; static char test_thread_7_filename[64]; static void test_thread_7_string_tobuf(easy_pool_t *pool, easy_list_t *bc, char *name, easy_buf_string_t *s) { if (s->len) { easy_buf_t *b = easy_buf_check_write_space(pool, bc, s->len + strlen(name) + 16); b->last += sprintf(b->last, "%s%.*s
\n", name, s->len, easy_buf_string_ptr(s)); } } static void test_thread_7_request_tobuf(easy_pool_t *pool, easy_list_t *bc, easy_http_request_t *p) { easy_string_pair_t *t; easy_buf_t *b; test_thread_7_string_tobuf(pool, bc, "path: ", &p->str_path); test_thread_7_string_tobuf(pool, bc, "query_sring: ", &p->str_query_string); test_thread_7_string_tobuf(pool, bc, "str_fragment: ", &p->str_fragment); test_thread_7_string_tobuf(pool, bc, "str_body: ", &p->str_body); // headers easy_list_for_each_entry(t, &p->headers_in->list, list) { if (t->name.len && t->value.len) { b = easy_buf_check_write_space(pool, bc, t->name.len + t->value.len + 16); b->last += sprintf(b->last, "%.*s: %.*s
\n", t->name.len, easy_buf_string_ptr(&t->name), t->value.len, easy_buf_string_ptr(&t->value)); } } } static easy_thread_pool_t *test_thread_7_server_tp; static int test_thread_7_request_process(easy_request_t *r, void *args) { easy_file_task_t *ft = (easy_file_task_t *) r->args; easy_http_request_t *p = (easy_http_request_t *) r->ipacket; int rc = 0; easy_file_buf_t *fb = NULL; if (p->str_query_string.len > 0 && memcmp("sendfile=y", p->str_query_string.data, 10) == 0) { easy_file_task_reset(ft, EASY_BUF_FILE); posix_fadvise(ft->fd, ft->offset, ft->bufsize, POSIX_FADV_WILLNEED); // set sendfile to output fb = (easy_file_buf_t *)ft->b; fb->fd = ft->fd; fb->offset = ft->offset; fb->count = ft->bufsize; rc = ft->bufsize; } else { easy_file_task_reset(ft, 0); rc = pread(ft->fd, ft->b->pos, ft->bufsize, ft->offset); ft->b->last = ft->b->pos + rc; } if (rc > 0) { easy_buf_chain_offer(&p->output, ft->b); r->opacket = p; } // first if (ft->offset == 0) { p->content_length = ft->count; p->is_raw_header = 0; } else { p->is_raw_header = 1; } // next ft->offset += rc; if (ft->offset >= ft->count || rc <= 0) { if (fb) easy_file_buf_set_close(fb); else close(ft->fd); return EASY_OK; } else if (ft->offset + ft->bufsize > ft->count) { ft->bufsize = ft->count - ft->offset; } return EASY_AGAIN; } static int test_thread_7_server_process(easy_request_t *r) { easy_http_request_t *p; int fd; char filename[128], url[128]; easy_string_pair_t *t, *t1, *t2; r->opacket = p = (easy_http_request_t *)r->ipacket; // 得到header t = easy_hash_string_get(p->headers_in, "Accept-Language", 15); EXPECT_TRUE(t != NULL); t2 = easy_hash_string_get(p->headers_in, "Accept-Language", 16); EXPECT_TRUE(t2 == NULL); t1 = easy_hash_string_del(p->headers_in, "Accept-Language", 15); EXPECT_EQ((long)t, (long)t1); t1 = easy_hash_string_del(p->headers_in, "Accept-Language", 15); EXPECT_TRUE(t1 == NULL); if (p->parser.method == HTTP_POST) p->str_query_string = p->str_body; if (p->str_query_string.len == 0) { test_thread_7_request_tobuf(r->ms->pool, &p->output, p); } else { // 处理文件名 url[0] = '\0'; if (p->str_path.len) lnprintf(url, 128, "%s", easy_buf_string_ptr(&p->str_path)); if (easy_http_merge_path(filename, 128, TEST_ROOT_DIR, url)) { easy_buf_string_set(&p->status_line, EASY_HTTP_STATUS_400); return EASY_OK; } // 打开文件 fd = open(filename, O_RDONLY); if (fd >= 0) { r->args = (void *)easy_file_task_create(r, fd, 0); easy_thread_pool_push(test_thread_7_server_tp, r, easy_hash_key((uint64_t)(long)r)); return EASY_AGAIN; } else { easy_buf_string_set(&p->status_line, EASY_HTTP_STATUS_404); } } return EASY_OK; } static int test_thread_7_connect(easy_connection_t *c) { return EASY_OK; } static int test_thread_7_disconnect(easy_connection_t *c) { return EASY_OK; } static void test_thread_7_server(int fd) { easy_listen_t *l; easy_io_handler_pt io_handler; int i, port; easy_log_level = (easy_log_level_t)0; easy_io_create(4); easy_io_var.tcp_cork = 1; memset(&io_handler, 0, sizeof(easy_io_handler_pt)); io_handler.decode = easy_http_server_on_decode; io_handler.encode = easy_http_server_on_encode; io_handler.process = test_thread_7_server_process; io_handler.on_connect = test_thread_7_connect; io_handler.on_disconnect = test_thread_7_disconnect; port = 2011; for(i = 0; i < 10; i++, port++) { if ((l = easy_io_add_listen(NULL, port, &io_handler)) != NULL) break; } test_thread_7_server_tp = easy_request_thread_create(2, test_thread_7_request_process, NULL); easy_io_start(); i = write(fd, &port, 2); easy_io_wait(); easy_io_destroy(); } static void *test_thread_7_client_start(void *args) { easy_session_t *s; easy_http_packet_t *packet; easy_http_request_t *p1; easy_addr_t addr; easy_io_handler_pt *io_handler = (easy_io_handler_pt *)args; int i, cnt, total, port, status; cnt = 0; total = 10; port = (int)(long)io_handler->user_data; addr = easy_inet_str_to_addr("localhost", port); i = easy_io_connect(addr, io_handler, 0, NULL); EXPECT_TRUE(i == EASY_OK); for(i = 0; i < total; i++) { if ((packet = easy_session_packet_create(easy_http_packet_t, s, 0)) == NULL) { EXPECT_TRUE(0); break; } easy_list_init(&packet->output); status = 200; easy_buf_string_set(&packet->str_path, test_thread_7_filename); if ((i % 3) == 1) { easy_buf_string_set(&packet->str_query_string, "sendfile=y"); } else if ((i % 3) == 2) { easy_buf_string_set(&packet->str_query_string, "sendfile=n#abc"); } if (i % 2) packet->method = HTTP_POST; packet->headers_out = easy_header_create_table(s->pool); easy_http_add_header(s->pool, packet->headers_out, "Host", "localhost"); easy_http_add_header(s->pool, packet->headers_out, "Connection", "keep-alive"); easy_http_add_header(s->pool, packet->headers_out, "Accept", "image/jpeg"); easy_http_add_header(s->pool, packet->headers_out, "User-Agent", "Mozilla/4.0"); easy_http_add_header(s->pool, packet->headers_out, "Accept-Language", "zh-CN"); p1 = (easy_http_request_t *) easy_io_send(addr, s); cnt ++; if (p1 == NULL) { EXPECT_TRUE(0); cnt --; } else { EXPECT_EQ(p1->parser.status_code, status); if ((i % 3) && (p1->str_body.len == 0 || strncmp(easy_buf_string_ptr(&p1->str_body), test_thread_7_server_text, strlen(test_thread_7_server_text)))) { EXPECT_TRUE(0); cnt --; } } easy_session_destroy(s); if (p1 == NULL) break; } easy_io_disconnect(addr); // EXPECT_EQ(cnt, total); return (void *)NULL; } static void test_thread_7_client(int port) { easy_io_handler_pt io_handler; pthread_t tids[4]; char fullname[128]; int i, fd; easy_log_level = (easy_log_level_t)0; easy_io_create(4); easy_io_var.tcp_cork = 1; easy_io_start(); memset(&io_handler, 0, sizeof(easy_io_handler_pt)); io_handler.decode = easy_http_client_on_decode; io_handler.encode = easy_http_client_on_encode; io_handler.process = easy_client_wait_process; io_handler.on_connect = test_thread_7_connect; io_handler.user_data = (void *)(long)port; memset(test_thread_7_server_text, 'A', 400); test_thread_7_server_text[399] = '\0'; lnprintf(test_thread_7_filename, 64, "/b_%lu_%lu", pthread_self(), time(NULL)); lnprintf(fullname, 128, "%s%s", TEST_ROOT_DIR, test_thread_7_filename); fd = open(fullname, O_CREAT | O_RDWR, 0600); i = write(fd, test_thread_7_server_text, strlen(test_thread_7_server_text)); close(fd); for(i = 0; i < 1; i++) { pthread_create(&tids[i], NULL, test_thread_7_client_start, &io_handler); } for(i = 0; i < 1; i++) { pthread_join(tids[i], NULL); } easy_io_stop(); easy_io_wait(); easy_io_destroy(); unlink(fullname); } TEST(easy_file, thread_7) { int pfd[2]; pid_t pid1, pid2; int ret = 0; int port = 0; if (pipe(pfd) == -1) return; // server if ((pid1 = fork()) == 0) { close(pfd[0]); test_thread_7_server(pfd[1]); close(pfd[1]); exit(easy_test_retval); } else { close(pfd[1]); ret = read(pfd[0], &port, 2); close(pfd[0]); } // client if ((pid2 = fork()) == 0) { test_thread_7_client(port); exit(easy_test_retval); } waitpid(pid2, &ret, 0); EXPECT_EQ(WEXITSTATUS(ret), 0); kill(pid1, SIGINT); usleep(1000); waitpid(pid1, &ret, 0); EXPECT_EQ(WEXITSTATUS(ret), 0); } ///////////////////////////////////////////////////////////////////////////////////////////////////