examples now are real tests;
This commit is contained in:
		
							parent
							
								
									2b0df25d2e
								
							
						
					
					
						commit
						db24e791a4
					
				
							
								
								
									
										381
									
								
								examples/sntlc.c
									
									
									
									
									
								
							
							
						
						
									
										381
									
								
								examples/sntlc.c
									
									
									
									
									
								
							| @ -1,4 +1,5 @@ | ||||
| #include <stdio.h> | ||||
| #define __USE_GNU | ||||
| #include <stdlib.h> | ||||
| #include <stdarg.h> | ||||
| #include <sys/types.h> | ||||
| @ -12,15 +13,129 @@ | ||||
| #include <errno.h> | ||||
| #include <assert.h> | ||||
| #include <time.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/wait.h> | ||||
| #include <execinfo.h> | ||||
| #include <sys/resource.h> | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| #include <sexpr/sexp.h> | ||||
| #include <sntl/connection.h> | ||||
| 
 | ||||
|             | ||||
| /* 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; | ||||
| } | ||||
| 
 | ||||
| void *test_channel(void *ctx) | ||||
| { | ||||
|   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 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; | ||||
|   } | ||||
|   assert(rc == 0); | ||||
|    | ||||
|   // 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); | ||||
|   } | ||||
|    | ||||
|   rc = channel_close(channel); | ||||
|   if(rc) { | ||||
|     printf("Failed to close channel. rc=%d\n", rc); | ||||
|   } | ||||
|   assert(rc == 0); | ||||
|    | ||||
|   return 0x00; | ||||
| } | ||||
| 
 | ||||
| /*static*/ int start_testing(conn_t *co) | ||||
| { | ||||
|   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; | ||||
|     } | ||||
|   } | ||||
|   for(i = 0; i < CHANNEL_COUNT; ++i) { | ||||
|     pthread_join(threads[i], NULL); | ||||
|   } | ||||
|   printf("---------------===========   Testing end   ===========------------------\n"); | ||||
|   return 0;   | ||||
| } | ||||
|             | ||||
| /*static*/ int test_error_codes(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); | ||||
|    | ||||
|   printf("---------------=========== Error codes end ===========------------------\n"); | ||||
|   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_invalid_channel(void *ctx) | ||||
| { | ||||
|   log_begin("Invalid channel testing"); | ||||
|   conn_t *co = (conn_t *)ctx; | ||||
|   chnl_t *channel = NULL; | ||||
|   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);
 | ||||
|   } | ||||
|   log_end("Invalid channel testing"); | ||||
|   return 0x00; | ||||
| } | ||||
| 
 | ||||
| void *test_correct_channel(void *ctx) | ||||
| { | ||||
|   log_begin("Channel testing"); | ||||
|    | ||||
|   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; | ||||
|    | ||||
|   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);
 | ||||
|   } | ||||
|    | ||||
|   log_end("Channel testing"); | ||||
|   return 0x00; | ||||
| } | ||||
| 
 | ||||
| int test_channels(test_data_t *data, int index) | ||||
| { | ||||
|   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); | ||||
|   } | ||||
|    | ||||
|   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); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void test_message_handling(conn_t* co) | ||||
| { | ||||
|   chnl_t *channel = NULL; | ||||
|   int rc = 0, i = 0, a = 0, b = 0; | ||||
|   sexp_t *sx = NULL; | ||||
|   char *buf = NULL; | ||||
|   sxmsg_t *msg = NULL; | ||||
|    | ||||
|   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); | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| #include <stdio.h> | ||||
| #define __USE_GNU | ||||
| #include <stdlib.h> | ||||
| #include <stdarg.h> | ||||
| #include <sys/types.h> | ||||
| @ -9,11 +10,50 @@ | ||||
| #include <stdint.h> | ||||
| #include <getopt.h> | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/wait.h> | ||||
| #include <execinfo.h> | ||||
| #include <sys/resource.h> | ||||
| 
 | ||||
| #include <tdata/usrtc.h> | ||||
| #include <sexpr/sexp.h> | ||||
| #include <sntl/connection.h> | ||||
| 
 | ||||
| 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; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user