diff --git a/src/lib/Iex/IexThrowErrnoExc.cpp b/src/lib/Iex/IexThrowErrnoExc.cpp index 0e0da1169a..12adf3de90 100644 --- a/src/lib/Iex/IexThrowErrnoExc.cpp +++ b/src/lib/Iex/IexThrowErrnoExc.cpp @@ -209,7 +209,7 @@ throwErrnoExc (const std::string& text, int errnum) case EUNATCH: throw EunatchExc (tmp); #endif -#if defined(ENOSCI) +#if defined(ENOCSI) case ENOCSI: throw EnocsiExc (tmp); #endif diff --git a/src/test/IexTest/CMakeLists.txt b/src/test/IexTest/CMakeLists.txt index 58652178aa..4aed14bae8 100644 --- a/src/test/IexTest/CMakeLists.txt +++ b/src/test/IexTest/CMakeLists.txt @@ -5,6 +5,10 @@ add_executable(IexTest main.cpp testBaseExc.cpp testBaseExc.h + testMathExc.cpp + testMathExc.h + mathFuncs.cpp + mathFuncs.h ) target_link_libraries(IexTest OpenEXR::Iex) diff --git a/src/test/IexTest/main.cpp b/src/test/IexTest/main.cpp index e7931af0b7..98356bd0d8 100644 --- a/src/test/IexTest/main.cpp +++ b/src/test/IexTest/main.cpp @@ -8,6 +8,7 @@ #endif #include +#include #include @@ -18,5 +19,6 @@ int main (int argc, char* argv[]) { TEST (testBaseExc); + TEST (testMathExc); return 0; } diff --git a/src/test/IexTest/mathFuncs.cpp b/src/test/IexTest/mathFuncs.cpp new file mode 100644 index 0000000000..de7ebd10b1 --- /dev/null +++ b/src/test/IexTest/mathFuncs.cpp @@ -0,0 +1,28 @@ +#undef __THROW +#include +#include + +float +divide (float x, float y) +{ + std::cout << x << " / " << y << std::endl; + return x / y; +} + +float +root (float x) +{ + std::cout << "sqrt (" << x << ")" << std::endl; + return sqrt (x); +} + +float +grow (float x, int y) +{ + std::cout << "grow (" << x << ", " << y << ")" << std::endl; + + for (int i = 0; i < y; i++) + x = x * x; + + return x; +} diff --git a/src/test/IexTest/mathFuncs.h b/src/test/IexTest/mathFuncs.h new file mode 100644 index 0000000000..1ebd2fbcae --- /dev/null +++ b/src/test/IexTest/mathFuncs.h @@ -0,0 +1,5 @@ + +float divide (float x, float y); +float root (float x); +float grow (float x, int y); + diff --git a/src/test/IexTest/testBaseExc.cpp b/src/test/IexTest/testBaseExc.cpp index b4bfc1d03e..cf8c2e1a9d 100644 --- a/src/test/IexTest/testBaseExc.cpp +++ b/src/test/IexTest/testBaseExc.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include namespace @@ -191,14 +193,16 @@ test6 () // and the += and assign functions. // + T e0; + T e1 ("arg"); e1 += "X"; - std::stringstream s; - s << "Y"; - e1 += s; + std::stringstream ss; + ss << "Y"; + e1 += ss; - T e2 (e1); + T e2 (e1); assert (e1.message () == "argXY"); assert (e1.stackTrace () == getStackTrace ()); @@ -208,12 +212,31 @@ test6 () e2.assign ("Z"); assert (e2.message () == "Z"); - e2.assign (s); + e2.assign (ss); assert (e2.message () == "Y"); - T e3 (s); - assert (e3.message () == s.str ()); + T e3 (ss); + assert (e3.message () == ss.str ()); + std::string str4 ("e4"); + T e4(str4); + assert (e4.message() == str4); + + const std::string str5 ("e5"); + T e5(str5); + assert (e5.message() == str5); + + { + const T e6("e6"); + T e7(e6); + assert (e7.message() == e6.message()); + } + + { + e5 = e4; + assert (e5.message() == e4.message()); + } + // // Confirm the throw/catch // @@ -237,6 +260,508 @@ test6 () assert (caught); } +template +void +testThrowErrnoExc(int err) +{ + bool caught = false; + + try + { + IEX_INTERNAL_NAMESPACE::throwErrnoExc("err", err); + } + catch (const T& e) + { + caught = true; + } + catch (const std::exception& e) + { + std::cerr << "testThrowErrnoExc: caught " << typeid(e).name() + << ", expected " << typeid(T).name() + << std::endl; + } + + assert (caught); +} + +void +test7() +{ +#if defined(EPERM) + testThrowErrnoExc(EPERM); +#endif +#if defined(ENOENT) + testThrowErrnoExc(ENOENT); +#endif +#if defined(ESRCH) + testThrowErrnoExc(ESRCH); +#endif +#if defined(EINTR) + testThrowErrnoExc(EINTR); +#endif +#if defined(EIO) + testThrowErrnoExc(EIO); +#endif +#if defined(ENXIO) + testThrowErrnoExc(ENXIO); +#endif +#if defined(E2BIG) + testThrowErrnoExc(E2BIG); +#endif +#if defined(ENOEXEC) + testThrowErrnoExc(ENOEXEC); +#endif +#if defined(EBADF) + testThrowErrnoExc(EBADF); +#endif +#if defined(ECHILD) + testThrowErrnoExc(ECHILD); +#endif +#if defined(EAGAIN) + testThrowErrnoExc(EAGAIN); +#endif +#if defined(ENOMEM) + testThrowErrnoExc(ENOMEM); +#endif +#if defined(EACCES) + testThrowErrnoExc(EACCES); +#endif +#if defined(EFAULT) + testThrowErrnoExc(EFAULT); +#endif +#if defined(ENOTBLK) + testThrowErrnoExc(ENOTBLK); +#endif +#if defined(EBUSY) + testThrowErrnoExc(EBUSY); +#endif +#if defined(EEXIST) + testThrowErrnoExc(EEXIST); +#endif +#if defined(EXDEV) + testThrowErrnoExc(EXDEV); +#endif +#if defined(ENODEV) + testThrowErrnoExc(ENODEV); +#endif +#if defined(ENOTDIR) + testThrowErrnoExc(ENOTDIR); +#endif +#if defined(EISDIR) + testThrowErrnoExc(EISDIR); +#endif +#if defined(EINVAL) + testThrowErrnoExc(EINVAL); +#endif +#if defined(ENFILE) + testThrowErrnoExc(ENFILE); +#endif +#if defined(EMFILE) + testThrowErrnoExc(EMFILE); +#endif +#if defined(ENOTTY) + testThrowErrnoExc(ENOTTY); +#endif +#if defined(ETXTBSY) + testThrowErrnoExc(ETXTBSY); +#endif +#if defined(EFBIG) + testThrowErrnoExc(EFBIG); +#endif +#if defined(ENOSPC) + testThrowErrnoExc(ENOSPC); +#endif +#if defined(ESPIPE) + testThrowErrnoExc(ESPIPE); +#endif +#if defined(EROFS) + testThrowErrnoExc(EROFS); +#endif +#if defined(EMLINK) + testThrowErrnoExc(EMLINK); +#endif +#if defined(EPIPE) + testThrowErrnoExc(EPIPE); +#endif +#if defined(EDOM) + testThrowErrnoExc(EDOM); +#endif +#if defined(ERANGE) + testThrowErrnoExc(ERANGE); +#endif +#if defined(ENOMSG) + testThrowErrnoExc(ENOMSG); +#endif +#if defined(EIDRM) + testThrowErrnoExc(EIDRM); +#endif +#if defined(ECHRNG) + testThrowErrnoExc(ECHRNG); +#endif +#if defined(EL2NSYNC) + testThrowErrnoExc(EL2NSYNC); +#endif +#if defined(EL3HLT) + testThrowErrnoExc(EL3HLT); +#endif +#if defined(EL3RST) + testThrowErrnoExc(EL3RST); +#endif +#if defined(ELNRNG) + testThrowErrnoExc(ELNRNG); +#endif +#if defined(EUNATCH) + testThrowErrnoExc(EUNATCH); +#endif +#if defined(ENOCSI) + testThrowErrnoExc(ENOCSI); +#endif +#if defined(EL2HLT) + testThrowErrnoExc(EL2HLT); +#endif +#if defined(EDEADLK) + testThrowErrnoExc(EDEADLK); +#endif +#if defined(ENOLCK) + testThrowErrnoExc(ENOLCK); +#endif +#if defined(EBADE) + testThrowErrnoExc(EBADE); +#endif +#if defined(EBADR) + testThrowErrnoExc(EBADR); +#endif +#if defined(EXFULL) + testThrowErrnoExc(EXFULL); +#endif +#if defined(ENOANO) + testThrowErrnoExc(ENOANO); +#endif +#if defined(EBADRQC) + testThrowErrnoExc(EBADRQC); +#endif +#if defined(EBADSLT) + testThrowErrnoExc(EBADSLT); +#endif +#if defined(EDEADLOCK) && defined(EDEADLK) +# if EDEADLOCK != EDEADLK + testThrowErrnoExc(EDEADLOCK); +# endif +#elif defined(EDEADLOCK) + testThrowErrnoExc(EDEADLOCK); +#endif +#if defined(EBFONT) + testThrowErrnoExc(EBFONT); +#endif +#if defined(ENOSTR) + testThrowErrnoExc(ENOSTR); +#endif +#if defined(ENODATA) + testThrowErrnoExc(ENODATA); +#endif +#if defined(ETIME) + testThrowErrnoExc(ETIME); +#endif +#if defined(ENOSR) + testThrowErrnoExc(ENOSR); +#endif +#if defined(ENONET) + testThrowErrnoExc(ENONET); +#endif +#if defined(ENOPKG) + testThrowErrnoExc(ENOPKG); +#endif +#if defined(EREMOTE) + testThrowErrnoExc(EREMOTE); +#endif +#if defined(ENOLINK) + testThrowErrnoExc(ENOLINK); +#endif +#if defined(EADV) + testThrowErrnoExc(EADV); +#endif +#if defined(ESRMNT) + testThrowErrnoExc(ESRMNT); +#endif +#if defined(ECOMM) + testThrowErrnoExc(ECOMM); +#endif +#if defined(EPROTO) + testThrowErrnoExc(EPROTO); +#endif +#if defined(EMULTIHOP) + testThrowErrnoExc(EMULTIHOP); +#endif +#if defined(EBADMSG) + testThrowErrnoExc(EBADMSG); +#endif +#if defined(ENAMETOOLONG) + testThrowErrnoExc(ENAMETOOLONG); +#endif +#if defined(EOVERFLOW) + testThrowErrnoExc(EOVERFLOW); +#endif +#if defined(ENOTUNIQ) + testThrowErrnoExc(ENOTUNIQ); +#endif +#if defined(EBADFD) + testThrowErrnoExc(EBADFD); +#endif +#if defined(EREMCHG) + testThrowErrnoExc(EREMCHG); +#endif +#if defined(ELIBACC) + testThrowErrnoExc(ELIBACC); +#endif +#if defined(ELIBBAD) + testThrowErrnoExc(ELIBBAD); +#endif +#if defined(ELIBSCN) + testThrowErrnoExc(ELIBSCN); +#endif +#if defined(ELIBMAX) + testThrowErrnoExc(ELIBMAX); +#endif +#if defined(ELIBEXEC) + testThrowErrnoExc(ELIBEXEC); +#endif +#if defined(EILSEQ) + testThrowErrnoExc(EILSEQ); +#endif +#if defined(ENOSYS) + testThrowErrnoExc(ENOSYS); +#endif +#if defined(ELOOP) + testThrowErrnoExc(ELOOP); +#endif +#if defined(ERESTART) + testThrowErrnoExc(ERESTART); +#endif +#if defined(ESTRPIPE) + testThrowErrnoExc(ESTRPIPE); +#endif +#if defined(ENOTEMPTY) + testThrowErrnoExc(ENOTEMPTY); +#endif +#if defined(EUSERS) + testThrowErrnoExc(EUSERS); +#endif +#if defined(ENOTSOCK) + testThrowErrnoExc(ENOTSOCK); +#endif +#if defined(EDESTADDRREQ) + testThrowErrnoExc(EDESTADDRREQ); +#endif +#if defined(EMSGSIZE) + testThrowErrnoExc(EMSGSIZE); +#endif +#if defined(EPROTOTYPE) + testThrowErrnoExc(EPROTOTYPE); +#endif +#if defined(ENOPROTOOPT) + testThrowErrnoExc(ENOPROTOOPT); +#endif +#if defined(EPROTONOSUPPORT) + testThrowErrnoExc(EPROTONOSUPPORT); +#endif +#if defined(ESOCKTNOSUPPORT) + testThrowErrnoExc(ESOCKTNOSUPPORT); +#endif +#if defined(EOPNOTSUPP) + testThrowErrnoExc(EOPNOTSUPP); +#endif +#if defined(EPFNOSUPPORT) + testThrowErrnoExc(EPFNOSUPPORT); +#endif +#if defined(EAFNOSUPPORT) + testThrowErrnoExc(EAFNOSUPPORT); +#endif +#if defined(EADDRINUSE) + testThrowErrnoExc(EADDRINUSE); +#endif +#if defined(EADDRNOTAVAIL) + testThrowErrnoExc(EADDRNOTAVAIL); +#endif +#if defined(ENETDOWN) + testThrowErrnoExc(ENETDOWN); +#endif +#if defined(ENETUNREACH) + testThrowErrnoExc(ENETUNREACH); +#endif +#if defined(ENETRESET) + testThrowErrnoExc(ENETRESET); +#endif +#if defined(ECONNABORTED) + testThrowErrnoExc(ECONNABORTED); +#endif +#if defined(ECONNRESET) + testThrowErrnoExc(ECONNRESET); +#endif +#if defined(ENOBUFS) + testThrowErrnoExc(ENOBUFS); +#endif +#if defined(EISCONN) + testThrowErrnoExc(EISCONN); +#endif +#if defined(ENOTCONN) + testThrowErrnoExc(ENOTCONN); +#endif +#if defined(ESHUTDOWN) + testThrowErrnoExc(ESHUTDOWN); +#endif +#if defined(ETOOMANYREFS) + testThrowErrnoExc(ETOOMANYREFS); +#endif +#if defined(ETIMEDOUT) + testThrowErrnoExc(ETIMEDOUT); +#endif +#if defined(ECONNREFUSED) + testThrowErrnoExc(ECONNREFUSED); +#endif +#if defined(EHOSTDOWN) + testThrowErrnoExc(EHOSTDOWN); +#endif +#if defined(EHOSTUNREACH) + testThrowErrnoExc(EHOSTUNREACH); +#endif +#if defined(EALREADY) + testThrowErrnoExc(EALREADY); +#endif +#if defined(EINPROGRESS) + testThrowErrnoExc(EINPROGRESS); +#endif +#if defined(ESTALE) + testThrowErrnoExc(ESTALE); +#endif +#if defined(EIORESID) + testThrowErrnoExc(EIORESID); +#endif +#if defined(EUCLEAN) + testThrowErrnoExc(EUCLEAN); +#endif +#if defined(ENOTNAM) + testThrowErrnoExc(ENOTNAM); +#endif +#if defined(ENAVAIL) + testThrowErrnoExc(ENAVAIL); +#endif +#if defined(EISNAM) + testThrowErrnoExc(EISNAM); +#endif +#if defined(EREMOTEIO) + testThrowErrnoExc(EREMOTEIO); +#endif +#if defined(EINIT) + testThrowErrnoExc(EINIT); +#endif +#if defined(EREMDEV) + testThrowErrnoExc(EREMDEV); +#endif +#if defined(ECANCELED) + testThrowErrnoExc(ECANCELED); +#endif +#if defined(ENOLIMFILE) + testThrowErrnoExc(ENOLIMFILE); +#endif +#if defined(EPROCLIM) + testThrowErrnoExc(EPROCLIM); +#endif +#if defined(EDISJOINT) + testThrowErrnoExc(EDISJOINT); +#endif +#if defined(ENOLOGIN) + testThrowErrnoExc(ENOLOGIN); +#endif +#if defined(ELOGINLIM) + testThrowErrnoExc(ELOGINLIM); +#endif +#if defined(EGROUPLOOP) + testThrowErrnoExc(EGROUPLOOP); +#endif +#if defined(ENOATTACH) + testThrowErrnoExc(ENOATTACH); +#endif +#if defined(ENOTSUP) && defined(EOPNOTSUPP) +# if ENOTSUP != EOPNOTSUPP + testThrowErrnoExc(ENOTSUP); +# endif +#elif defined(ENOTSUP) + testThrowErrnoExc(ENOTSUP); +#endif +#if defined(ENOATTR) + testThrowErrnoExc(ENOATTR); +#endif +#if defined(EDIRCORRUPTED) + testThrowErrnoExc(EDIRCORRUPTED); +#endif +#if defined(EDQUOT) + testThrowErrnoExc(EDQUOT); +#endif +#if defined(ENFSREMOTE) + testThrowErrnoExc(ENFSREMOTE); +#endif +#if defined(ECONTROLLER) + testThrowErrnoExc(ECONTROLLER); +#endif +#if defined(ENOTCONTROLLER) + testThrowErrnoExc(ENOTCONTROLLER); +#endif +#if defined(EENQUEUED) + testThrowErrnoExc(EENQUEUED); +#endif +#if defined(ENOTENQUEUED) + testThrowErrnoExc(ENOTENQUEUED); +#endif +#if defined(EJOINED) + testThrowErrnoExc(EJOINED); +#endif +#if defined(ENOTJOINED) + testThrowErrnoExc(ENOTJOINED); +#endif +#if defined(ENOPROC) + testThrowErrnoExc(ENOPROC); +#endif +#if defined(EMUSTRUN) + testThrowErrnoExc(EMUSTRUN); +#endif +#if defined(ENOTSTOPPED) + testThrowErrnoExc(ENOTSTOPPED); +#endif +#if defined(ECLOCKCPU) + testThrowErrnoExc(ECLOCKCPU); +#endif +#if defined(EINVALSTATE) + testThrowErrnoExc(EINVALSTATE); +#endif +#if defined(ENOEXIST) + testThrowErrnoExc(ENOEXIST); +#endif +#if defined(EENDOFMINOR) + testThrowErrnoExc(EENDOFMINOR); +#endif +#if defined(EBUFSIZE) + testThrowErrnoExc(EBUFSIZE); +#endif +#if defined(EEMPTY) + testThrowErrnoExc(EEMPTY); +#endif +#if defined(ENOINTRGROUP) + testThrowErrnoExc(ENOINTRGROUP); +#endif +#if defined(EINVALMODE) + testThrowErrnoExc(EINVALMODE); +#endif +#if defined(ECANTEXTENT) + testThrowErrnoExc(ECANTEXTENT); +#endif +#if defined(EINVALTIME) + testThrowErrnoExc(EINVALTIME); +#endif +#if defined(EDESTROYED) + testThrowErrnoExc(EDESTROYED); +#endif +} + } // namespace void @@ -420,5 +945,7 @@ testBaseExc () test6 (); test6 (); + test7(); + std::cout << "ok\n" << std::endl; } diff --git a/src/test/IexTest/testMathExc.cpp b/src/test/IexTest/testMathExc.cpp new file mode 100644 index 0000000000..b0c3217577 --- /dev/null +++ b/src/test/IexTest/testMathExc.cpp @@ -0,0 +1,171 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) Contributors to the OpenEXR Project. +// + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +void +print (float f) +{ + std::cout << f << std::endl; +} + + +void +test1 () +{ + // + // Turn math exception handling off, and verify that no C++ exceptions + // are thrown even though "exceptional" floating-point operations are + // performed. + // + + std::cout << "invalid operations / exception handling off" << std::endl; + + IEX_INTERNAL_NAMESPACE::mathExcOn (0); + + for (int i = 0; i < 3; ++i) + { + try + { + print (divide (1, 0)); // division by zero + print (root (-1)); // invalid operation + print (grow (1000, 100)); // overflow + } + catch (...) + { + assert (false); + } + } +} + + +void +test2a () +{ + try + { + print (divide (1, 0)); // division by zero + } + catch (const IEX_INTERNAL_NAMESPACE::DivzeroExc &e) + { + std::cout << "caught exception: " << e.what() << std::endl; + } +} + + +void +test2b () +{ + try + { + print (root (-1)); // invalid operation + } + catch (const IEX_INTERNAL_NAMESPACE::InvalidFpOpExc &e) + { + std::cout << "caught exception: " << e.what() << std::endl; + } +} + + +void +test2c () +{ + try + { + print (grow (1000, 100)); // overflow + } + catch (const IEX_INTERNAL_NAMESPACE::OverflowExc &e) + { + std::cout << "caught exception: " << e.what() << std::endl; + } +} + + +void +test2 () +{ + // + // Turn math exception handling on, and verify that C++ exceptions + // are thrown when "exceptional" floating-point operations are + // performed. + // + + std::cout << "invalid operations / exception handling on" << std::endl; + + IEX_INTERNAL_NAMESPACE::mathExcOn (IEX_INTERNAL_NAMESPACE::IEEE_OVERFLOW | IEX_INTERNAL_NAMESPACE::IEEE_DIVZERO | IEX_INTERNAL_NAMESPACE::IEEE_INVALID); + + for (int i = 0; i < 3; ++i) + { + test2a(); + test2b(); + test2c(); + } +} + + +void +test3 () +{ + // + // Verify that getMathExcOn() returns the value that + // was most recently set with setMathExcOn(). + // + + +#if defined(HAVE_UCONTEXT_H) && \ + (defined(IEX_HAVE_SIGCONTEXT_CONTROL_REGISTER_SUPPORT) || \ + defined(IEX_HAVE_CONTROL_REGISTER_SUPPORT)) + + std::cout << "getMathExc()" << std::endl; + + int when = 0; + + IEX_INTERNAL_NAMESPACE::mathExcOn (when); + assert (IEX_INTERNAL_NAMESPACE::getMathExcOn() == when); + + when = IEX_INTERNAL_NAMESPACE::IEEE_OVERFLOW; + + IEX_INTERNAL_NAMESPACE::mathExcOn (when); + assert (IEX_INTERNAL_NAMESPACE::getMathExcOn() == when); + + when = IEX_INTERNAL_NAMESPACE::IEEE_DIVZERO; + + IEX_INTERNAL_NAMESPACE::mathExcOn (when); + assert (IEX_INTERNAL_NAMESPACE::getMathExcOn() == when); + + when = IEX_INTERNAL_NAMESPACE::IEEE_INVALID; + + IEX_INTERNAL_NAMESPACE::mathExcOn (when); + assert (IEX_INTERNAL_NAMESPACE::getMathExcOn() == when); + + when = IEX_INTERNAL_NAMESPACE::IEEE_OVERFLOW | IEX_INTERNAL_NAMESPACE::IEEE_DIVZERO | IEX_INTERNAL_NAMESPACE::IEEE_INVALID; + + IEX_INTERNAL_NAMESPACE::mathExcOn (when); + assert (IEX_INTERNAL_NAMESPACE::getMathExcOn() == when); +#endif +} + +} // namespace + + +void +testMathExc() +{ + std::cout << "See if floating-point exceptions work:" << std::endl; + + test1(); + test2(); + test3(); + + std::cout << " ok" << std::endl; +} diff --git a/src/test/IexTest/testMathExc.h b/src/test/IexTest/testMathExc.h new file mode 100644 index 0000000000..89c8d507bb --- /dev/null +++ b/src/test/IexTest/testMathExc.h @@ -0,0 +1,3 @@ + +void testMathExc(); +