modified: src1/input.c
[GalaxyCodeBases.git] / c_cpp / lib / htslib / test / test_bgzf.c
blobe34b22f014602ba5ebf32312089c816aa9ecbd44
1 /* test/test_bgzf.c -- bgzf unit tests
3 Copyright (C) 2017 Genome Research Ltd
5 Author: Robert Davies <rmd@sanger.ac.uk>
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 DEALINGS IN THE SOFTWARE.
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include "htslib/bgzf.h"
34 #include "htslib/hfile.h"
36 const char *bgzf_suffix = ".gz";
37 const char *idx_suffix = ".gzi";
38 const char *tmp_suffix = ".tmp";
40 #define BUFSZ 32768
42 typedef struct {
43 char *src_plain;
44 char *src_bgzf;
45 char *src_idx;
46 char *tmp_bgzf;
47 char *tmp_idx;
48 FILE *f_plain;
49 FILE *f_bgzf;
50 FILE *f_idx;
51 const unsigned char *text;
52 size_t ltext;
53 } Files;
55 typedef enum {
56 USE_BGZF_OPEN,
57 USE_BGZF_DOPEN,
58 USE_BGZF_HOPEN
59 } Open_method;
61 static FILE * try_fopen(const char *name, const char *mode) {
62 FILE *f = fopen(name, mode);
63 if (!f) {
64 fprintf(stderr, "Couldn't open %s : %s\n", name, strerror(errno));
65 return NULL;
67 return f;
70 static int try_fclose(FILE **file, const char *name, const char *func) {
71 FILE *to_close = *file;
72 *file = NULL;
73 if (fclose(to_close) != 0) {
74 fprintf(stderr, "%s : Error on closing %s : %s\n",
75 func, name, strerror(errno));
76 return -1;
79 return 0;
82 static ssize_t try_fread(FILE *in, void *buf, size_t len,
83 const char *func, const char *fname) {
84 size_t got = fread(buf, 1, len, in);
85 if (got == 0 && ferror(in)) {
86 fprintf(stderr, "%s : Error reading from %s : %s\n",
87 func, fname, strerror(errno));
88 return -1;
90 return got;
93 static int try_fseek_start(FILE *f, const char *name, const char *func) {
94 if (0 != fseek(f, 0, SEEK_SET)) {
95 fprintf(stderr, "%s : Couldn't seek on %s : %s\n",
96 func, name, strerror(errno));
97 return -1;
99 return 0;
102 static BGZF * try_bgzf_open(const char *name, const char *mode,
103 const char *func) {
104 BGZF * bgz = bgzf_open(name, mode);
105 if (!bgz) {
106 fprintf(stderr, "%s : Couldn't bgzf_open %s with mode %s : %s\n",
107 func, name, mode, strerror(errno));
108 return NULL;
110 return bgz;
113 static BGZF * try_bgzf_dopen(const char *name, const char *mode,
114 const char *func) {
115 BGZF *bgz = NULL;
116 int fd = -1;
117 if (strchr(mode, 'r')) {
118 fd = open(name, O_RDONLY);
119 } else if (strchr(mode, 'w')) {
120 fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
121 } else if (strchr(mode, 'a')) {
122 fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666);
123 } else {
124 errno = EINVAL;
127 if (fd < 0) {
128 fprintf(stderr, "%s : Failed to open %s with mode %s : %s\n",
129 func, name, mode, strerror(errno));
130 return NULL;
133 bgz = bgzf_dopen(fd, mode);
134 if (!bgz) {
135 fprintf(stderr, "%s : bgzf_dopen failed on %s mode %s : %s\n",
136 func, name, mode, strerror(errno));
137 close(fd);
138 return NULL;
141 return bgz;
144 static BGZF * try_bgzf_hopen(const char *name, const char *mode,
145 const char *func) {
146 hFILE *hfp = hopen(name, mode);
147 BGZF *bgz = NULL;
149 if (!hfp) {
150 fprintf(stderr, "%s : hopen failed on %s mode %s : %s\n",
151 func, name, mode, strerror(errno));
152 return NULL;
155 bgz = bgzf_hopen(hfp, mode);
156 if (!bgz) {
157 fprintf(stderr, "%s : bgzf_hopen failed on %s mode %s : %s\n",
158 func, name, mode, strerror(errno));
159 hclose_abruptly(hfp);
160 return NULL;
163 return bgz;
166 static int try_bgzf_close(BGZF **bgz, const char *name, const char *func) {
167 BGZF *to_close = *bgz;
168 *bgz = NULL;
169 if (bgzf_close(to_close) != 0) {
170 fprintf(stderr, "%s : bgzf_close failed on %s : %s\n",
171 func, name, strerror(errno));
172 return -1;
174 return 0;
177 static ssize_t try_bgzf_read(BGZF *fp, void *data, size_t length,
178 const char *name, const char *func) {
179 ssize_t got = bgzf_read(fp, data, length);
180 if (got < 0) {
181 fprintf(stderr, "%s : Error from bgzf_read %s : %s\n",
182 func, name, strerror(errno));
184 return got;
187 static ssize_t try_bgzf_write(BGZF *fp, const void *data, size_t length,
188 const char *name, const char *func) {
189 ssize_t put = bgzf_write(fp, data, length);
190 if (put < (ssize_t) length) {
191 fprintf(stderr, "%s : %s %s : %s\n",
192 func, put < 0 ? "Error writing to" : "Short write on",
193 name, strerror(errno));
194 return -1;
197 return put;
200 static int try_bgzf_compression(BGZF *fp, int expect,
201 const char *name, const char *func) {
202 int res = bgzf_compression(fp);
203 if (res != expect) {
204 fprintf(stderr,
205 "%s : Unexpected result %d from bgzf_compression on %s; "
206 "expected %d\n",
207 func, res, name, expect);
208 return -1;
210 return 0;
213 static int try_bgzf_mt(BGZF *bgz, int nthreads, const char *func) {
214 if (bgzf_mt(bgz, nthreads, 64) != 0) {
215 fprintf(stderr, "%s : Error from bgzf_mt : %s\n",
216 func, strerror(errno));
217 return -1;
219 return 0;
222 static int try_bgzf_index_build_init(BGZF *bgz,
223 const char *name, const char *func) {
224 if (bgzf_index_build_init(bgz) != 0) {
225 fprintf(stderr, "%s : Error from bgzf_index_build_init on %s : %s\n",
226 func, name, strerror(errno));
227 return -1;
229 return 0;
232 static int try_bgzf_index_load(BGZF *fp, const char *bname, const char *suffix,
233 const char *func) {
234 if (bgzf_index_load(fp, bname, suffix) != 0) {
235 fprintf(stderr, "%s : Couldn't bgzf_index_load %s%s : %s\n",
236 func, bname, suffix ? suffix : "", strerror(errno));
237 return -1;
239 return 0;
242 static int try_bgzf_index_dump(BGZF *fp, const char *bname, const char *suffix,
243 const char *func) {
244 if (bgzf_index_dump(fp, bname, suffix) != 0) {
245 fprintf(stderr, "%s : Couldn't bgzf_index_dump %s%s : %s\n",
246 func, bname, suffix ? suffix : "", strerror(errno));
247 return -1;
249 return 0;
252 static int try_bgzf_useek(BGZF *fp, long uoffset, int where,
253 const char *name, const char *func) {
254 if (bgzf_useek(fp, uoffset, where) < 0) {
255 fprintf(stderr, "%s : Error from bgzf_useek(%s, %ld, %d) : %s\n",
256 func, name, uoffset, where, strerror(errno));
257 return -1;
259 return 0;
262 static int try_bgzf_getc(BGZF *fp, size_t pos, int expected,
263 const char *name, const char *func) {
264 int c = bgzf_getc(fp);
265 if (c != expected) {
266 fprintf(stderr,
267 "%s : Unexpected value (%d) from bgzf_getc on %s pos %zu; "
268 "expected %d\n",
269 func, c, name, pos, expected);
270 return -1;
272 return c;
275 static int compare_buffers(const unsigned char *b1, const unsigned char *b2,
276 size_t l1, size_t l2,
277 const char *name1, const char *name2,
278 const char *func) {
279 if (l1 != l2) {
280 fprintf(stderr, "%s : EOF on %s\n", func, l1 < l2 ? name1 : name2);
281 return -1;
283 if (memcmp(b1, b2, l1) != 0) {
284 fprintf(stderr, "%s : difference between %s and %s\n",
285 func, name1, name2);
286 return -1;
289 return 0;
292 static void cleanup(Files *f, int retval) {
293 /* Remove temp files if successful. If not, leave them for inspection */
294 if (retval == EXIT_SUCCESS) {
295 unlink(f->tmp_bgzf);
296 unlink(f->tmp_idx);
298 if (f->f_plain) fclose(f->f_plain);
299 if (f->f_bgzf) fclose(f->f_bgzf);
300 if (f->f_idx) fclose(f->f_idx);
301 free(f->src_plain);
302 free((unsigned char *) f->text);
305 static int setup(const char *src, Files *f) {
306 size_t len = (strlen(src) + strlen(bgzf_suffix) + strlen(idx_suffix)
307 + strlen(tmp_suffix) + 8);
308 char *mem, *text;
309 const unsigned int max = 50000;
310 unsigned int i;
311 size_t text_sz = max * 8 + 1;
313 mem = calloc(5, len);
314 if (mem == NULL) {
315 perror(__func__);
316 return -1;
319 snprintf(mem, len, "%s", src);
320 snprintf(mem + len * 1, len, "%s%s", src, bgzf_suffix);
321 snprintf(mem + len * 2, len, "%s%s%s", src, bgzf_suffix, idx_suffix);
322 snprintf(mem + len * 3, len, "%s%s%s", src, tmp_suffix, bgzf_suffix);
323 snprintf(mem + len * 4, len, "%s%s%s%s",
324 src, tmp_suffix, bgzf_suffix, idx_suffix);
326 f->src_plain = mem;
327 f->src_bgzf = mem + len * 1;
328 f->src_idx = mem + len * 2;
329 f->tmp_bgzf = mem + len * 3;
330 f->tmp_idx = mem + len * 4;
332 text = malloc(text_sz);
333 if (!text) {
334 perror(__func__);
335 goto fail;
337 for (i = 0; i < max; i++) snprintf(text + i*8, text_sz - i*8, "%07d\n", i);
338 f->text = (unsigned char *) text;
339 f->ltext = text_sz - 1;
341 if ((f->f_plain = try_fopen(f->src_plain, "rb")) == NULL) goto fail;
342 if ((f->f_bgzf = try_fopen(f->src_bgzf, "rb")) == NULL) goto fail;
343 if ((f->f_idx = try_fopen(f->src_idx, "rb")) == NULL) goto fail;
345 return 0;
347 fail:
348 return -1;
351 static int test_read(Files *f) {
352 BGZF* bgz;
353 ssize_t bg_got, f_got;
354 unsigned char bg_buf[BUFSZ], f_buf[BUFSZ];
356 bgz = try_bgzf_open(f->src_bgzf, "r", __func__);
357 if (!bgz) return -1;
359 do {
360 bg_got = try_bgzf_read(bgz, bg_buf, BUFSZ, f->src_bgzf, __func__);
361 if (bg_got < 0) goto fail;
363 f_got = try_fread(f->f_plain, f_buf, BUFSZ, __func__, f->src_plain);
364 if (f_got < 0) goto fail;
366 if (compare_buffers(f_buf, bg_buf, f_got, bg_got,
367 f->src_plain, f->src_bgzf, __func__) != 0) {
368 goto fail;
370 } while (bg_got > 0 && f_got > 0);
372 if (try_bgzf_close(&bgz, f->src_bgzf, __func__) != 0) return -1;
373 if (try_fseek_start(f->f_plain, f->src_plain, __func__) != 0) return -1;
375 return 0;
377 fail:
378 if (bgz) bgzf_close(bgz);
379 return -1;
382 static int test_write_read(Files *f, const char *mode, Open_method method,
383 int nthreads, int expected_compression) {
384 BGZF* bgz = NULL;
385 ssize_t bg_put, bg_got;
386 size_t pos = 0;
387 unsigned char bg_buf[BUFSZ];
389 switch (method) {
390 case USE_BGZF_DOPEN:
391 bgz = try_bgzf_dopen(f->tmp_bgzf, mode, __func__);
392 break;
393 case USE_BGZF_HOPEN:
394 bgz = try_bgzf_hopen(f->tmp_bgzf, mode, __func__);
395 break;
396 default:
397 bgz = try_bgzf_open(f->tmp_bgzf, mode, __func__);
398 break;
400 if (!bgz) goto fail;
402 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
404 bg_put = try_bgzf_write(bgz, f->text, f->ltext, f->tmp_bgzf, __func__);
405 if (bg_put < 0) goto fail;
407 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
409 switch (method) {
410 case USE_BGZF_DOPEN:
411 bgz = try_bgzf_dopen(f->tmp_bgzf, "r", __func__);
412 break;
413 case USE_BGZF_HOPEN:
414 bgz = try_bgzf_hopen(f->tmp_bgzf, "r", __func__);
415 break;
416 default:
417 bgz = try_bgzf_open(f->tmp_bgzf, "r", __func__);
418 break;
420 if (!bgz) goto fail;
422 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
424 if (try_bgzf_compression(bgz, expected_compression,
425 f->tmp_bgzf, __func__) != 0) {
426 goto fail;
429 do {
430 bg_got = try_bgzf_read(bgz, bg_buf, BUFSZ, f->tmp_bgzf, __func__);
431 if (bg_got < 0) goto fail;
433 if (pos < f->ltext &&
434 memcmp(f->text + pos, bg_buf,
435 pos + bg_got < f->ltext ? bg_got : f->ltext - pos) != 0) {
436 fprintf(stderr, "%s : Got wrong data from %s, pos %zu\n",
437 __func__, f->tmp_bgzf, pos);
438 goto fail;
440 pos += bg_got;
441 } while (bg_got > 0);
443 if (pos != bg_put) {
444 fprintf(stderr, "%s : bgzf_read got %zd bytes; expected %zd\n",
445 __func__, pos, bg_put);
446 goto fail;
449 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
451 return 0;
453 fail:
454 if (bgz) bgzf_close(bgz);
455 return -1;
458 static int test_embed_eof(Files *f, const char *mode, int nthreads) {
459 BGZF* bgz = NULL;
460 ssize_t bg_put, bg_got;
461 size_t pos = 0, half = BUFSZ < f->ltext ? BUFSZ : f->ltext / 2;
462 char append_mode[16];
463 unsigned char bg_buf[BUFSZ];
465 for (pos = 0; pos < sizeof(append_mode) - 1 && mode[pos] != 0; pos++) {
466 append_mode[pos] = mode[pos] == 'w' ? 'a' : mode[pos];
468 append_mode[pos] ='\0';
470 // Write first half
471 bgz = try_bgzf_open(f->tmp_bgzf, mode, __func__);
472 if (!bgz) goto fail;
474 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
476 bg_put = try_bgzf_write(bgz, f->text, half, f->tmp_bgzf, __func__);
477 if (bg_put < 0) goto fail;
479 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
482 // Write second half. Append mode, so an EOF block should be in the
483 // middle.
484 bgz = try_bgzf_open(f->tmp_bgzf, append_mode, __func__);
485 if (!bgz) goto fail;
487 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
489 bg_put = try_bgzf_write(bgz, f->text + half, f->ltext - half, f->tmp_bgzf,
490 __func__);
491 if (bg_put < 0) goto fail;
493 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
495 // Try reading
496 pos = 0;
497 bgz = try_bgzf_open(f->tmp_bgzf, "r", __func__);
498 if (!bgz) goto fail;
500 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
502 do {
503 bg_got = try_bgzf_read(bgz, bg_buf, BUFSZ, f->tmp_bgzf, __func__);
504 if (bg_got < 0) goto fail;
506 if (pos < f->ltext &&
507 memcmp(f->text + pos, bg_buf,
508 pos + bg_got < f->ltext ? bg_got : f->ltext - pos) != 0) {
509 fprintf(stderr, "%s : Got wrong data from %s, pos %zu\n",
510 __func__, f->tmp_bgzf, pos);
511 goto fail;
513 pos += bg_got;
514 } while (bg_got > 0);
516 if (pos != f->ltext) {
517 fprintf(stderr, "%s : bgzf_read got %zd bytes; expected %zd\n",
518 __func__, pos, f->ltext);
519 goto fail;
522 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
524 return 0;
526 fail:
527 if (bgz) bgzf_close(bgz);
528 return -1;
531 static int test_index_load_dump(Files *f) {
532 BGZF* bgz = NULL;
533 FILE *fdest = NULL;
534 unsigned char buf_src[BUFSZ], buf_dest[BUFSZ];
535 ssize_t got_src, got_dest;
537 bgz = try_bgzf_open(f->src_bgzf, "r", __func__);
538 if (!bgz) return -1;
540 if (try_bgzf_index_load(bgz, f->src_bgzf, idx_suffix, __func__) != 0) {
541 goto fail;
544 if (try_bgzf_index_dump(bgz, f->tmp_bgzf, idx_suffix, __func__) != 0) {
545 goto fail;
548 fdest = try_fopen(f->tmp_idx, "r");
549 do {
550 got_src = try_fread(f->f_idx, buf_src, BUFSZ, __func__, f->src_idx);
551 if (got_src < 0) goto fail;
552 got_dest = try_fread(fdest, buf_dest, BUFSZ, __func__, f->tmp_idx);
553 if (got_dest < 0) goto fail;
554 if (compare_buffers(buf_src, buf_dest, got_src, got_dest,
555 f->src_idx, f->tmp_idx, __func__) != 0) goto fail;
556 } while (got_src > 0 && got_dest > 0);
557 if (try_fclose(&fdest, f->tmp_idx, __func__) != 0) goto fail;
559 if (try_bgzf_close(&bgz, f->src_bgzf, __func__) != 0) goto fail;
561 return 0;
563 fail:
564 if (fdest) fclose(fdest);
565 if (bgz) bgzf_close(bgz);
566 return -1;
569 static int test_check_EOF(char *name, int expected) {
570 BGZF *bgz = try_bgzf_open(name, "r", __func__);
571 int eof;
572 if (!bgz) return -1;
573 eof = bgzf_check_EOF(bgz);
574 if (eof != expected) {
575 fprintf(stderr, "%s : Unexpected result %d from bgzf_check_EOF on %s; "
576 "expected %d\n",
577 __func__, eof, name, expected);
578 bgzf_close(bgz);
579 return -1;
582 return try_bgzf_close(&bgz, name, __func__);
585 static int test_index_seek_getc(Files *f, const char *mode,
586 int cache_size, int nthreads) {
587 BGZF* bgz = NULL;
588 ssize_t bg_put;
589 size_t i, j, iskip = f->ltext / 10;
590 int is_uncompressed = strchr(mode, 'u') != NULL;
592 bgz = try_bgzf_open(f->tmp_bgzf, mode, __func__);
593 if (!bgz) goto fail;
595 if (try_bgzf_index_build_init(bgz, f->tmp_bgzf, __func__) != 0) goto fail;
597 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
599 bg_put = try_bgzf_write(bgz, f->text, f->ltext, f->tmp_bgzf, __func__);
600 if (bg_put < 0) goto fail;
602 if (!is_uncompressed) {
603 if (try_bgzf_index_dump(bgz, f->tmp_idx, NULL, __func__) != 0) {
604 goto fail;
608 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
610 bgz = try_bgzf_open(f->tmp_bgzf, "r", __func__);
611 if (!bgz) goto fail;
613 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
615 if (!is_uncompressed) {
616 if (try_bgzf_index_load(bgz, f->tmp_bgzf, idx_suffix, __func__) != 0) {
617 goto fail;
621 for (i = 0; i < f->ltext; i += iskip) {
622 if (try_bgzf_useek(bgz, i, SEEK_SET, f->tmp_bgzf, __func__) != 0) {
623 goto fail;
626 for (j = 0; j < 16 && i + j < f->ltext; j++) {
627 if (try_bgzf_getc(bgz, i + j, f->text[i + j],
628 f->tmp_bgzf, __func__) < 0) goto fail;
632 if (try_bgzf_useek(bgz, 0, SEEK_SET, f->tmp_bgzf, __func__) != 0) {
633 goto fail;
635 for (j = 0; j < 70000 && j < f->ltext; j++) { // Should force a block load
636 if (try_bgzf_getc(bgz, j, f->text[j],
637 f->tmp_bgzf, __func__) < 0) goto fail;
640 if (cache_size > 0) {
641 size_t mid = f->ltext / 2;
642 bgzf_set_cache_size(bgz, cache_size);
644 for (i = 0; i < 10; i++) {
645 if (try_bgzf_useek(bgz, 0, SEEK_SET, f->tmp_bgzf, __func__) != 0) {
646 goto fail;
648 for (j = 0; j < 64 && j < f->ltext; j++) {
649 if (try_bgzf_getc(bgz, j, f->text[j],
650 f->tmp_bgzf, __func__) < 0) goto fail;
653 if (try_bgzf_useek(bgz, mid, SEEK_SET,
654 f->tmp_bgzf, __func__) != 0) {
655 goto fail;
657 for (j = 0; j < 64 && j + mid < f->ltext; j++) {
658 if (try_bgzf_getc(bgz, j + mid, f->text[j + mid],
659 f->tmp_bgzf, __func__) < 0) goto fail;
664 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
666 return 0;
668 fail:
669 if (bgz) bgzf_close(bgz);
670 return -1;
673 static int test_bgzf_getline(Files *f, const char *mode, int nthreads) {
674 BGZF* bgz = NULL;
675 ssize_t bg_put;
676 size_t pos;
677 kstring_t str = { 0, 0, NULL };
678 const char *text = (const char *) f->text;
680 bgz = try_bgzf_open(f->tmp_bgzf, mode, __func__);
681 if (!bgz) goto fail;
683 if (nthreads > 0 && try_bgzf_mt(bgz, nthreads, __func__) != 0) goto fail;
685 bg_put = try_bgzf_write(bgz, f->text, f->ltext, f->tmp_bgzf, __func__);
686 if (bg_put < 0) goto fail;
688 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
690 bgz = try_bgzf_open(f->tmp_bgzf, "r", __func__);
691 if (!bgz) goto fail;
693 for (pos = 0; pos < f->ltext; ) {
694 const char *end = strchr(text + pos, '\n');
695 size_t l = end ? end - (text + pos) : f->ltext - pos;
696 int res;
698 if ((res = bgzf_getline(bgz, '\n', &str)) < 0) {
699 fprintf(stderr, "%s : %s from bgzf_getline on %s : %s\n",
700 __func__, res < -1 ? "Error" : "Unexpected EOF",
701 f->tmp_bgzf, res < -1 ? strerror(errno) : "EOF");
702 goto fail;
705 if (str.l != l || memcmp(text + pos, str.s, l) != 0) {
706 fprintf(stderr,
707 "%s : Unexpected data from bgzf_getline on %s\n"
708 "Expected : %.*s\n"
709 "Got : %.*s\n",
710 __func__, f->tmp_bgzf, (int) l, (char *) f->text + pos,
711 (int) str.l, str.s);
714 pos += l + 1;
717 if (try_bgzf_close(&bgz, f->tmp_bgzf, __func__) != 0) goto fail;
718 return 0;
720 fail:
721 if (bgz) bgzf_close(bgz);
722 return -1;
725 int main(int argc, char **argv) {
726 Files f = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 };
727 int retval = EXIT_FAILURE;
729 if (argc != 2) {
730 fprintf(stderr, "Usage: %s <source file>\n", argv[0]);
731 return EXIT_FAILURE;
734 if (setup(argv[1], &f) != 0) goto out;
736 // Try reading an existing file
737 if (test_check_EOF(f.src_bgzf, 1) != 0) goto out;
738 if (test_read(&f) != 0) goto out;
740 // Try writing some data and reading it back
741 if (test_write_read(&f, "wu", USE_BGZF_OPEN, 0, 0) != 0) goto out;
742 if (test_check_EOF(f.tmp_bgzf, 0) != 0) goto out;
743 if (test_write_read(&f, "w", USE_BGZF_OPEN, 0, 2) != 0) goto out;
744 if (test_check_EOF(f.tmp_bgzf, 1) != 0) goto out;
745 if (test_write_read(&f, "w0", USE_BGZF_OPEN, 0, 2) != 0) goto out;
746 if (test_check_EOF(f.tmp_bgzf, 1) != 0) goto out;
747 if (test_write_read(&f, "w1", USE_BGZF_DOPEN, 0, 2) != 0) goto out;
748 if (test_check_EOF(f.tmp_bgzf, 1) != 0) goto out;
749 if (test_write_read(&f, "w9", USE_BGZF_HOPEN, 0, 2) != 0) goto out;
750 if (test_check_EOF(f.tmp_bgzf, 1) != 0) goto out;
751 if (test_write_read(&f, "wg", USE_BGZF_OPEN, 0, 1) != 0) goto out;
752 if (test_check_EOF(f.tmp_bgzf, 0) != 0) goto out;
754 // Try writing and reading with threads
755 if (test_write_read(&f, "w", USE_BGZF_OPEN, 1, 2) != 0) goto out;
756 if (test_check_EOF(f.tmp_bgzf, 1) != 0) goto out;
757 if (test_write_read(&f, "w", USE_BGZF_OPEN, 2, 2) != 0) goto out;
758 if (test_check_EOF(f.tmp_bgzf, 1) != 0) goto out;
760 // Embedded EOF block
761 if (test_embed_eof(&f, "w", 0) != 0) goto out;
762 if (test_embed_eof(&f, "w", 1) != 0) goto out;
763 if (test_embed_eof(&f, "w", 2) != 0) goto out;
765 // Index load and dump
766 if (test_index_load_dump(&f) != 0) goto out;
768 // Index building on the fly and bgzf_useek
769 if (test_index_seek_getc(&f, "w", 1000000, 0) != 0) goto out;
771 // Index building on the fly and bgzf_useek, with threads
772 // ** Not implemented yet **
773 // if (test_index_seek_getc(&f, "w", 1000000, 1) != 0) goto out;
774 // if (test_index_seek_getc(&f, "w", 1000000, 2) != 0) goto out;
776 // bgzf_useek on an uncompressed file
777 if (test_index_seek_getc(&f, "wu", 0, 0) != 0) goto out;
779 // getline
780 if (test_bgzf_getline(&f, "w", 0) != 0) goto out;
781 if (test_bgzf_getline(&f, "w", 1) != 0) goto out;
782 if (test_bgzf_getline(&f, "w", 2) != 0) goto out;
784 retval = EXIT_SUCCESS;
786 out:
787 cleanup(&f, retval);
788 return retval;