void t01_url() { INIT_LOCAL(); onion_url *url = onion_url_new(); onion_url_add_handler(url, "^handler1.$", onion_handler_new((onion_handler_handler) handler1, NULL, NULL)); onion_url_add(url, "handler2/", handler2); onion_url_add_with_data(url, "^handler(3|4)/", handler3, NULL, NULL); onion_set_root_handler(server, onion_url_to_handler(url)); onion_request *req = onion_request_new(onion_get_listen_point(server, 0)); #define R "GET /handler1/ HTTP/1.1\n\n" onion_request_write(req, R, sizeof(R)); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 1); FAIL_IF_NOT_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_clean(req); onion_request_write(req, "GET /handler2/ HTTP/1.1\n\n", sizeof(R)); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 2); ONION_DEBUG("%s", urltxt); FAIL_IF_NOT_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_clean(req); onion_request_write(req, "GET /handler3/hello HTTP/1.1\n\n", sizeof(R) + 5); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 3); FAIL_IF_NOT_EQUAL_STR(urltxt, "hello"); free(urltxt); urltxt = NULL; handler_called = 0; onion_request_clean(req); onion_request_write(req, "GET /handler2/hello HTTP/1.1\n\n", sizeof(R) + 5); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 0); FAIL_IF_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_free(req); onion_url_free(url); onion_set_root_handler(server, NULL); END_LOCAL(); }
/** * @short Performs the processing of the request. * @memberof onion_server_t * * Returns the OCS_KEEP_ALIVE or OCS_CLOSE_CONNECTION value. If on keep alive the struct is already reinitialized. * * It calls the root_handler and if it returns an error of any type (or not processed), it calls the * default internal_error_handler. * * Normally it could get the server from the request, but it is passed for homogenity, and * to allow unforseen posibilities. * * @see onion_connection_status */ onion_connection_status onion_server_handle_request(onion_server *server, onion_request *req){ onion_response *res=onion_response_new(req); // Call the main handler. onion_connection_status hs=onion_handler_handle(server->root_handler, req, res); if (hs==OCS_INTERNAL_ERROR || hs==OCS_NOT_IMPLEMENTED || hs==OCS_NOT_PROCESSED){ if (hs==OCS_INTERNAL_ERROR) req->flags|=OR_INTERNAL_ERROR; if (hs==OCS_NOT_IMPLEMENTED) req->flags|=OR_NOT_IMPLEMENTED; if (hs==OCS_NOT_PROCESSED) req->flags|=OR_NOT_FOUND; if (hs==OCS_FORBIDDEN) req->flags|=OR_FORBIDDEN; hs=onion_handler_handle(server->internal_error_handler, req, res); } int rs=onion_response_free(res); if (hs>=0 && rs==OCS_KEEP_ALIVE) // if keep alive, reset struct to get the new petition. onion_request_clean(req); return hs>0 ? rs : hs; }
void t06_create_add_free_POST_toobig(){ INIT_LOCAL(); onion_request *req; int ok; req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); onion_set_max_post_size(server, 10); // Very small limit const char *query="POST /myurl%20/is/very/deeply/nested?test=test&query2=query%202&more_query=%20more%20query+10 HTTP/1.0\n" "Host: 127.0.0.1\n\rContent-Length: 24\n" "Other-Header: My header is very long and with spaces...\r\n\r\npost_data=1&post_data2=2&post_data=1&post_data2=2"; int i; // Straight write, with clean (keep alive like) for (i=0;i<10;i++){ FAIL_IF_NOT_EQUAL(req->flags,0); ok=REQ_WRITE(req,query); FAIL_IF_NOT_EQUAL(ok,OCS_INTERNAL_ERROR); onion_request_clean(req); FAIL_IF_NOT_EQUAL(req->GET,NULL); } onion_request_free(req); END_LOCAL(); }
void t02_create_add_free_overflow(){ INIT_LOCAL(); onion_request *req; int ok, i; req=onion_request_new(custom_io); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); FAIL_IF_EQUAL(req,NULL); char of[14096]; for (i=0;i<sizeof(of);i++) of[i]='a'+i%26; of[i-1]='\0'; char get[14096*4]; sprintf(get,"%s %s %s",of,of,of); ok=REQ_WRITE(req,get); FAIL_IF_NOT_EQUAL(ok,OCS_INTERNAL_ERROR); onion_request_clean(req); sprintf(get,"%s %s %s\n",of,of,of); ok=REQ_WRITE(req,get); FAIL_IF_NOT_EQUAL(ok,OCS_INTERNAL_ERROR); onion_request_clean(req); sprintf(get,"GET %s %s\n",of,of); ok=REQ_WRITE(req,get); printf("%d\n",ok); FAIL_IF_NOT_EQUAL(ok,OCS_INTERNAL_ERROR); onion_request_free(req); END_LOCAL(); }
void t05_create_add_free_POST(){ INIT_LOCAL(); onion_request *req; int ok; req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); const char *query="POST /myurl%20/is/very/deeply/nested?test=test&query2=query%202&more_query=%20more%20query+10 HTTP/1.0\n" "Host: 127.0.0.1\n\rContent-Length: 50\n" "Other-Header: My header is very long and with spaces...\r\n\r\nempty_post=&post_data=1&post_data2=2&empty_post_2=\n"; int i; // Straight write, with clean (keep alive like) for (i=0;i<10;i++){ FAIL_IF_NOT_EQUAL(req->flags,0); ok=REQ_WRITE(req,query); FAIL_IF_NOT_EQUAL(ok, OCS_CLOSE_CONNECTION); FAIL_IF_EQUAL(req->flags,OR_GET|OR_HTTP11); FAIL_IF_EQUAL(req->headers, NULL); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->headers,"Host"), "127.0.0.1"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->headers,"Other-Header"), "My header is very long and with spaces..."); FAIL_IF_NOT_EQUAL_STR(req->fullpath,"/myurl /is/very/deeply/nested"); FAIL_IF_NOT_EQUAL_STR(req->path,"myurl /is/very/deeply/nested"); FAIL_IF_EQUAL(req->GET,NULL); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->GET,"test"), "test"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->GET,"query2"), "query 2"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(req->GET,"more_query"), " more query 10"); const onion_dict *post=onion_request_get_post_dict(req); FAIL_IF_EQUAL(post,NULL); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(post,"post_data"), "1"); FAIL_IF_NOT_EQUAL_STR( onion_dict_get(post,"post_data2"), "2"); FAIL_IF_NOT_EQUAL_STR( onion_request_get_post(req, "empty_post"), ""); FAIL_IF_NOT_EQUAL_STR( onion_request_get_post(req, "empty_post_2"), ""); onion_request_clean(req); FAIL_IF_NOT_EQUAL(req->GET,NULL); } onion_request_free(req); END_LOCAL(); }
/// A BUG were detected: transformed \n to \r\n on files. void t03_post_carriage_return_new_lines_file(){ INIT_LOCAL(); buffer *b=buffer_new(1024); expected_post post={};; post.filename="file.dat"; post.test_ok=0; // Not ok as not called processor yet post.tmpfilename=NULL; post.size=3; onion_server *server=onion_server_new(); onion_server_set_write(server, (void*)&buffer_append); onion_server_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL)); onion_request *req=onion_request_new(server,b,"test"); #define POST_EMPTY "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length:81\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\n\n\n\r\n\n--end--" //ONION_DEBUG("%s",POST_EMPTY); onion_request_write(req,POST_EMPTY,sizeof(POST_EMPTY)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTY onion_request_clean(req); post.test_ok=0; // Not ok as not called processor yet #define POST_EMPTYR "POST / HTTP/1.1\r\nContent-Type: multipart/form-data; boundary=end\r\nContent-Length:85\r\n\r\n--end\r\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\r\n\r\n\n\r\n\r\n--end--" onion_request_write(req,POST_EMPTYR,sizeof(POST_EMPTYR)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTYR onion_request_free(req); if (post.tmpfilename){ struct stat st; FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist free(post.tmpfilename); } if (post.tmplink) free(post.tmplink); onion_server_free(server); buffer_free(b); END_LOCAL(); }
/// A BUG were detected: transformed \n to \r\n on files. void t02_post_new_lines_file(){ INIT_LOCAL(); expected_post post={};; post.filename="file.dat"; post.test_ok=0; // Not ok as not called processor yet post.tmpfilename=NULL; post.size=1; onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL)); onion_request *req=onion_request_new(lp); #define POST_EMPTY "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length:81\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\n\n\n\n--end--" onion_request_write(req,POST_EMPTY,sizeof(POST_EMPTY)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTY onion_request_clean(req); post.test_ok=0; // Not ok as not called processor yet #define POST_EMPTYR "POST / HTTP/1.1\r\nContent-Type: multipart/form-data; boundary=end\r\nContent-Length:85\r\n\r\n--end\r\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\r\n\r\n\n\r\n--end--" onion_request_write(req,POST_EMPTYR,sizeof(POST_EMPTYR)); FAIL_IF_NOT_EQUAL(post.test_ok,1); #undef POST_EMPTYR onion_request_free(req); if (post.tmpfilename){ struct stat st; FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist free(post.tmpfilename); } if (post.tmplink) free(post.tmplink); onion_free(server); END_LOCAL(); }
void t07_multiline_headers(){ INIT_LOCAL(); onion_request *req; int ok; onion_set_max_post_size(server, 1024); req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); { const char *query="GET / HTTP/1.0\n" "Host: 127.0.0.1\n\rContent-Length: 24\n" "Other-Header: My header is very long and with several\n lines\n" "Extra-Other-Header: My header is very long and with several\n \n lines\n" "My-Other-Header: My header is very long and with several\n\tlines\n\n"; ok=onion_request_write(req,query,strlen(query)); } FAIL_IF_EQUAL(ok,OCS_INTERNAL_ERROR); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"other-header"),"My header is very long and with several lines"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"extra-other-header"),"My header is very long and with several lines"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"My-other-header"),"My header is very long and with several lines"); onion_request_clean(req); { const char *query="GET / HTTP/1.0\n" "Host: 127.0.0.1\n\rContent-Length: 24\n" "Other-Header: My header is very long and with several\n lines\n" "My-Other-Header: My header is very long and with several\nlines\n\n"; ok=onion_request_write(req,query,strlen(query)); } FAIL_IF_NOT_EQUAL(ok,OCS_INTERNAL_ERROR); // No \t at my-other-header onion_request_free(req); END_LOCAL(); }
/** * @short Launches one handler for the given request * @ingroup request * * Once the request is ready, launch it. * * @returns The connection status: if it should be closed, error codes... */ onion_connection_status onion_request_process(onion_request *req){ onion_response *res=onion_response_new(req); if (!req->path){ onion_request_polish(req); } // Call the main handler. onion_connection_status hs=onion_handler_handle(req->connection.listen_point->server->root_handler, req, res); if (hs==OCS_INTERNAL_ERROR || hs==OCS_NOT_IMPLEMENTED || hs==OCS_NOT_PROCESSED){ if (hs==OCS_INTERNAL_ERROR) req->flags|=OR_INTERNAL_ERROR; if (hs==OCS_NOT_IMPLEMENTED) req->flags|=OR_NOT_IMPLEMENTED; if (hs==OCS_NOT_PROCESSED) req->flags|=OR_NOT_FOUND; if (hs==OCS_FORBIDDEN) req->flags|=OR_FORBIDDEN; hs=onion_handler_handle(req->connection.listen_point->server->internal_error_handler, req, res); } if (hs==OCS_YIELD){ // Remove from the poller, and yield thread to poller. From now on it will be processed somewhere else (longpoll thread). onion_poller *poller=onion_get_poller(req->connection.listen_point->server); onion_poller_slot *slot=onion_poller_get(poller, req->connection.fd); onion_poller_slot_set_shutdown(slot, NULL, NULL); return hs; } int rs=onion_response_free(res); if (hs>=0 && rs==OCS_KEEP_ALIVE) // if keep alive, reset struct to get the new petition. onion_request_clean(req); return hs>0 ? rs : hs; }
/// There is a bug when posting large files. Introduced when change write 1 by 1, to write by blocks on the FILE parser void t04_post_largefile(){ INIT_LOCAL(); int postfd=open(BIG_FILE, O_RDONLY); off_t filesize=lseek(postfd, 0, SEEK_END); lseek(postfd, 0, SEEK_SET); expected_post post={};; post.filename=BIG_FILE_BASE; post.test_ok=0; // Not ok as not called processor yet post.tmpfilename=NULL; post.size=filesize; onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL)); onion_request *req=onion_request_new(lp); #define POST_HEADER "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length: %d\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"" BIG_FILE_BASE "\"\n\n" char tmp[1024]; ONION_DEBUG("Post size is about %d",filesize+73); snprintf(tmp, sizeof(tmp), POST_HEADER, (int)filesize+73); ONION_DEBUG("%s",tmp); onion_request_write(req,tmp,strlen(tmp)); int r=read(postfd, tmp, sizeof(tmp)); while ( r>0 ){ onion_request_write(req, tmp, r); r=read(postfd, tmp, sizeof(tmp)); } onion_request_write(req,"\n--end--",8); FAIL_IF_NOT_EQUAL_INT(post.test_ok,1); #undef POST_HEADER onion_request_clean(req); //post.test_ok=0; // Not ok as not called processor yet lseek(postfd, 0, SEEK_SET); int difffd=open(post.tmpfilename, O_RDONLY); FAIL_IF_NOT_EQUAL_INT(difffd,-1); // Orig file is removed at handler returns. But i have a copy difffd=open(post.tmplink, O_RDONLY); FAIL_IF_EQUAL_INT(difffd,-1); ONION_DEBUG("tmp filename %s",post.tmpfilename); int r1=1, r2=1; char c1=0, c2=0; int p=0; while ( r1 && r2 && c1==c2){ r1=read(difffd, &c1, 1); r2=read(postfd, &c2, 1); //ONION_DEBUG("%d %d",c1,c2); FAIL_IF_NOT_EQUAL_INT(c1,c2); p++; } if ( r1 || r2 ){ ONION_ERROR("At %d",p); FAIL_IF_NOT_EQUAL_INT(r1,0); FAIL_IF_NOT_EQUAL_INT(r2,0); FAIL_IF_NOT_EQUAL_INT(c1,c2); FAIL("Files are different"); } else ONION_DEBUG("Files are ok"); close(difffd); close(postfd); onion_request_free(req); if (post.tmpfilename){ struct stat st; FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist } onion_free(server); if (post.tmpfilename) free(post.tmpfilename); if (post.tmplink) free(post.tmplink); END_LOCAL(); }
/** * @short Opens a script file, and executes it. */ void prerecorded(const char *oscript, int do_r){ INIT_LOCAL(); FILE *fd=fopen(oscript, "r"); if (!fd){ FAIL("Could not open script file"); END_LOCAL(); return; } const char *script=basename((char*)oscript); buffer *buffer=buffer_new(1024*1024); onion_request *req=onion_request_new(server, buffer, "test"); ssize_t r; const size_t LINE_SIZE=1024; char *line=malloc(LINE_SIZE); size_t len=LINE_SIZE; onion_connection_status ret; int ntest=0; int linen=0; while (!feof(fd)){ ntest++; ret=OCS_NEED_MORE_DATA; ONION_DEBUG("Test %d",ntest); // Read request while ( (r=getline(&line, &len, fd)) != -1 ){ linen++; if (strcmp(line,"-- --\n")==0){ break; } if (do_r){ line[r-1]='\r'; line[r]='\n'; r++; } if (ret==OCS_NEED_MORE_DATA) ret=onion_request_write(req, line, r); //line[r]='\0'; //ONION_DEBUG0("Write: %s\\n (%d). Ret %d",line,r,ret); len=LINE_SIZE; } if (r<0){ buffer_free(buffer); fclose(fd); onion_request_free(req); free(line); END_LOCAL(); return; } if (r==0){ FAIL_IF("Found end of file before end of request"); buffer_free(buffer); fclose(fd); onion_request_free(req); free(line); END_LOCAL(); return; } // Check response buffer->data[buffer->pos]='\0'; if (buffer->pos==0){ ONION_DEBUG("Empty response"); } else{ ONION_DEBUG0("Response: %s",buffer->data); } while ( (r=getline(&line, &len, fd)) != -1 ){ linen++; if (strcmp(line,"++ ++\n")==0){ break; } line[strlen(line)-1]='\0'; if (strcmp(line,"INTERNAL_ERROR")==0){ // Checks its an internal error ONION_DEBUG("%s:%d Check INTERNAL_ERROR",script,linen); ONION_DEBUG0("Returned %d",ret); FAIL_IF_NOT_EQUAL(ret, OCS_INTERNAL_ERROR); } else if (strcmp(line,"NOT_IMPLEMENTED")==0){ // Checks its an internal error ONION_DEBUG("Check NOT_IMPLEMENTED"); ONION_DEBUG0("Returned %d",ret); FAIL_IF_NOT_EQUAL(ret, OCS_NOT_IMPLEMENTED); } else{ regex_t re; regmatch_t match[1]; int l=strlen(line)-1; int _not=line[0]=='!'; if (_not){ ONION_DEBUG("Oposite regexp"); memmove(line, line+1, l); l--; } memmove(line+1,line,l+1); line[0]='^'; line[l+2]='$'; line[l+3]='\0'; ONION_DEBUG("%s:%d Check regexp: '%s'",script, linen, line); int r; r=regcomp(&re, line, REG_EXTENDED); if ( r !=0 ){ char error[1024]; regerror(r, &re, error, sizeof(error)); ONION_ERROR("%s:%d Error compiling regular expression %s: %s",script, linen, line, error); FAIL(line); } else{ int _match=regexec_multiline(&re, buffer->data, 1, match, 0); if ( (_not && _match==0) || (!_not && _match!=0) ){ ONION_ERROR("%s:%d cant find %s",script, linen, line); FAIL(line); } else{ ONION_DEBUG0("Found at %d-%d",match[0].rm_so, match[0].rm_eo); FAIL_IF(0); // To mark a passed test } } regfree(&re); } len=1024; } buffer_clean(buffer); onion_request_clean(req); } free(line); onion_request_free(req); buffer_free(buffer); fclose(fd); END_LOCAL(); }
void t01_call_otemplate(){ INIT_LOCAL(); onion *s=onion_new(0); onion_set_root_handler(s, onion_handler_new((void*)_13_otemplate_html_handler_page, NULL, NULL)); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(s,NULL,NULL,lp); struct tests_call_otemplate tests; onion_request *req=onion_request_new(lp); FAIL_IF_NOT_EQUAL_INT(onion_request_write0(req, "GET /\n\n"), OCS_REQUEST_READY); FAIL_IF_NOT_EQUAL_INT(onion_request_process(req), OCS_CLOSE_CONNECTION); ONION_INFO("Got %s",onion_buffer_listen_point_get_buffer_data(req)); check_tests(onion_buffer_listen_point_get_buffer(req), &tests); FAIL_IF_NOT_EQUAL_INT(tests.ok_hello,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_list,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_title,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_title_title,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_encoding,0); onion_dict *d=onion_dict_new(); onion_dict_add(d, "title", "TITLE",0); onion_dict_add(d, "hello", "SHOULD NOT APPEAR",0); onion_dict_add(d, "quoted", "<\"Hello>",0); onion_request_clean(req); onion_handler_free(onion_get_root_handler(s)); onion_set_root_handler(s, onion_handler_new((void*)_13_otemplate_html_handler_page, d, NULL)); FAIL_IF_NOT_EQUAL_INT(onion_request_write0(req, "GET /\n\n"), OCS_REQUEST_READY); FAIL_IF_NOT_EQUAL_INT(onion_request_process(req), OCS_CLOSE_CONNECTION); ONION_INFO("Got %s",onion_buffer_listen_point_get_buffer_data(req)); check_tests(onion_buffer_listen_point_get_buffer(req), &tests); FAIL_IF_NOT_EQUAL_INT(tests.ok_hello,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_list,0); FAIL_IF_NOT_EQUAL_INT(tests.ok_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_title_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_encoding,1); onion_dict *d2=onion_dict_new(); onion_dict_add(d2,"0","LIST 1",0); onion_dict_add(d2,"1","LIST 2",0); onion_dict_add(d2,"2","LIST 3",0); onion_dict_add(d,"list",d2, OD_DICT|OD_FREE_VALUE); onion_dict *f1=onion_dict_new(); onion_dict *f2=onion_dict_new(); onion_dict_add(f2, "0", "internal",0); onion_dict_add(f2, "1", "loop",0); onion_dict_add(f1, "loop", f2, OD_DICT|OD_FREE_VALUE); onion_dict_add(d, "loop", f1, OD_DICT|OD_FREE_VALUE); onion_request_clean(req); onion_handler_free(onion_get_root_handler(s)); onion_set_root_handler(s, onion_handler_new((void*)_13_otemplate_html_handler_page, d, (void*)onion_dict_free)); FAIL_IF_NOT_EQUAL_INT(onion_request_write0(req, "GET /\n\n"), OCS_REQUEST_READY); FAIL_IF_NOT_EQUAL_INT(onion_request_process(req), OCS_CLOSE_CONNECTION); check_tests(onion_buffer_listen_point_get_buffer(req), &tests); ONION_INFO("Got %s",onion_buffer_listen_point_get_buffer_data(req)); FAIL_IF_NOT_EQUAL_INT(tests.ok_hello,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_list,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_title_title,1); FAIL_IF_NOT_EQUAL_INT(tests.ok_internal_loop,1); onion_request_free(req); onion_free(s); END_LOCAL(); }