示例#1
0
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();
}
示例#2
0
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();
}
示例#3
0
文件: 08-post.c 项目: 511860050/onion
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();
}
示例#4
0
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();
}
示例#5
0
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();
}
示例#6
0
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();
}
示例#7
0
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();
}
示例#8
0
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();
}
示例#9
0
文件: 01-hash.c 项目: 511860050/onion
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();
}
示例#10
0
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();
}
示例#11
0
文件: runtime.c 项目: utrhira/mpik
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;
}
示例#12
0
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();
}
示例#13
0
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();
}
示例#14
0
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();
}
示例#15
0
文件: 01-hash.c 项目: 511860050/onion
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();
}
示例#16
0
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();
}
示例#17
0
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();
}
示例#18
0
文件: 01-hash.c 项目: 511860050/onion
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();
}
示例#19
0
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();
}
示例#20
0
文件: 01-hash.c 项目: 511860050/onion
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();
}
示例#21
0
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();
};
示例#22
0
文件: 01-hash.c 项目: 511860050/onion
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();
}
示例#23
0
文件: 08-post.c 项目: Andrepuel/onion
/// 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();
}
示例#24
0
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();
}
示例#25
0
文件: 01-hash.c 项目: 511860050/onion
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();
}
示例#26
0
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();
}
示例#27
0
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();
}
示例#28
0
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();
}
示例#29
0
/**
 * @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();
}
示例#30
0
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();
}