Test framework#116
Conversation
15514cb to
1866a9e
Compare
|
This is a huge contribution. Unit tests have long been much needed. Thank you! The CI is currently failing with: |
I recommend opening separate issues for these in https://github.com/HEASARC/cfitsio/issues/ I would then delete the ISSUES file from the pull request. |
|
Removed ISSUES and created issues 117-119. PTAL |
|
Checking the test failures on ubuntu. |
c73266f to
3b66baa
Compare
|
All CI workflows are passing now. LGTM. |
|
Rebased on d5d4888 |
The pseudo-random number generator in test_rcomp_high_entropy() used
signed integer arithmetic that overflows when i >= 2:
original[i] = ((i * 1103515245 + 12345) >> 16) & 0x7FFF;
The multiplication i * 1103515245 exceeds INT_MAX (2147483647) at i=2,
producing 2207030490 which cannot be represented as a signed int. This
is undefined behavior per the C standard (C11 6.5/5).
GCC on Ubuntu ARM with -O2 exploits this UB via aggressive loop
optimizations (-Waggressive-loop-optimizations), causing the test
to abort with a core dump during distcheck. The compiler warning:
warning: iteration 2 invokes undefined behavior
The fix uses unsigned arithmetic throughout:
original[i] = (((unsigned)i * 1103515245U + 12345U) >> 16) & 0x7FFF;
This produces identical pseudo-random values but with well-defined
overflow semantics (modulo 2^32 per C11 6.2.5/9).
The fits_rcomp, fits_rcomp_short, and fits_rcomp_byte functions do not
perform end-of-buffer checking. As documented in ricecomp.c:
"Note that beginning with CFITSIO v3.08, EOB checking was removed
to improve speed, and so now the input compressed bytes buffers
must have been allocated big enough so that they will never be
overflowed."
The removed tests passed intentionally undersized buffers expecting
the library to detect this and return an error. Instead, the library
writes past the buffer bounds, causing stack corruption. This was
detected on Linux by FORTIFY_SOURCE/glibc, triggering SIGABRT.
The test_rdecomp_buffer_too_small test is retained since decompression
reads from the buffer (bounded by clen parameter) rather than writing.
fits_hdecompress was modified to take an additional argument, and this commit adds that new argument to the tests.
| #AC_CONFIG_HEADERS(config.h) | ||
| AC_CONFIG_SRCDIR([fitscore.c]) | ||
| AM_INIT_AUTOMAKE([foreign]) | ||
| AM_SILENT_RULES([yes]) |
There was a problem hiding this comment.
This edits the output of the make system and is unrelated to testing. Please remove. (and update the generated configure and Makefile.in files)
|
|
||
| # Distribution: ========================================================== | ||
|
|
||
| DISTCHECK_CONFIGURE_FLAGS = --enable-reentrant |
There was a problem hiding this comment.
This is unrelated to the test framework and conflicts/is redundant with our existing CI, which already tests reentrant. Please remove.
|
now that PR133 is merged, you can merge develop into this PR and remove your fits_hdecompress.c commit from this PR. |
| * Test ffcalc with LONGLONG column | ||
| */ | ||
| static void | ||
| test_ffcalc_longlong_column(void) |
There was a problem hiding this comment.
This test should fail on any platform where long is 32bits instead of 64 bits.
|
|
||
| #define test_path "test_grparser.fits" | ||
| #define template_path "test_grparser.tpl" | ||
|
|
There was a problem hiding this comment.
To run on windows you'll need:
| #ifdef _WIN32 | |
| /* MSVC lacks POSIX setenv/unsetenv; emulate with _putenv. */ | |
| static int | |
| setenv(const char *name, const char *value, int overwrite) | |
| { | |
| char buf[1024]; | |
| (void) overwrite; | |
| snprintf(buf, sizeof(buf), "%s=%s", name, value); | |
| return _putenv(buf); | |
| } | |
| static int | |
| unsetenv(const char *name) | |
| { | |
| char buf[1024]; | |
| snprintf(buf, sizeof(buf), "%s=", name); | |
| return _putenv(buf); | |
| } | |
| #endif | |
| int status = 0; | ||
| char *ttype[] = { "DBLCOL" }; | ||
| char *tform[] = { "1D" }; | ||
| double nan_val = 0.0 / 0.0; /* Generate NaN. */ |
There was a problem hiding this comment.
For windows:
| double nan_val = 0.0 / 0.0; /* Generate NaN. */ | |
| /* 'zero' is volatile so the division is performed at runtime rather | |
| than folded by the compiler. A literal 0.0/0.0 is a compile-time | |
| constant expression that MSVC rejects with error C2124 ("divide or | |
| mod by zero"); the volatile forces a genuine runtime NaN. */ | |
| volatile double zero = 0.0; | |
| double nan_val = zero / zero; /* Generate NaN. */ |
| int status = 0; | ||
| char *ttype[] = { "DBLCOL" }; | ||
| char *tform[] = { "1D" }; | ||
| double inf_val = 1.0 / 0.0; /* Generate infinity. */ |
There was a problem hiding this comment.
For windows:
| double inf_val = 1.0 / 0.0; /* Generate infinity. */ | |
| /* volatile for the same reason as in test_write_nan_values(): a literal | |
| 1.0/0.0 is a compile-time constant that MSVC rejects (C2124), so the | |
| operands are made volatile to force a runtime division to infinity. */ | |
| volatile double one = 1.0, zero = 0.0; | |
| double inf_val = one / zero; /* Generate infinity. */ |
| int status = 0; | ||
| char *ttype[] = { "FLOATCOL" }; | ||
| char *tform[] = { "1E" }; | ||
| float nan_val = 0.0f / 0.0f; /* Generate NaN. */ |
There was a problem hiding this comment.
For windows:
| float nan_val = 0.0f / 0.0f; /* Generate NaN. */ | |
| /* 'zero' is volatile so the division is performed at runtime rather | |
| than folded by the compiler. A literal 0.0f/0.0f is a compile-time | |
| constant expression that MSVC rejects with error C2124 ("divide or | |
| mod by zero"); the volatile forces a genuine runtime NaN. */ | |
| volatile float zero = 0.0f; | |
| float nan_val = zero / zero; /* Generate NaN. */ |
AI port of heasarc/cfitsio#116 test framework. Huge increase in code coverage and detected many bugs
Add a simplistic test framework. testprog only exercises about 16% of the code (as reported by gcov), and 22 files have zero coverage. This adds some basic unit testing to exercise a larger chunk of the code base to protect against regressions.
Note that, other than trivial changes to Makefile.am and configure.ac (and the subsequent changes to the autogenerated Makefile.in and configure) and a change to comments in fits_hdcompress.c, this PR is just adding files in tests/. Although the PR is large, it does not modify the existing code in any significant way.