static int thread_printheader(logbuffer_t * logbuf) { logbuf->logsize = 0; log_header_t header = log_header_INIT("thread_printheader", __FILE__, 100); printheader_logbuffer(logbuf, &header); TEST(0 == compare_header(logbuf->logsize, logbuf->addr, "thread_printheader", __FILE__, 100)); return 0; ONERR: CLEARBUFFER_ERRLOG(); return EINVAL; }
static int test_update(void) { logbuffer_t logbuf = logbuffer_FREE; thread_t * thread = 0; pipe_t pipe = pipe_FREE; uint8_t buffer[1024]; uint8_t readbuffer[1024+1]; // prepare TEST(0 == init_pipe(&pipe)); logbuf = (logbuffer_t) logbuffer_INIT(sizeof(buffer), buffer, pipe.write); // TEST truncate_logbuffer for (unsigned i = 0; i < 32; ++i) { logbuf.logsize = 32; logbuf.addr[i] = 'a'; truncate_logbuffer(&logbuf, i); TEST(logbuf.addr == buffer); TEST(logbuf.size == sizeof(buffer)); TEST(logbuf.io == pipe.write); TEST(logbuf.addr[i] == 0); TEST(logbuf.logsize == i); } // TEST truncate_logbuffer: parameter with bigger or equal size are ignored for (unsigned i = 0; i < 32; ++i) { logbuf.logsize = i; logbuf.addr[i] = 'a'; logbuf.addr[i+1] = 'a'; truncate_logbuffer(&logbuf, i+1); truncate_logbuffer(&logbuf, i); TEST(logbuf.addr == buffer); TEST(logbuf.size == sizeof(buffer)); TEST(logbuf.io == pipe.write); TEST(logbuf.addr[i] == 'a'); TEST(logbuf.addr[i+1] == 'a'); TEST(logbuf.logsize == i); } // TEST write_logbuffer memset(readbuffer, 0, sizeof(readbuffer)); for (unsigned i = 0; i < sizeof(buffer); ++i) { buffer[i] = (uint8_t)i; } logbuf.logsize = logbuf.size; // test TEST( 0 == write_logbuffer(&logbuf)); // check logbuf TEST( logbuf.addr == buffer); TEST( logbuf.size == sizeof(buffer)); TEST( logbuf.logsize == sizeof(buffer)); TEST( logbuf.io == pipe.write); // check content of pipe static_assert(sizeof(readbuffer) > sizeof(buffer), "check that only sizeof(buffer) are written"); TEST(sizeof(buffer) == read(pipe.read, readbuffer, sizeof(readbuffer))); for (unsigned i = 0; i < sizeof(buffer); ++i) { TEST(buffer[i] == readbuffer[i]); } // TEST printheader_logbuffer logbuf.logsize = 0; log_header_t header = log_header_INIT("test_update", "file", 123456); printheader_logbuffer(&logbuf, &header); TEST(0 == compare_header(logbuf.logsize, logbuf.addr, "test_update", "file", 123456)); for (size_t len = logbuf.logsize, i = 1; i < 10; ++i) { printheader_logbuffer(&logbuf, &header); TEST((i+1)*len == logbuf.logsize); TEST(0 == compare_header(len, logbuf.addr + i*len, "test_update", "file", 123456)); } // TEST printheader_logbuffer: other thread TEST(0 == newgeneric_thread(&thread, &thread_printheader, &logbuf)); TEST(0 == join_thread(thread)); TEST(0 == returncode_thread(thread)); TEST(0 == delete_thread(&thread)); // TEST printheader_logbuffer: adds " ..." at end in case of truncated message logbuf.logsize = logbuf.size - 10; logbuf.addr[logbuf.logsize] = 0; printheader_logbuffer(&logbuf, &header); TEST(logbuf.logsize == logbuf.size - 1) TEST(0 == memcmp(logbuf.addr + logbuf.size - 10, "[", 1)); TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5)); // TEST vprintf_logbuffer: append on already stored content for (unsigned i = 0; i < sizeof(buffer)-100; ++i) { memset(buffer, 0, sizeof(buffer)); memset(readbuffer, 0, sizeof(readbuffer)); logbuf.logsize = i; printf_logbuffer(&logbuf, "%d : %s : %c;;", i, "OK!", '0'); snprintf((char*)readbuffer + i, 100, "%d : %s : %c;;", i, "OK!", '0'); TEST(0 == memcmp(buffer, readbuffer, sizeof(buffer))); } // TEST vprintf_logbuffer: different formats logbuf.logsize = 0; printf_logbuffer(&logbuf, "%%%s%%", "str" ); printf_logbuffer(&logbuf, "%"PRIi8";", (int8_t)-1); printf_logbuffer(&logbuf, "%"PRIu8";", (uint8_t)1); printf_logbuffer(&logbuf, "%"PRIi16";", (int16_t)-256); printf_logbuffer(&logbuf, "%"PRIu16";", (uint16_t)256); printf_logbuffer(&logbuf, "%"PRIi32";", (int32_t)-65536); printf_logbuffer(&logbuf, "%"PRIu32";", (uint32_t)65536); printf_logbuffer(&logbuf, "%zd;", (ssize_t)-65536); printf_logbuffer(&logbuf, "%zu;", (size_t)65536); printf_logbuffer(&logbuf, "%g;", 2e100); printf_logbuffer(&logbuf, "%.0f;", (double)1234567); const char * result = "%str%-1;1;-256;256;-65536;65536;-65536;65536;2e+100;1234567;"; TEST(strlen(result) == logbuf.logsize); TEST(0 == memcmp(logbuf.addr, result, logbuf.logsize)); // TEST vprintf_logwriter: adds " ..." at end in case of truncated message char strtoobig[100]; memset(strtoobig, '1', sizeof(strtoobig)); logbuf.logsize = logbuf.size - sizeof(strtoobig); logbuf.addr[logbuf.logsize] = 0; printf_logbuffer(&logbuf, "%.100s", strtoobig); TEST(logbuf.logsize == logbuf.size - 1) TEST(0 == memcmp(logbuf.addr + logbuf.size - sizeof(strtoobig), strtoobig, sizeof(strtoobig)-5)); TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5)); // TEST vprintf_logbuffer: format == 0 logbuf.logsize = 0; printf_logbuffer(&logbuf, 0); // nothing printed TEST(0 == logbuf.logsize); // TEST vprintf_logbuffer: sizefree_logbuffer() == 0 logbuf.logsize = logbuf.size; memset(logbuf.addr, 255, logbuf.size); printf_logbuffer(&logbuf, "%d", 12345); // check logbuf not changed TEST(buffer == logbuf.addr); TEST(sizeof(buffer) == logbuf.size); TEST(sizeof(buffer) == logbuf.logsize); TEST(pipe.write == logbuf.io); // check content of logbuf not changed except for " ..." for (size_t i = 0; i < logbuf.logsize - 5; ++i) { TEST(255 == logbuf.addr[i]); } TEST(0 == memcmp(logbuf.addr + logbuf.logsize - 5, " ...", 4)); TEST(255 == logbuf.addr[logbuf.logsize-1]); // TEST vprintf_logbuffer: logbuffer_t.size <= 5 for (size_t s = 5; s <= 5; --s) { TEST(sizeof(buffer) == logbuf.size); logbuf.size = s; logbuf.logsize = 0; memset(logbuf.addr, 255, s); printf_logbuffer(&logbuf, "%d", 12345); // check logbuf TEST(buffer == logbuf.addr); TEST(s == logbuf.size); TEST((s?s-1:0) == logbuf.logsize); TEST(pipe.write == logbuf.io); // check content of logbuf if (s == 5) { // " ..." TEST(0 == memcmp(logbuf.addr, " ...", 5)); } else { // truncated 12345 for (size_t i = 0; i < logbuf.logsize; ++i) { TEST(i+'1' == logbuf.addr[i]); } TEST(0 == (logbuf.size ? logbuf.addr[logbuf.size-1] : 0)); } // reset logbuf.size = sizeof(buffer); } // unprepare TEST(-1 == read(pipe.read, readbuffer, sizeof(readbuffer))); TEST(0 == free_pipe(&pipe)); return 0; ONERR: delete_thread(&thread); free_pipe(&pipe); return EINVAL; }
int main_vcfquery(int argc, char *argv[]) { int c, collapse = 0; args_t *args = (args_t*) calloc(1,sizeof(args_t)); args->argc = argc; args->argv = argv; int regions_is_file = 0, targets_is_file = 0; static struct option loptions[] = { {"help",0,0,'h'}, {"list-samples",0,0,'l'}, {"include",1,0,'i'}, {"exclude",1,0,'e'}, {"format",1,0,'f'}, {"output-file",1,0,'o'}, {"regions",1,0,'r'}, {"regions-file",1,0,'R'}, {"targets",1,0,'t'}, {"targets-file",1,0,'T'}, {"annots",1,0,'a'}, {"samples",1,0,'s'}, {"samples-file",1,0,'S'}, {"print-header",0,0,'H'}, {"collapse",1,0,'c'}, {"vcf-list",1,0,'v'}, {"allow-undef-tags",0,0,'u'}, {0,0,0,0} }; while ((c = getopt_long(argc, argv, "hlr:R:f:a:s:S:Ht:T:c:v:i:e:o:u",loptions,NULL)) >= 0) { switch (c) { case 'o': args->fn_out = optarg; break; case 'f': args->format_str = strdup(optarg); break; case 'H': args->print_header = 1; break; case 'v': args->vcf_list = optarg; break; case 'c': if ( !strcmp(optarg,"snps") ) collapse |= COLLAPSE_SNPS; else if ( !strcmp(optarg,"indels") ) collapse |= COLLAPSE_INDELS; else if ( !strcmp(optarg,"both") ) collapse |= COLLAPSE_SNPS | COLLAPSE_INDELS; else if ( !strcmp(optarg,"any") ) collapse |= COLLAPSE_ANY; else if ( !strcmp(optarg,"all") ) collapse |= COLLAPSE_ANY; else if ( !strcmp(optarg,"some") ) collapse |= COLLAPSE_SOME; else error("The --collapse string \"%s\" not recognised.\n", optarg); break; case 'a': { kstring_t str = {0,0,0}; kputs("%CHROM\t%POS\t%MASK\t%REF\t%ALT\t%", &str); char *p = optarg; while ( *p ) { if ( *p==',' ) kputs("\t%", &str); else kputc(*p, &str); p++; } kputc('\n', &str); args->format_str = str.s; break; } case 'e': args->filter_str = optarg; args->filter_logic |= FLT_EXCLUDE; break; case 'i': args->filter_str = optarg; args->filter_logic |= FLT_INCLUDE; break; case 'r': args->regions_list = optarg; break; case 'R': args->regions_list = optarg; regions_is_file = 1; break; case 't': args->targets_list = optarg; break; case 'T': args->targets_list = optarg; targets_is_file = 1; break; case 'l': args->list_columns = 1; break; case 'u': args->allow_undef_tags = 1; break; case 's': args->sample_list = optarg; break; case 'S': args->sample_list = optarg; args->sample_is_file = 1; break; case 'h': case '?': usage(); default: error("Unknown argument: %s\n", optarg); } } char *fname = NULL; if ( optind>=argc ) { if ( !isatty(fileno((FILE *)stdin)) ) fname = "-"; } else fname = argv[optind]; if ( args->list_columns ) { if ( !fname ) error("Missing the VCF file name\n"); args->files = bcf_sr_init(); if ( !bcf_sr_add_reader(args->files, fname) ) error("Failed to open %s: %s\n", fname,bcf_sr_strerror(args->files->errnum)); list_columns(args); bcf_sr_destroy(args->files); free(args); return 0; } if ( !args->format_str ) usage(); args->out = args->fn_out ? fopen(args->fn_out, "w") : stdout; if ( !args->out ) error("%s: %s\n", args->fn_out,strerror(errno)); if ( !args->vcf_list ) { if ( !fname ) usage(); args->files = bcf_sr_init(); args->files->collapse = collapse; if ( optind+1 < argc ) args->files->require_index = 1; if ( args->regions_list && bcf_sr_set_regions(args->files, args->regions_list, regions_is_file)<0 ) error("Failed to read the regions: %s\n", args->regions_list); if ( args->targets_list ) { if ( bcf_sr_set_targets(args->files, args->targets_list, targets_is_file, 0)<0 ) error("Failed to read the targets: %s\n", args->targets_list); } while ( fname ) { if ( !bcf_sr_add_reader(args->files, fname) ) error("Failed to open %s: %s\n", fname,bcf_sr_strerror(args->files->errnum)); fname = ++optind < argc ? argv[optind] : NULL; } init_data(args); query_vcf(args); free(args->format_str); destroy_data(args); bcf_sr_destroy(args->files); fclose(args->out); free(args); return 0; } // multiple VCFs int i, k, nfiles, prev_nsamples = 0; char **fnames, **prev_samples = NULL; fnames = hts_readlist(args->vcf_list, 1, &nfiles); if ( !nfiles ) error("No files in %s?\n", args->vcf_list); for (i=0; i<nfiles; i++) { args->files = bcf_sr_init(); args->files->collapse = collapse; if ( args->regions_list && bcf_sr_set_regions(args->files, args->regions_list, regions_is_file)<0 ) error("Failed to read the regions: %s\n", args->regions_list); if ( optind < argc ) args->files->require_index = 1; if ( args->targets_list ) { if ( bcf_sr_set_targets(args->files, args->targets_list,targets_is_file, 0)<0 ) error("Failed to read the targets: %s\n", args->targets_list); } if ( !bcf_sr_add_reader(args->files, fnames[i]) ) error("Failed to open %s: %s\n", fnames[i],bcf_sr_strerror(args->files->errnum)); for (k=optind; k<argc; k++) if ( !bcf_sr_add_reader(args->files, argv[k]) ) error("Failed to open %s: %s\n", argv[k],bcf_sr_strerror(args->files->errnum)); init_data(args); if ( i==0 ) prev_samples = copy_header(args->header, args->files->readers[0].header->samples, bcf_hdr_nsamples(args->files->readers[0].header)); else { args->print_header = 0; if ( compare_header(args->header, args->files->readers[0].header->samples, bcf_hdr_nsamples(args->files->readers[0].header), prev_samples, prev_nsamples) ) error("Different samples in %s and %s\n", fnames[i-1],fnames[i]); } query_vcf(args); destroy_data(args); bcf_sr_destroy(args->files); } fclose(args->out); destroy_list(fnames, nfiles); destroy_list(prev_samples, prev_nsamples); free(args->format_str); free(args); return 0; }