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(); }
void t04_cookies(){ INIT_LOCAL(); onion_response *res=onion_response_new(NULL); onion_dict *h=onion_response_get_headers(res); onion_response_add_cookie(res, "key1", "value1", -1, NULL, NULL, 0); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key1=value1"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key2", "value2", -1, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key2=value2; path=/; domain=*.example.org; HttpOnly; Secure"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key3", "value3", 0, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key3=value3; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=*.example.org; HttpOnly; Secure"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key4", "value4", 60, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key4=value4; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=*.example.org; HttpOnly; Secure"); FAIL_IF_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key4=value4; domain=*.example.org; HttpOnly; path=/; Secure"); int i; int valid_expires=0; char tmpdate[100]; const char *setcookie=onion_dict_get(h, "Set-Cookie"); for(i=59;i<62;i++){ struct tm *tmp; time_t t=time(NULL) + i; tmp = localtime(&t); strftime(tmpdate, sizeof(tmpdate), "key4=value4; expires=%a, %d %b %Y %H:%M:%S %Z; path=/; domain=*.example.org; HttpOnly; Secure", tmp); ONION_DEBUG("\ntest %s =? \nonion %s", tmpdate, setcookie); if (strcmp(tmpdate, setcookie)==0) valid_expires=1; } FAIL_IF_NOT(valid_expires); onion_response_free(res); END_LOCAL(); }
void t01_post_empty_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=0; 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:80\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\n\n\n--end--" onion_request_write(req,POST_EMPTY,sizeof(POST_EMPTY)); FAIL_IF_NOT_EQUAL(post.test_ok,1); onion_request_clean(req); post.test_ok=0; // Not ok as not called processor yet #undef POST_EMPTY #define POST_EMPTYR "POST / HTTP/1.1\r\nContent-Type: multipart/form-data; boundary=end\r\nContent-Length:84\r\n\r\n--end\r\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\r\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_free(server); END_LOCAL(); }
void t01_basic(){ INIT_LOCAL(); Onion::Dict normal; normal.add("Hello", "World"); onion_dict *d=onion_dict_new(); onion_dict_add(d, "Hello", "2", 0); Onion::Dict non_owner(d); FAIL_IF_NOT_EQUAL_STRING(non_owner.get("Hello"), "2"); Onion::Dict owner(d, true); FAIL_IF_NOT_EQUAL_STRING(owner.get("Hello"), "2"); non_owner.add("non-owner", "true"); FAIL_IF_NOT_EQUAL_STRING(owner.get("non-owner"), "true"); FAIL_IF_NOT_EQUAL_STRING(onion_dict_get(d,"non-owner"), "true"); END_LOCAL(); }
void t04_langtest(){ INIT_LOCAL(); Onion::Dict main_dict; /* == With bug do not fail with this workaround: == const Onion::Dict test = getLanguagesDict(); main_dict.add("languages", test); */ main_dict.add("languages", getLanguagesDict()); std::string json=main_dict.toJSON(); std::cout<<json<<std::endl;; Onion::Dict languages = main_dict.getDict("languages"); json=main_dict.toJSON(); std::cout<<json<<std::endl;; FAIL_IF_NOT_EQUAL_STRING(languages.get("en"), "English"); FAIL_IF_NOT_EQUAL_STRING(languages.get("es"), "Español"); END_LOCAL(); }
void t03_full_cycle_http11(){ INIT_LOCAL(); onion *server=onion_new(0); onion_add_listen_point(server, NULL,NULL,onion_buffer_listen_point_new()); onion_request *request; char buffer[4096]; memset(buffer,0,sizeof(buffer)); request=onion_request_new(server->listen_points[0]); FILL(request,"GET / HTTP/1.1\n"); onion_response *response=onion_response_new(request); onion_response_set_length(response, 30); FAIL_IF_NOT_EQUAL(response->length,30); onion_response_write_headers(response); onion_response_write0(response,"123456789012345678901234567890"); onion_response_flush(response); FAIL_IF_NOT_EQUAL(response->sent_bytes,30); onion_response_free(response); buffer[sizeof(buffer)-1]=0; strncpy(buffer,onion_buffer_listen_point_get_buffer_data(request),sizeof(buffer)-1); onion_request_free(request); onion_free(server); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_STRSTR(buffer, "Connection: Keep-Alive\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 30\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Server: libonion"); FAIL_IF_NOT_STRSTR(buffer, "coralbits"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\n123456789012345678901234567890"); //FAIL_IF_NOT_EQUAL_STR(buffer, "HTTP/1.1 200 OK\r\nContent-Length: 30\r\nServer: libonion v0.1 - coralbits.com\r\n\r\n123456789012345678901234567890"); END_LOCAL(); }
void t09_very_long_header(){ 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_t="GET / HTTP/1.0\n" "Content-Type: application/x-www-form-urlencoded\n" "Host: 127.0.0.1\n\r" "Content-Length: 24\n" "Accept-Language: en\n" "Content-Type: "; const int longsize=strlen(query_t)+16; char *query=malloc(longsize); // 1MB enought? strcpy(query, query_t); int i; for (i=strlen(query); i<longsize -2; i++) // fill with crap query[i]='a'+(i%30); query[longsize-3]='\n'; query[longsize-2]='\n'; query[longsize-1]=0; FAIL_IF_NOT_EQUAL_INT(strlen(query), longsize-1); ok=onion_request_write(req, query, longsize); free(query); } FAIL_IF_EQUAL_INT(ok,OCS_INTERNAL_ERROR); onion_request_free(req); END_LOCAL(); }
void t01_stop_listening(){ INIT_LOCAL(); signal(SIGTERM, shutdown_server); o=onion_new(O_POOL); pthread_t th; pthread_create(&th, NULL, listen_thread_f, NULL); sleep(2); FAIL_IF_NOT(ok_listening); kill(getpid(), SIGTERM); sleep(2); FAIL_IF(ok_listening); pthread_join(th, NULL); onion_free(o); END_LOCAL(); }
void t08_threaded_lock(){ INIT_LOCAL(); onion_dict *d=onion_dict_new(); pthread_t thread[N_READERS]; int i; for (i=0;i<N_READERS;i++){ onion_dict *d2=onion_dict_dup(d); pthread_create(&thread[i], NULL, (void*)t08_thread_read, d2); } //sleep(1); t08_thread_write(d); for (i=0;i<N_READERS;i++){ char *v; pthread_join(thread[i],(void**) &v); FAIL_IF_NOT_EQUAL(v, (char *)v); } END_LOCAL(); }
void t04_codecs_base64_encode_decode(){ INIT_LOCAL(); char text[1025]; int tlength=0; int i,j; int l; for (i=0;i<100;i++){ tlength=1024*(rand()/((double)RAND_MAX)); for (j=0;j<tlength;j++) text[j]=rand()&0x0FF; text[j]=0; char *enc=onion_base64_encode(text, tlength); char *res=onion_base64_decode(enc, &l); FAIL_IF_NOT_EQUAL(l,tlength); FAIL_IF( memcmp(res,text, l)!=0 ); free(res); free(enc); } END_LOCAL(); }
static int knh_runMain(CTX ctx, int argc, const char **argv) { KONOHA_BEGIN(ctx); kMethod *mtd = ClassTBL_getMethodNULL(ctx, O_cTBL(ctx->script), MN_main); int res = 0; if(mtd != NULL) { int thisidx = 1 + K_CALLDELTA; BEGIN_LOCAL(ctx, lsfp, 5); lsfp[1].ivalue = 0; lsfp[thisidx+K_PCIDX].pc = NULL; klr_setmtdNC(ctx,lsfp[thisidx+K_MTDIDX], mtd); KNH_SETv(ctx, lsfp[thisidx].o, ctx->script); KNH_SETv(ctx, lsfp[thisidx+1].o, knh_getPropertyNULL(ctx, STEXT("script.argv"))); klr_setesp(ctx, lsfp + thisidx+2); if(knh_VirtualMachine_launch(ctx, lsfp + thisidx)) { res = (int)lsfp[1].ivalue; } END_LOCAL(ctx, lsfp); } KONOHA_END(ctx); return res; }
void t11_cookies(){ 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="GET / HTTP/1.0\n" "Content-Type: application/x-www-form-urlencoded\n" "Host: 127.0.0.1\n\r" "Cookie: key1=value1; key2=value2;\n" "Accept-Language: en\n"; // Missing \n caused memleak, to check with valgrind 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,"Host"),"127.0.0.1"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Cookie"), "key1=value1; key2=value2;"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_cookie(req,"key1"), "value1"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_cookie(req,"key2"), "value2"); FAIL_IF_EQUAL_STR(onion_request_get_cookie(req," key2"), "value2"); onion_dict *cookies=onion_request_get_cookies_dict(req); FAIL_IF_EQUAL(cookies, NULL); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(cookies,"key1"), "value1"); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(cookies,"key2"), "value2"); onion_request_free(req); END_LOCAL(); }
void t03_codecs_base64_encode_decode_10(){ INIT_LOCAL(); char text[11]; int i,j; int l; for (i=0;i<10;i++){ //memset(text,0,sizeof(text)); for (j=0;j<i;j++) text[j]='1'+j; text[j]='\0'; char *enc=onion_base64_encode(text, i); char *res=onion_base64_decode(enc, &l); //fprintf(stderr, "%s:%d Encoded '%s', is '%s', decoded as '%s'\n",__FILE__,__LINE__,text, enc, res); FAIL_IF_NOT_EQUAL(l,i); FAIL_IF( memcmp(res,text, l)!=0 ); free(res); free(enc); } END_LOCAL(); }
void t00_server_empty(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_request *req=onion_request_new(lp); onion_request_write(req, "GET ",4); onion_request_write(req, "/",1); onion_request_write(req, " HTTP/1.1\r\n",11); onion_request_write(req, "\r\n",2); const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer,"404"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t07_replace(){ INIT_LOCAL(); onion_dict *dict=onion_dict_new(); onion_dict_add(dict,"a","1", OD_DUP_ALL|OD_REPLACE); onion_dict_add(dict,"a","1", OD_REPLACE); onion_dict_add(dict,"a","1", OD_DUP_ALL|OD_REPLACE); onion_dict_add(dict,"a","1", OD_REPLACE); onion_dict_add(dict,"a","1", OD_DUP_ALL|OD_REPLACE); int n=0; onion_dict_preorder(dict, t07_sum, &n); FAIL_IF_NOT_EQUAL_INT(n,1); onion_dict_add(dict,"a","1", 0); n=0; onion_dict_preorder(dict, t07_sum, &n); FAIL_IF_NOT_EQUAL_INT(n,2); onion_dict_free(dict); END_LOCAL(); }
void t02_dup(){ INIT_LOCAL(); Onion::Dict normal; normal.add("Hello", "World"); Onion::Dict copy4; copy4=normal.c_handler(); FAIL_IF_NOT_EQUAL_STRING(copy4.get("Hello"), "World"); Onion::Dict copy2; copy2=normal; FAIL_IF_NOT_EQUAL_STRING(copy2.get("Hello"), "World"); Onion::Dict copy=normal; FAIL_IF_NOT_EQUAL_STRING(copy.get("Hello"), "World"); Onion::Dict copy3(normal); FAIL_IF_NOT_EQUAL_STRING(copy3.get("Hello"), "World"); Onion::Dict dup=normal.hard_dup(); FAIL_IF_NOT_EQUAL_STRING(dup.get("Hello"), "World"); dup.add("Hello","world!",OD_REPLACE|OD_DUP_ALL); FAIL_IF_EQUAL_STRING(dup.get("Hello"), "World"); FAIL_IF_NOT_EQUAL_STRING(dup.get("Hello"), "world!"); FAIL_IF_EQUAL_STRING(copy.get("Hello"), "world!"); FAIL_IF_EQUAL_STRING(copy2.get("Hello"), "world!"); normal.add("Tst","tst"); FAIL_IF_NOT_EQUAL_STRING(copy.get("Tst"), "tst"); FAIL_IF_NOT_EQUAL_STRING(copy2.get("Tst"), "tst"); FAIL_IF_EQUAL_STRING(dup.get("Tst"), "tst"); 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_preorder(){ INIT_LOCAL(); onion_dict *dict; dict=onion_dict_new(); onion_dict_add(dict,"A","B",0); onion_dict_add(dict,"C","D",0); onion_dict_add(dict,"E","F",0); onion_dict_add(dict,"G","H",0); onion_dict_add(dict,"I","J",0); onion_dict_add(dict,"K","L",0); onion_dict_add(dict,"M","N",0); onion_dict_add(dict,"O","P",0); onion_dict_add(dict,"Q","R",0); onion_dict_add(dict,"S","T",0); char buffer[4096]; memset(buffer,0,sizeof(buffer)); onion_dict_preorder(dict, append_as_headers, buffer); FAIL_IF_NOT_EQUAL_STR(buffer,"A: B\nC: D\nE: F\nG: H\nI: J\nK: L\nM: N\nO: P\nQ: R\nS: T\n"); onion_dict_free(dict); END_LOCAL(); }
void t01_listen_port() { INIT_LOCAL(); if (!geteuid()) { // current user is root // set user to nobody struct passwd * pwd = calloc(1, sizeof(struct passwd)); FAIL_IF_NOT(pwd); size_t buffer_length = sysconf(_SC_GETPW_R_SIZE_MAX); FAIL_IF_NOT(buffer_length > 0); char * buffer = malloc(buffer_length * sizeof(char)); FAIL_IF_NOT(buffer); int lookup_result = getpwnam_r("nobody", pwd, buffer, buffer_length, &pwd); FAIL_IF(lookup_result); FAIL_IF_NOT(pwd); int setuid_result = setuid(pwd->pw_uid); FAIL_IF(setuid_result); free(pwd); free(buffer); } // current user is not root // it has no permissions to bind to port 88 t01_server=onion_new(O_THREADED); onion_set_max_threads(t01_server, 2); t01_errors_count=0; t01_failed=false; onion_log=t01_listen_port_error_handler; onion_set_port(t01_server, "88"); onion_listen(t01_server); onion_free(t01_server); FAIL_IF(t01_failed); END_LOCAL(); }
void t01_create_add_free_10(){ INIT_LOCAL(); onion_dict *dict; const char *value; dict=onion_dict_new(); FAIL_IF_EQUAL(dict,NULL); // Get before anything in value=onion_dict_get(dict, "Request"); FAIL_IF_NOT_EQUAL(value,NULL); // basic add int i; char tmp[256]; for (i=0;i<10;i++){ snprintf(tmp,sizeof(tmp),"%d",(i*13)%10); ////ONION_DEBUG("add key %s",tmp); onion_dict_add(dict, tmp, "GET /", OD_DUP_ALL); value=onion_dict_get(dict, tmp); FAIL_IF_NOT_EQUAL_STR(value,"GET /"); //onion_dict_print_dot(dict); } for (i=0;i<10;i++){ snprintf(tmp,sizeof(tmp),"%d",i); ////ONION_DEBUG("rm key %s",tmp); onion_dict_remove(dict, tmp); value=onion_dict_get(dict, tmp); FAIL_IF_NOT_EQUAL(value,NULL); //onion_dict_print_dot(dict); } onion_dict_free(dict); END_LOCAL(); }
void t03_subdict(){ INIT_LOCAL(); Onion::Dict a; a.add("Hello", "World"); { #if __cplusplus >= 201103L // C++11 Style add, if not using c++11, compile anyway. Onion::Dict b( {{"Hello","World"},{"Another","item"}} ); #else Onion::Dict b; b.add("Hello","World"); b.add("Another","item"); #endif a.add("dict",b); } std::string json=a.toJSON(); std::cout<<json<<std::endl;; FAIL_IF_NOT_EQUAL_STRING(json, "{\"Hello\":\"World\", \"dict\":{\"Another\":\"item\", \"Hello\":\"World\"}}"); END_LOCAL(); };
void t11_hard_dup(){ INIT_LOCAL(); onion_dict *orig=onion_dict_new(); char tmp[9]; int i; for (i=0;i<256;i++){ sprintf(tmp,"%08X",rand()); onion_dict_add(orig, tmp, tmp, OD_DUP_ALL); } onion_dict_add(orig, "0", "no frees", 0); onion_dict *dest=onion_dict_hard_dup(orig); /// Check they have exactly the same keys. onion_dict_preorder(orig, cmpdict, dest); onion_dict_preorder(dest, cmpdict, orig); onion_dict_free(orig); onion_dict_free(dest); END_LOCAL(); }
/// 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(); }
void t03_handle_path_request(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server, NULL, NULL, lp); onion_url *urls=onion_url_new(); onion_url_add_static(urls, "^$", "Test index\n", HTTP_OK); onion_url_add_static(urls, "^index.html$", "Index test", 200); onion_url *pathu=onion_url_new(); onion_handler *path=onion_url_to_handler(pathu); onion_url_add_url(pathu, "^test/", urls); onion_handler_add(path, onion_handler_static("Internal error", 500 ) ); onion_set_root_handler(server, path); onion_request *request; onion_response *response; request=onion_request_new(lp); FILL(request,"GET / HTTP/1.1\n"); onion_request_polish(request); response=onion_response_new(request); onion_handler_handle(path, request, response); onion_response_free(response); const char *buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 500 INTERNAL ERROR\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 14\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nInternal error"); onion_request_free(request); // gives error, as such url does not exist. request=onion_request_new(lp); FILL(request,"GET /test/ HTTP/1.1\n"); onion_request_polish(request); response=onion_response_new(request); onion_handler_handle(path, request, response); onion_response_free(response); buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 11\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nTest index\n"); onion_request_free(request); request=onion_request_new(lp); FILL(request,"GET /test/index.html HTTP/1.1\n"); onion_request_polish(request); response=onion_response_new(request); onion_handler_handle(path, request, response); onion_response_free(response); buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 10\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nIndex test"); onion_request_free(request); onion_free(server); END_LOCAL(); }
void t10_tojson(){ INIT_LOCAL(); onion_dict *d=onion_dict_new(); const char *tmp; int s; onion_block *b; b=onion_dict_to_json(d); tmp=onion_block_data(b); ONION_DEBUG("Json returned is '%s'", tmp); FAIL_IF_NOT_EQUAL_STR(tmp,"{}"); onion_block_free(b); onion_dict_add(d, "test", "json", 0); b=onion_dict_to_json(d); tmp=onion_block_data(b); s=onion_block_size(b); ONION_DEBUG("Json returned is '%s'", tmp); FAIL_IF(s<=0); FAIL_IF_EQUAL(strstr(tmp,"{"), NULL); FAIL_IF_EQUAL(strstr(tmp,"}"), NULL); FAIL_IF_EQUAL(strstr(tmp,"\"test\""), NULL); FAIL_IF_EQUAL(strstr(tmp,"\"json\""), NULL); FAIL_IF_NOT_EQUAL(strstr(tmp,","), NULL); onion_block_free(b); onion_dict_add(d, "other", "data", 0); b=onion_dict_to_json(d); tmp=onion_block_data(b); s=onion_block_size(b); ONION_DEBUG("Json returned is '%s'", tmp); FAIL_IF(s<=0); FAIL_IF_EQUAL(strstr(tmp,"{"), NULL); FAIL_IF_EQUAL(strstr(tmp,"}"), NULL); FAIL_IF_EQUAL(strstr(tmp,"\"test\""), NULL); FAIL_IF_EQUAL(strstr(tmp,"\"json\""), NULL); FAIL_IF_EQUAL(strstr(tmp,","), NULL); FAIL_IF_EQUAL(strstr(tmp,"\"other\""), NULL); FAIL_IF_EQUAL(strstr(tmp,"\"data\""), NULL); onion_block_free(b); onion_dict_add(d, "with\"", "data\n", 0); b=onion_dict_to_json(d); tmp=onion_block_data(b); s=onion_block_size(b); ONION_DEBUG("Json returned is '%s'", tmp); FAIL_IF(s<=0); FAIL_IF_EQUAL(strstr(tmp,"\\n"), NULL); FAIL_IF_EQUAL(strstr(tmp,"\\\""), NULL); onion_block_free(b); onion_dict_free(d); END_LOCAL(); }
void t08_sockaddr_storage(){ INIT_LOCAL(); onion_request *req; { struct sockaddr_storage client_addr; socklen_t client_len=0; req=onion_request_new(custom_io); FAIL_IF_EQUAL(onion_request_get_sockadd_storage(req, NULL), &client_addr); FAIL_IF_EQUAL(onion_request_get_sockadd_storage(req, &client_len), &client_addr); FAIL_IF_NOT_EQUAL_INT(client_len, 0); onion_request_free(req); } { struct sockaddr_storage *client_addr; socklen_t client_len=0; struct addrinfo hints; struct addrinfo *result, *rp; char hostA[128], portA[16]; char hostB[128], portB[16]; memset(&hints,0, sizeof(struct addrinfo)); hints.ai_canonname=NULL; hints.ai_addr=NULL; hints.ai_next=NULL; hints.ai_socktype=SOCK_STREAM; hints.ai_family=AF_UNSPEC; hints.ai_flags=AI_PASSIVE|AI_NUMERICSERV; int err=getaddrinfo("localhost","8080", &hints, &result); FAIL_IF_NOT_EQUAL_INT(err,0); if (err!=0) goto exit; for(rp=result;rp!=NULL;rp=rp->ai_next){ memset(hostA,0,sizeof(hostA)); memset(hostB,0,sizeof(hostB)); memset(portA,0,sizeof(portA)); memset(portB,0,sizeof(portB)); getnameinfo(rp->ai_addr, rp->ai_addrlen, hostA, sizeof(hostA), portA, sizeof(portA), NI_NUMERICHOST | NI_NUMERICSERV); req=onion_request_new_from_socket(NULL, 0,(struct sockaddr_storage *)rp->ai_addr, rp->ai_addrlen); client_addr=onion_request_get_sockadd_storage(req, &client_len); FAIL_IF_EQUAL(client_addr, (struct sockaddr_storage *)rp->ai_addr); FAIL_IF_EQUAL(client_addr, NULL); getnameinfo((struct sockaddr *)client_addr, client_len, hostB, sizeof(hostB), portB, sizeof(portB), NI_NUMERICHOST | NI_NUMERICSERV); FAIL_IF_NOT_EQUAL_STR(hostA, hostB); FAIL_IF_NOT_EQUAL_STR(portA, portB); FAIL_IF_NOT_EQUAL_STR(hostA, onion_request_get_client_description(req)); onion_request_free(req); } freeaddrinfo(result); } { req=onion_request_new(custom_io); //NULL, NULL, NULL); struct sockaddr_storage *client_addr; socklen_t client_len; client_addr=onion_request_get_sockadd_storage(req, &client_len); FAIL_IF_NOT_EQUAL(client_addr, NULL); onion_request_free(req); } exit: END_LOCAL(); }
void t01_test_session(){ INIT_LOCAL(); onion_sessions *sessions=onion_sessions_new(); // create a session onion_dict *ses=onion_sessions_get(sessions, "s01"); FAIL_IF_NOT_EQUAL(ses, NULL); // It does not auto create the sessions, to avoid problems char *s01=onion_sessions_create(sessions); ses=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL(ses, NULL); // It does not auto create the sessions, to avoid problems // get another pointer to the same session onion_dict *ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses, ses2); //Check it is really the same onion_dict_add(ses, "foo", "bar", 0); FAIL_IF_NOT_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); // When removed, it should refcount-- onion_dict_free(ses2); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses, ses2); // also all removal, should stay at the sessions onion_dict_free(ses); onion_dict_free(ses2); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); onion_dict_free(ses2); // Create a second session char *s02=onion_sessions_create(sessions); ses2=onion_sessions_get(sessions, s02); onion_dict_add(ses2, "hello", "world", 0); ses=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL_STR(onion_dict_get(ses, "hello"), onion_dict_get(ses2, "hello")); FAIL_IF_EQUAL_STR(onion_dict_get(ses, "foo"), onion_dict_get(ses2, "foo")); onion_dict_free(ses); onion_dict_free(ses2); // And finally really remove it onion_sessions_remove(sessions, s01); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses2, NULL); // this created a new one free(s01); s01=onion_sessions_create(sessions); ses2=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); onion_dict_free(ses2); // This should remove the sessions, and still hanging s02 onion_sessions_free(sessions); free(s01); free(s02); END_LOCAL(); }
void t02_cookies(){ INIT_LOCAL(); onion *o=onion_new(O_ONE_LOOP); onion_request *req; onion_dict *session; char *cookieid; char tmp[256]; req=onion_request_new(o->server, NULL, NULL); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); onion_dict_add(session,"Test","tseT", 0); FAIL_IF_EQUAL(req->session_id, NULL); cookieid=strdup(req->session_id); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); onion_dict_add(session,"Test","Another value", 0); FAIL_IF_EQUAL_STR(req->session_id, cookieid); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"sessionid=%s",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_NOT_EQUAL_STR(req->session_id, cookieid); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"trashthingish=nothing interesting; sessionid=%s; wtf=ianal",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_NOT_EQUAL_STR(req->session_id, cookieid); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"sessionid=nothing interesting; sessionid=%s; other_sessionid=ianal",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_NOT_EQUAL_STR(req->session_id, cookieid); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"sessionid=nothing interesting; xsessionid=%s; other_sessionid=ianal",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_EQUAL_STR(req->session_id, cookieid); FAIL_IF_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); onion_free(o); free(cookieid); 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(); }