diff --git a/examples/sntlc.c b/examples/sntlc.c index beb6276..2cd3488 100644 --- a/examples/sntlc.c +++ b/examples/sntlc.c @@ -1,4 +1,5 @@ #include +#define __USE_GNU #include #include #include @@ -12,15 +13,129 @@ #include #include #include +#include +#include +#include +#include #include #include #include - + /* define a little bit */ #define DEFAULT_PORT 13133 -#define CHANNEL_COUNT 1 -#define CLIENT_COUNT 2 +#define CHANNEL_COUNT 4000 +#define CLIENT_COUNT 2000 +#define MESSAGES_PER_SESSION 10 +#define ITERATION_COUNT 10 + +#define FAILS_ONLY +//#define SIMPLE_TESTING + +static FILE *log_file = NULL; + +inline int log_init(const char *file) +{ + if(log_file) { + fclose(log_file); + } + log_file = fopen(file, "w"); + if(!log_file) return EIO; + return 0; +} + +inline void log_msg(const char *prefix, const char *data) +{ + if(log_file) fprintf(log_file, "[%s]: %s\n", prefix, data); +} + +inline void log_begin(const char *data) +{ +#ifndef FAILS_ONLY + log_msg("BEGIN", data); +#endif +} + +inline void log_end(const char *data) +{ +#ifndef FAILS_ONLY + log_msg("END", data); +#endif +} + +inline void log_info(const char *data) +{ +#ifndef FAILS_ONLY + log_msg("INFO", data); +#endif +} + +inline void log_error(const char *data) +{ + log_msg("FAILED", data); +} + +inline void log_assert(const char *info, int rc, int exp) +{ + if(log_file && (rc) != (exp)) { + fprintf(log_file, "[FAILED]: %s result: %d, expected: %d\n", info, rc, exp); + } +} + +inline void log_close() +{ + if(log_file) { + fflush(log_file); + fclose(log_file); + } +} + +inline void log_flush() +{ + fflush(log_file); +} + +void signal_error(int sig, siginfo_t *si, void *ptr) +{ + void* error_addr; + void* trace[16]; + int x; + int trace_size; + char** messages; + + fprintf(stderr, "Something is wrong: backtrace: \n"); + uintptr_t fptr = (uintptr_t)(si->si_addr); + fprintf(stderr, "Signal: %d, function pointer: 0x%.12lX \n", sig, fptr); + #if __WORDSIZE == 64 + error_addr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_RIP]; + #else + error_addr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_EIP]; + #endif + + trace_size = backtrace(trace, 16); + trace[1] = error_addr; + + messages = backtrace_symbols(trace, trace_size); + if (messages) + { + for (x = 1; x < trace_size; x++) + { + fprintf(stderr, "%s\n", messages[x]); + } + free(messages); + } + + fprintf(stderr, "end of backtrace\n"); + + exit(1); +} + +typedef struct +{ + pthread_t **threads; + int thread_count; + conn_t *co; +} test_data_t; /*static*/ sexp_t *make_request(const char *req) { @@ -30,96 +145,160 @@ return sx; } -void *test_send_message(void *ch) +/*static */int allocate_threads(int count, test_data_t *data) { - __DBGLINE; - chnl_t *chnl = (chnl_t *)ch; - char buf[1024]; - int a = rand() % 100; - int b = rand() % 100; - sprintf(buf, "(ar-add (%d %d))", a, b); - sexp_t *add_request = make_request(buf); - sxmsg_t *msg = NULL; - int rc = 0; - clock_t start = clock(); - rc = msg_send(chnl, add_request, &msg); - clock_t end = clock(); - double time = (double)(end - start) / CLOCKS_PER_SEC; - printf("msg_send execution time: %lf. rc = %d\n", time, rc); - assert(rc == a + b); - destroy_sexp(add_request); - return 0x00; + int i = 0; + data->threads = (pthread_t **)malloc(count * sizeof(pthread_t *)); + for(i = 0; i < count; ++i) { + data->threads[i] = (pthread_t *)malloc(sizeof(pthread_t)); + if(!data->threads) return ENOMEM; + } + data->thread_count = count; + return 0; +} +/*static */int deallocate_threads(test_data_t *data) +{ + int i = 0; + for(i = 0; i < data->thread_count; ++i) { + if(!data->threads[i]) return EINVAL; + pthread_join(*data->threads[i], NULL); + free(data->threads[i]); + data->threads[i] = 0; + } + free(data->threads); + data->thread_count = 0; + + return 0; } -void *test_channel(void *ctx) +void *test_invalid_channel(void *ctx) { + log_begin("Invalid channel testing"); conn_t *co = (conn_t *)ctx; - printf("Testing channel (%ld)\n", pthread_self()); chnl_t *channel = NULL; - int rc = 0; - rc = channel_open(co, &channel, 12); - if(rc) { - printf("Failed to open channel. rc=%d\n", rc); + int rc = 0, i; + for(i = 0; i < ITERATION_COUNT || ITERATION_COUNT < 0; ++i) { + rc = channel_open(co, &channel, 1); + log_assert("channel_open with type 1", rc, EINVAL); + // TODO: segmentation fault below + //rc = channel_close(channel); + //log_assert("channel_close with type 1", rc, EINVAL); } - assert(rc == 0); + log_end("Invalid channel testing"); + return 0x00; +} + +void *test_correct_channel(void *ctx) +{ + log_begin("Channel testing"); - // test message sending - int i; - pthread_t threads[CLIENT_COUNT]; - for(i = 0; i < CLIENT_COUNT; ++i) { - if(pthread_create(&(threads[i]), NULL, test_send_message, channel)) { - fprintf(stderr, "Error creating thread\n"); - return 0x00; - } - } - for(i = 0; i < CLIENT_COUNT; ++i) { - pthread_join(threads[i], NULL); - } + conn_t *co = (conn_t *)ctx; + chnl_t *channel = NULL; + int rc = 0, i, j; + char buf[128]; + time_t start, end; + int a, b; + sexp_t *add_request = NULL; + sxmsg_t *msg = NULL; + double exec_time; - rc = channel_close(channel); - if(rc) { - printf("Failed to close channel. rc=%d\n", rc); + for(j = 0; j < ITERATION_COUNT || ITERATION_COUNT < 0; ++j) { + rc = channel_open(co, &channel, 12); + log_assert("channel_open with type 12", rc, 0); + log_begin("Test messaging"); + for(i = 0; i < MESSAGES_PER_SESSION; ++i) { + a = rand() % 100; + b = rand() % 100; + sprintf(buf, "(ar-add (%d %d))", a, b); + add_request = make_request(buf); + time(&start); + rc = msg_send(channel, add_request, &msg); + time(&end); + exec_time = difftime(end, start); + sprintf(buf, "rpc execution time: %lf", exec_time); + log_info(buf); + log_assert("rpc execution", rc, a + b); + //destroy_sexp(add_request); + } + log_end("Test messaging"); + +// rc = channel_close(channel); +// log_assert("channel_close with type 12", rc, 0); } - assert(rc == 0); + log_end("Channel testing"); return 0x00; } -/*static*/ int start_testing(conn_t *co) +int test_channels(test_data_t *data, int index) { - printf("---------------=========== Testing... ===========------------------\n"); - int i; - pthread_t threads[CHANNEL_COUNT]; - for(i = 0; i < CHANNEL_COUNT; ++i) { - if(pthread_create(&(threads[i]), NULL, test_channel, co)) { - fprintf(stderr, "Error creating thread\n"); - return EINVAL; - } + int rc = 0; + if(index < CLIENT_COUNT) { + rc = pthread_create(data->threads[index], NULL, test_correct_channel, data->co); + } else { + rc = pthread_create(data->threads[index], NULL, test_invalid_channel, data->co); } - for(i = 0; i < CHANNEL_COUNT; ++i) { - pthread_join(threads[i], NULL); + + return rc; +} + +void test_channel_handling(conn_t *co) +{ + chnl_t *channel = NULL; + int rc = 0, i = 0; + + for(i = 0; i < ITERATION_COUNT; ++i) { + rc = channel_open(co, &channel, 12); + log_assert("channel open function", rc, 0); + rc = channel_close(channel); + log_assert("channel close function", rc, 0); } - printf("---------------=========== Testing end ===========------------------\n"); - return 0; } - -/*static*/ int test_error_codes(conn_t *co) + +void test_message_handling(conn_t* co) { - printf("---------------=========== Error codes ===========------------------\n"); chnl_t *channel = NULL; - // there is no such channel on the server - assert(channel_open(co, &channel, 777) == EINVAL); + int rc = 0, i = 0, a = 0, b = 0; + sexp_t *sx = NULL; + char *buf = NULL; + sxmsg_t *msg = NULL; - printf("---------------=========== Error codes end ===========------------------\n"); - return 0; + buf = malloc(4096); + rc = channel_open(co, &channel, 12); + log_assert("channel open function", rc, 0); + for(i = 0; i < ITERATION_COUNT; ++i) { + a = rand() % 100; + b = rand() % 100; + sprintf(buf, "(ar-add (%d %d))", a, b); + sx = parse_sexp(buf, strlen(buf)); + rc = msg_send(channel, sx, &msg); + log_assert("message send function", rc, a + b); + // destroy_sexp(sx); + } + rc = channel_close(channel); + free(buf); + log_assert("channel close function", rc, 0); } - + int main(int argc, char **argv) { + // set detailed signal handler + struct sigaction sigact; + sigact.sa_flags = SA_SIGINFO; + sigact.sa_sigaction = signal_error; + sigemptyset(&sigact.sa_mask); + sigaction(SIGFPE, &sigact, 0); + sigaction(SIGILL, &sigact, 0); + sigaction(SIGSEGV, &sigact, 0); + sigaction(SIGBUS, &sigact, 0); + char *rootca = NULL, *cert = NULL; int port = DEFAULT_PORT; char *addr = NULL, *login = NULL, *password = NULL; int opt; +#ifndef SIMPLE_TESTING + int rc, i; +#endif while((opt = getopt(argc, argv, "p:r:a:u:l:w:")) != -1) { switch(opt) { case 'p': @@ -184,18 +363,44 @@ int main(int argc, char **argv) fprintf(stderr, "Subsystem init failed (set SSL x.509 pems): %d\n", opt); return opt; } - + /* Tests */ /* try to open connection */ conn_t *co = malloc(sizeof(conn_t)); perm_ctx_t *ctx = (perm_ctx_t *)malloc(sizeof(perm_ctx_t)); ctx->login = login; ctx->passwd = password; + + log_init("test.log"); + + log_begin("Connection initiate"); + log_assert("Connection initiate", connection_initiate(co, addr, port, cert, ctx), 0); + log_end("Connection initiate"); + +#ifndef SIMPLE_TESTING + test_data_t data; + data.co = co; + rc = allocate_threads(CHANNEL_COUNT, &data); + log_assert("Thread list allocation", rc, 0); + + for(i = 0; i < CHANNEL_COUNT; ++i) { + log_assert("Channel testing", test_channels(&data, i), 0); + } + + rc = deallocate_threads(&data); + log_assert("Thread list deallocation", rc, 0); +#endif +#ifdef SIMPLE_TESTING + //test_channel_handling(co); + test_message_handling(co); +#endif + printf("HERE!!!!\n"); + log_begin("Connection close"); + log_assert("Connection close", connection_close(co), 0); + log_end("Connection close"); + + log_close(); - assert(connection_initiate(co, addr, port, cert, ctx) == 0); - assert(start_testing(co) == 0); - assert(test_error_codes(co) == 0); - assert(connection_close(co) == 0); free(rootca); free(cert); diff --git a/examples/sntld.c b/examples/sntld.c index 5477d9e..3603a53 100644 --- a/examples/sntld.c +++ b/examples/sntld.c @@ -1,4 +1,5 @@ #include +#define __USE_GNU #include #include #include @@ -9,11 +10,50 @@ #include #include #include +#include +#include +#include +#include #include #include #include +void signal_error(int sig, siginfo_t *si, void *ptr) +{ + void* error_addr; + void* trace[16]; + int x; + int trace_size; + char** messages; + + fprintf(stderr, "Something is wrong: backtrace: \n"); + uintptr_t fptr = (uintptr_t)(si->si_addr); + fprintf(stderr, "Signal: %d, function pointer: 0x%.12lX \n", sig, fptr); + #if __WORDSIZE == 64 + error_addr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_RIP]; + #else + error_addr = (void*)((ucontext_t*)ptr)->uc_mcontext.gregs[REG_EIP]; + #endif + + trace_size = backtrace(trace, 16); + trace[1] = error_addr; + + messages = backtrace_symbols(trace, trace_size); + if (messages) + { + for (x = 1; x < trace_size; x++) + { + fprintf(stderr, "%s\n", messages[x]); + } + free(messages); + } + + fprintf(stderr, "end of backtrace\n"); + + exit(1); +} + /* helper functions */ int __openlistener(int port) { @@ -75,6 +115,8 @@ usrtc_t *__rettlist(conn_t *c) /* RPC functions implementation */ static int __ar_add(void *m, sexp_t *sx) { +// int timout = rand() % 1000000; +// usleep(timout); sexp_t *lsx = NULL, *sx_iter; sxmsg_t *msg = (sxmsg_t *)m; int idx, rc = 0; @@ -126,6 +168,16 @@ static int __ar_multiply(void *data, sexp_t *sx) int main(int argc, char **argv) { + // set detailed signal handler + struct sigaction sigact; + sigact.sa_flags = SA_SIGINFO; + sigact.sa_sigaction = signal_error; + sigemptyset(&sigact.sa_mask); + sigaction(SIGFPE, &sigact, 0); + sigaction(SIGILL, &sigact, 0); + sigaction(SIGSEGV, &sigact, 0); + sigaction(SIGBUS, &sigact, 0); + char *rootca = NULL, *cert = NULL; int port = DEFAULT_PORT; int opt;