virtual bool Accept(const ByteString &key, const ByteString &value) { TEST_LOG("\"%.*s\": \"%.*s\"", key.length, key.buffer, value.length, value.buffer); if (strncmp(what.buffer, key.buffer, min(what.length, key.length)) == 0) { if (strncmp(where.buffer, value.buffer, min(where.length, value.length)) == 0) { TEST_LOG(" matched: \"%.*s\": \"%.*s\"", key.length, key.buffer, value.length, value.buffer); } } return true; }
static void check_widget_rect( LCUI_SysEvent ev, void *arg ) { int ret = 0; LCUI_RectF rectf; LCUI_Rect rect, old_rect; LCUI_Rect *paint_rect = &ev->paint.rect; rectf.x = self.x; rectf.y = self.y; rectf.width = WIDGET_WIDTH; rectf.height = WIDGET_WIDTH; LCUIMetrics_ComputeRectActual( &old_rect, &rectf ); LCUIMetrics_ComputeRectActual( &rect, &self.widget->box.canvas ); LCUIRect_MergeRect( &rect, &rect, &old_rect ); CHECK2( check_rect_correct( &rect, paint_rect ) ); if( ret != 0 ) { TEST_LOG( "[%d] correct: (%d, %d, %d, %d)," " actual: (%d, %d, %d, %d)\n", self.step, rect.x, rect.y, rect.width, rect.height, paint_rect->x, paint_rect->y, paint_rect->width, paint_rect->height ); } else { self.pass += 1; } self.count += 1; self.x = self.widget->x; self.y = self.widget->y; LCUI_PostSimpleTask( test_move_widget, NULL, NULL ); }
int BasicLinkedListTest() { LinkedList2<Elem, &Elem::nextA, &Elem::prevA> listA; LinkedList2<Elem, &Elem::nextB, &Elem::prevB> listB; LinkedList<Elem, &Elem::node> listC; LList<Elem, &Elem::llnode> llist; for (int i = 0; i < 3; i++) { Elem* elem; elem = new Elem; elem->buffer.Printf("%i", i); //listC.Append(*elem); llist.Add(*elem); } Elem* next = NULL; for (Elem* e = listC.Head(); e; e = next) { TEST_LOG("%.*s", e->buffer.length, e->buffer.data); next = listC.Remove(e); delete e; } return TEST_SUCCESS; }
static void TestWorker_Thread( void *arg ) { TestWorker worker = arg; worker->active = TRUE; worker->data_count = 0; LCUIMutex_Lock( &worker->mutex ); while( worker->active ) { TEST_LOG( "waiting...\n" ); LCUICond_Wait( &worker->cond, &worker->mutex ); TEST_LOG( "get data: %s\n", worker->data ); worker->data_count += 1; } LCUIMutex_Unlock( &worker->mutex ); TEST_LOG( "count: %lu\n", worker->data_count ); }
int test_widget_rect( void ) { int i, ret = 0; float values[3] = { 1.0f, 1.5f, 2.0f }; for( i = 0; i < 3; ++i ) { memset( &self, 0, sizeof( self ) ); TEST_LOG( "test widget rectagle in " "%g%% scaling mode\n", values[i] * 100 ); LCUI_Init(); #ifdef _WIN32 Logger_SetHandler( LoggerHandler ); Logger_SetHandlerW( LoggerHandlerW ); #endif self.widget = create_widget(); LCUIMetrics_SetScale( values[i] ); LCUIDisplay_SetSize( SCREEN_WIDTH, SCREEN_HEIGHT ); /* 等一段时间后再开始测试,避免初始化 LCUI 时产生的脏矩形影响测试结果 */ LCUITimer_Set( 100, start_test, NULL, FALSE ); LCUIWidget_Update(); if( LCUI_Main() != 0 ) { ret -= 1; } } return ret; }
static void s_SingleBouncePrint (CONN conn, FILE* data_file) { static const char write_str[] = "This is a s_*BouncePrint test string.\n"; size_t n_written, n_read; char message[128]; char buf[8192]; EIO_Status status; TEST_LOG(eIO_Success, "[s_SingleBouncePrint] Starting..."); /* WRITE */ status = CONN_Write(conn, write_str, strlen(write_str), &n_written, eIO_WritePersist); if (status != eIO_Success || n_written != strlen(write_str)) { TEST_LOG(status, "[s_SingleBouncePrint] CONN_Write(persistent) failed"); } assert(n_written == strlen(write_str)); assert(status == eIO_Success); /* READ the "bounced" data from the connection */ status = CONN_Read(conn, buf, sizeof(buf) - 1, &n_read, eIO_ReadPersist); sprintf(message, "[s_SingleBouncePrint] CONN_Read(persistent)" " %lu byte%s read", (unsigned long) n_read, &"s"[n_read == 1]); TEST_LOG(status, message); /* Printout to data file, if any */ if (data_file && n_read) { fprintf(data_file, "\ns_SingleBouncePrint(BEGIN PRINT)\n"); assert(fwrite(buf, n_read, 1, data_file) == 1); fprintf(data_file, "\ns_SingleBouncePrint(END PRINT)\n"); fflush(data_file); } /* Check-up */ assert(n_read >= n_written); buf[n_read] = '\0'; assert(strstr(buf, write_str)); TEST_LOG(eIO_Success, "[s_SingleBouncePrint] ...finished"); }
static void TimeOfDayMessage(const char *msg, PRThread* me) { char buffer[100]; PRExplodedTime tod; PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tod); (void)PR_FormatTime(buffer, sizeof(buffer), "%H:%M:%S", &tod); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("%s(0x%p): %s\n", msg, me, buffer)); } /* TimeOfDayMessage */
int test_image_reader( void ) { LCUI_Graph img; int ret = 0, i, width, height; char file[256], *formats[] = { "png", "bmp", "jpg" }; for( i = 0; i < 3; ++i ) { width = height = 0; Graph_Init( &img ); snprintf( file, 255, "test_image_reader.%s", formats[i] ); TEST_LOG( "image file: %s\n", file ); CHECK( LCUI_ReadImageFile( file, &img ) == 0 ); CHECK( img.width == 91 && img.height == 69 ); CHECK( LCUI_GetImageSize( file, &width, &height ) == 0 ); TEST_LOG( "image size: (%d, %d)\n", width, height ); CHECK( width == 91 && height == 69 ); Graph_Free( &img ); } return ret; }
static void s_MultiBouncePrint (CONN conn, FILE* data_file) { int i; TEST_LOG(eIO_Success, "[s_MultiBouncePrint] Starting..."); if ( data_file ) { fprintf(data_file, "\ns_MultiBouncePrint(BEGIN)\n"); fflush(data_file); } for (i = 0; i < 5; i++) { s_SingleBouncePrint(conn, data_file); } TEST_LOG(eIO_Success, "[s_MultiBouncePrint] ...finished"); if ( data_file ) { fprintf(data_file, "\ns_MultiBouncePrint(END)\n"); fflush(data_file); } }
/*static*/ void Pointer::axis( void *data, wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { Pointer* pointer = static_cast<Pointer*>(data); ASSERT(wl_pointer == *pointer); TEST_LOG( boost::format("%016p::Pointer::axis() : axis=%d; value=%f") % pointer % axis % wl_fixed_to_double(value) ); pointer->axis_ = axis; pointer->axisValue_ = wl_fixed_to_double(value); }
/*static*/ void Pointer::leave( void *data, wl_pointer *wl_pointer, uint32_t serial, wl_surface *wl_surface) { Pointer* pointer = static_cast<Pointer*>(data); ASSERT(wl_pointer == *pointer); TEST_LOG( boost::format("%016p::Pointer::leave() : %016p") % pointer % wl_surface ); pointer->focus_ = NULL; pointer->x_ = -1; pointer->y_ = -1; }
/*static*/ void Pointer::motion( void *data, wl_pointer *wl_pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) { Pointer* pointer = static_cast<Pointer*>(data); ASSERT(wl_pointer == *pointer); TEST_LOG( boost::format("%016p::Pointer::motion(): %d,%d") % pointer % wl_fixed_to_int(x) % wl_fixed_to_int(y) ); pointer->x_ = wl_fixed_to_int(x); pointer->y_ = wl_fixed_to_int(y); }
/*static*/ void Pointer::enter( void *data, wl_pointer *wl_pointer, uint32_t serial, wl_surface *wl_surface, wl_fixed_t x, wl_fixed_t y) { Pointer* pointer = static_cast<Pointer*>(data); ASSERT(wl_pointer == *pointer); TEST_LOG( boost::format("%016p::Pointer::enter() : %016p @ %d,%d") % pointer % wl_surface % wl_fixed_to_int(x) % wl_fixed_to_int(y) ); pointer->focus_ = wl_surface; pointer->focusSerial_ = serial; pointer->x_ = wl_fixed_to_int(x); pointer->y_ = wl_fixed_to_int(y); }
void update_throughput(double alpha, double buck_size, proxy_session_list_t* node, char *ip, struct timespec ts){ double throughput, duration; LOG("Update throughput\n"); chunk_tracker_list_t* tracker_list = search_seg(node); chunk_tracker_t *tracker; chunk_tracker_t *tmp_tracker = NULL; for(tracker = tracker_list->chunks; tracker->next !=NULL; tracker = tracker->next){ tmp_tracker = tracker; } tracker_list->throughput = est_tp(alpha, tracker_list->throughput, ts, buck_size, &throughput, &duration); LOG("New throughput is %lf\n", tracker_list->throughput); printf("New throughput is %lf\n", tracker_list->throughput); if(tmp_tracker != NULL) tmp_tracker->next = NULL; TEST_LOG("%u %lf %lf %lf %d %s %s\n", (unsigned)time(NULL), duration, throughput, tracker_list->throughput, tracker_list->bitrate, ip, tracker->file); LOG("free tracker\n"); return; }
static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool) { CSWorker_t *worker = PR_NEWZAP(CSWorker_t); worker->server = server; PR_INIT_CLIST(&worker->element); worker->thread = PR_CreateThread( PR_USER_THREAD, Worker, worker, DEFAULT_SERVER_PRIORITY, thread_scope, PR_UNJOINABLE_THREAD, 0); if (NULL == worker->thread) { PR_DELETE(worker); return PR_FAILURE; } TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS, ("\tCreateWorker(0x%p): create new worker (0x%p)\n", PR_GetCurrentThread(), worker->thread)); return PR_SUCCESS; } /* CreateWorker */
int BasicQueueTest() { Buffer *buffer; Queue<Buffer, &Buffer::next> q; for (int i = 0; i < 3; i++) { buffer = new Buffer(); buffer->Printf("%i", i); q.Append(buffer); } for (int i = 0; i < 3; i++) { buffer = q.Get(); TEST_LOG("%.*s", buffer->length, buffer->buffer); delete buffer; } return TEST_SUCCESS; }
/*static*/ void Pointer::button( void *data, wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { Pointer* pointer = static_cast<Pointer*>(data); ASSERT(wl_pointer == *pointer); TEST_LOG( boost::format("%016p::Pointer::button(): button=%d; state=%d") % pointer % button % state ); pointer->button_ = button; pointer->buttonState_ = state; ButtonEvent event; event.serial = serial; event.time = time; event.button = button; event.state = state; pointer->btnNotify_(*pointer, event); }
int test_widget_inline_block_layout( void ) { int ret = 0; LCUI_Widget root, pack; LCUI_Init(); TEST_LOG( "test widget inline block layout\n" ); LCUIDisplay_SetSize( SCREEN_WIDTH, SCREEN_HEIGHT ); root = LCUIWidget_GetRoot(); CHECK( pack = LCUIBuilder_LoadFile( "test_widget_inline_block_layout.xml" ) ); if( !pack ) { LCUI_Destroy(); return ret; } Widget_UpdateStyle( root, TRUE ); Widget_Append( root, pack ); Widget_Unwrap( pack ); LCUIWidget_Update(); ret += check_layout(); LCUI_Destroy(); return ret; }
int test_xml_parser( void ) { int ret = 0; LCUI_Widget root, pack; LCUI_Init(); TEST_LOG( "test widget layout\n" ); LCUIDisplay_SetSize( 960, 680 ); root = LCUIWidget_GetRoot(); CHECK( pack = LCUIBuilder_LoadFile( "test_xml_parser.xml" ) ); if( !pack ) { LCUI_Destroy(); return ret; } Widget_UpdateStyle( root, TRUE ); Widget_Append( root, pack ); Widget_Unwrap( pack ); LCUIWidget_Update(); ret += check_widget_attribute(); LCUI_Destroy(); return ret; }
virtual bool Accept(const ByteString &key, const ByteString &value) { TEST_LOG("\"%.*s\": \"%.*s\"", key.length, key.buffer, value.length, value.buffer); return true; }
int main(int argc, char** argv) { PRUintn index; PRBool boolean; CSClient_t *client; PRStatus rv, joinStatus; CSServer_t *server = NULL; PRUintn backlog = DEFAULT_BACKLOG; PRUintn clients = DEFAULT_CLIENTS; const char *serverName = DEFAULT_SERVER; PRBool serverIsLocal = PR_TRUE; PRUintn accepting = ALLOWED_IN_ACCEPT; PRUintn workersMin = DEFAULT_WORKERS_MIN; PRUintn workersMax = DEFAULT_WORKERS_MAX; PRIntn execution = DEFAULT_EXECUTION_TIME; PRIntn low = DEFAULT_LOW, high = DEFAULT_HIGH; /* * -G use global threads * -a <n> threads allowed in accept * -b <n> backlock for listen * -c <threads> number of clients to create * -f <low> low water mark for caching FDs * -F <high> high water mark for caching FDs * -w <threads> minimal number of server threads * -W <threads> maximum number of server threads * -e <seconds> duration of the test in seconds * -s <string> dsn name of server (implies no server here) * -v verbosity */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:f:F:w:W:e:s:vdhp"); debug_out = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'X': /* use XTP as transport */ protocol = 36; break; case '6': /* Use IPv6 */ domain = PR_AF_INET6; break; case 'a': /* the value for accepting */ accepting = atoi(opt->value); break; case 'b': /* the value for backlock */ backlog = atoi(opt->value); break; case 'c': /* number of client threads */ clients = atoi(opt->value); break; case 'f': /* low water fd cache */ low = atoi(opt->value); break; case 'F': /* low water fd cache */ high = atoi(opt->value); break; case 'w': /* minimum server worker threads */ workersMin = atoi(opt->value); break; case 'W': /* maximum server worker threads */ workersMax = atoi(opt->value); break; case 'e': /* program execution time in seconds */ execution = atoi(opt->value); break; case 's': /* server's address */ serverName = opt->value; break; case 'v': /* verbosity */ verbosity = IncrementVerbosity(); break; case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'p': /* pthread mode */ pthread_stats = PR_TRUE; break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); if (0 != PL_strcmp(serverName, DEFAULT_SERVER)) serverIsLocal = PR_FALSE; if (0 == execution) execution = DEFAULT_EXECUTION_TIME; if (0 == workersMax) workersMax = DEFAULT_WORKERS_MAX; if (0 == workersMin) workersMin = DEFAULT_WORKERS_MIN; if (0 == accepting) accepting = ALLOWED_IN_ACCEPT; if (0 == backlog) backlog = DEFAULT_BACKLOG; if (workersMin > accepting) accepting = workersMin; PR_STDIO_INIT(); TimeOfDayMessage("Client/Server started at", PR_GetCurrentThread()); cltsrv_log_file = PR_NewLogModule("cltsrv_log"); MY_ASSERT(NULL != cltsrv_log_file); boolean = PR_SetLogFile("cltsrv.log"); MY_ASSERT(boolean); rv = PR_SetFDCacheSize(low, high); PR_ASSERT(PR_SUCCESS == rv); if (serverIsLocal) { /* Establish the server */ TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("main(0x%p): starting server\n", PR_GetCurrentThread())); server = PR_NEWZAP(CSServer_t); PR_INIT_CLIST(&server->list); server->state = cs_init; server->ml = PR_NewLock(); server->backlog = backlog; server->port = DEFAULT_PORT; server->workers.minimum = workersMin; server->workers.maximum = workersMax; server->workers.accepting = accepting; server->stateChange = PR_NewCondVar(server->ml); server->pool.exiting = PR_NewCondVar(server->ml); server->pool.acceptComplete = PR_NewCondVar(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): creating server thread\n", PR_GetCurrentThread())); server->thread = PR_CreateThread( PR_USER_THREAD, Server, server, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 0); TEST_ASSERT(NULL != server->thread); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): waiting for server init\n", PR_GetCurrentThread())); PR_Lock(server->ml); while (server->state == cs_init) PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): server init complete (port #%d)\n", PR_GetCurrentThread(), server->port)); } if (clients != 0) { /* Create all of the clients */ PRHostEnt host; char buffer[BUFFER_SIZE]; client = (CSClient_t*)PR_CALLOC(clients * sizeof(CSClient_t)); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): creating %d client threads\n", PR_GetCurrentThread(), clients)); if (!serverIsLocal) { rv = PR_GetHostByName(serverName, buffer, BUFFER_SIZE, &host); if (PR_SUCCESS != rv) { PL_FPrintError(PR_STDERR, "PR_GetHostByName"); return 2; } } for (index = 0; index < clients; ++index) { client[index].state = cs_init; client[index].ml = PR_NewLock(); if (serverIsLocal) { if (PR_AF_INET6 != domain) (void)PR_InitializeNetAddr( PR_IpAddrLoopback, DEFAULT_PORT, &client[index].serverAddress); else rv = PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, DEFAULT_PORT, &client[index].serverAddress); } else { (void)PR_EnumerateHostEnt( 0, &host, DEFAULT_PORT, &client[index].serverAddress); } client[index].stateChange = PR_NewCondVar(client[index].ml); TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("main(0x%p): creating client threads\n", PR_GetCurrentThread())); client[index].thread = PR_CreateThread( PR_USER_THREAD, Client, &client[index], PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); TEST_ASSERT(NULL != client[index].thread); PR_Lock(client[index].ml); while (cs_init == client[index].state) PR_WaitCondVar(client[index].stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(client[index].ml); } } /* Then just let them go at it for a bit */ TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("main(0x%p): waiting for execution interval (%d seconds)\n", PR_GetCurrentThread(), execution)); WaitForCompletion(execution); TimeOfDayMessage("Shutting down", PR_GetCurrentThread()); if (clients != 0) { for (index = 0; index < clients; ++index) { TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS, ("main(0x%p): notifying client(0x%p) to stop\n", PR_GetCurrentThread(), client[index].thread)); PR_Lock(client[index].ml); if (cs_run == client[index].state) { client[index].state = cs_stop; PR_Interrupt(client[index].thread); while (cs_stop == client[index].state) PR_WaitCondVar( client[index].stateChange, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(client[index].ml); TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): joining client(0x%p)\n", PR_GetCurrentThread(), client[index].thread)); joinStatus = PR_JoinThread(client[index].thread); TEST_ASSERT(PR_SUCCESS == joinStatus); PR_DestroyCondVar(client[index].stateChange); PR_DestroyLock(client[index].ml); } PR_DELETE(client); } if (NULL != server) { /* All clients joined - retrieve the server */ TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): notifying server(0x%p) to stop\n", PR_GetCurrentThread(), server->thread)); PR_Lock(server->ml); server->state = cs_stop; PR_Interrupt(server->thread); while (cs_exit != server->state) PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): joining server(0x%p)\n", PR_GetCurrentThread(), server->thread)); joinStatus = PR_JoinThread(server->thread); TEST_ASSERT(PR_SUCCESS == joinStatus); PR_DestroyCondVar(server->stateChange); PR_DestroyCondVar(server->pool.exiting); PR_DestroyCondVar(server->pool.acceptComplete); PR_DestroyLock(server->ml); PR_DELETE(server); } TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("main(0x%p): test complete\n", PR_GetCurrentThread())); PT_FPrintStats(debug_out, "\nPThread Statistics\n"); TimeOfDayMessage("Test exiting at", PR_GetCurrentThread()); PR_Cleanup(); return 0; } /* main */
static void s_SingleBounceCheck (CONN conn, const STimeout* timeout, FILE* data_file) { static const char sym[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; EIO_Status status; char message[128]; #define TEST_N_LINES 200 #define TEST_BUF_SIZE (TEST_N_LINES * (TEST_N_LINES + 3) / 2) char buf[TEST_BUF_SIZE]; TEST_LOG(eIO_Success, "[s_SingleBounceCheck] Starting..."); /* WRITE to the connection: "0\n12\n345\n6789\n01234\n........" */ {{ size_t k = 0, j = 0; size_t i; for (i = 0; k != sizeof(buf); i++) { /* prepare output data */ size_t n_write, n_written; for (n_write = 0; n_write < i; n_write++, k++) { assert(k < sizeof(buf)); buf[n_write] = sym[j++ % sizeof(sym)]; } assert(k < sizeof(buf)); if ( n_write ) { buf[n_write++] = '\n'; k++; } buf[n_write] = '\0'; do { /* persistently */ /* WAIT... sometimes */ if (n_write % 5 == 3) { status = CONN_Wait(conn, eIO_Write, timeout); if (status != eIO_Success) { TEST_LOG(status, "[s_SingleBounceCheck] CONN_Wait(write)" " failed, retrying..."); assert(status == eIO_Timeout); } } /* WRITE */ status = CONN_Write(conn, buf, n_write, &n_written, eIO_WritePersist); if (status != eIO_Success) { TEST_LOG(status, "[s_SingleBounceCheck] CONN_Write(persistent)" " failed, retrying..."); assert(n_written < n_write); assert(status == eIO_Timeout); } else { assert(n_written == n_write); } } while (status != eIO_Success); } }} /* READ the "bounced" data from the connection, the first TEST_BUF_SIZE * bytes must be: "0\n12\n345\n6789\n01234\n........" */ {{ char* x_buf; size_t n_read, n_to_read; memset(buf, '\0', TEST_BUF_SIZE); /* PEEK until the 1st 1/3 of the "bounced" data is available */ x_buf = buf; n_to_read = TEST_BUF_SIZE/3; do { TEST_LOG(eIO_Success, "[s_SingleBounceCheck] 1/3 PEEK..."); status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPeek); if (status != eIO_Success) { TEST_LOG(status, "[s_SingleBounceCheck] 1/3 CONN_Read(peek)" " failed, retrying..."); assert(n_read < n_to_read); assert(status == eIO_Timeout); } if (n_read < n_to_read) { sprintf(message, "[s_SingleBounceCheck] 1/3 CONN_Read(peek)" " %lu byte%s peeked out of %lu byte%s, continuing...", (unsigned long) n_read, &"s"[n_read == 1], (unsigned long) n_to_read, &"s"[n_to_read == 1]); TEST_LOG(status, message); } } while (n_read != n_to_read); /* READ 1st 1/3 of "bounced" data, compare it with the PEEKed data */ TEST_LOG(eIO_Success, "[s_SingleBounceCheck] 1/3 READ..."); status = CONN_Read(conn, x_buf + n_to_read, n_to_read, &n_read, eIO_ReadPlain); if (status != eIO_Success) { TEST_LOG(status, "[s_SingleBounceCheck] 1/3 CONN_Read(plain) failed"); } assert(status == eIO_Success); assert(n_read == n_to_read); assert(memcmp(x_buf, x_buf + n_to_read, n_to_read) == 0); memset(x_buf + n_to_read, '\0', n_to_read); /* WAIT on read */ status = CONN_Wait(conn, eIO_Read, timeout); if (status != eIO_Success) { TEST_LOG(status, "[s_SingleBounceCheck] CONN_Wait(read) failed"); assert(status == eIO_Timeout); } /* READ the 2nd 1/3 of "bounced" data */ x_buf = buf + TEST_BUF_SIZE/3; n_to_read = TEST_BUF_SIZE/3; while ( n_to_read ) { TEST_LOG(eIO_Success, "[s_SingleBounceCheck] 2/3 READ..."); status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPlain); if (status != eIO_Success) { sprintf(message, "[s_SingleBounceCheck] 2/3 CONN_Read(plain)" " %lu byte%s read out of %lu byte%s, retrying...", (unsigned long) n_read, &"s"[n_read == 1], (unsigned long) n_to_read, &"s"[n_to_read == 1]); TEST_LOG(status, message); assert(n_read < n_to_read); assert(status == eIO_Timeout); } else { assert(n_read <= n_to_read); } n_to_read -= n_read; x_buf += n_read; } assert(status == eIO_Success); /* Persistently READ the 3rd 1/3 of "bounced" data */ n_to_read = TEST_BUF_SIZE - (x_buf - buf); TEST_LOG(eIO_Success, "[s_SingleBounceCheck] 3/3 READ..."); status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPersist); if (status != eIO_Success) { sprintf(message, "[s_SingleBounceCheck] 3/3 CONN_Read(persistent)" " %lu byte%s read", (unsigned long) n_read, &"s"[n_read == 1]); TEST_LOG(status, message); assert(n_read < n_to_read); assert(0); } else { assert(n_read == n_to_read); } }} /* Check for the received "bounced" data is identical to the sent data */ {{ const char* x_buf = buf; size_t k = 0, j = 0; size_t i; for (i = 1; k != sizeof(buf); i++) { size_t n; for (n = 0; n < i; n++, k++) { if (k == sizeof(buf)) break; assert(*x_buf++ == sym[j++ % sizeof(sym)]); } assert(*x_buf++ == '\n'); k++; } }} /* Now when the "bounced" data is read and tested, READ an arbitrary extra * data sent in by the peer and print it out to LOG file */ if ( data_file ) { fprintf(data_file, "\ns_SingleBounceCheck(BEGIN EXTRA DATA)\n"); fflush(data_file); for (;;) { size_t n; TEST_LOG(eIO_Success, "[s_SingleBounceCheck] EXTRA READ..."); status = CONN_Read(conn, buf, sizeof(buf), &n, eIO_ReadPersist); TEST_LOG(status, "[s_SingleBounceCheck] EXTRA CONN_Read(persistent)"); if ( n ) { assert(fwrite(buf, n, 1, data_file) == 1); fflush(data_file); } if (status == eIO_Closed || status == eIO_Timeout) break; /* okay */ assert(status == eIO_Success); } fprintf(data_file, "\ns_SingleBounceCheck(END EXTRA DATA)\n\n"); fflush(data_file); } TEST_LOG(eIO_Success, "[s_SingleBounceCheck] ...finished"); }
static void PR_CALLBACK Server(void *arg) { PRStatus rv; PRNetAddr serverAddress; PRThread *me = PR_GetCurrentThread(); CSServer_t *server = (CSServer_t*)arg; PRSocketOptionData sockOpt; server->listener = PR_Socket(domain, SOCK_STREAM, protocol); sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; rv = PR_SetSocketOption(server->listener, &sockOpt); TEST_ASSERT(PR_SUCCESS == rv); memset(&serverAddress, 0, sizeof(serverAddress)); if (PR_AF_INET6 != domain) rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress); else rv = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, DEFAULT_PORT, &serverAddress); rv = PR_Bind(server->listener, &serverAddress); TEST_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(server->listener, server->backlog); TEST_ASSERT(PR_SUCCESS == rv); server->started = PR_IntervalNow(); TimeOfDayMessage("Server started at", me); PR_Lock(server->ml); server->state = cs_run; PR_NotifyCondVar(server->stateChange); PR_Unlock(server->ml); /* ** Create the first worker (actually, a thread that accepts ** connections and then processes the work load as needed). ** From this point on, additional worker threads are created ** as they are needed by existing worker threads. */ rv = CreateWorker(server, &server->pool); TEST_ASSERT(PR_SUCCESS == rv); /* ** From here on this thread is merely hanging around as the contact ** point for the main test driver. It's just waiting for the driver ** to declare the test complete. */ TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tServer(0x%p): waiting for state change\n", me)); PR_Lock(server->ml); while ((cs_run == server->state) && !Aborted(rv)) { rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(server->ml); PR_ClearInterrupt(); TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("\tServer(0x%p): shutting down workers\n", me)); /* ** Get all the worker threads to exit. They know how to ** clean up after themselves, so this is just a matter of ** waiting for clorine in the pool to take effect. During ** this stage we're ignoring interrupts. */ server->workers.minimum = server->workers.maximum = 0; PR_Lock(server->ml); while (!PR_CLIST_IS_EMPTY(&server->list)) { PRCList *head = PR_LIST_HEAD(&server->list); CSWorker_t *worker = (CSWorker_t*)head; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker)); rv = PR_Interrupt(worker->thread); TEST_ASSERT(PR_SUCCESS == rv); PR_REMOVE_AND_INIT_LINK(head); } while (server->pool.workers > 0) { TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\tServer(0x%p): waiting for %u workers to exit\n", me, server->pool.workers)); (void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT); } server->state = cs_exit; PR_NotifyCondVar(server->stateChange); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("\tServer(0x%p): stopped after %u operations and %u bytes\n", me, server->operations, server->bytesTransferred)); if (NULL != server->listener) PR_Close(server->listener); server->stopped = PR_IntervalNow(); } /* Server */
static void PR_CALLBACK Worker(void *arg) { PRStatus rv; PRNetAddr from; PRFileDesc *fd = NULL; PRThread *me = PR_GetCurrentThread(); CSWorker_t *worker = (CSWorker_t*)arg; CSServer_t *server = worker->server; CSPool_t *pool = &server->pool; TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1)); PR_Lock(server->ml); PR_APPEND_LINK(&worker->element, &server->list); pool->workers += 1; /* define our existance */ while (cs_run == server->state) { while (pool->accepting >= server->workers.accepting) { TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): waiting for accept slot[%d]\n", me, pool->accepting)); rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT); if (Aborted(rv) || (cs_run != server->state)) { TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\tWorker(0x%p): has been %s\n", me, (Aborted(rv) ? "interrupted" : "stopped"))); goto exit; } } pool->accepting += 1; /* how many are really in accept */ PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): calling accept\n", me)); fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT); PR_Lock(server->ml); pool->accepting -= 1; PR_NotifyCondVar(pool->acceptComplete); if ((NULL == fd) && Aborted(PR_FAILURE)) { if (NULL != server->listener) { PR_Close(server->listener); server->listener = NULL; } goto exit; } if (NULL != fd) { /* ** Create another worker of the total number of workers is ** less than the minimum specified or we have none left in ** accept() AND we're not over the maximum. ** This sort of presumes that the number allowed in accept ** is at least as many as the minimum. Otherwise we'll keep ** creating new threads and deleting them soon after. */ PRBool another = ((pool->workers < server->workers.minimum) || ((0 == pool->accepting) && (pool->workers < server->workers.maximum))) ? PR_TRUE : PR_FALSE; pool->active += 1; PR_Unlock(server->ml); if (another) (void)CreateWorker(server, pool); rv = ProcessRequest(fd, server); if (PR_SUCCESS != rv) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tWorker(0x%p): server process ended abnormally\n", me)); (void)PR_Close(fd); fd = NULL; PR_Lock(server->ml); pool->active -= 1; } } exit: PR_ClearInterrupt(); PR_Unlock(server->ml); if (NULL != fd) { (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH); (void)PR_Close(fd); } TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): exiting [%u]\n", PR_GetCurrentThread(), pool->workers)); PR_Lock(server->ml); pool->workers -= 1; /* undefine our existance */ PR_REMOVE_AND_INIT_LINK(&worker->element); PR_NotifyCondVar(pool->exiting); PR_Unlock(server->ml); PR_DELETE(worker); /* destruction of the "worker" object */ } /* Worker */
void CONN_TestConnector (CONNECTOR connector, const STimeout* timeout, FILE* data_file, TTestConnFlags flags) { EIO_Status status; SConnector dummy; CONN conn; memset(&dummy, 0, sizeof(dummy)); TEST_LOG(eIO_Success, "[CONN_TestConnector] Starting..."); /* Fool around with dummy connector / connection */ assert(CONN_Create(0, &conn) != eIO_Success && !conn); assert(CONN_Create(&dummy, &conn) != eIO_Success && !conn); dummy.setup = s_DummySetup; assert(CONN_Create(&dummy, &conn) == eIO_Success); assert(CONN_Flush (conn) != eIO_Success); assert(CONN_ReInit(conn, 0) == eIO_Success); assert(CONN_ReInit(conn, 0) != eIO_Success); assert(CONN_ReInit(conn, &dummy) == eIO_Success); assert(CONN_Flush (conn) != eIO_Success); assert(CONN_ReInit(conn, &dummy) == eIO_Success); assert(CONN_ReInit(conn, 0) == eIO_Success); assert(CONN_Close (conn) == eIO_Success); /* CREATE new connection on the base of the connector, set * TIMEOUTs, try to RECONNECT, WAIT for the connection is writable */ assert(CONN_Create(connector, &conn) == eIO_Success); assert(CONN_SetTimeout(conn, eIO_Open, timeout) == eIO_Success); assert(CONN_SetTimeout(conn, eIO_ReadWrite, timeout) == eIO_Success); assert(CONN_SetTimeout(conn, eIO_Close, timeout) == eIO_Success); assert(CONN_ReInit(conn, connector) == eIO_Success); status = CONN_Wait(conn, eIO_Write, timeout); if (status != eIO_Success) { TEST_LOG(status, "[CONN_TestConnector] CONN_Wait(write) failed"); assert(status == eIO_Timeout); } /* Run the specified TESTs */ if ( !flags ) { flags = fTC_Everything; } if (flags & fTC_SingleBouncePrint) { s_SingleBouncePrint(conn, data_file); } if (flags & fTC_MultiBouncePrint) { s_MultiBouncePrint(conn, data_file); } if (flags & fTC_SingleBounceCheck) { s_SingleBounceCheck(conn, timeout, data_file); } /* And CLOSE the connection... */ assert(CONN_Close(conn) == eIO_Success); TEST_LOG(eIO_Success, "[CONN_TestConnector] Completed"); }
static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server) { PRStatus drv, rv; char buffer[1024]; PRFileDesc *file = NULL; PRThread * me = PR_GetCurrentThread(); PRInt32 bytes, descbytes, netbytes, filebytes = 0; CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t); PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): receiving desciptor\n", me)); bytes = PR_Recv( fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout); if (-1 == bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto exit; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): receive timeout\n", me)); } goto exit; } if (0 == bytes) { rv = PR_FAILURE; TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): unexpected end of file\n", me)); goto exit; } descbytes = PR_ntohl(descriptor->size); TEST_ASSERT(sizeof(*descriptor) == bytes); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n", me, descbytes, descriptor->filename)); file = PR_Open( descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666); if (NULL == file) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): open file timeout\n", me)); goto aborted; } } TEST_ASSERT(NULL != file); filebytes = 0; while (filebytes < descbytes) { netbytes = sizeof(buffer); if ((descbytes - filebytes) < netbytes) netbytes = descbytes - filebytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes)); bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout); if (-1 == bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): receive data timeout\n", me)); goto aborted; } /* * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED) * on NT here. This is equivalent to ECONNRESET on Unix. * -wtc */ TEST_LOG( cltsrv_log_file, TEST_LOG_WARNING, ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } if(0 == bytes) { TEST_LOG( cltsrv_log_file, TEST_LOG_WARNING, ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me)); rv = PR_FAILURE; goto aborted; } filebytes += bytes; netbytes = bytes; /* The byte count for PR_Write should be positive */ MY_ASSERT(netbytes > 0); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes)); bytes = PR_Write(file, buffer, netbytes); if (netbytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): write file timeout\n", me)); goto aborted; } } TEST_ASSERT(bytes > 0); } PR_Lock(server->ml); server->operations += 1; server->bytesTransferred += filebytes; PR_Unlock(server->ml); rv = PR_Close(file); if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); file = NULL; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename)); file = PR_Open(descriptor->filename, PR_RDONLY, 0); if (NULL == file) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): open file timeout\n", PR_GetCurrentThread())); goto aborted; } TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } TEST_ASSERT(NULL != file); netbytes = 0; while (netbytes < descbytes) { filebytes = sizeof(buffer); if ((descbytes - netbytes) < filebytes) filebytes = descbytes - netbytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes)); bytes = PR_Read(file, buffer, filebytes); if (filebytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): read file timeout\n", me)); else TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } TEST_ASSERT(bytes > 0); netbytes += bytes; filebytes = bytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes)); bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout); if (filebytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): send data timeout\n", me)); goto aborted; } break; } TEST_ASSERT(bytes > 0); } PR_Lock(server->ml); server->bytesTransferred += filebytes; PR_Unlock(server->ml); rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH); if (Aborted(rv)) goto aborted; rv = PR_Close(file); if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); file = NULL; aborted: PR_ClearInterrupt(); if (NULL != file) PR_Close(file); drv = PR_Delete(descriptor->filename); TEST_ASSERT(PR_SUCCESS == drv); exit: TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): Finished\n", me)); PR_DELETE(descriptor); #if defined(WIN95) PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */ #endif return rv; } /* ProcessRequest */
static void PR_CALLBACK Client(void *arg) { PRStatus rv; PRIntn index; char buffer[1024]; PRFileDesc *fd = NULL; PRUintn clipping = DEFAULT_CLIPPING; PRThread *me = PR_GetCurrentThread(); CSClient_t *client = (CSClient_t*)arg; CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t); PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT); for (index = 0; index < sizeof(buffer); ++index) buffer[index] = (char)index; client->started = PR_IntervalNow(); PR_Lock(client->ml); client->state = cs_run; PR_NotifyCondVar(client->stateChange); PR_Unlock(client->ml); TimeOfDayMessage("Client started at", me); while (cs_run == client->state) { PRInt32 bytes, descbytes, filebytes, netbytes; (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer)); TEST_LOG(cltsrv_log_file, TEST_LOG_INFO, ("\tClient(0x%p): connecting to server at %s\n", me, buffer)); fd = PR_Socket(domain, SOCK_STREAM, protocol); TEST_ASSERT(NULL != fd); rv = PR_Connect(fd, &client->serverAddress, timeout); if (PR_FAILURE == rv) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): conection failed (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } memset(descriptor, 0, sizeof(*descriptor)); descriptor->size = PR_htonl(descbytes = rand() % clipping); PR_snprintf( descriptor->filename, sizeof(descriptor->filename), "CS%p%p-%p.dat", client->started, me, client->operations); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes)); bytes = PR_Send( fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout); if (sizeof(CSDescriptor_t) != bytes) { if (Aborted(PR_FAILURE)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): send descriptor timeout\n", me)); goto retry; } } TEST_ASSERT(sizeof(*descriptor) == bytes); netbytes = 0; while (netbytes < descbytes) { filebytes = sizeof(buffer); if ((descbytes - netbytes) < filebytes) filebytes = descbytes - netbytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): sending %d bytes\n", me, filebytes)); bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout); if (filebytes != bytes) { if (Aborted(PR_FAILURE)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): send data timeout\n", me)); goto retry; } } TEST_ASSERT(bytes == filebytes); netbytes += bytes; } filebytes = 0; while (filebytes < descbytes) { netbytes = sizeof(buffer); if ((descbytes - filebytes) < netbytes) netbytes = descbytes - filebytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): receiving %d bytes\n", me, netbytes)); bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout); if (-1 == bytes) { if (Aborted(PR_FAILURE)) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive data aborted\n", me)); goto aborted; } else if (PR_IO_TIMEOUT_ERROR == PR_GetError()) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive data timeout\n", me)); else TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto retry; } if (0 == bytes) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tClient(0x%p): unexpected end of stream\n", PR_GetCurrentThread())); break; } filebytes += bytes; } rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH); if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); retry: (void)PR_Close(fd); fd = NULL; TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("\tClient(0x%p): disconnected from server\n", me)); PR_Lock(client->ml); client->operations += 1; client->bytesTransferred += 2 * descbytes; rv = PR_WaitCondVar(client->stateChange, rand() % clipping); PR_Unlock(client->ml); if (Aborted(rv)) break; } aborted: client->stopped = PR_IntervalNow(); PR_ClearInterrupt(); if (NULL != fd) rv = PR_Close(fd); PR_Lock(client->ml); client->state = cs_exit; PR_NotifyCondVar(client->stateChange); PR_Unlock(client->ml); PR_DELETE(descriptor); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("\tClient(0x%p): stopped after %u operations and %u bytes\n", PR_GetCurrentThread(), client->operations, client->bytesTransferred)); } /* Client */