util/cexec: Implement exception helpers
See src/stdplus/util/cexec.hpp callCheckErrno for the motivation behind
this change.
Change-Id: I0225b87398b632624f2ef8ccd6c00b5dd6b7e056
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/util/cexec.cpp b/test/util/cexec.cpp
new file mode 100644
index 0000000..51fdb8b
--- /dev/null
+++ b/test/util/cexec.cpp
@@ -0,0 +1,230 @@
+#include <gtest/gtest.h>
+#include <stdplus/util/cexec.hpp>
+#include <string_view>
+#include <system_error>
+
+namespace stdplus
+{
+namespace util
+{
+namespace
+{
+
+int sample1()
+{
+ return 1;
+}
+
+int sample2(int val)
+{
+ return val;
+}
+
+ssize_t sample3(int val, ssize_t* val2)
+{
+ return *val2 + val;
+}
+
+const char* ptr(const char* p)
+{
+ return p;
+}
+
+struct sample
+{
+ int count = 3;
+
+ int one()
+ {
+ return count++;
+ }
+
+ int two(int val) const
+ {
+ return val;
+ }
+
+ int* ptr()
+ {
+ return &count;
+ }
+
+ int* ptr2()
+ {
+ return nullptr;
+ }
+
+ static int s(int val)
+ {
+ return val;
+ }
+};
+
+int makeTrivialError(int error, const char* msg)
+{
+ (void)msg;
+ return error;
+}
+
+TEST(Cexec, CallCheckErrnoInt)
+{
+ EXPECT_EQ(1, callCheckErrno("sample1", sample1));
+ EXPECT_EQ(2, callCheckErrno("sample2", &sample2, 2));
+ EXPECT_EQ(4, callCheckErrno("sample::s", sample::s, 4));
+ ssize_t v = 10;
+ EXPECT_EQ(12, callCheckErrno("sample3", sample3, 2, &v));
+
+ constexpr auto error = "sample2 error";
+ try
+ {
+ errno = EBADF;
+ callCheckErrno(error, sample2, -1);
+ EXPECT_TRUE(false);
+ }
+ catch (const std::system_error& e)
+ {
+ EXPECT_EQ(std::string_view(error),
+ std::string_view(e.what(), strlen(error)));
+ EXPECT_EQ(EBADF, e.code().value());
+ }
+}
+
+TEST(Cexec, CallCheckErrnoIntMem)
+{
+ sample s;
+ const sample* sp = &s;
+ EXPECT_EQ(3, callCheckErrno("sample::one", &sample::one, s));
+ EXPECT_EQ(4, callCheckErrno("sample::one", &sample::one, &s));
+ EXPECT_EQ(5, callCheckErrno("sample::two", &sample::two, sp, 5));
+
+ constexpr auto error = "sample error";
+ try
+ {
+ errno = EBADF;
+ callCheckErrno(error, &sample::two, sp, -1);
+ EXPECT_TRUE(false);
+ }
+ catch (const std::system_error& e)
+ {
+ EXPECT_EQ(std::string_view(error),
+ std::string_view(e.what(), strlen(error)));
+ EXPECT_EQ(EBADF, e.code().value());
+ }
+}
+
+TEST(Cexec, CallCheckErrnoPtr)
+{
+ constexpr auto sample = "sample";
+ EXPECT_EQ(sample, callCheckErrno("sample1", ptr, sample));
+
+ constexpr auto error = "sample error";
+ try
+ {
+ errno = EBADF;
+ callCheckErrno(error, &ptr, nullptr);
+ EXPECT_TRUE(false);
+ }
+ catch (const std::system_error& e)
+ {
+ EXPECT_EQ(std::string_view(error),
+ std::string_view(e.what(), strlen(error)));
+ EXPECT_EQ(EBADF, e.code().value());
+ }
+}
+
+TEST(Cexec, CallCheckErrnoPtrMem)
+{
+ sample s;
+ EXPECT_EQ(&s.count, callCheckErrno("sample1", &sample::ptr, &s));
+
+ constexpr auto error = "sample error";
+ try
+ {
+ errno = EBADF;
+ callCheckErrno(error, &sample::ptr2, s);
+ EXPECT_TRUE(false);
+ }
+ catch (const std::system_error& e)
+ {
+ EXPECT_EQ(std::string_view(error),
+ std::string_view(e.what(), strlen(error)));
+ EXPECT_EQ(EBADF, e.code().value());
+ }
+}
+
+TEST(Cexec, CallCheckErrnoErrorFunc)
+{
+ errno = EBADF;
+ try
+ {
+ callCheckErrno<makeTrivialError>("sample2", sample2, -1);
+ EXPECT_TRUE(false);
+ }
+ catch (int error)
+ {
+ EXPECT_EQ(errno, error);
+ }
+}
+
+TEST(Cexec, CallCheckRetInt)
+{
+ EXPECT_EQ(1, callCheckRet("sample1", sample1));
+ EXPECT_EQ(2, callCheckRet("sample2", &sample2, 2));
+ EXPECT_EQ(4, callCheckRet("sample::s", sample::s, 4));
+ ssize_t v = 10;
+ EXPECT_EQ(12, callCheckRet("sample3", sample3, 2, &v));
+
+ constexpr auto error = "sample2 error";
+ try
+ {
+ errno = EBADF;
+ callCheckRet(error, sample2, -EINTR);
+ EXPECT_TRUE(false);
+ }
+ catch (const std::system_error& e)
+ {
+ EXPECT_EQ(std::string_view(error),
+ std::string_view(e.what(), strlen(error)));
+ EXPECT_EQ(EINTR, e.code().value());
+ }
+}
+
+TEST(Cexec, CallCheckRetIntMem)
+{
+ sample s;
+ const sample* sp = &s;
+ EXPECT_EQ(3, callCheckRet("sample::one", &sample::one, s));
+ EXPECT_EQ(4, callCheckRet("sample::one", &sample::one, &s));
+ EXPECT_EQ(5, callCheckRet("sample::two", &sample::two, sp, 5));
+
+ constexpr auto error = "sample error";
+ try
+ {
+ errno = EBADF;
+ callCheckRet(error, &sample::two, s, -EINTR);
+ EXPECT_TRUE(false);
+ }
+ catch (const std::system_error& e)
+ {
+ EXPECT_EQ(std::string_view(error),
+ std::string_view(e.what(), strlen(error)));
+ EXPECT_EQ(EINTR, e.code().value());
+ }
+}
+
+TEST(Cexec, CallCheckRetErrorFunc)
+{
+ try
+ {
+ callCheckRet<makeTrivialError>("sample2", sample2, -EBADF);
+ EXPECT_TRUE(false);
+ }
+ catch (int error)
+ {
+ EXPECT_EQ(EBADF, error);
+ }
+}
+
+} // namespace
+} // namespace util
+} // namespace stdplus