1 /* test/hts_endian.c -- hts_endian.h unit tests
3 Copyright (C) 2017 Genome Research Ltd.
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:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
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. */
29 #include "htslib/hts_endian.h"
33 uint8_t u8_unaligned
[3];
40 uint8_t u8_unaligned
[5];
47 uint8_t u8_unaligned
[9];
54 uint8_t u8_unaligned
[5];
60 uint8_t u8_unaligned
[9];
64 #define T16(b0, b1, sgn, unsgn) { { b0, b1 }, { 0x00, b0, b1 }, sgn, unsgn }
66 Test16 tests_16_bit
[] = {
67 T16(0x00, 0x00, 0, 0),
68 T16(0x01, 0x00, 1, 1),
69 T16(0x00, 0x01, 256, 256),
70 T16(0xff, 0x7f, 32767, 32767),
71 T16(0x00, 0x80, -32768, 32768),
72 T16(0xff, 0xff, -1, 65535),
75 #define T32(b0, b1, b2, b3, sgn, unsgn) { \
77 { 0x00, b0, b1, b2, b3 }, \
81 Test32 tests_32_bit
[] = {
82 T32(0x00, 0x00, 0x00, 0x00, 0, 0),
83 T32(0x01, 0x00, 0x00, 0x00, 1, 1),
84 T32(0x00, 0x01, 0x00, 0x00, 256, 256),
85 T32(0x00, 0x00, 0x01, 0x00, 65536, 65536),
86 T32(0xff, 0xff, 0xff, 0x7f, 2147483647, 2147483647),
87 // Odd coding of signed result below avoids a compiler warning
88 // as 2147483648 can't fit in a signed 32-bit number
89 T32(0x00, 0x00, 0x00, 0x80, -2147483647 - 1, 2147483648U),
90 T32(0xff, 0xff, 0xff, 0xff, -1, 4294967295U),
93 #define T64(b0, b1, b2, b3, b4, b5, b6, b7, sgn, unsgn) { \
94 { b0, b1, b2, b3, b4, b5, b6, b7 }, \
95 { 0x00, b0, b1, b2, b3, b4, b5, b6, b7 }, \
100 Test64 tests_64_bit
[] = {
101 T64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0),
102 T64(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1, 1),
103 T64(0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 256, 256),
104 T64(0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 65536, 65536),
105 T64(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 4294967296, 4294967296),
106 T64(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
107 9223372036854775807LL, 9223372036854775807ULL),
108 // Odd coding of signed result below avoids a compiler warning
109 // as 9223372036854775808 can't fit in a signed 64-bit number
110 T64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
111 -9223372036854775807LL - 1LL, 9223372036854775808ULL),
112 T64(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
113 -1, 18446744073709551615ULL),
116 #define TF(b0, b1, b2, b3, f) { { b0, b1, b2, b3 }, { 0x00, b0, b1, b2, b3}, f }
118 Test_float tests_float
[] = {
119 TF(0x00, 0x00, 0x00, 0x00, 0.0f
),
120 TF(0x00, 0x00, 0x80, 0x3f, 1.0f
),
121 TF(0x00, 0x00, 0x80, 0xbf, -1.0f
),
122 TF(0x00, 0x00, 0x20, 0x41, 10.0f
),
123 TF(0xd0, 0x0f, 0x49, 0x40, 3.14159f
),
124 TF(0xa8, 0x0a, 0xff, 0x66, 6.022e23f
),
125 TF(0xcd, 0x84, 0x03, 0x13, 1.66e-27f
),
128 #define TD(b0, b1, b2, b3, b4, b5, b6, b7, d) { \
129 { b0, b1, b2, b3, b4, b5, b6, b7 }, \
130 { 0x00, b0, b1, b2, b3, b4, b5, b6, b7 }, \
134 Test_double tests_double
[] = {
135 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0.0),
136 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 1.0),
137 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, -1.0),
138 TD(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 10.0),
139 TD(0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40, 3.141592653589793),
140 TD(0x2b, 0x08, 0x0c, 0xd3, 0x85, 0xe1, 0xdf, 0x44, 6.022140858e23
),
141 TD(0x55, 0xfa, 0x81, 0x74, 0xf7, 0x71, 0x60, 0x3a, 1.66053904e-27),
144 #define NELE(x) (sizeof(x)/sizeof(x[0]))
146 static char * to_hex(uint8_t *buf
, int len
) {
150 for (i
= 0, o
= 0; i
< len
; i
++, o
+= 3) {
151 snprintf(str
+ o
, sizeof(str
) - o
, "%02x ", buf
[i
]);
156 static int t16_bit(int verbose
) {
161 for (i
= 0; i
< NELE(tests_16_bit
); i
++) {
166 fprintf(stderr
, "%s %6"PRId16
" %6"PRId16
"\n",
167 to_hex(tests_16_bit
[i
].u8
, 2),
168 tests_16_bit
[i
].i16
, tests_16_bit
[i
].u16
);
171 u16
= le_to_u16(tests_16_bit
[i
].u8
);
172 if (u16
!= tests_16_bit
[i
].u16
) {
173 fprintf(stderr
, "Failed %s => %"PRIu16
"; expected %"PRIu16
"\n",
174 to_hex(tests_16_bit
[i
].u8
, 2), u16
, tests_16_bit
[i
].u16
);
178 i16
= le_to_i16(tests_16_bit
[i
].u8
);
179 if (i16
!= tests_16_bit
[i
].i16
) {
180 fprintf(stderr
, "Failed %s => %"PRId16
"; expected %"PRId16
"\n",
181 to_hex(tests_16_bit
[i
].u8
, 2), i16
, tests_16_bit
[i
].i16
);
185 u16
= le_to_u16(tests_16_bit
[i
].u8_unaligned
+ 1);
186 if (u16
!= tests_16_bit
[i
].u16
) {
188 "Failed unaligned %s => %"PRIu16
"; expected %"PRIu16
"\n",
189 to_hex(tests_16_bit
[i
].u8_unaligned
+ 1, 2),
190 u16
, tests_16_bit
[i
].u16
);
194 i16
= le_to_i16(tests_16_bit
[i
].u8_unaligned
+ 1);
195 if (i16
!= tests_16_bit
[i
].i16
) {
197 "Failed unaligned %s => %"PRId16
"; expected %"PRId16
"\n",
198 to_hex(tests_16_bit
[i
].u8_unaligned
+ 1, 2),
199 i16
, tests_16_bit
[i
].i16
);
203 u16_to_le(tests_16_bit
[i
].u16
, buf
);
204 if (memcmp(buf
, tests_16_bit
[i
].u8
, 2) != 0) {
205 fprintf(stderr
, "Failed %"PRIu16
" => %s; expected %s\n",
207 to_hex(buf
, 2), to_hex(tests_16_bit
[i
].u8
, 2));
211 i16_to_le(tests_16_bit
[i
].i16
, buf
);
212 if (memcmp(buf
, tests_16_bit
[i
].u8
, 2) != 0) {
213 fprintf(stderr
, "Failed %"PRId16
" => %s; expected %s\n",
215 to_hex(buf
, 2), to_hex(tests_16_bit
[i
].u8
, 2));
219 u16_to_le(tests_16_bit
[i
].u16
, buf
+ 1);
220 if (memcmp(buf
+ 1, tests_16_bit
[i
].u8
, 2) != 0) {
221 fprintf(stderr
, "Failed unaligned %"PRIu16
" => %s; expected %s\n",
223 to_hex(buf
+ 1, 2), to_hex(tests_16_bit
[i
].u8
, 2));
227 i16_to_le(tests_16_bit
[i
].i16
, buf
+ 1);
228 if (memcmp(buf
+ 1, tests_16_bit
[i
].u8
, 2) != 0) {
229 fprintf(stderr
, "Failed unaligned %"PRId16
" => %s; expected %s\n",
231 to_hex(buf
+ 1, 2), to_hex(tests_16_bit
[i
].u8
, 2));
239 static int t32_bit(int verbose
) {
244 for (i
= 0; i
< NELE(tests_32_bit
); i
++) {
249 fprintf(stderr
, "%s %11"PRId32
" %11"PRIu32
"\n",
250 to_hex(tests_32_bit
[i
].u8
, 4),
251 tests_32_bit
[i
].i32
, tests_32_bit
[i
].u32
);
254 u32
= le_to_u32(tests_32_bit
[i
].u8
);
255 if (u32
!= tests_32_bit
[i
].u32
) {
256 fprintf(stderr
, "Failed %s => %"PRIu32
"; expected %"PRIu32
"\n",
257 to_hex(tests_32_bit
[i
].u8
, 4), u32
, tests_32_bit
[i
].u32
);
260 i32
= le_to_i32(tests_32_bit
[i
].u8
);
261 if (i32
!= tests_32_bit
[i
].i32
) {
262 fprintf(stderr
, "Failed %s => %"PRId32
"; expected %"PRId32
"\n",
263 to_hex(tests_32_bit
[i
].u8
, 4), i32
, tests_32_bit
[i
].i32
);
267 u32
= le_to_u32(tests_32_bit
[i
].u8_unaligned
+ 1);
268 if (u32
!= tests_32_bit
[i
].u32
) {
270 "Failed unaligned %s => %"PRIu32
"; expected %"PRIu32
"\n",
271 to_hex(tests_32_bit
[i
].u8_unaligned
+ 1, 4),
272 u32
, tests_32_bit
[i
].u32
);
275 i32
= le_to_i32(tests_32_bit
[i
].u8_unaligned
+ 1);
276 if (i32
!= tests_32_bit
[i
].i32
) {
278 "Failed unaligned %s => %"PRId32
"; expected %"PRId32
"\n",
279 to_hex(tests_32_bit
[i
].u8_unaligned
+ 1, 4),
280 i32
, tests_32_bit
[i
].i32
);
284 u32_to_le(tests_32_bit
[i
].u32
, buf
);
285 if (memcmp(buf
, tests_32_bit
[i
].u8
, 4) != 0) {
286 fprintf(stderr
, "Failed %"PRIu32
" => %s; expected %s\n",
288 to_hex(buf
, 4), to_hex(tests_32_bit
[i
].u8
, 4));
292 i32_to_le(tests_32_bit
[i
].i32
, buf
);
293 if (memcmp(buf
, tests_32_bit
[i
].u8
, 4) != 0) {
294 fprintf(stderr
, "Failed %"PRId32
" => %s; expected %s\n",
296 to_hex(buf
, 4), to_hex(tests_32_bit
[i
].u8
, 4));
300 u32_to_le(tests_32_bit
[i
].u32
, buf
+ 1);
301 if (memcmp(buf
+ 1, tests_32_bit
[i
].u8
, 4) != 0) {
302 fprintf(stderr
, "Failed unaligned %"PRIu32
" => %s; expected %s\n",
304 to_hex(buf
+ 1, 4), to_hex(tests_32_bit
[i
].u8
, 4));
308 i32_to_le(tests_32_bit
[i
].i32
, buf
+ 1);
309 if (memcmp(buf
+ 1, tests_32_bit
[i
].u8
, 4) != 0) {
310 fprintf(stderr
, "Failed unaligned %"PRId32
" => %s; expected %s\n",
312 to_hex(buf
+ 1, 4), to_hex(tests_32_bit
[i
].u8
, 4));
320 static int t64_bit(int verbose
) {
325 for (i
= 0; i
< NELE(tests_64_bit
); i
++) {
330 fprintf(stderr
, "%s %20"PRId64
" %20"PRIu64
"\n",
331 to_hex(tests_64_bit
[i
].u8
, 8),
332 tests_64_bit
[i
].i64
, tests_64_bit
[i
].u64
);
335 u64
= le_to_u64(tests_64_bit
[i
].u8
);
336 if (u64
!= tests_64_bit
[i
].u64
) {
337 fprintf(stderr
, "Failed %s => %"PRIu64
"; expected %"PRIu64
"\n",
338 to_hex(tests_64_bit
[i
].u8
, 8), u64
, tests_64_bit
[i
].u64
);
342 i64
= le_to_i64(tests_64_bit
[i
].u8
);
343 if (i64
!= tests_64_bit
[i
].i64
) {
344 fprintf(stderr
, "Failed %s => %"PRId64
"; expected %"PRId64
"\n",
345 to_hex(tests_64_bit
[i
].u8
, 8), i64
, tests_64_bit
[i
].i64
);
349 u64
= le_to_u64(tests_64_bit
[i
].u8_unaligned
+ 1);
350 if (u64
!= tests_64_bit
[i
].u64
) {
352 "Failed unaligned %s => %"PRIu64
"; expected %"PRIu64
"\n",
353 to_hex(tests_64_bit
[i
].u8_unaligned
+ 1, 8),
354 u64
, tests_64_bit
[i
].u64
);
358 i64
= le_to_i64(tests_64_bit
[i
].u8_unaligned
+ 1);
359 if (i64
!= tests_64_bit
[i
].i64
) {
361 "Failed unaligned %s => %"PRId64
"; expected %"PRId64
"\n",
362 to_hex(tests_64_bit
[i
].u8_unaligned
+ 1, 8),
363 i64
, tests_64_bit
[i
].i64
);
367 u64_to_le(tests_64_bit
[i
].u64
, buf
);
368 if (memcmp(buf
, tests_64_bit
[i
].u8
, 8) != 0) {
369 fprintf(stderr
, "Failed %"PRIu64
" => %s; expected %s\n",
371 to_hex(buf
, 8), to_hex(tests_64_bit
[i
].u8
, 8));
375 i64_to_le(tests_64_bit
[i
].i64
, buf
);
376 if (memcmp(buf
, tests_64_bit
[i
].u8
, 8) != 0) {
377 fprintf(stderr
, "Failed %"PRId64
" => %s; expected %s\n",
379 to_hex(buf
, 8), to_hex(tests_64_bit
[i
].u8
, 8));
383 u64_to_le(tests_64_bit
[i
].u64
, buf
+ 1);
384 if (memcmp(buf
+ 1, tests_64_bit
[i
].u8
, 8) != 0) {
385 fprintf(stderr
, "Failed unaligned %"PRIu64
" => %s; expected %s\n",
387 to_hex(buf
+ 1, 8), to_hex(tests_64_bit
[i
].u8
, 8));
391 i64_to_le(tests_64_bit
[i
].i64
, buf
+ 1);
392 if (memcmp(buf
+ 1, tests_64_bit
[i
].u8
, 8) != 0) {
393 fprintf(stderr
, "Failed unaligned %"PRId64
" => %s; expected %s\n",
395 to_hex(buf
+ 1, 8), to_hex(tests_64_bit
[i
].u8
, 8));
403 int t_float(int verbose
) {
408 for (i
= 0; i
< NELE(tests_float
); i
++) {
412 fprintf(stderr
, "%s %g\n",
413 to_hex(tests_float
[i
].u8
, 4), tests_float
[i
].f
);
416 f
= le_to_float(tests_float
[i
].u8
);
417 if (f
!= tests_float
[i
].f
) {
418 fprintf(stderr
, "Failed %s => %g; expected %g\n",
419 to_hex(tests_float
[i
].u8
, 4), f
, tests_float
[i
].f
);
423 f
= le_to_float(tests_float
[i
].u8_unaligned
+ 1);
424 if (f
!= tests_float
[i
].f
) {
425 fprintf(stderr
, "Failed unaligned %s => %g; expected %g\n",
426 to_hex(tests_float
[i
].u8_unaligned
+ 1, 4),
427 f
, tests_float
[i
].f
);
431 float_to_le(tests_float
[i
].f
, buf
);
432 if (memcmp(tests_float
[i
].u8
, buf
, 4) != 0) {
433 fprintf(stderr
, "Failed %g => %s; expected %s\n",
435 to_hex(buf
, 4), to_hex(tests_float
[i
].u8
, 4));
438 float_to_le(tests_float
[i
].f
, buf
+ 1);
439 if (memcmp(tests_float
[i
].u8
, buf
+ 1, 4) != 0) {
440 fprintf(stderr
, "Failed unaligned %g => %s; expected %s\n",
442 to_hex(buf
+ 1, 4), to_hex(tests_float
[i
].u8
, 4));
448 int t_double(int verbose
) {
453 for (i
= 0; i
< NELE(tests_double
); i
++) {
457 fprintf(stderr
, "%s %.15g\n",
458 to_hex(tests_double
[i
].u8
, 8), tests_double
[i
].d
);
461 f
= le_to_double(tests_double
[i
].u8
);
462 if (f
!= tests_double
[i
].d
) {
463 fprintf(stderr
, "Failed %s => %.15g; expected %.15g\n",
464 to_hex(tests_double
[i
].u8
, 8), f
, tests_double
[i
].d
);
468 f
= le_to_double(tests_double
[i
].u8_unaligned
+ 1);
469 if (f
!= tests_double
[i
].d
) {
470 fprintf(stderr
, "Failed unaligned %s => %.15g; expected %.15g\n",
471 to_hex(tests_double
[i
].u8_unaligned
+ 1, 8),
472 f
, tests_double
[i
].d
);
476 double_to_le(tests_double
[i
].d
, buf
);
477 if (memcmp(tests_double
[i
].u8
, buf
, 8) != 0) {
478 fprintf(stderr
, "Failed %.15g => %s; expected %s\n",
480 to_hex(buf
, 8), to_hex(tests_double
[i
].u8
, 8));
483 double_to_le(tests_double
[i
].d
, buf
+ 1);
484 if (memcmp(tests_double
[i
].u8
, buf
+ 1, 8) != 0) {
485 fprintf(stderr
, "Failed unaligned %.15g => %s; expected %s\n",
487 to_hex(buf
+ 1, 8), to_hex(tests_double
[i
].u8
, 8));
493 int main(int argc
, char **argv
) {
497 if (argc
> 1 && strcmp(argv
[1], "-v") == 0) verbose
= 1;
499 errors
+= t16_bit(verbose
);
500 errors
+= t32_bit(verbose
);
501 errors
+= t64_bit(verbose
);
502 errors
+= t_float(verbose
);
503 errors
+= t_double(verbose
);
505 fprintf(stderr
, "%d errors\n", errors
);