void close_connection(struct connection *c) { if(c->read == 0 && c->keepalive) { /* server has legitiamately shut down an idle keep alive request */ good--; /* connection never happend */ } else { if(good==1) { /* first time here */ doclen = c->bread; } else if (c->bread!=doclen) { bad++; err_length++; } /* save out time */ if(done < requests) { struct data s; gettimeofday(&c->done,0); s.read = c->read; s.ctime = timedif(c->connect, c->start); s.time = timedif(c->done, c->start); stats[done++] = s; } } close(c->fd); FD_CLR(c->fd, &readbits); FD_CLR(c->fd, &writebits); /* connect again */ start_connect(c); return; }
void output_results() { int timetaken; gettimeofday(&endtime,0); timetaken = timedif(endtime, start); printf("\n---\n"); printf("Server: %s\n", server_name); printf("Document Length: %d\n", doclen); printf("Concurency Level: %d\n", concurrency); printf("Time taken for tests: %d.%03d seconds\n", timetaken/1000, timetaken%1000); printf("Complete requests: %d\n", done); printf("Failed requests: %d\n", bad); if(bad) printf(" (Connect: %d, Length: %d, Exceptions: %d)\n", err_conn, err_length, err_except); if(keepalive) printf("Keep-Alive requests: %d\n", doneka); printf("Bytes transfered: %d\n", totalread); printf("HTML transfered: %d\n", totalbread); /* avoid divide by zero */ if(timetaken) { printf("Requests per seconds: %.2f\n", 1000*(float)(done)/timetaken); printf("Transfer rate: %.2f kb/s\n", (float)(totalread)/timetaken); } { /* work out connection times */ int i; int totalcon=0, total=0; int mincon=9999999, mintot=999999; int maxcon=0, maxtot=0; for(i=0; i<requests; i++) { struct data s = stats[i]; mincon = min(mincon, s.ctime); mintot = min(mintot, s.time); maxcon = max(maxcon, s.ctime); maxtot = max(maxtot, s.time); totalcon += s.ctime; total += s.time; } printf("\nConnnection Times (ms)\n"); printf(" min avg max\n"); printf("Connect: %5d %5d %5d\n",mincon, totalcon/requests, maxcon ); printf("Total: %5d %5d %5d\n", mintot, total/requests, maxtot); printf("---\n\n"); } exit(0); }
int test() { struct timeval timeout, now; fd_set sel_read, sel_except, sel_write; int i; { /* get server information */ struct hostent *he; he = gethostbyname(machine); if (!he) err("gethostbyname"); server.sin_family = he->h_addrtype; server.sin_port = htons(port); server.sin_addr.s_addr = ((unsigned long *)(he->h_addr_list[0]))[0]; } con = malloc(concurrency*sizeof(struct connection)); memset(con,0,concurrency*sizeof(struct connection)); stats = malloc(requests * sizeof(struct data)); FD_ZERO(&readbits); FD_ZERO(&writebits); /* setup request */ sprintf(request,"GET %s HTTP/1.0\r\nUser-Agent: ZeusBench/1.0\r\n" "%sHost: %s\r\nAccept: */*\r\n\r\n", file, keepalive?"Connection: Keep-Alive\r\n":"", machine ); reqlen = strlen(request); /* ok - lets start */ gettimeofday(&start,0); /* initialise lots of requests */ for(i=0; i<concurrency; i++) start_connect(&con[i]); while(done<requests) { int n; /* setup bit arrays */ memcpy(&sel_except, &readbits, sizeof(readbits)); memcpy(&sel_read, &readbits, sizeof(readbits)); memcpy(&sel_write, &writebits, sizeof(readbits)); /* check for time limit expiry */ gettimeofday(&now,0); if(tlimit && timedif(now,start) > (tlimit*1000)) { requests=done; /* so stats are correct */ output_results(); } /* Timeout of 30 seconds. */ timeout.tv_sec=30; timeout.tv_usec=0; n=select(256, &sel_read, &sel_write, &sel_except, &timeout); if(!n) { printf("\nServer timed out\n\n"); exit(1); } if(n<1) err("select"); for(i=0; i<concurrency; i++) { int s = con[i].fd; if(FD_ISSET(s, &sel_except)) { bad++; err_except++; start_connect(&con[i]); continue; } if(FD_ISSET(s, &sel_read)) read_connection(&con[i]); if(FD_ISSET(s, &sel_write)) write_request(&con[i]); } if(done>=requests) output_results(); } return 0; }
void read_connection(struct connection *c) { int r; r=read(c->fd,buffer,sizeof(buffer)); if(r==0 || (r<0 && errno!=EAGAIN)) { good++; close_connection(c); return; } if(r<0 && errno==EAGAIN) return; c->read += r; totalread += r; if(!c->gotheader) { char *s; int l=4; int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */ int tocopy = (space<r)?space:r; memcpy(c->cbuff+c->cbx, buffer, space); c->cbx += tocopy; space -= tocopy; c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */ s = strstr(c->cbuff, "\r\n\r\n"); /* this next line is so that we talk to NCSA 1.5 which blatantly breaks the http specifaction */ if(!s) { s = strstr(c->cbuff,"\n\n"); l=2; } if(!s) { /* read rest next time */ if(space) return; else { /* header is in invalid or too big - close connection */ close(c->fd); if(bad++>10) { printf("\nTest aborted after 10 failures\n\n"); exit(1); } FD_CLR(c->fd, &writebits); start_connect(c); } } else { /* have full header */ if(!good) { /* this is first time, extract some interesting info */ char *p, *q; p = strstr(c->cbuff, "Server:"); q = server_name; if(p) { p+=8; while(*p>32) *q++ = *p++; } *q = 0; } c->gotheader = 1; *s = 0; /* terminate at end of header */ if(keepalive && (strstr(c->cbuff, "Keep-Alive") || strstr(c->cbuff, "keep-alive"))) /* for benefit of MSIIS */ { char *cl; cl = strstr(c->cbuff, "Content-Length:"); /* for cacky servers like NCSA which break the spec and send a lower case 'l' */ if(!cl) cl = strstr(c->cbuff, "Content-length:"); if(cl) { c->keepalive=1; c->length = atoi(cl+16); } } c->bread += c->cbx - (s+l-c->cbuff) + r-tocopy; totalbread += c->bread; } } else { /* outside header, everything we have read is entity body */ c->bread += r; totalbread += r; } if(c->keepalive && (c->bread >= c->length)) { /* finished a keep-alive connection */ good++; doneka++; /* save out time */ if(good==1) { /* first time here */ doclen = c->bread; } else if(c->bread!=doclen) { bad++; err_length++; } if(done < requests) { struct data s; gettimeofday(&c->done,0); s.read = c->read; s.ctime = timedif(c->connect, c->start); s.time = timedif(c->done, c->start); stats[done++] = s; } c->keepalive = 0; c->length = 0; c->gotheader=0; c->cbx = 0; c->read = c->bread = 0; write_request(c); c->start = c->connect; /* zero connect time with keep-alive */ } }
static void test(struct global * registry) { struct timeval timeout, now; fd_set sel_read, sel_except, sel_write; int i; registry->con = calloc(registry->concurrency, sizeof(struct connection)); memset(registry->con, 0, registry->concurrency * sizeof(struct connection)); #ifdef AB_DEBUG printf("AB_DEBUG: start of test()\n"); #endif for (i = 0; i < registry->concurrency; i++) { registry->con[i].url = registry->ready_to_run_queue[i].url; registry->con[i].run = registry->ready_to_run_queue[i].run; registry->con[i].state = STATE_READY; registry->con[i].thread = registry->ready_to_run_queue[i].thread; } #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 1\n"); #endif registry->stats = calloc(registry->number_of_urls, sizeof(struct data *)); for (i = 0; i < registry->number_of_runs; i++) { int j; for (j = registry->position[i]; j < registry->position[i+1]; j++) registry->stats[j] = calloc(registry->repeats[i], sizeof(struct data)); } #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 2\n"); #endif FD_ZERO(®istry->readbits); FD_ZERO(®istry->writebits); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 3\n"); #endif /* ok - lets start */ gettimeofday(®istry->starttime, 0); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 4\n"); #endif /* initialise lots of requests */ registry->head = registry->concurrency; for (i = 0; i < registry->concurrency; i++) start_connect(registry, ®istry->con[i]); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5\n"); #endif while (registry->done < registry->need_to_be_done) { int n; #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.1, registry->done = %d\n", registry->done); #endif /* setup bit arrays */ memcpy(&sel_except, ®istry->readbits, sizeof(registry->readbits)); memcpy(&sel_read, ®istry->readbits, sizeof(registry->readbits)); memcpy(&sel_write, ®istry->writebits, sizeof(registry->writebits)); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.2, registry->done = %d\n", registry->done); #endif /* Timeout of 30 seconds, or minimum time limit specified by config. */ timeout.tv_sec = registry->min_tlimit.tv_sec; timeout.tv_usec = registry->min_tlimit.tv_usec; n = select(FD_SETSIZE, &sel_read, &sel_write, &sel_except, &timeout); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.3, registry->done = %d\n", registry->done); #endif if (!n) myerr(registry->warn_and_error, "Server timed out"); if (n < 1) myerr(registry->warn_and_error, "Select error."); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.4, registry->done = %d\n", registry->done); #endif /* check for time limit expiry */ gettimeofday(&now, 0); if (registry->tlimit && timedif(now, registry->starttime) > (registry->tlimit * 1000)) { char *warn = malloc(256 * sizeof(char)); sprintf(warn, "Global time limit reached (%.2f sec), premature exit", registry->tlimit); myerr(registry->warn_and_error, warn); free(warn); registry->need_to_be_done = registry->done; /* break out of loop */ } for (i = 0; i < registry->concurrency; i++) { int s = registry->con[i].fd; #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.5, registry->done = %d, i = %d\n", registry->done, i); #endif if (registry->started[registry->con[i].url] > registry->finished[registry->con[i].url]) { struct connection * c = ®istry->con[i]; struct timeval url_now; /* check for per-url time limit expiry */ gettimeofday(&url_now, 0); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.5.4, Time taken for current request = %d ms; Per-url time limit = %.4f sec; for run %d, url %d\n", timedif(url_now, c->start_time), registry->url_tlimit[c->url], c->run, c->url - registry->position[c->run]); printf("AB_DEBUG: test() - stage 5.5.5, registry->done = %d, i = %d\n", registry->done, i); #endif if (registry->url_tlimit[c->url] && timedif(url_now, c->start_time) > (registry->url_tlimit[c->url] * 1000)) { char *warn = malloc(256 * sizeof(char)); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.5.5.3, registry->done = %d, i = %d\n", registry->done, i); #endif sprintf(warn, "Per-url time limit reached (%.3f sec) for run %d, url %d, iteration %d; connection closed prematurely", registry->url_tlimit[c->url], c->run, c->url - registry->position[c->run], c->thread); myerr(registry->warn_and_error, warn); free(warn); registry->failed[c->url]++; close_connection(registry, c); continue; } } if (registry->con[i].state == STATE_DONE) continue; #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.6, registry->done = %d, i = %d\n", registry->done, i); #endif if (FD_ISSET(s, &sel_except)) { registry->failed[registry->con[i].url]++; start_connect(registry, ®istry->con[i]); continue; } #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.7, registry->done = %d, i = %d\n", registry->done, i); #endif if (FD_ISSET(s, &sel_read)) { read_connection(registry, ®istry->con[i]); continue; } #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.8, registry->done = %d, i = %d\n", registry->done, i); #endif if (FD_ISSET(s, &sel_write)) write_request(registry, ®istry->con[i]); #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 5.9, registry->done = %d, i = %d\n", registry->done, i); #endif } } #ifdef AB_DEBUG printf("AB_DEBUG: test() - stage 6\n"); #endif gettimeofday(®istry->endtime, 0); if (strlen(registry->warn_and_error) == 28) myerr(registry->warn_and_error, "None.\n"); else myerr(registry->warn_and_error, "Done.\n"); }
/* ------------------------------------------------------------------------ */ void time_span_out () { int i; /* counter */ struct data_hdr temp_hdr; /* data header */ struct time end_time; /* block ending time */ unsigned int offset; /* local computations */ double duration; struct type52 *save_channel_ptr = current_channel; struct twindow *twin; /* * if output is intended for a seed volume, update the blockette info 74 * only... * */ if (Seed_flag) { update_type74(data_hdr); data_hdr->nsamples = 0; return; } /* +=======================================+ */ /*================| Look for Time Spans |================*/ /* +=======================================+ */ if (read_summary_flag) { char start[23]; char end[23]; struct time endtime; struct time starttime; duration = ((double)(data_hdr->nsamples)*TIME_PRECISION)/data_hdr->sample_rate; endtime = timeadd_double(data_hdr->time, duration); #if 0 sprintf(start, "%d,%d,%d:%d:%d.%d", data_hdr->time.year, data_hdr->time.day, data_hdr->time.hour, data_hdr->time.minute, data_hdr->time.second, data_hdr->time.fracsec); sprintf(end, "%d,%d,%d:%d:%d.%d", endtime.year, endtime.day, endtime.hour, endtime.minute, endtime.second, endtime.fracsec); if (input_file_type == DISK_DEVICE) /* if from disk drive, already scanned the * block 74s for matching data, just use * what was scanned previously */ twin = get_twin_from_summary(); else /* tape drive seed volume, we must scan the * summary file for "clipping" */ twin = scan_summary_file(data_hdr->station, data_hdr->channel, data_hdr->network, data_hdr->location, data_hdr->time, endtime); if (twin == NULL) { fprintf(stderr, "Error - time_span_out(): Unable to locate timespan in the summary file!\nStation: %s;Channel: %s\n for timespan %s to %s \n", data_hdr->station, data_hdr->channel, start, end); fprintf(stderr, "Ignoring summary file for this timespan.\n"); output_data(data_hdr, 0); data_hdr->nsamples = 0; return; } timecvt(&starttime, twin->time_start); timecvt(&endtime, twin->time_end); start_time_point = &starttime; end_time_point = &endtime; start_time_count = end_time_count = 1; #endif set_event(&(data_hdr->time), &endtime); } /* if user didn't enter any time spans, output all data */ if (start_time_count == 0) { output_data(data_hdr, 0); data_hdr->nsamples = 0; return; } /* look through time span list as entered by the user */ for (i=0;i<start_time_count;i++) { current_channel = save_channel_ptr; /* copy current data header */ temp_hdr = *data_hdr; /* is span start equal to start of data? */ if (timecmp (start_time_point[i],data_hdr->time) == 0) { /* is there a corresponding end time? */ if (i < end_time_count) { /* use current data start time */ /* calc number of samples */ duration = timedif(temp_hdr.time,end_time_point[i]); /* took this out of timedif */ if (duration < 0) duration = 0; temp_hdr.nsamples = (int) (((duration*temp_hdr.sample_rate)/TIME_PRECISION)+.999); /* make sure it's not more than available data */ if (temp_hdr.nsamples > data_hdr->nsamples) temp_hdr.nsamples = data_hdr->nsamples; output_data(&temp_hdr, 0); } else { output_data(data_hdr, 0); } } /* is span start less than start of data? */ else if (timecmp (start_time_point[i],data_hdr->time) < 0) { /* is there a corresponding end time? */ if (i < end_time_count) { if (timecmp (end_time_point[i],data_hdr->time) > 0) { /* use current data start time */ /* calc number of samples */ duration = timedif(temp_hdr.time,end_time_point[i]); /* took this out of timedif */ if (duration < 0) duration = 0; temp_hdr.nsamples = (int) (((duration*temp_hdr.sample_rate)/TIME_PRECISION)+.999); /* make sure it's not more than available data */ if (end_time_point[i].year == 9999) temp_hdr.nsamples = data_hdr->nsamples; if (temp_hdr.nsamples > data_hdr->nsamples) temp_hdr.nsamples = data_hdr->nsamples; output_data(&temp_hdr, 0); } } else { output_data(data_hdr, 0); } } /* span start must be greater than start of data */ else { /* figure out data ending time */ if (data_hdr->sample_rate != 0) duration = (((double)data_hdr->nsamples * TIME_PRECISION) / data_hdr->sample_rate); else duration = 0; end_time = timeadd_double (data_hdr->time, duration); /* is span start before end of data? */ if (timecmp(start_time_point[i],end_time) < 0) { /* calc new start time and sample offset*/ duration = timedif(temp_hdr.time,start_time_point[i]); /* took this out of timedif */ if (duration < 0) duration = 0; offset = (int) ((duration * data_hdr->sample_rate)/TIME_PRECISION); /* changed to float to avoid overflow - CL */ duration = ((float) offset * TIME_PRECISION) / data_hdr->sample_rate; temp_hdr.time = timeadd_double (data_hdr->time, duration); /* calc number of samples */ if (i < end_time_count) { if (end_time_point[i].year != 9999) duration = timedif(temp_hdr.time,end_time_point[i]); else duration = timedif(temp_hdr.time,end_time); } else duration = timedif(temp_hdr.time,end_time); /* took this out of timedif */ if (duration < 0) duration = 0; temp_hdr.nsamples = (int)(((duration*temp_hdr.sample_rate)/TIME_PRECISION)+.999); /* make sure it's not more than available data */ if ((temp_hdr.nsamples+offset) > data_hdr->nsamples) temp_hdr.nsamples = data_hdr->nsamples - offset; output_data(&temp_hdr, offset); } } } data_hdr->nsamples = 0; if (read_summary_flag) /* will avoid unnecessary free()s as these weren't malloced */ start_time_count = end_time_count = 0; /* +=======================================+ */ /*================| clean-up |================*/ /* +=======================================+ */ }
void scheduler(memcached_server_st *servers, conclusions_st *conclusion) { unsigned int x; unsigned int actual_loaded= 0; /* Fix warning */ memcached_st *memc; struct timeval start_time, end_time; pthread_t mainthread; /* Thread descriptor */ pthread_attr_t attr; /* Thread attributes */ pairs_st *pairs= NULL; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); memc= memcached_create(NULL); memcached_server_push(memc, servers); memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary); if (opt_flush) flush_all(memc); if (opt_createial_load) pairs= load_create_data(memc, opt_createial_load, &actual_loaded); /* We set this after we have loaded */ { if (opt_non_blocking_io) memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); if (opt_tcp_nodelay) memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); } pthread_mutex_lock(&counter_mutex); thread_counter= 0; pthread_mutex_lock(&sleeper_mutex); master_wakeup= 1; pthread_mutex_unlock(&sleeper_mutex); for (x= 0; x < opt_concurrency; x++) { thread_context_st *context; context= (thread_context_st *)malloc(sizeof(thread_context_st)); memset(context, 0, sizeof(thread_context_st)); context->memc= memcached_clone(NULL, memc); context->test= opt_test; context->initial_pairs= pairs; context->initial_number= actual_loaded; if (opt_test == SET_TEST) { context->execute_pairs= pairs_generate(opt_execute_number, 400); context->execute_number= opt_execute_number; } /* now you create the thread */ if (pthread_create(&mainthread, &attr, run_task, (void *)context) != 0) { fprintf(stderr,"Could not create thread\n"); exit(1); } thread_counter++; } pthread_mutex_unlock(&counter_mutex); pthread_attr_destroy(&attr); pthread_mutex_lock(&sleeper_mutex); master_wakeup= 0; pthread_mutex_unlock(&sleeper_mutex); pthread_cond_broadcast(&sleep_threshhold); gettimeofday(&start_time, NULL); /* We loop until we know that all children have cleaned up. */ pthread_mutex_lock(&counter_mutex); while (thread_counter) { struct timespec abstime; memset(&abstime, 0, sizeof(struct timespec)); abstime.tv_sec= 1; pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime); } pthread_mutex_unlock(&counter_mutex); gettimeofday(&end_time, NULL); conclusion->load_time= timedif(end_time, start_time); conclusion->read_time= timedif(end_time, start_time); pairs_free(pairs); memcached_free(memc); }
int main(int argc, char *argv[]) { test_return_t return_code; unsigned int x; char *collection_to_run= NULL; char *wildcard= NULL; world_st world; collection_st *collection; collection_st *next; void *world_ptr; world_stats_st stats; #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT if (sasl_client_init(NULL) != SASL_OK) { fprintf(stderr, "Failed to initialize sasl library!\n"); return 1; } #endif memset(&stats, 0, sizeof(stats)); memset(&world, 0, sizeof(world)); get_world(&world); collection= init_world(&world); if (world.create) { test_return_t error; world_ptr= world.create(&error); if (error != TEST_SUCCESS) exit(1); } else { world_ptr= NULL; } if (argc > 1) collection_to_run= argv[1]; if (argc == 3) wildcard= argv[2]; for (next= collection; next->name; next++) { test_return_t collection_rc= TEST_SUCCESS; test_st *run; bool failed= false; bool skipped= false; run= next->tests; if (collection_to_run && fnmatch(collection_to_run, next->name, 0)) continue; stats.collection_total++; collection_rc= world.collection.startup(world_ptr); if (collection_rc != TEST_SUCCESS) goto skip_pre; if (next->pre) { collection_rc= world.runner->pre(next->pre, world_ptr); } skip_pre: switch (collection_rc) { case TEST_SUCCESS: fprintf(stderr, "\n%s\n\n", next->name); break; case TEST_FAILURE: fprintf(stderr, "\n%s [ failed ]\n\n", next->name); stats.collection_failed++; goto cleanup; case TEST_SKIPPED: fprintf(stderr, "\n%s [ skipping ]\n\n", next->name); stats.collection_skipped++; goto cleanup; case TEST_MEMORY_ALLOCATION_FAILURE: case TEST_MAXIMUM_RETURN: default: assert(0); break; } for (x= 0; run->name; run++) { struct timeval start_time, end_time; long int load_time= 0; if (wildcard && fnmatch(wildcard, run->name, 0)) continue; fprintf(stderr, "Testing %s", run->name); if (world.test.startup) { world.test.startup(world_ptr); } if (run->requires_flush && world.test.flush) { world.test.flush(world_ptr); } if (world.test.pre_run) { world.test.pre_run(world_ptr); } // Runner code { #if 0 if (next->pre && world.runner->pre) { return_code= world.runner->pre(next->pre, world_ptr); if (return_code != TEST_SUCCESS) { goto error; } } #endif gettimeofday(&start_time, NULL); return_code= world.runner->run(run->test_fn, world_ptr); gettimeofday(&end_time, NULL); load_time= timedif(end_time, start_time); #if 0 if (next->post && world.runner->post) { (void) world.runner->post(next->post, world_ptr); } #endif } if (world.test.post_run) { world.test.post_run(world_ptr); } stats.total++; fprintf(stderr, "\t\t\t\t\t"); switch (return_code) { case TEST_SUCCESS: fprintf(stderr, "%ld.%03ld ", load_time / 1000, load_time % 1000); stats.success++; break; case TEST_FAILURE: stats.failed++; failed= true; break; case TEST_SKIPPED: stats.skipped++; skipped= true; break; case TEST_MEMORY_ALLOCATION_FAILURE: fprintf(stderr, "Exhausted memory, quitting\n"); abort(); case TEST_MAXIMUM_RETURN: default: assert(0); // Coding error. break; } fprintf(stderr, "[ %s ]\n", test_strerror(return_code)); if (world.test.on_error) { test_return_t rc; rc= world.test.on_error(return_code, world_ptr); if (rc != TEST_SUCCESS) break; } } if (next->post && world.runner->post) { (void) world.runner->post(next->post, world_ptr); } if (! failed && ! skipped) { stats.collection_success++; } cleanup: world.collection.shutdown(world_ptr); } if (stats.collection_failed || stats.collection_skipped) { fprintf(stderr, "Some test failures and/or skipped test occurred.\n\n"); } else { fprintf(stderr, "All tests completed successfully\n\n"); } if (world.destroy) { test_return_t error; error= world.destroy(world_ptr); if (error != TEST_SUCCESS) { fprintf(stderr, "Failure during shutdown.\n"); stats.failed++; // We do this to make our exit code return 1 } } world_stats_print(&stats); #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT sasl_done(); #endif return stats.failed == 0 ? 0 : 1; }