Add tryCatch and exceptions messages tests 47/234647/6
authorZofia Abramowska <z.abramowska@samsung.com>
Mon, 25 May 2020 16:29:38 +0000 (18:29 +0200)
committerZofia Abramowska <z.abramowska@samsung.com>
Thu, 9 Jul 2020 18:05:24 +0000 (20:05 +0200)
Change-Id: I1d82762ca73e491821336b069570ac961e38c8a8

test/CMakeLists.txt
test/common/exceptions/trycatch.cpp [new file with mode: 0644]

index 6e200a9571a390206e4894f479b1458189013366..5d080e7c4425cddc35ba0555a5524e03b65ea173 100644 (file)
@@ -115,6 +115,7 @@ SET(CYNARA_TESTS_SOURCES
     common/containers/binaryqueue.cpp
     common/error/safestrerror.cpp
     common/exceptions/bucketrecordcorrupted.cpp
+    common/exceptions/trycatch.cpp
     common/protocols/admin/admincheckrequest.cpp
     common/protocols/admin/admincheckresponse.cpp
     common/protocols/admin/descriptionlistrequest.cpp
diff --git a/test/common/exceptions/trycatch.cpp b/test/common/exceptions/trycatch.cpp
new file mode 100644 (file)
index 0000000..6288531
--- /dev/null
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+/**
+ * @file        test/common/exceptions/trycatch.cpp
+ * @author      Zofia Abramowska <z.abramowska@samsung.com>
+ * @version     1.0
+ * @brief       Tests for tryCatch function
+ */
+
+#include <common/exceptions/TryCatch.h>
+#include <common/exceptions/Exception.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <cstring>
+#include <exception>
+#include <functional>
+#include <iostream>
+#include <limits>
+#include <map>
+#include <string>
+
+#include <cxxabi.h>
+#include <pthread.h>
+
+#include <common/exceptions/Exception.h>
+
+#include <common/exceptions/AccessDeniedException.h>
+#include <common/exceptions/BucketDeserializationException.h>
+#include <common/exceptions/BucketNotExistsException.h>
+#include <common/exceptions/BucketRecordCorruptedException.h>
+#include <common/exceptions/BucketSerializationException.h>
+#include <common/exceptions/CannotCreateFileException.h>
+#include <common/exceptions/ChecksumRecordCorruptedException.h>
+#include <common/exceptions/ContextErrorException.h>
+#include <common/exceptions/DatabaseBusyException.h>
+#include <common/exceptions/DatabaseCorruptedException.h>
+#include <common/exceptions/DatabaseReadException.h>
+#include <common/exceptions/DatabaseWriteException.h>
+#include <common/exceptions/DefaultBucketDeletionException.h>
+#include <common/exceptions/DefaultBucketSetNoneException.h>
+#include <common/exceptions/DescriptorNotExistsException.h>
+#include <common/exceptions/FileLockAcquiringException.h>
+#include <common/exceptions/FileNotFoundException.h>
+#include <common/exceptions/InitException.h>
+#include <common/exceptions/InvalidBucketIdException.h>
+#include <common/exceptions/InvalidProtocolException.h>
+#include <common/exceptions/NoMemoryException.h>
+#include <common/exceptions/NotImplementedException.h>
+#include <common/exceptions/NullPointerException.h>
+#include <common/exceptions/OutOfDataException.h>
+#include <common/exceptions/PluginErrorException.h>
+#include <common/exceptions/PluginNotFoundException.h>
+#include <common/exceptions/UnexpectedErrorException.h>
+#include <common/exceptions/UnknownPolicyTypeException.h>
+#include <common/exceptions/TryCatch.h>
+
+#include <cynara-error.h>
+
+namespace {
+
+const std::string SOME_ERROR = "some error";
+const std::string SOME_BUCKET = "someBucket";
+const std::string SOME_LINE = "some line";
+const std::string SOME_FILE = "some.file";
+
+} // namespace anonymous
+
+class DerivedException : public Cynara::Exception {
+public:
+    DerivedException() {}
+    DerivedException(const DerivedException &) {}
+
+    const std::string &message() const {
+        return SOME_ERROR;
+    };
+};
+
+TEST(TryCatch, forcedUnwindNegative)
+{
+    pthread_t id;
+    int ret = pthread_create(&id, nullptr, [](void *)
+        {
+            Cynara::tryCatch([](){
+                while(1) {
+                    sleep(5);
+                }
+                return CYNARA_API_SUCCESS;
+            });
+
+        return (void *)nullptr;
+        },
+        nullptr);
+
+    ASSERT_EQ(ret, 0);
+    ASSERT_EQ(pthread_cancel(id), 0);
+
+    void *res;
+    ASSERT_EQ(pthread_join(id, &res), 0);
+    ASSERT_EQ(res, PTHREAD_CANCELED);
+}
+
+TEST(TryCatch, stdExceptionNegative)
+{
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw std::runtime_error("some error"); return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, stdBadAllocNegative)
+{
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw std::bad_alloc(); return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_OUT_OF_MEMORY);
+}
+
+TEST(TryCatch, derivedExceptionNegative)
+{
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw DerivedException(); return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, accessDeniedExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::AccessDeniedException e(SOME_ERROR);
+    ASSERT_THAT(e.what(), StartsWith("Access denied from: " + SOME_ERROR));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_PERMISSION_DENIED);
+}
+
+TEST(TryCatch, bucketDeserializationExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::BucketDeserializationException e(SOME_BUCKET);
+    ASSERT_THAT(e.what(), StartsWith("Could not deserialize bucket " + SOME_BUCKET));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, bucketNotExistsExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::BucketNotExistsException e(SOME_BUCKET);
+    ASSERT_THAT(e.what(), StartsWith("Bucket " + SOME_BUCKET + " does not exist"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, bucketRecordCorruptionExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::BucketRecordCorruptedException e(SOME_LINE);
+    ASSERT_THAT(e.what(), StartsWith("Bucket record corrupted at line: <" + SOME_LINE + ">"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, bucketSerializationExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::BucketSerializationException e(SOME_BUCKET);
+    ASSERT_THAT(e.what(), StartsWith("Could not serialize bucket " + SOME_BUCKET));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, cannotCreateFileExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::CannotCreateFileException e(SOME_FILE);
+    ASSERT_THAT(e.what(), StartsWith("File " + SOME_FILE + " cannot be created"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, checksumRecordCorruptedExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::ChecksumRecordCorruptedException e(SOME_LINE);
+    ASSERT_THAT(e.what(), StartsWith("Checksum record corrupted at line: <" + SOME_LINE + ">"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, contextErrorExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::ContextErrorException e;
+    ASSERT_THAT(e.what(), StartsWith("ContextErrorException"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, databaseBusyExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::DatabaseBusyException e;
+    ASSERT_THAT(e.what(), StartsWith("Database busy"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, databaseCorruptedExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::DatabaseCorruptedException e;
+    ASSERT_THAT(e.what(), StartsWith("DatabaseCorruptedException"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, databaseReadExceptionNegative)
+{
+    using ::testing::StartsWith;
+    const std::string SOME_OP = "some operation";
+
+    Cynara::DatabaseReadException e(SOME_FILE, SOME_OP);
+    ASSERT_THAT(e.what(),
+                StartsWith("Loading the database from the file <" + SOME_FILE
+                    + "> failed during " + SOME_OP));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, databaseWriteExceptionNegative)
+{
+    using ::testing::StartsWith;
+    const std::string SOME_OP = "some operation";
+
+    Cynara::DatabaseWriteException e(SOME_FILE, SOME_OP);
+    ASSERT_THAT(e.what(),
+                StartsWith("Saving the database to file <" + SOME_FILE
+                    + "> failed during " + SOME_OP));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, defaultBucketDeletionExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::DefaultBucketDeletionException e;
+    ASSERT_THAT(e.what(), StartsWith("DefaultBucketDeletionException"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, defaultBucketSetNoneExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::DefaultBucketSetNoneException e;
+    ASSERT_THAT(e.what(), StartsWith("DefaultBucketSetNoneException"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, descriptorNotExistsExceptionNegative)
+{
+    using ::testing::StartsWith;
+    const int SOME_DSCR = 42;
+
+    Cynara::DescriptorNotExistsException e(SOME_DSCR);
+    ASSERT_THAT(e.what(), StartsWith("trying access not existing descriptor ["
+                                     + std::to_string(SOME_DSCR) + "]"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, fileLockAcquiringExceptionNegative)
+{
+    using ::testing::StartsWith;
+    const int SOME_ERRNO = 42;
+    const std::string SOME_ERRNO_STR = strerror(SOME_ERRNO);
+
+    Cynara::FileLockAcquiringException e(SOME_ERRNO);
+
+    ASSERT_THAT(e.what(),
+                StartsWith("File lock acquiring error [" + std::to_string(SOME_ERRNO) + "]"
+                    + " <" + SOME_ERRNO_STR + ">"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, fileNotFoundExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::FileNotFoundException e(SOME_FILE);
+    ASSERT_THAT(e.what(),
+                StartsWith("File " + SOME_FILE + " not found or corrupted badly"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, initExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::InitException e;
+    ASSERT_THAT(e.what(), StartsWith("InitException"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, invalidBucketIdExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::InvalidBucketIdException e(SOME_BUCKET);
+    ASSERT_THAT(e.what(),
+                StartsWith("Bucket ID " + SOME_BUCKET + " contains forbidden characters"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, invalidProtocolExceptionNegative)
+{
+    using ::testing::StartsWith;
+    const std::map<Cynara::InvalidProtocolException::ExceptionType, std::string>
+        INVALID_PROTOCOL_EXCEPTION_TYPE_TO_STRING = {
+        {Cynara::InvalidProtocolException::ExceptionType::InvalidSignature,
+         "No valid signature found"},
+        {Cynara::InvalidProtocolException::ExceptionType::WrongOpCode,
+         "Wrong request code"},
+        {Cynara::InvalidProtocolException::ExceptionType::IdentifierTooLong,
+         "Identifier too long"},
+        {Cynara::InvalidProtocolException::ExceptionType::Other,
+         "Unknown problem"}
+    };
+
+    for (auto& typeToString : INVALID_PROTOCOL_EXCEPTION_TYPE_TO_STRING) {
+        Cynara::InvalidProtocolException e(typeToString.first);
+        ASSERT_THAT(e.what(), StartsWith(typeToString.second));
+    }
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() {
+        throw Cynara::InvalidProtocolException(
+            Cynara::InvalidProtocolException::ExceptionType::Other);
+        return ret;
+    };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_INVALID_PARAM);
+}
+
+TEST(TryCatch, noMemoryExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::NoMemoryException e(SOME_ERROR);
+    ASSERT_THAT(e.what(), StartsWith("NoMemoryException with message <" + SOME_ERROR + ">"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_OUT_OF_MEMORY);
+}
+
+TEST(TryCatch, notImplementedExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    Cynara::NotImplementedException e;
+    ASSERT_THAT(e.what(), StartsWith("NotImplementedException"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, nullPointerExceptionNegative)
+{
+    using ::testing::StartsWith;
+    const std::string SOME_VAR = "someVar";
+
+    Cynara::NullPointerException e(SOME_VAR.c_str());
+    ASSERT_THAT(e.what(),
+                StartsWith("unexpected null value in variable <" + SOME_VAR + ">"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, outOfDataExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    const int SOME_RANGE = 42;
+    const int SOME_ACCESS = 4242;
+
+    Cynara::OutOfDataException e(SOME_RANGE, SOME_ACCESS);
+    ASSERT_THAT(e.what(),
+                StartsWith("trying access [" + std::to_string(SOME_ACCESS) + "]"
+                           + " which exceeds data range [" + std::to_string(SOME_RANGE) + "]"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, pluginErrorExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    const Cynara::PolicyKey SOME_KEY("someClient", "someUser", "somePrivilege");
+
+    Cynara::PluginErrorException e(SOME_KEY);
+    ASSERT_THAT(e.what(),
+                StartsWith("Plugin couldn't get result for user <"
+                           + SOME_KEY.user().toString() + ">, "
+                           "client <" + SOME_KEY.client().toString() + ">, "
+                           "privilege <" + SOME_KEY.privilege().toString() + ">"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, pluginNotFoundExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    const Cynara::PolicyResult SOME_RESULT(42);
+
+    Cynara::PluginNotFoundException e(SOME_RESULT);
+    ASSERT_THAT(e.what(),
+                StartsWith("No proper plugin found to interprete PolicyResult {type = ["
+                  + std::to_string(SOME_RESULT.policyType()) + "], metadata = <"
+                  + SOME_RESULT.metadata().substr(0, 20) + ">}"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, unexpectedErrorExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    const int SOME_ERROR_CODE = 42;
+    const char *SOME_ERROR_CSTR = "some error cstr";
+
+    Cynara::UnexpectedErrorException e1(SOME_ERROR_CODE, SOME_ERROR_CSTR);
+    ASSERT_THAT(e1.what(),
+                StartsWith("UnexpectedErrorException with errorCode =["
+                           + std::to_string(SOME_ERROR_CODE)
+                           + "] and message <" + SOME_ERROR_CSTR + ">"));
+    Cynara::UnexpectedErrorException e2(SOME_ERROR_CODE, SOME_ERROR);
+    ASSERT_THAT(e2.what(),
+                StartsWith("UnexpectedErrorException with errorCode =["
+                           + std::to_string(SOME_ERROR_CODE)
+                           + "] and message <" + SOME_ERROR + ">"));
+    Cynara::UnexpectedErrorException e3(SOME_ERROR);
+    ASSERT_THAT(e3.what(),
+                StartsWith("UnexpectedErrorException with message <" + SOME_ERROR + ">"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e1; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, unknownPolicyTypeExceptionNegative)
+{
+    using ::testing::StartsWith;
+
+    const Cynara::PolicyType SOME_POLICY_TYPE = 42;
+
+    Cynara::UnknownPolicyTypeException e(SOME_POLICY_TYPE);
+    ASSERT_THAT(e.what(),
+                StartsWith("Unknown PolicyType [" + std::to_string(SOME_POLICY_TYPE) + "]"));
+
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw e; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, throwSomeNegative)
+{
+    int ret = CYNARA_API_SUCCESS;
+    auto throwFun = [&]() { throw "some error"; return ret; };
+
+    ASSERT_NO_THROW(ret = Cynara::tryCatch(throwFun));
+    ASSERT_EQ(ret, CYNARA_API_UNKNOWN_ERROR);
+}
+
+TEST(TryCatch, returnValuePositive)
+{
+    for (int i = CYNARA_API_PERMISSION_DENIED; i <= CYNARA_API_INTERRUPTED; i++) {
+        // set initial value to different than expected
+        int ret = i + 1;
+        auto returnFun = [&](){ return i; };
+        ASSERT_NO_THROW(ret = Cynara::tryCatch(returnFun));
+        ASSERT_EQ(ret, i);
+    }
+}
+