X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=tests%2Ftest.c;h=755455f618941261c3542a17736b58ce1b0d7197;hb=9e9572af3e9be02dd3de5c71bf1665217a770e1b;hp=4cf41c63f8074a16fd788589266c7e7eb8672fb4;hpb=87424051896224c7fbc3744a1dcf94dbd76ccfef;p=awesomized%2Flibmemcached diff --git a/tests/test.c b/tests/test.c index 4cf41c63..755455f6 100644 --- a/tests/test.c +++ b/tests/test.c @@ -6,94 +6,95 @@ #include #include #include +#include -void init_test(void) +long int timedif(struct timeval a, struct timeval b) +{ + register int us, s; + + us = a.tv_usec - b.tv_usec; + us /= 1000; + s = a.tv_sec - b.tv_sec; + s *= 1000; + return s + us; +} + +void init_test(memcached_st *not_used) { memcached_st memc; - (void)memcached_init(&memc); - memcached_deinit(&memc); + (void)memcached_create(&memc); + memcached_free(&memc); } -void allocation_test(void) +void allocation_test(memcached_st *not_used) { memcached_st *memc; - memc= memcached_init(NULL); + memc= memcached_create(NULL); assert(memc); - memcached_deinit(memc); + memcached_free(memc); } -void connection_test(void) +void connection_test(memcached_st *memc) { memcached_return rc; - memcached_st *memc; - memc= memcached_init(NULL); + rc= memcached_server_add(memc, "localhost", 0); assert(rc == MEMCACHED_SUCCESS); - assert(memc); - memcached_deinit(memc); } -void set_test(void) +void error_test(memcached_st *memc) +{ + memcached_return rc; + + for (rc= MEMCACHED_SUCCESS; rc < MEMCACHED_MAXIMUM_RETURN; rc++) + { + printf("Error %d -> %s\n", rc, memcached_strerror(memc, rc)); + } +} + +void set_test(memcached_st *memc) { - memcached_st *memc; memcached_return rc; char *key= "foo"; char *value= "when we sanitize"; - memc= memcached_init(NULL); - assert(memc); rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); assert(rc == MEMCACHED_SUCCESS); - - memcached_deinit(memc); } -void add_test(void) +void add_test(memcached_st *memc) { - memcached_st *memc; memcached_return rc; char *key= "foo"; char *value= "when we sanitize"; - memc= memcached_init(NULL); - assert(memc); rc= memcached_add(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); assert(rc == MEMCACHED_NOTSTORED); - - memcached_deinit(memc); } -void replace_test(void) +void replace_test(memcached_st *memc) { - memcached_st *memc; memcached_return rc; char *key= "foo"; char *value= "when we sanitize"; - memc= memcached_init(NULL); - assert(memc); rc= memcached_replace(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); assert(rc == MEMCACHED_SUCCESS); - - memcached_deinit(memc); } -void delete_test(void) +void delete_test(memcached_st *memc) { - memcached_st *memc; memcached_return rc; char *key= "foo"; char *value= "when we sanitize"; - memc= memcached_init(NULL); - assert(memc); rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); @@ -101,48 +102,34 @@ void delete_test(void) rc= memcached_delete(memc, key, strlen(key), (time_t)0); assert(rc == MEMCACHED_SUCCESS); - - memcached_deinit(memc); } -void flush_test(void) +void flush_test(memcached_st *memc) { - memcached_st *memc; memcached_return rc; - memc= memcached_init(NULL); - assert(memc); rc= memcached_flush(memc, 0); assert(rc == MEMCACHED_SUCCESS); - - memcached_deinit(memc); } -void get_test(void) +void get_test(memcached_st *memc) { - memcached_st *memc; memcached_return rc; char *key= "foo"; char *string; size_t string_length; uint16_t flags; - memc= memcached_init(NULL); - assert(memc); - string= memcached_get(memc, key, strlen(key), &string_length, &flags, &rc); assert(rc == MEMCACHED_NOTFOUND); assert(string_length == 0); assert(!string); - - memcached_deinit(memc); } -void get_test2(void) +void get_test2(memcached_st *memc) { - memcached_st *memc; memcached_return rc; char *key= "foo"; char *value= "when we sanitize"; @@ -150,8 +137,6 @@ void get_test2(void) size_t string_length; uint16_t flags; - memc= memcached_init(NULL); - assert(memc); rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); @@ -160,33 +145,145 @@ void get_test2(void) string= memcached_get(memc, key, strlen(key), &string_length, &flags, &rc); + assert(string); + assert(rc == MEMCACHED_SUCCESS); assert(string_length == strlen(value)); assert(!memcmp(string, value, string_length)); free(string); +} + +void set_test2(memcached_st *memc) +{ + memcached_return rc; + char *key= "foo"; + char *value= "train in the brain"; + size_t value_length= strlen(value); + unsigned int x; + + for (x= 0; x < 10; x++) + { + rc= memcached_set(memc, key, strlen(key), + value, value_length, + (time_t)0, (uint16_t)0); + assert(rc == MEMCACHED_SUCCESS); + } +} + +void set_test3(memcached_st *memc) +{ + memcached_return rc; + char *key= "foo"; + char *value; + size_t value_length= 8191; + unsigned int x; + + value = (char*)malloc(value_length); + assert(value); + + for (x= 0; x < value_length; x++) + value[x] = (char) (x % 127); + + for (x= 0; x < 1; x++) + { + rc= memcached_set(memc, key, strlen(key), + value, value_length, + (time_t)0, (uint16_t)0); + assert(rc == MEMCACHED_SUCCESS); + } + + free(value); +} + +void get_test3(memcached_st *memc) +{ + memcached_return rc; + char *key= "foo"; + char *value; + size_t value_length= 8191; + char *string; + size_t string_length; + uint16_t flags; + int x; + + value = (char*)malloc(value_length); + assert(value); + + for (x= 0; x < value_length; x++) + value[x] = (char) (x % 127); + + rc= memcached_set(memc, key, strlen(key), + value, value_length, + (time_t)0, (uint16_t)0); + assert(rc == MEMCACHED_SUCCESS); + + string= memcached_get(memc, key, strlen(key), + &string_length, &flags, &rc); + + WATCHPOINT_ERRNO(memc->my_errno); + WATCHPOINT_ERROR(rc); + assert(rc == MEMCACHED_SUCCESS); + assert(string); + assert(string_length == value_length); + assert(!memcmp(string, value, string_length)); + + free(string); + free(value); +} - memcached_deinit(memc); +void get_test4(memcached_st *memc) +{ + memcached_return rc; + char *key= "foo"; + char *value; + size_t value_length= 8191; + char *string; + size_t string_length; + uint16_t flags; + int x; + + value = (char*)malloc(value_length); + assert(value); + + for (x= 0; x < value_length; x++) + value[x] = (char) (x % 127); + + rc= memcached_set(memc, key, strlen(key), + value, value_length, + (time_t)0, (uint16_t)0); + assert(rc == MEMCACHED_SUCCESS); + + for (x= 0; x < 10; x++) + { + string= memcached_get(memc, key, strlen(key), + &string_length, &flags, &rc); + + assert(rc == MEMCACHED_SUCCESS); + assert(string); + assert(string_length == value_length); + assert(!memcmp(string, value, string_length)); + free(string); + } + + free(value); } -void stats_hostname_test(void) +void stats_servername_test(memcached_st *memc) { memcached_return rc; memcached_stat_st stat; - rc= memcached_stat_hostname(&stat, NULL, - "localhost", - MEMCACHED_DEFAULT_PORT); + rc= memcached_stat_servername(&stat, NULL, + "localhost", + MEMCACHED_DEFAULT_PORT); } -void increment_test(void) +void increment_test(memcached_st *memc) { - memcached_st *memc; unsigned int new_number; memcached_return rc; char *key= "number"; char *value= "0"; - memc= memcached_init(NULL); - assert(memc); rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); @@ -201,20 +298,15 @@ void increment_test(void) 1, &new_number); assert(rc == MEMCACHED_SUCCESS); assert(new_number == 2); - - memcached_deinit(memc); } -void decrement_test(void) +void decrement_test(memcached_st *memc) { - memcached_st *memc; unsigned int new_number; memcached_return rc; char *key= "number"; char *value= "3"; - memc= memcached_init(NULL); - assert(memc); rc= memcached_set(memc, key, strlen(key), value, strlen(value), (time_t)0, (uint16_t)0); @@ -229,32 +321,508 @@ void decrement_test(void) 1, &new_number); assert(rc == MEMCACHED_SUCCESS); assert(new_number == 1); +} + +void quit_test(memcached_st *memc) +{ + memcached_return rc; + char *key= "fudge"; + char *value= "sanford and sun"; - memcached_deinit(memc); + rc= memcached_set(memc, key, strlen(key), + value, strlen(value), + (time_t)10, (uint16_t)3); + assert(rc == MEMCACHED_SUCCESS); + memcached_quit(memc); + + rc= memcached_set(memc, key, strlen(key), + value, strlen(value), + (time_t)50, (uint16_t)9); + assert(rc == MEMCACHED_SUCCESS); +} + +void mget_test(memcached_st *memc) +{ + memcached_return rc; + char *keys[]= {"fudge", "son", "food"}; + size_t key_length[]= {5, 3, 4}; + unsigned int x; + uint16_t flags; + + char return_key[MEMCACHED_MAX_KEY]; + size_t return_key_length; + char *return_value; + size_t return_value_length; + + /* We need to empty the server before continueing test */ + rc= memcached_flush(memc, 0); + assert(rc == MEMCACHED_SUCCESS); + + rc= memcached_mget(memc, keys, key_length, 3); + assert(rc == MEMCACHED_SUCCESS); + + while ((return_value= memcached_fetch(memc, return_key, &return_key_length, + &return_value_length, &flags, &rc)) != NULL) + { + assert(return_value); + } + assert(!return_value); + assert(return_value_length == 0); + assert(rc == MEMCACHED_NOTFOUND); + + for (x= 0; x < 3; x++) + { + rc= memcached_set(memc, keys[x], key_length[x], + keys[x], key_length[x], + (time_t)50, (uint16_t)9); + assert(rc == MEMCACHED_SUCCESS); + } + + rc= memcached_mget(memc, keys, key_length, 3); + assert(rc == MEMCACHED_SUCCESS); + + x= 0; + while ((return_value= memcached_fetch(memc, return_key, &return_key_length, + &return_value_length, &flags, &rc))) + { + assert(return_value); + assert(rc == MEMCACHED_SUCCESS); + assert(return_key_length == return_value_length); + assert(!memcmp(return_value, return_key, return_value_length)); + free(return_value); + x++; + } +} + +void get_stats_keys(memcached_st *memc) +{ + char **list; + char **ptr; + memcached_stat_st stat; + memcached_return rc; + + list= memcached_stat_get_keys(memc, &stat, &rc); + assert(rc == MEMCACHED_SUCCESS); + for (ptr= list; *ptr; ptr++) + printf("Found key %s\n", *ptr); + fflush(stdout); + + free(list); +} + +void get_stats(memcached_st *memc) +{ + unsigned int x; + char **list; + char **ptr; + memcached_return rc; + memcached_stat_st *stat; + + stat= memcached_stat(memc, NULL, &rc); + assert(rc == MEMCACHED_SUCCESS); + + assert(rc == MEMCACHED_SUCCESS); + assert(stat); + + for (x= 0; x < memcached_server_count(memc); x++) + { + list= memcached_stat_get_keys(memc, &stat[x], &rc); + assert(rc == MEMCACHED_SUCCESS); + for (ptr= list; *ptr; ptr++) + printf("Found key %s\n", *ptr); + + free(list); + } + + free(stat); +} + +void add_host_test(memcached_st *memc) +{ + unsigned int x; + memcached_server_st *servers; + memcached_return rc; + char servername[]= "0.example.com"; + + servers= memcached_server_list_append(NULL, servername, 400, &rc); + assert(servers); + assert(1 == memcached_server_list_count(servers)); + + for (x= 2; x < 20; x++) + { + char buffer[SMALL_STRING_LEN]; + + snprintf(buffer, SMALL_STRING_LEN, "%u.example.com", 400+x); + servers= memcached_server_list_append(servers, buffer, 401, + &rc); + assert(rc == MEMCACHED_SUCCESS); + assert(x == memcached_server_list_count(servers)); + } + + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + + memcached_server_list_free(servers); +} + +/* We don't test the behavior itself, we test the switches */ +void behavior_test(memcached_st *memc) +{ + unsigned long long value; + unsigned int set= 1; + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, &set); + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK); + assert(value == 1); + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, &set); + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY); + assert(value == 1); + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_MD5_HASHING, &set); + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_MD5_HASHING); + assert(value == 1); + + set= 0; + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, &set); + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NO_BLOCK); + assert(value == 0); + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, &set); + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY); + assert(value == 0); + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_MD5_HASHING, &set); + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_MD5_HASHING); + assert(value == 0); } -int main(void) +/* Test case provided by Cal Haldenbrand */ +void user_supplied_bug1(memcached_st *memc) { + unsigned int setter= 1; + unsigned int x; + + long total= 0; + int size= 0; + srand(time(NULL)); + char key[10]; + char *randomstuff = (char *)malloc(6 * 1024); + memset(randomstuff, 0, 6 * 1024); + + memcached_return rc; + + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, &setter); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, &setter); + + + /* add key */ + for (x= 0 ; total < 20 * 1024576 ; x++ ) + { + unsigned int j= 0; + + size= (rand() % ( 5 * 1024 ) ) + 400; + memset(randomstuff, 0, 6 * 1024); + assert(size < 6 * 1024); /* Being safe here */ + + for (j= 0 ; j < size ;j++) + randomstuff[j] = (char) (rand() % 26) + 97; + + total += size; + sprintf(key, "%d", x); + rc = memcached_set(memc, key, strlen(key), + randomstuff, strlen(randomstuff), 10, 0); + /* If we fail, lets try again */ + if (rc != MEMCACHED_SUCCESS) + rc = memcached_set(memc, key, strlen(key), + randomstuff, strlen(randomstuff), 10, 0); + assert(rc == MEMCACHED_SUCCESS); + } +} +void add_host_test1(memcached_st *memc) +{ + unsigned int x; + memcached_return rc; + char servername[]= "0.example.com"; + memcached_server_st *servers; + + servers= memcached_server_list_append(NULL, servername, 400, &rc); + assert(servers); + assert(1 == memcached_server_list_count(servers)); + + for (x= 2; x < 20; x++) + { + char buffer[SMALL_STRING_LEN]; + + snprintf(buffer, SMALL_STRING_LEN, "%u.example.com", 400+x); + servers= memcached_server_list_append(servers, buffer, 401, + &rc); + assert(rc == MEMCACHED_SUCCESS); + assert(x == memcached_server_list_count(servers)); + } + + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + + memcached_server_list_free(servers); +} + +typedef struct test_st test_st; + +struct test_st { + char *function_name; + unsigned int requires_flush; + void (*function)(memcached_st *memc); +}; + +int main(int argc, char *argv[]) +{ + unsigned int x; + char *server_list; + char *test_to_run= NULL; + char *wildcard= NULL; + memcached_server_st *servers; + + if (argc > 2) + test_to_run= argv[1]; + + if (argc == 3) + wildcard= argv[2]; + + if (!(server_list= getenv("MEMCACHED_SERVERS"))) + server_list= "localhost"; + + printf("servers %s\n", server_list); + srandom(time(NULL)); + + servers= memcached_servers_parse(server_list); + assert(servers); + + for (x= 0; x < memcached_server_list_count(servers); x++) + { + printf("\t%s : %u\n", servers[x].hostname, servers[x].port); + assert(servers[x].stack_responses == 0); + assert(servers[x].fd == -1); + assert(servers[x].cursor_active == 0); + } + + printf("\n"); + /* Clean the server before beginning testing */ - flush_test(); - - init_test(); - allocation_test(); - connection_test(); - set_test(); - add_test(); - replace_test(); - flush_test(); - delete_test(); - flush_test(); - get_test(); - get_test2(); - stats_hostname_test(); - - increment_test(); - decrement_test(); + test_st tests[] ={ + {"flush", 0, flush_test }, + {"init", 0, init_test }, + {"allocation", 0, allocation_test }, + {"error", 0, error_test }, + {"set", 0, set_test }, + {"set2", 0, set_test2 }, + {"set3", 0, set_test3 }, + {"add", 0, add_test }, + {"replace", 0, replace_test }, + {"delete", 1, delete_test }, + {"get", 0, get_test }, + {"get2", 0, get_test2 }, + {"get3", 0, get_test3 }, + {"get4", 0, get_test4 }, + {"stats_servername", 0, stats_servername_test }, + {"increment", 0, increment_test }, + {"decrement", 0, decrement_test }, + {"quit", 0, quit_test }, + {"mget", 0, mget_test }, + {"get_stats", 0, get_stats }, + {"add_host_test", 0, add_host_test }, + {"get_stats_keys", 0, get_stats_keys }, + {"behavior_test", 0, get_stats_keys }, + {0, 0, 0} + }; + + test_st user_tests[] ={ + {"user_supplied_bug1", 0, user_supplied_bug1 }, + {0, 0, 0} + }; + + if ((test_to_run && !strcmp(test_to_run, "block")) || !test_to_run) + { + fprintf(stderr, "\nBlock tests\n\n"); + for (x= 0; tests[x].function_name; x++) + { + if (wildcard) + if (strcmp(wildcard, tests[x].function_name)) + continue; + + memcached_st *memc; + memcached_return rc; + struct timeval start_time, end_time; + + memc= memcached_create(NULL); + assert(memc); + + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + + unsigned int loop; + for (loop= 0; loop < memcached_server_list_count(servers); loop++) + { + assert(memc->hosts[loop].stack_responses == 0); + assert(memc->hosts[loop].fd == -1); + assert(memc->hosts[loop].cursor_active == 0); + } + + fprintf(stderr, "Testing %s", tests[x].function_name); + gettimeofday(&start_time, NULL); + tests[x].function(memc); + gettimeofday(&end_time, NULL); + long int load_time= timedif(end_time, start_time); + fprintf(stderr, "\t\t\t\t\t %ld.%03ld [ ok ]\n", load_time / 1000, + load_time % 1000); + assert(memc); + memcached_free(memc); + } + } + + if ((test_to_run && !strcmp(test_to_run, "nonblock")) || !test_to_run) + { + fprintf(stderr, "\nNonblock tests\n\n"); + for (x= 0; tests[x].function_name; x++) + { + if (wildcard) + if (strcmp(wildcard, tests[x].function_name)) + continue; + + memcached_st *memc; + memcached_return rc; + struct timeval start_time, end_time; + + memc= memcached_create(NULL); + assert(memc); + + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + + fprintf(stderr, "Testing %s", tests[x].function_name); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, NULL); + gettimeofday(&start_time, NULL); + tests[x].function(memc); + gettimeofday(&end_time, NULL); + long int load_time= timedif(end_time, start_time); + fprintf(stderr, "\t\t\t\t\t %ld.%03ld [ ok ]\n", load_time / 1000, + load_time % 1000); + assert(memc); + memcached_free(memc); + } + } + + if ((test_to_run && !strcmp(test_to_run, "nodelay")) || !test_to_run) + { + fprintf(stderr, "\nTCP Nodelay tests\n\n"); + for (x= 0; tests[x].function_name; x++) + { + if (wildcard) + if (strcmp(wildcard, tests[x].function_name)) + continue; + + memcached_st *memc; + memcached_return rc; + struct timeval start_time, end_time; + + memc= memcached_create(NULL); + assert(memc); + + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + + fprintf(stderr, "Testing %s", tests[x].function_name); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, NULL); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, NULL); + gettimeofday(&start_time, NULL); + tests[x].function(memc); + gettimeofday(&end_time, NULL); + long int load_time= timedif(end_time, start_time); + fprintf(stderr, "\t\t\t\t\t %ld.%03ld [ ok ]\n", load_time / 1000, + load_time % 1000); + assert(memc); + memcached_free(memc); + } + } + + if ((test_to_run && !strcmp(test_to_run, "md5")) || !test_to_run) + { + fprintf(stderr, "\nMD5 Hashing\n\n"); + for (x= 0; tests[x].function_name; x++) + { + if (wildcard) + if (strcmp(wildcard, tests[x].function_name)) + continue; + + memcached_st *memc; + memcached_return rc; + struct timeval start_time, end_time; + + memc= memcached_create(NULL); + assert(memc); + + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + + fprintf(stderr, "Testing %s", tests[x].function_name); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_MD5_HASHING, NULL); + gettimeofday(&start_time, NULL); + tests[x].function(memc); + gettimeofday(&end_time, NULL); + long int load_time= timedif(end_time, start_time); + fprintf(stderr, "\t\t\t\t\t %ld.%03ld [ ok ]\n", load_time / 1000, + load_time % 1000); + assert(memc); + memcached_free(memc); + } + } + + if ((test_to_run && !strcmp(test_to_run, "user")) || !test_to_run) + { + fprintf(stderr, "\nUser Supplied tests\n\n"); + for (x= 0; user_tests[x].function_name; x++) + { + if (wildcard) + if (strcmp(wildcard, tests[x].function_name)) + continue; + + memcached_st *memc; + memcached_return rc; + struct timeval start_time, end_time; + + memc= memcached_create(NULL); + assert(memc); + + rc= memcached_server_push(memc, servers); + assert(rc == MEMCACHED_SUCCESS); + + fprintf(stderr, "Testing %s", user_tests[x].function_name); + gettimeofday(&start_time, NULL); + user_tests[x].function(memc); + gettimeofday(&end_time, NULL); + long int load_time= timedif(end_time, start_time); + fprintf(stderr, "\t\t\t\t\t %ld.%03ld [ ok ]\n", load_time / 1000, + load_time % 1000); + assert(memc); + memcached_free(memc); + } + } /* Clean up whatever we might have left */ - flush_test(); + { + memcached_st *memc; + memc= memcached_create(NULL); + assert(memc); + flush_test(memc); + memcached_free(memc); + } + + fprintf(stderr, "All tests completed successfully\n\n"); + return 0; }