1 /* test/hfile.c -- Test cases for low-level input/output streams.
3 Copyright (C) 2013-2014, 2016 Genome Research Ltd.
5 Author: John Marshall <jm18@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. */
34 #include "htslib/hfile.h"
35 #include "htslib/hts_defs.h"
37 void HTS_NORETURN
fail(const char *format
, ...)
41 va_start(args
, format
);
42 vfprintf(stderr
, format
, args
);
44 if (err
!= 0) fprintf(stderr
, ": %s", strerror(err
));
45 fprintf(stderr
, "\n");
49 void check_offset(hFILE
*f
, off_t off
, const char *message
)
52 if (ret
< 0) fail("htell(%s)", message
);
53 if (ret
== off
) return;
55 fprintf(stderr
, "%s offset incorrect: expected %ld but got %ld\n",
56 message
, (long)off
, (long)ret
);
60 char *slurp(const char *filename
)
65 FILE *f
= fopen(filename
, "r");
66 if (f
== NULL
) fail("fopen(\"%s\", \"r\")", filename
);
67 if (fstat(fileno(f
), &sbuf
) != 0) fail("fstat(\"%s\")", filename
);
68 filesize
= sbuf
.st_size
;
70 text
= (char *) malloc(filesize
+ 1);
71 if (text
== NULL
) fail("malloc(text)");
73 if (fread(text
, 1, filesize
, f
) != filesize
) fail("fread");
76 text
[filesize
] = '\0';
83 void reopen(const char *infname
, const char *outfname
)
85 if (fin
) { if (hclose(fin
) != 0) fail("hclose(input)"); }
86 if (fout
) { if (hclose(fout
) != 0) fail("hclose(output)"); }
88 fin
= hopen(infname
, "r");
89 if (fin
== NULL
) fail("hopen(\"%s\")", infname
);
91 fout
= hopen(outfname
, "w");
92 if (fout
== NULL
) fail("hopen(\"%s\")", outfname
);
97 static const int size
[] = { 1, 13, 403, 999, 30000 };
105 reopen("vcf.c", "test/hfile1.tmp");
106 while ((c
= hgetc(fin
)) != EOF
) {
107 if (hputc(c
, fout
) == EOF
) fail("hputc");
109 if (herrno(fin
)) { errno
= herrno(fin
); fail("hgetc"); }
111 reopen("test/hfile1.tmp", "test/hfile2.tmp");
112 if (hpeek(fin
, buffer
, 50) < 0) fail("hpeek");
113 while ((n
= hread(fin
, buffer
, 17)) > 0) {
114 if (hwrite(fout
, buffer
, n
) != n
) fail("hwrite");
116 if (n
< 0) fail("hread");
118 reopen("test/hfile2.tmp", "test/hfile3.tmp");
119 while ((n
= hread(fin
, buffer
, sizeof buffer
)) > 0) {
120 if (hwrite(fout
, buffer
, n
) != n
) fail("hwrite");
121 if (hpeek(fin
, buffer
, 700) < 0) fail("hpeek");
123 if (n
< 0) fail("hread");
125 reopen("test/hfile3.tmp", "test/hfile4.tmp");
128 while ((n
= hread(fin
, buffer
, size
[i
++ % 5])) > 0) {
131 check_offset(fin
, off
, "pre-peek");
132 if (hputs(buffer
, fout
) == EOF
) fail("hputs");
133 if ((n
= hpeek(fin
, buffer
, size
[(i
+3) % 5])) < 0) fail("hpeek");
134 check_offset(fin
, off
, "post-peek");
136 if (n
< 0) fail("hread");
138 reopen("test/hfile4.tmp", "test/hfile5.tmp");
139 while (hgets(buffer
, 80, fin
) != NULL
) {
140 size_t l
= strlen(buffer
);
141 if (l
> 79) fail("hgets read %zu bytes, should be < 80", l
);
142 if (hwrite(fout
, buffer
, l
) != l
) fail("hwrite");
144 if (herrno(fin
)) fail("hgets");
146 reopen("test/hfile5.tmp", "test/hfile6.tmp");
147 n
= hread(fin
, buffer
, 200);
148 if (n
< 0) fail("hread");
149 else if (n
!= 200) fail("hread only got %d", (int)n
);
150 if (hwrite(fout
, buffer
, 1000) != 1000) fail("hwrite");
151 check_offset(fin
, 200, "input/first200");
152 check_offset(fout
, 1000, "output/first200");
154 if (hseek(fin
, 800, SEEK_CUR
) < 0) fail("hseek/cur");
155 check_offset(fin
, 1000, "input/seek");
156 for (off
= 1000; (n
= hread(fin
, buffer
, sizeof buffer
)) > 0; off
+= n
)
157 if (hwrite(fout
, buffer
, n
) != n
) fail("hwrite");
158 if (n
< 0) fail("hread");
159 check_offset(fin
, off
, "input/eof");
160 check_offset(fout
, off
, "output/eof");
162 if (hseek(fin
, 200, SEEK_SET
) < 0) fail("hseek/set");
163 if (hseek(fout
, 200, SEEK_SET
) < 0) fail("hseek(output)");
164 check_offset(fin
, 200, "input/backto200");
165 check_offset(fout
, 200, "output/backto200");
166 n
= hread(fin
, buffer
, 800);
167 if (n
< 0) fail("hread");
168 else if (n
!= 800) fail("hread only got %d", (int)n
);
169 if (hwrite(fout
, buffer
, 800) != 800) fail("hwrite");
170 check_offset(fin
, 1000, "input/wrote800");
171 check_offset(fout
, 1000, "output/wrote800");
173 if (hflush(fout
) == EOF
) fail("hflush");
175 original
= slurp("vcf.c");
176 for (i
= 1; i
<= 6; i
++) {
178 sprintf(buffer
, "test/hfile%d.tmp", i
);
179 text
= slurp(buffer
);
180 if (strcmp(original
, text
) != 0) {
181 fprintf(stderr
, "%s differs from vcf.c\n", buffer
);
188 if (hclose(fin
) != 0) fail("hclose(input)");
189 if (hclose(fout
) != 0) fail("hclose(output)");
191 fout
= hopen("test/hfile_chars.tmp", "w");
192 if (fout
== NULL
) fail("hopen(\"test/hfile_chars.tmp\")");
193 for (i
= 0; i
< 256; i
++)
194 if (hputc(i
, fout
) != i
) fail("chars: hputc (%d)", i
);
195 if (hclose(fout
) != 0) fail("hclose(test/hfile_chars.tmp)");
197 fin
= hopen("test/hfile_chars.tmp", "r");
198 if (fin
== NULL
) fail("hopen(\"test/hfile_chars.tmp\") for reading");
199 for (i
= 0; i
< 256; i
++)
200 if ((c
= hgetc(fin
)) != i
)
201 fail("chars: hgetc (%d = 0x%x) returned %d = 0x%x", i
, i
, c
, c
);
202 if ((c
= hgetc(fin
)) != EOF
) fail("chars: hgetc (EOF) returned %d", c
);
203 if (hclose(fin
) != 0) fail("hclose(test/hfile_chars.tmp) for reading");
205 fin
= hopen("data:,hello, world!%0A", "r");
206 if (fin
== NULL
) fail("hopen(\"data:...\")");
207 n
= hread(fin
, buffer
, 300);
208 if (n
< 0) fail("hread");
210 if (strcmp(buffer
, "hello, world!\x0A") != 0) fail("hread result");
211 if (hclose(fin
) != 0) fail("hclose(\"data:...\")");
213 fin
= hopen("test/xx#blank.sam", "r");
214 if (fin
== NULL
) fail("hopen(\"test/xx#blank.sam\") for reading");
215 if (hread(fin
, buffer
, 100) != 0) fail("test/xx#blank.sam is non-empty");
216 if (hclose(fin
) != 0) fail("hclose(\"test/xx#blank.sam\") for reading");
218 fin
= hopen("data:,", "r");
219 if (fin
== NULL
) fail("hopen(\"data:\") for reading");
220 if (hread(fin
, buffer
, 100) != 0) fail("empty data: URL is non-empty");
221 if (hclose(fin
) != 0) fail("hclose(\"data:\") for reading");
223 fin
= hopen("data:;base64,"
224 // Wikipedia's example quote from Thomas Hobbes' Leviathan
225 "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
226 "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
227 "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu"
228 "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
229 "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=", "r");
230 if (fin
== NULL
) fail("hopen(\"data:;base64,...\")");
231 n
= hread(fin
, buffer
, 300);
232 if (n
< 0) fail("hread for base64");
234 if (strcmp(buffer
, "Man is distinguished, not only by his reason, but by "
235 "this singular passion from other animals, which is a lust of the mind, that "
236 "by a perseverance of delight in the continued and indefatigable generation "
237 "of knowledge, exceeds the short vehemence of any carnal pleasure.") != 0)
238 fail("hread result for base64");
239 if (hclose(fin
) != 0) fail("hclose(\"data:;base64,...\")");