1 /* test/hts_endian.c -- hts_endian.h unit tests
2
3 Copyright (C) 2017 Genome Research Ltd.
4
5 Author: Rob Davies <rmd@sanger.ac.uk>
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE. */
23
24 #include <config.h>
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include <inttypes.h>
31
32 #include "../htslib/hts_endian.h"
33
34 typedef struct {
35 uint8_t u8[2];
36 uint8_t u8_unaligned[3];
37 int16_t i16;
38 uint16_t u16;
39 } Test16;
40
41 typedef struct {
42 uint8_t u8[4];
43 uint8_t u8_unaligned[5];
44 int32_t i32;
45 uint32_t u32;
46 } Test32;
47
48 typedef struct {
49 uint8_t u8[8];
50 uint8_t u8_unaligned[9];
51 int64_t i64;
52 uint64_t u64;
53 } Test64;
54
55 typedef struct {
56 uint8_t u8[4];
57 uint8_t u8_unaligned[5];
58 float f;
59 } Test_float;
60
61 typedef struct {
62 uint8_t u8[8];
63 uint8_t u8_unaligned[9];
64 double d;
65 } Test_double;
66
67 #define T16(b0, b1, sgn, unsgn) { { b0, b1 }, { 0x00, b0, b1 }, sgn, unsgn }
68
69 Test16 tests_16_bit[] = {
70 T16(0x00, 0x00, 0, 0),
71 T16(0x01, 0x00, 1, 1),
72 T16(0x00, 0x01, 256, 256),
73 T16(0xff, 0x7f, 32767, 32767),
74 T16(0x00, 0x80, -32768, 32768),
75 T16(0xff, 0xff, -1, 65535),
76 };
77
78 #define T32(b0, b1, b2, b3, sgn, unsgn) { \
79 { b0, b1, b2, b3 }, \
80 { 0x00, b0, b1, b2, b3 }, \
81 sgn, unsgn \
82 }
83
84 Test32 tests_32_bit[] = {
85 T32(0x00, 0x00, 0x00, 0x00, 0, 0),
86 T32(0x01, 0x00, 0x00, 0x00, 1, 1),
87 T32(0x00, 0x01, 0x00, 0x00, 256, 256),
88 T32(0x00, 0x00, 0x01, 0x00, 65536, 65536),
89 T32(0xff, 0xff, 0xff, 0x7f, 2147483647, 2147483647),
90 // Odd coding of signed result below avoids a compiler warning
91 // as 2147483648 can't fit in a signed 32-bit number
92 T32(0x00, 0x00, 0x00, 0x80, -2147483647 - 1, 2147483648U),
93 T32(0xff, 0xff, 0xff, 0xff, -1, 4294967295U),
94 };
95
96 #define T64(b0, b1, b2, b3, b4, b5, b6, b7, sgn, unsgn) { \
97 { b0, b1, b2, b3, b4, b5, b6, b7 }, \
98 { 0x00, b0, b1, b2, b3, b4, b5, b6, b7 }, \
99 sgn, unsgn \
100 }
101
102
103 Test64 tests_64_bit[] = {
104 T64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0),
105 T64(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1, 1),
106 T64(0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 256, 256),
107 T64(0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 65536, 65536),
108 T64(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 4294967296LL, 4294967296ULL),
109 T64(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
110 9223372036854775807LL, 9223372036854775807ULL),
111 // Odd coding of signed result below avoids a compiler warning
112 // as 9223372036854775808 can't fit in a signed 64-bit number
113 T64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
114 -9223372036854775807LL - 1LL, 9223372036854775808ULL),
115 T64(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116 -1, 18446744073709551615ULL),
117 };
118
119 #define TF(b0, b1, b2, b3, f) { { b0, b1, b2, b3 }, { 0x00, b0, b1, b2, b3}, f }
120
121 Test_float tests_float[] = {
122 TF(0x00, 0x00, 0x00, 0x00, 0.0f),
123 TF(0x00, 0x00, 0x80, 0x3f, 1.0f),
124 TF(0x00, 0x00, 0x80, 0xbf, -1.0f),
125 TF(0x00, 0x00, 0x20, 0x41, 10.0f),
126 TF(0xd0, 0x0f, 0x49, 0x40, 3.14159f),
127 TF(0xa8, 0x0a, 0xff, 0x66, 6.022e23f),
128 TF(0xcd, 0x84, 0x03, 0x13, 1.66e-27f),
129 };
130
131 #define TD(b0, b1, b2, b3, b4, b5, b6, b7, d) { \
132 { b0, b1, b2, b3, b4, b5, b6, b7 }, \
133 { 0x00, b0, b1, b2, b3, b4, b5, b6, b7 }, \
134 d \
135 }
136
137 Test_double tests_double[] = {
138 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0.0),
139 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 1.0),
140 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, -1.0),
141 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 10.0),
142 TD(0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40, 3.141592653589793),
143 TD(0x2b, 0x08, 0x0c, 0xd3, 0x85, 0xe1, 0xdf, 0x44, 6.022140858e23),
144 TD(0x55, 0xfa, 0x81, 0x74, 0xf7, 0x71, 0x60, 0x3a, 1.66053904e-27),
145 };
146
147 #define NELE(x) (sizeof(x)/sizeof(x[0]))
148
to_hex(uint8_t * buf,int len)149 static char * to_hex(uint8_t *buf, int len) {
150 static char str[64];
151 int i, o;
152
153 for (i = 0, o = 0; i < len; i++, o += 3) {
154 snprintf(str + o, sizeof(str) - o, "%02x ", buf[i]);
155 }
156 return str;
157 }
158
t16_bit(int verbose)159 static int t16_bit(int verbose) {
160 uint8_t buf[9];
161 size_t i;
162 int errors = 0;
163
164 for (i = 0; i < NELE(tests_16_bit); i++) {
165 uint16_t u16;
166 int16_t i16;
167
168 if (verbose) {
169 fprintf(stderr, "%s %6"PRId16" %6"PRId16"\n",
170 to_hex(tests_16_bit[i].u8, 2),
171 tests_16_bit[i].i16, tests_16_bit[i].u16);
172 }
173
174 u16 = le_to_u16(tests_16_bit[i].u8);
175 if (u16 != tests_16_bit[i].u16) {
176 fprintf(stderr, "Failed %s => %"PRIu16"; expected %"PRIu16"\n",
177 to_hex(tests_16_bit[i].u8, 2), u16, tests_16_bit[i].u16);
178 errors++;
179 }
180
181 i16 = le_to_i16(tests_16_bit[i].u8);
182 if (i16 != tests_16_bit[i].i16) {
183 fprintf(stderr, "Failed %s => %"PRId16"; expected %"PRId16"\n",
184 to_hex(tests_16_bit[i].u8, 2), i16, tests_16_bit[i].i16);
185 errors++;
186 }
187
188 u16 = le_to_u16(tests_16_bit[i].u8_unaligned + 1);
189 if (u16 != tests_16_bit[i].u16) {
190 fprintf(stderr,
191 "Failed unaligned %s => %"PRIu16"; expected %"PRIu16"\n",
192 to_hex(tests_16_bit[i].u8_unaligned + 1, 2),
193 u16, tests_16_bit[i].u16);
194 errors++;
195 }
196
197 i16 = le_to_i16(tests_16_bit[i].u8_unaligned + 1);
198 if (i16 != tests_16_bit[i].i16) {
199 fprintf(stderr,
200 "Failed unaligned %s => %"PRId16"; expected %"PRId16"\n",
201 to_hex(tests_16_bit[i].u8_unaligned + 1, 2),
202 i16, tests_16_bit[i].i16);
203 errors++;
204 }
205
206 u16_to_le(tests_16_bit[i].u16, buf);
207 if (memcmp(buf, tests_16_bit[i].u8, 2) != 0) {
208 fprintf(stderr, "Failed %"PRIu16" => %s; expected %s\n",
209 tests_16_bit[i].u16,
210 to_hex(buf, 2), to_hex(tests_16_bit[i].u8, 2));
211 errors++;
212 }
213
214 i16_to_le(tests_16_bit[i].i16, buf);
215 if (memcmp(buf, tests_16_bit[i].u8, 2) != 0) {
216 fprintf(stderr, "Failed %"PRId16" => %s; expected %s\n",
217 tests_16_bit[i].i16,
218 to_hex(buf, 2), to_hex(tests_16_bit[i].u8, 2));
219 errors++;
220 }
221
222 u16_to_le(tests_16_bit[i].u16, buf + 1);
223 if (memcmp(buf + 1, tests_16_bit[i].u8, 2) != 0) {
224 fprintf(stderr, "Failed unaligned %"PRIu16" => %s; expected %s\n",
225 tests_16_bit[i].u16,
226 to_hex(buf + 1, 2), to_hex(tests_16_bit[i].u8, 2));
227 errors++;
228 }
229
230 i16_to_le(tests_16_bit[i].i16, buf + 1);
231 if (memcmp(buf + 1, tests_16_bit[i].u8, 2) != 0) {
232 fprintf(stderr, "Failed unaligned %"PRId16" => %s; expected %s\n",
233 tests_16_bit[i].i16,
234 to_hex(buf + 1, 2), to_hex(tests_16_bit[i].u8, 2));
235 errors++;
236 }
237 }
238
239 return errors;
240 }
241
t32_bit(int verbose)242 static int t32_bit(int verbose) {
243 uint8_t buf[9];
244 size_t i;
245 int errors = 0;
246
247 for (i = 0; i < NELE(tests_32_bit); i++) {
248 uint32_t u32;
249 int32_t i32;
250
251 if (verbose) {
252 fprintf(stderr, "%s %11"PRId32" %11"PRIu32"\n",
253 to_hex(tests_32_bit[i].u8, 4),
254 tests_32_bit[i].i32, tests_32_bit[i].u32);
255 }
256
257 u32 = le_to_u32(tests_32_bit[i].u8);
258 if (u32 != tests_32_bit[i].u32) {
259 fprintf(stderr, "Failed %s => %"PRIu32"; expected %"PRIu32"\n",
260 to_hex(tests_32_bit[i].u8, 4), u32, tests_32_bit[i].u32);
261 errors++;
262 }
263 i32 = le_to_i32(tests_32_bit[i].u8);
264 if (i32 != tests_32_bit[i].i32) {
265 fprintf(stderr, "Failed %s => %"PRId32"; expected %"PRId32"\n",
266 to_hex(tests_32_bit[i].u8, 4), i32, tests_32_bit[i].i32);
267 errors++;
268 }
269
270 u32 = le_to_u32(tests_32_bit[i].u8_unaligned + 1);
271 if (u32 != tests_32_bit[i].u32) {
272 fprintf(stderr,
273 "Failed unaligned %s => %"PRIu32"; expected %"PRIu32"\n",
274 to_hex(tests_32_bit[i].u8_unaligned + 1, 4),
275 u32, tests_32_bit[i].u32);
276 errors++;
277 }
278 i32 = le_to_i32(tests_32_bit[i].u8_unaligned + 1);
279 if (i32 != tests_32_bit[i].i32) {
280 fprintf(stderr,
281 "Failed unaligned %s => %"PRId32"; expected %"PRId32"\n",
282 to_hex(tests_32_bit[i].u8_unaligned + 1, 4),
283 i32, tests_32_bit[i].i32);
284 errors++;
285 }
286
287 u32_to_le(tests_32_bit[i].u32, buf);
288 if (memcmp(buf, tests_32_bit[i].u8, 4) != 0) {
289 fprintf(stderr, "Failed %"PRIu32" => %s; expected %s\n",
290 tests_32_bit[i].u32,
291 to_hex(buf, 4), to_hex(tests_32_bit[i].u8, 4));
292 errors++;
293 }
294
295 i32_to_le(tests_32_bit[i].i32, buf);
296 if (memcmp(buf, tests_32_bit[i].u8, 4) != 0) {
297 fprintf(stderr, "Failed %"PRId32" => %s; expected %s\n",
298 tests_32_bit[i].i32,
299 to_hex(buf, 4), to_hex(tests_32_bit[i].u8, 4));
300 errors++;
301 }
302
303 u32_to_le(tests_32_bit[i].u32, buf + 1);
304 if (memcmp(buf + 1, tests_32_bit[i].u8, 4) != 0) {
305 fprintf(stderr, "Failed unaligned %"PRIu32" => %s; expected %s\n",
306 tests_32_bit[i].u32,
307 to_hex(buf + 1, 4), to_hex(tests_32_bit[i].u8, 4));
308 errors++;
309 }
310
311 i32_to_le(tests_32_bit[i].i32, buf + 1);
312 if (memcmp(buf + 1, tests_32_bit[i].u8, 4) != 0) {
313 fprintf(stderr, "Failed unaligned %"PRId32" => %s; expected %s\n",
314 tests_32_bit[i].i32,
315 to_hex(buf + 1, 4), to_hex(tests_32_bit[i].u8, 4));
316 errors++;
317 }
318 }
319
320 return errors;
321 }
322
t64_bit(int verbose)323 static int t64_bit(int verbose) {
324 uint8_t buf[9];
325 size_t i;
326 int errors = 0;
327
328 for (i = 0; i < NELE(tests_64_bit); i++) {
329 uint64_t u64;
330 int64_t i64;
331
332 if (verbose) {
333 fprintf(stderr, "%s %20"PRId64" %20"PRIu64"\n",
334 to_hex(tests_64_bit[i].u8, 8),
335 tests_64_bit[i].i64, tests_64_bit[i].u64);
336 }
337
338 u64 = le_to_u64(tests_64_bit[i].u8);
339 if (u64 != tests_64_bit[i].u64) {
340 fprintf(stderr, "Failed %s => %"PRIu64"; expected %"PRIu64"\n",
341 to_hex(tests_64_bit[i].u8, 8), u64, tests_64_bit[i].u64);
342 errors++;
343 }
344
345 i64 = le_to_i64(tests_64_bit[i].u8);
346 if (i64 != tests_64_bit[i].i64) {
347 fprintf(stderr, "Failed %s => %"PRId64"; expected %"PRId64"\n",
348 to_hex(tests_64_bit[i].u8, 8), i64, tests_64_bit[i].i64);
349 errors++;
350 }
351
352 u64 = le_to_u64(tests_64_bit[i].u8_unaligned + 1);
353 if (u64 != tests_64_bit[i].u64) {
354 fprintf(stderr,
355 "Failed unaligned %s => %"PRIu64"; expected %"PRIu64"\n",
356 to_hex(tests_64_bit[i].u8_unaligned + 1, 8),
357 u64, tests_64_bit[i].u64);
358 errors++;
359 }
360
361 i64 = le_to_i64(tests_64_bit[i].u8_unaligned + 1);
362 if (i64 != tests_64_bit[i].i64) {
363 fprintf(stderr,
364 "Failed unaligned %s => %"PRId64"; expected %"PRId64"\n",
365 to_hex(tests_64_bit[i].u8_unaligned + 1, 8),
366 i64, tests_64_bit[i].i64);
367 errors++;
368 }
369
370 u64_to_le(tests_64_bit[i].u64, buf);
371 if (memcmp(buf, tests_64_bit[i].u8, 8) != 0) {
372 fprintf(stderr, "Failed %"PRIu64" => %s; expected %s\n",
373 tests_64_bit[i].u64,
374 to_hex(buf, 8), to_hex(tests_64_bit[i].u8, 8));
375 errors++;
376 }
377
378 i64_to_le(tests_64_bit[i].i64, buf);
379 if (memcmp(buf, tests_64_bit[i].u8, 8) != 0) {
380 fprintf(stderr, "Failed %"PRId64" => %s; expected %s\n",
381 tests_64_bit[i].i64,
382 to_hex(buf, 8), to_hex(tests_64_bit[i].u8, 8));
383 errors++;
384 }
385
386 u64_to_le(tests_64_bit[i].u64, buf + 1);
387 if (memcmp(buf + 1, tests_64_bit[i].u8, 8) != 0) {
388 fprintf(stderr, "Failed unaligned %"PRIu64" => %s; expected %s\n",
389 tests_64_bit[i].u64,
390 to_hex(buf + 1, 8), to_hex(tests_64_bit[i].u8, 8));
391 errors++;
392 }
393
394 i64_to_le(tests_64_bit[i].i64, buf + 1);
395 if (memcmp(buf + 1, tests_64_bit[i].u8, 8) != 0) {
396 fprintf(stderr, "Failed unaligned %"PRId64" => %s; expected %s\n",
397 tests_64_bit[i].i64,
398 to_hex(buf + 1, 8), to_hex(tests_64_bit[i].u8, 8));
399 errors++;
400 }
401 }
402
403 return errors;
404 }
405
t_float(int verbose)406 int t_float(int verbose) {
407 uint8_t buf[9];
408 size_t i;
409 int errors = 0;
410
411 for (i = 0; i < NELE(tests_float); i++) {
412 float f;
413
414 if (verbose) {
415 fprintf(stderr, "%s %g\n",
416 to_hex(tests_float[i].u8, 4), tests_float[i].f);
417 }
418
419 f = le_to_float(tests_float[i].u8);
420 if (f != tests_float[i].f) {
421 fprintf(stderr, "Failed %s => %g; expected %g\n",
422 to_hex(tests_float[i].u8, 4), f, tests_float[i].f);
423 errors++;
424 }
425
426 f = le_to_float(tests_float[i].u8_unaligned + 1);
427 if (f != tests_float[i].f) {
428 fprintf(stderr, "Failed unaligned %s => %g; expected %g\n",
429 to_hex(tests_float[i].u8_unaligned + 1, 4),
430 f, tests_float[i].f);
431 errors++;
432 }
433
434 float_to_le(tests_float[i].f, buf);
435 if (memcmp(tests_float[i].u8, buf, 4) != 0) {
436 fprintf(stderr, "Failed %g => %s; expected %s\n",
437 tests_float[i].f,
438 to_hex(buf, 4), to_hex(tests_float[i].u8, 4));
439 }
440
441 float_to_le(tests_float[i].f, buf + 1);
442 if (memcmp(tests_float[i].u8, buf + 1, 4) != 0) {
443 fprintf(stderr, "Failed unaligned %g => %s; expected %s\n",
444 tests_float[i].f,
445 to_hex(buf + 1, 4), to_hex(tests_float[i].u8, 4));
446 }
447 }
448 return errors;
449 }
450
t_double(int verbose)451 int t_double(int verbose) {
452 uint8_t buf[9];
453 size_t i;
454 int errors = 0;
455
456 for (i = 0; i < NELE(tests_double); i++) {
457 double f;
458
459 if (verbose) {
460 fprintf(stderr, "%s %.15g\n",
461 to_hex(tests_double[i].u8, 8), tests_double[i].d);
462 }
463
464 f = le_to_double(tests_double[i].u8);
465 if (f != tests_double[i].d) {
466 fprintf(stderr, "Failed %s => %.15g; expected %.15g\n",
467 to_hex(tests_double[i].u8, 8), f, tests_double[i].d);
468 errors++;
469 }
470
471 f = le_to_double(tests_double[i].u8_unaligned + 1);
472 if (f != tests_double[i].d) {
473 fprintf(stderr, "Failed unaligned %s => %.15g; expected %.15g\n",
474 to_hex(tests_double[i].u8_unaligned + 1, 8),
475 f, tests_double[i].d);
476 errors++;
477 }
478
479 double_to_le(tests_double[i].d, buf);
480 if (memcmp(tests_double[i].u8, buf, 8) != 0) {
481 fprintf(stderr, "Failed %.15g => %s; expected %s\n",
482 tests_double[i].d,
483 to_hex(buf, 8), to_hex(tests_double[i].u8, 8));
484 }
485
486 double_to_le(tests_double[i].d, buf + 1);
487 if (memcmp(tests_double[i].u8, buf + 1, 8) != 0) {
488 fprintf(stderr, "Failed unaligned %.15g => %s; expected %s\n",
489 tests_double[i].d,
490 to_hex(buf + 1, 8), to_hex(tests_double[i].u8, 8));
491 }
492 }
493 return errors;
494 }
495
main(int argc,char ** argv)496 int main(int argc, char **argv) {
497 int verbose = 0;
498 int errors = 0;
499
500 if (argc > 1 && strcmp(argv[1], "-v") == 0) verbose = 1;
501
502 errors += t16_bit(verbose);
503 errors += t32_bit(verbose);
504 errors += t64_bit(verbose);
505 errors += t_float(verbose);
506 errors += t_double(verbose);
507 if (errors) {
508 fprintf(stderr, "%d errors\n", errors);
509 return EXIT_FAILURE;
510 }
511
512 return EXIT_SUCCESS;
513 }
514