Unit test unit-geom-Envelope fails on FreeBSD 14.1 (clang vs gcc)
Hi,
One unit test fails on FreeBSD
183/494 Testing: unit-geom-Envelope
183/494 Test: unit-geom-Envelope
Command: "/usr/ports/graphics/geos/work/.build/bin/test_geos_unit" "geos::geom::Envelope"
Directory: /usr/ports/graphics/geos/work/.build/tests/unit
"unit-geom-Envelope" start time: Dec 07 12:21 CET
Output:
----------------------------------------------------------
===============================
GEOS Unit Test Suite
===============================
geos::geom::Envelope: .....[6=F].......[14=F]......
---> group: geos::geom::Envelope, test: test<6>
problem: assertion failed
failed assertion: `FE_INVALID raised`
---> group: geos::geom::Envelope, test: test<14>
problem: assertion failed
failed assertion: `FE_INVALID raised`
tests summary: failures:2 ok:18
<end of output>
Test time = 0.02 sec
----------------------------------------------------------
Test Failed.
"unit-geom-Envelope" end time: Dec 07 12:21 CET
"unit-geom-Envelope" time elapsed: 00:00:00
----------------------------------------------------------
OS: FreeBSD 14.1 (amd64) Version: 3.13.0 and latest main (dd0fdc5 Compiler: Clang 18.1.5 CMake: 3.31.0
Edit: All tests passes with GCC 13.3.0 but it would be nice if Clang also passed Also fails using Clang 15.0.7 Passes if -ffp-model=strict is added to CXXFLAGS https://clang.llvm.org/docs/UsersManual.html#controlling-floating-point-behavior
Friendly ping
Patches accepted! These things are obscure and since I do not have a FreeBSD system lying around to test it on, it is best to wait for someone with the system in question to fix it.
I'm going to guess it's not a FreeBSD thing but rather clang(llvm) vs gcc, unfortunately I don't have a Linux box to verify on.
We test many versions of gcc and clang on Linux in our CI and aren't seeing this.
It's showing on our FreeBSD ci - -
FreeBSD bessie 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64
FreeBSD clang version 18.1.5 (https://github.com/llvm/llvm-project.git llvmorg-18.1.5-0-g617a15a9eac9) Target: x86_64-unknown-freebsd14.1
@robe2 @pramsey I can take a look. I know that Clang 18.x raises many compiler bugs/errors (like gcc 15, some warnings become errors,etc).
@robe2 btw, can you update FreeBSD to 14.2, please?
I can confirm a problem with the test on FreeBSD and clang (@diizzyy tested on 14.2-RELEASE clang 15 to 19 (and 15.0-CURRENT clang19) vs 14.2-RELEASE gcc 14 and 15)
At contrary to @diizzyy, on my computer, only test 6 fails.
Never mind, the problem seems at https://github.com/libgeos/geos/blob/c1a3d838ced34c29f2d4ba9982dbde31f79b2a05/tests/unit/geom/EnvelopeTest.cpp#L75 and more exactly this line: https://github.com/libgeos/geos/blob/c1a3d838ced34c29f2d4ba9982dbde31f79b2a05/tests/unit/geom/EnvelopeTest.cpp#L78
I think that the problem is with the empty Enveloppe.
If you move tests inside the if (!e1.isNull()), it hides the assertion :
static void
check_intersects(const Envelope& e1, const CoordinateXY& q, bool expected)
{
if (!e1.isNull()) {
ensure_equals(e1.intersects(q), expected);
ensure_equals(e1.intersects(q.x, q.y), expected);
ensure_equals(e1.contains(q), expected);
ensure_equals(e1.contains(q.x, q.y), expected);
ensure_equals(e1.covers(&q), expected);
ensure_equals(e1.covers(q.x, q.y), expected);
CoordinateXY p0{e1.getMinX(), e1.getMinY()};
CoordinateXY p1{e1.getMaxX(), e1.getMaxY()};
ensure_equals(Envelope::intersects(p0, p1, q), expected);
}
}
static void
ensure_no_fp_except()
{
ensure("FE_DIVBYZERO raised", !std::fetestexcept(FE_DIVBYZERO));
//ensure("FE_INEXACT raised", !std::fetestexcept(FE_INEXACT));
ensure("FE_INVALID raised", !std::fetestexcept(FE_INVALID));
ensure("FE_OVERFLOW raised", !std::fetestexcept(FE_OVERFLOW));
ensure("FE_UNDERFLOW raised", !std::fetestexcept(FE_UNDERFLOW));
}
But, I don't understand, why this patch does not fix the FE_INVALID assert: e1.intersects* are fixed but not covers (contains uses covers)
Thanks @lbartoletti , this is helpful. It makes sense that the exception would be raised from e1.intersects(q.x, q.y). Looking at that overload I can see that it uses comparison operators that will raise this exception with nan arguments.
Could you please try changing line 60 of Envelope.cpp from
double envminx = (a.x < b.x) ? a.x : b.x;
to
double envminx = std::isless(a.x, b.x) ? a.x : b.x;
and so on for the other comparisons in this method?
@dbaston doesn't resolve the issue :/
Actual situation, individually tested:
ensure_equals(e1.intersects(q), expected); //fails
ensure_equals(e1.intersects(q.x, q.y), expected); // fails
ensure_equals(e1.contains(q), expected); //fails
ensure_equals(e1.contains(q.x, q.y), expected); //fails
ensure_equals(e1.covers(&q), expected); // fails
ensure_equals(e1.covers(q.x, q.y), expected); // fails
With my geos_enveloppe_v2.txt patch
(false if enveloppe isNull, or coordinate(s) is/are null, or double is nan):
ensure_equals(e1.intersects(q), expected); // OK
ensure_equals(e1.intersects(q.x, q.y), expected); // fails
ensure_equals(e1.contains(q), expected); //fails
ensure_equals(e1.contains(q.x, q.y), expected); //fails
ensure_equals(e1.covers(&q), expected); // fails
ensure_equals(e1.covers(q.x, q.y), expected); // fails
meh.... Moreover, it's ok with:
static void
check_intersects(const Envelope& e1, const CoordinateXY& q, bool expected)
{
if (!e1.isNull()) {
ensure_equals(e1.intersects(q), expected);
ensure_equals(e1.intersects(q.x, q.y), expected);
ensure_equals(e1.contains(q), expected);
ensure_equals(e1.contains(q.x, q.y), expected);
ensure_equals(e1.covers(&q), expected);
ensure_equals(e1.covers(q.x, q.y), expected);
CoordinateXY p0{e1.getMinX(), e1.getMinY()};
CoordinateXY p1{e1.getMaxX(), e1.getMaxY()};
ensure_equals(Envelope::intersects(p0, p1, q), expected);
}
}
@lbartoletti
I can confirm a problem with the test on FreeBSD and clang (@diizzyy tested on 14.2-RELEASE clang 15 to 19 (and 15.0-CURRENT clang19) vs 14.2-RELEASE gcc 14 and 15)
At contrary to @diizzyy, on my computer, only test 6 fails.
I only get one if I unset CPUTYPE?=znver4 in /etc/make.conf, also able to reproduce it on my laptop which uses CPUTYPE?=tigerlake (two vs one failures), CPUTYPE translates to --march= in this case
This is what we have in ports https://cgit.freebsd.org/ports/commit/graphics/geos/files/patch-CMakeLists.txt?id=53d2b997aba6f272d3f78e504e3c1911a6ff5b15
Best regards, Daniel
@robe2 @pramsey I can take a look. I know that Clang 18.x raises many compiler bugs/errors (like gcc 15, some warnings become errors,etc).
@robe2 btw, can you update FreeBSD to 14.2, please?
@lbartoletti sorry missed this note. I'll update to latest FreeBSD in a bit.
You probably want to go for 14.3 as 14.2 is EoL in September
@robe2 @pramsey I can take a look. I know that Clang 18.x raises many compiler bugs/errors (like gcc 15, some warnings become errors,etc).
@robe2 btw, can you update FreeBSD to 14.2, please?
okay updated bessie to freebsd 14.2
You probably want to go for 14.3 as 14.2 is EoL in September Okay I'll upgrade again later today.