Merging tizen into ckm. Stage 3. 21/38321/1
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 16 Apr 2015 10:17:53 +0000 (12:17 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 16 Apr 2015 10:26:31 +0000 (12:26 +0200)
Merged remote-tracking branch 'tizen.org/tizen' into ckm

Change-Id: Iffa2e26113f653cf4c6f685bc7e4dc7d25472ae5

60 files changed:
CMakeLists.txt
README
packaging/security-tests.spec
src/common/CMakeLists.txt
src/common/db_sqlite.h
src/common/passwd_access.cpp [new file with mode: 0644]
src/common/passwd_access.h [new file with mode: 0644]
src/common/service_manager.cpp
src/common/synchronization_pipe.cpp [new file with mode: 0644]
src/common/synchronization_pipe.h [new file with mode: 0644]
src/common/timeout.cpp [new file with mode: 0644]
src/common/timeout.h
src/common/uds.cpp [new file with mode: 0644]
src/common/uds.h [new file with mode: 0644]
src/cynara-tests/CMakeLists.txt
src/cynara-tests/common/cynara_test_agent.cpp
src/cynara-tests/common/cynara_test_agent_request.cpp
src/cynara-tests/common/cynara_test_client_async_client.cpp
src/cynara-tests/common/cynara_test_client_async_request_monitor.cpp
src/cynara-tests/common/cynara_test_client_async_status_monitor.cpp
src/cynara-tests/common/cynara_test_commons.cpp
src/cynara-tests/common/cynara_test_env.cpp
src/cynara-tests/common/cynara_test_env.h
src/cynara-tests/common/cynara_test_file_operations.cpp
src/cynara-tests/common/cynara_test_file_operations.h
src/cynara-tests/db_patterns/default/checksum [new file with mode: 0644]
src/cynara-tests/db_patterns/defaultAllowed/checksum [new file with mode: 0644]
src/cynara-tests/db_patterns/nonEmptyDatabase/checksum [new file with mode: 0644]
src/cynara-tests/test_cases_agent.cpp [new file with mode: 0644]
src/cynara-tests/test_cases_db.cpp
src/framework/config.cmake
src/framework/include/dpl/test/performance_result.h [new file with mode: 0644]
src/framework/include/dpl/test/statistic.h
src/framework/include/dpl/test/test_exception.h [new file with mode: 0644]
src/framework/include/dpl/test/test_failed.h [new file with mode: 0644]
src/framework/include/dpl/test/test_ignored.h [new file with mode: 0644]
src/framework/include/dpl/test/test_result.h [new file with mode: 0644]
src/framework/include/dpl/test/test_results_collector.h
src/framework/include/dpl/test/test_results_collector_commons.h
src/framework/include/dpl/test/test_results_collector_console.h
src/framework/include/dpl/test/test_results_collector_html.h
src/framework/include/dpl/test/test_results_collector_summary.h
src/framework/include/dpl/test/test_results_collector_xml.h
src/framework/include/dpl/test/test_runner.h
src/framework/include/dpl/test/test_runner_child.h
src/framework/src/test_failed.cpp [new file with mode: 0644]
src/framework/src/test_results_collector_commons.cpp
src/framework/src/test_results_collector_console.cpp
src/framework/src/test_results_collector_html.cpp
src/framework/src/test_results_collector_summary.cpp
src/framework/src/test_results_collector_xml.cpp
src/framework/src/test_runner.cpp
src/framework/src/test_runner_child.cpp
src/framework/src/test_runner_multiprocess.cpp
src/security-tests-all.sh
src/security-tests.sh
tests/CMakeLists.txt [new file with mode: 0644]
tests/common/test_cases_timeout.cpp [new file with mode: 0644]
tests/framework/test_cases_deferred.cpp [new file with mode: 0644]
tests/inner-test.cpp [new file with mode: 0644]

index 99f65e4..8b76681 100644 (file)
@@ -86,3 +86,4 @@ SET(COMMON_TARGET_TEST "tests-common")
 ############################# subdirectories ##################################
 
 ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(tests)
diff --git a/README b/README
index 87a2bed..c946fe7 100644 (file)
--- a/README
+++ b/README
@@ -26,6 +26,10 @@ security-manager
 cynara
   cynara-test
 
+There are also inner-tests for testing complex security-tests framework
+mechanisms with binary:
+  security-tests-inner-test
+
 ==HOW TO RUN===================================================================
 
 Each test suite may be run with options:
@@ -152,6 +156,25 @@ dpl-test-framework
     RUNNER_ERROR_MSG
           Print error message using red color.
 
+--Defer macros-----------------------------------------------------------------
+Used to defer throwing TestException exceptions (TestFailed, TestIgnored)
+by catching them and rethrowing later. This mechanism can help in breaking
+test and passing test result from places where throwing exceptions
+is not allowed
+
+dpl-test-framework
+  test_runner.h
+    RUNNER_DEFER_TRYCATCH
+          Catches thrown TestException exceptions and stores them in TestRunner
+          structures for later use. This macro works only inside deffered scope
+          defined by RUNNER_DEFER_SCOPE, otherwise it won't catch exceptions
+    RUNNER_DEFER_SCOPE
+          Defines deferred scope. All RUNNER_DEFER_TRYCATCH macros used inside
+          the scope catch and save TestException exceptions. After scope is left
+          all saved exceptions take part in setting result of test. If there
+          is no any uncaught exception then additionally first of saved
+          exceptions is thrown.
+
 --Collectors-------------------------------------------------------------------
 Collectors are classes which collect test results. Each class does it differently.
 Collectors can be registered by --output parameter (see HOW TO RUN section) but
index 8b561ac..fac0fe8 100644 (file)
@@ -59,13 +59,13 @@ make %{?jobs:-j%jobs}
 ln -sf /etc/smack/test_smack_rules %{buildroot}/etc/smack/test_smack_rules_lnk
 
 %post
-%{_bindir}/gum-utils --add-user --username=security-tests-app --usertype=4 --offline
+%{_bindir}/gum-utils --add-user --username=security-tests-app --usertype=normal --offline
 
 find /etc/smack/test_privilege_control_DIR/ -type f -name exec -exec chmod 0755 {} +
 find /usr/apps/test_DIR/ -type f -name exec -exec chmod 0755 {} +
 
 # Load permissions templates
-api_feature_loader --verbose --clear-permissions
+api_feature_loader --verbose
 
 # Set vconf key for cc-mode testing if vconf key isn't there.
 %if "%{sec_product_feature_security_mdfpp_enable}" != "1"
@@ -118,3 +118,4 @@ echo "security-tests postinst done ..."
 /usr/lib/security-tests/cynara-tests/plugins/single-policy/*
 /usr/lib/security-tests/cynara-tests/plugins/multiple-policy/*
 /usr/lib/security-tests/cynara-tests/plugins/test-agent/*
+/usr/bin/security-tests-inner-test
index 11a444f..fcfc13f 100644 (file)
@@ -20,6 +20,10 @@ SET(COMMON_TARGET_TEST_SOURCES
     ${PROJECT_SOURCE_DIR}/src/common/memory.cpp
     ${PROJECT_SOURCE_DIR}/src/common/db_sqlite.cpp
     ${PROJECT_SOURCE_DIR}/src/common/fs_label_manager.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/passwd_access.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/uds.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/synchronization_pipe.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/timeout.cpp
     )
 
 #system and local includes
index 9a17083..42092cf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2012-2015 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.
@@ -115,14 +115,14 @@ public:
  *
  * If database is already opened do nothing.
  *
- * @throw DPL::Test::TestRunner::TestFailed    when opening database fails
+ * @throw DPL::Test::TestFailed    when opening database fails
  */
     void open(void);
 
 /**
  * @brief Close database.
  *
- * @throw DPL::Test::TestRunner::TestFailed    when closing database fails
+ * @throw DPL::Test::TestFailed    when closing database fails
  */
     void close(void);
 
@@ -140,7 +140,7 @@ public:
  * @param sql_query     SQL query
  * @param result        returned result
  *
- * @throw DPL::Test::TestRunner::TestFailed    when execution of query fails
+ * @throw DPL::Test::TestFailed    when execution of query fails
  */
     void execute(const std::string& sql_query, Sqlite3DBaseSelectResult& result);
 
diff --git a/src/common/passwd_access.cpp b/src/common/passwd_access.cpp
new file mode 100644 (file)
index 0000000..6f55549
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 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        passwd_access.cpp
+ * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version     1.0
+ * @brief       Provides access to UID and GID
+ */
+
+#include <cerrno>
+#include <grp.h>
+#include <pwd.h>
+
+#include <dpl/test/test_runner.h>
+
+#include "passwd_access.h"
+
+namespace PasswdAccess {
+    uid_t uid(const std::string &username) {
+        struct passwd *passwd = nullptr;
+        do {
+            errno = 0;
+            passwd = getpwnam(username.c_str());
+        } while (passwd == nullptr && errno == EINTR);
+        RUNNER_ASSERT_ERRNO_MSG(passwd != nullptr, "Error in getpwnam(). Username: " << username);
+        return passwd->pw_uid;
+    }
+
+    gid_t gid(const std::string &groupname) {
+        struct group *group = nullptr;
+        do {
+            errno = 0;
+            group = getgrnam(groupname.c_str());
+        } while (group == nullptr && errno == EINTR);
+        RUNNER_ASSERT_ERRNO_MSG(group != nullptr, "Error in getgrnam(). Groupname: " << groupname);
+        return group->gr_gid;
+    }
+} // namespace PasswdAccess
diff --git a/src/common/passwd_access.h b/src/common/passwd_access.h
new file mode 100644 (file)
index 0000000..3638828
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015 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        passwd_access.h
+ * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version     1.0
+ * @brief       Provides access to UID and GID
+ */
+
+#ifndef TESTS_COMMON_PASSWD_ACCESS_H_
+#define TESTS_COMMON_PASSWD_ACCESS_H_
+
+#include <string>
+#include <sys/types.h>
+
+namespace PasswdAccess {
+    uid_t uid(const std::string &username);
+    gid_t gid(const std::string &groupname);
+} // namespace PasswdAccess
+
+#endif // TESTS_COMMON_PASSWD_ACCESS_H_
index 7321f77..5349171 100644 (file)
@@ -54,7 +54,7 @@ ServiceManager::ServiceManager(const std::string &serviceName)
     addBusMatch(MATCH_RELOADING);
     m_connection.flush();
     m_connection.addFilter(messageHandler,
-                           reinterpret_cast<void*>(this));
+                           static_cast<void*>(this));
     subscribeSignals();
     m_connection.requestName(DBUS_CLIENT_NAME);
     getUnitPath();
@@ -190,7 +190,7 @@ void ServiceManager::sendResetFailedToService()
 DBusHandlerResult ServiceManager::messageHandler(DBusConnection *conn, DBusMessage *msg, void *t)
 {
     (void) conn;
-    ServiceManager* self = reinterpret_cast<ServiceManager*>(t);
+    ServiceManager* self = static_cast<ServiceManager*>(t);
 
     DBus::MessageIn messageIn(msg, true);
     if (messageIn.isSignal(SYSTEMD_MANAGER_INTERFACE, MATCH_JOB_REMOVED))
diff --git a/src/common/synchronization_pipe.cpp b/src/common/synchronization_pipe.cpp
new file mode 100644 (file)
index 0000000..dcf9d30
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 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        synchronization_pipe.cpp
+ * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version     1.0
+ * @brief       A crippled abstraction of widely praised, but often misused communication mechanism
+ */
+
+#include <stdexcept>
+#include <unistd.h>
+
+#include <dpl/test/test_runner.h>
+
+#include "synchronization_pipe.h"
+
+static void closeFd(int *fd) {
+    if (*fd > -1) {
+        close(*fd);
+        *fd = -1;
+    }
+}
+
+SynchronizationPipe::SynchronizationPipe() {
+    auto ret = pipe(m_pipeCP);
+    RUNNER_ASSERT_ERRNO_MSG(ret == 0, "pipe failed");
+
+    ret = pipe(m_pipePC);
+    RUNNER_ASSERT_ERRNO_MSG(ret == 0, "pipe failed");
+}
+
+SynchronizationPipe::~SynchronizationPipe() {
+    closeFd(m_pipeCP + 0);
+    closeFd(m_pipeCP + 1);
+    closeFd(m_pipePC + 0);
+    closeFd(m_pipePC + 1);
+}
+
+void SynchronizationPipe::claimParentEp() {
+    if (m_epClaimed)
+        return;
+
+    m_readEp = m_pipeCP[0];
+    closeFd(m_pipeCP + 1);
+
+    m_writeEp = m_pipePC[1];
+    closeFd(m_pipePC + 0);
+
+    m_epClaimed = true;
+}
+
+void SynchronizationPipe::claimChildEp() {
+    if (m_epClaimed)
+        return;
+
+    m_readEp = m_pipePC[0];
+    closeFd(m_pipePC + 1);
+
+    m_writeEp = m_pipeCP[1];
+    closeFd(m_pipeCP + 0);
+
+    m_epClaimed = true;
+}
+
+void SynchronizationPipe::post() {
+    RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
+    auto ret = TEMP_FAILURE_RETRY(write(m_writeEp, "#", 1));
+    RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Write failed ret = " << ret);
+}
+
+void SynchronizationPipe::wait() {
+    RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
+
+    char buf;
+    auto ret = TEMP_FAILURE_RETRY(read(m_readEp, &buf, 1));
+    RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Read failed ret = " << ret);
+}
diff --git a/src/common/synchronization_pipe.h b/src/common/synchronization_pipe.h
new file mode 100644 (file)
index 0000000..e072ca2
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 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        synchronization_pipe.h
+ * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version     1.0
+ * @brief       A crippled abstraction of widely praised, but often misused communication mechanism
+ */
+
+#ifndef TESTS_COMMON_SYNCHRONIZATION_PIPE_H_
+#define TESTS_COMMON_SYNCHRONIZATION_PIPE_H_
+
+class SynchronizationPipe {
+public:
+    SynchronizationPipe();
+    ~SynchronizationPipe();
+
+    void claimParentEp();
+    void claimChildEp();
+
+    void post();
+    void wait();
+
+private:
+    int m_pipeCP[2];    // Child -> Parent
+    int m_pipePC[2];    // Parent -> Child
+    int m_readEp = -1;
+    int m_writeEp = -1;
+    bool m_epClaimed = false;
+};
+
+#endif // TESTS_COMMON_SYNCHRONIZATION_PIPE_H_
diff --git a/src/common/timeout.cpp b/src/common/timeout.cpp
new file mode 100644 (file)
index 0000000..c9e1347
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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        timeout.cpp
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @brief       Definition of future_status serialization operator
+ */
+
+#include <timeout.h>
+
+namespace Timeout {
+
+std::ostream& operator<<(std::ostream& os, const std::future_status &status)
+{
+    switch (status) {
+        case std::future_status::ready:
+            os << "<READY>";
+            break;
+        case std::future_status::timeout:
+            os << "<TIMEOUT>";
+            break;
+        case std::future_status::deferred:
+            os << "<DEFERRED>";
+            break;
+    }
+    os << " [" << static_cast<int>(status) << "]";
+    return os;
+}
+
+} // namespace Timeout
index 7e985ab..01ef862 100644 (file)
 #include <chrono>
 #include <functional>
 #include <future>
+#include <type_traits>
 #include <utility>
 
-#include <tests_common.h>
+#include <dpl/test/test_runner.h>
 
 namespace Timeout {
 
 template <class Rep, class Period>
 using Timeout = std::chrono::duration<Rep, Period>;
 
-template <class Ret, class... Args>
-using Function = std::function<Ret(Args...)>;
-
 typedef std::function<void(void)> CancelFunction;
 
 enum ExpectMode {
@@ -45,33 +43,17 @@ enum ExpectMode {
     IGNORE,
 };
 
-std::ostream& operator<<(std::ostream& os, const std::future_status &status)
-{
-    switch (status) {
-        case std::future_status::ready:
-            os << "<READY>";
-            break;
-        case std::future_status::timeout:
-            os << "<TIMEOUT>";
-            break;
-        case std::future_status::deferred:
-            os << "<DEFERRED>";
-            break;
-    }
-    os << " [" << static_cast<int>(status) << "]";
-    return os;
-}
+std::ostream& operator<<(std::ostream& os, const std::future_status &status);
 
-template <class Rep, class Period, class Ret, class... Args>
-Ret callAndWait(const Timeout<Rep, Period> &timeout,
+template <class Rep, class Period, class F, class... Args>
+    typename std::result_of<F(Args...)>::type
+    callAndWait(const Timeout<Rep, Period> &timeout,
                  ExpectMode expect,
                  CancelFunction cancelFunction,
-                 Function<Ret, Args...> function,
-                 Args... args) {
-    RUNNER_ASSERT_MSG(function,
-                         "not empty function must be passed to callAndWait");
+                 F&& function,
+                 Args&&... args) {
 
-    std::future<Ret> fut = std::async(std::launch::async, function, std::forward<Args>(args)...);
+    auto fut = std::async(std::launch::async, function, std::forward<Args>(args)...);
     std::future_status status = fut.wait_for(timeout);
 
     if (status == std::future_status::timeout && cancelFunction)
diff --git a/src/common/uds.cpp b/src/common/uds.cpp
new file mode 100644 (file)
index 0000000..7523539
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 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        uds.cpp
+ * @author      Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version     1.0
+ * @brief       Helpers for Unix Domain Sockets
+ */
+
+#include <cstring>
+#include <poll.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <dpl/test/test_runner.h>
+#include <memory.h>
+
+#include "uds.h"
+
+namespace UDSHelpers {
+
+int createServer(const struct sockaddr_un *sockaddr) {
+    int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    RUNNER_ASSERT_ERRNO_MSG(sock >= 0, "socket failed");
+
+    SockUniquePtr sockPtr(&sock);
+
+    int bindResult = bind(sock, (const struct sockaddr*) sockaddr, sizeof(struct sockaddr_un));
+    RUNNER_ASSERT_ERRNO_MSG(bindResult == 0, "bind failed");
+
+    int listenResult = listen(sock, 1);
+    RUNNER_ASSERT_ERRNO_MSG(listenResult == 0, "listen failed");
+
+    sockPtr.release();
+    return sock;
+}
+
+int createClient(const struct sockaddr_un *sockaddr) {
+    int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    RUNNER_ASSERT_ERRNO_MSG(sock >= 0, "socket failed");
+
+    SockUniquePtr sockPtr(&sock);
+
+    int connectResult = TEMP_FAILURE_RETRY(
+            connect(sock, (const struct sockaddr*) sockaddr, sizeof(struct sockaddr_un)));
+    RUNNER_ASSERT_ERRNO_MSG(connectResult == 0, "connect failed");
+
+    sockPtr.release();
+    return sock;
+}
+
+int acceptClient(int sock) {
+    int clientSock = TEMP_FAILURE_RETRY(accept(sock, NULL, NULL));
+    RUNNER_ASSERT_ERRNO_MSG(clientSock >= 0, "accept failed");
+    return clientSock;
+}
+
+void waitForDisconnect(int sock) {
+    const nfds_t fdCount = 1;
+    const int timeout = -1; // no timeout
+
+    struct pollfd pfd { sock, POLLRDHUP, 0 };
+    int ret = TEMP_FAILURE_RETRY(poll(&pfd, fdCount, timeout));
+    RUNNER_ASSERT_ERRNO_MSG(ret >= 0, "poll failed");
+}
+
+struct sockaddr_un makeAbstractAddress(const std::string &path) {
+    struct sockaddr_un sockaddr;
+    RUNNER_ASSERT_MSG(path.size() <= sizeof(sockaddr.sun_path) - 1, "Socket path too long");
+    memset(&sockaddr, 0, sizeof(struct sockaddr_un));
+    sockaddr.sun_family = AF_UNIX;
+    // Leave '\0' as a first character of path
+    memcpy(sockaddr.sun_path + 1, path.c_str(), path.size());
+    return sockaddr;
+}
+
+} // namespace UDSHelpers
diff --git a/src/common/uds.h b/src/common/uds.h
new file mode 100644 (file)
index 0000000..7af0631
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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        uds.h
+ * @author      Aleksander Zdyb <a.zdyb@partner.samsung.com>
+ * @version     1.0
+ * @brief       Helpers for Unix Domain Sockets
+ */
+
+#ifndef TESTS_COMMON_UDS_H_
+#define TESTS_COMMON_UDS_H_
+
+#include <string>
+#include <sys/un.h>
+
+namespace UDSHelpers {
+    int createServer(const struct sockaddr_un *sockaddr);
+    int createClient(const struct sockaddr_un *sockaddr);
+    int acceptClient(int sock);
+    void waitForDisconnect(int sock);
+    struct sockaddr_un makeAbstractAddress(const std::string &path);
+};
+
+#endif // TESTS_COMMON_UDS_H_
index cde27fe..1b275fd 100644 (file)
@@ -46,6 +46,7 @@ SET(CYNARA_TARGET_TEST_SOURCES
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/plugins/plugins.cpp
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/cynara-test.cpp
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/test_cases.cpp
+    ${PROJECT_SOURCE_DIR}/src/cynara-tests/test_cases_agent.cpp
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/test_cases_async.cpp
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/test_cases_db.cpp
     )
index 840d393..e2f408d 100644 (file)
@@ -61,11 +61,13 @@ void Agent::getRequest(AgentRequest &request, int expectedResult)
 
 void Agent::putResponse(const AgentResponse &response, int expectedResult)
 {
+    auto size = response.data().size();
     int ret = cynara_agent_put_response(m_agent,
                                         response.type(),
                                         response.id(),
-                                        reinterpret_cast<const void*>(response.data().data()),
-                                        response.data().size());
+                                        size ? static_cast<const void*>(response.data().data())
+                                               : nullptr,
+                                        size);
 
     RUNNER_ASSERT_MSG(ret == expectedResult,
                      "cynara_agent_put_response returned wrong value: "
index 52cb46a..821624e 100644 (file)
@@ -39,7 +39,7 @@ void AgentRequest::set(cynara_agent_msg_type type, cynara_agent_req_id id,
 {
     m_type = type;
     m_id = id;
-    m_data = Cynara::PluginData(reinterpret_cast<const char*>(data), dataSize);
+    m_data = Cynara::PluginData(static_cast<const char*>(data), dataSize);
     m_client.clear();
     m_user.clear();
     m_privilege.clear();
index 3201f97..6c70813 100644 (file)
@@ -52,8 +52,10 @@ CheckKey CheckData::toAdminPolicy()
 Client::Client(const StatusFunction &userFunction)
     : m_cynara(nullptr), m_statusMonitor(userFunction)
 {
-    int ret = cynara_async_initialize(&m_cynara, nullptr, StatusMonitor::updateStatus,
-                                      reinterpret_cast<void*>(&m_statusMonitor));
+    int ret;
+    RUNNER_DEFER_SCOPE(ret = cynara_async_initialize(&m_cynara, nullptr,
+                                                     StatusMonitor::updateStatus,
+                                                     static_cast<void*>(&m_statusMonitor)););
     RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS,
                          "cynara_async_initialize() failed. ret = " << ret << ".");
     RUNNER_ASSERT_MSG(m_cynara != nullptr, "cynara_async struct was not initialized.");
@@ -65,7 +67,7 @@ Client::~Client() noexcept(false)
 {
     bool oops = std::uncaught_exception();
     try {
-        cynara_async_finish(m_cynara);
+        RUNNER_DEFER_SCOPE(cynara_async_finish(m_cynara););
         assertStatus(DISCONNECTED);
     } catch (...) {
         if (!oops)
@@ -85,9 +87,11 @@ void Client::assertStatus(enum SocketStatus expectedStatus)
 
 void Client::checkCache(const CheckData &checkData, int expectedResult)
 {
-    int ret = cynara_async_check_cache(m_cynara, checkData.m_client.c_str(),
-                                       checkData.m_session.c_str(), checkData.m_user.c_str(),
-                                       checkData.m_privilege.c_str());
+    int ret;
+    RUNNER_DEFER_SCOPE(ret = cynara_async_check_cache(m_cynara, checkData.m_client.c_str(),
+                                                      checkData.m_session.c_str(),
+                                                      checkData.m_user.c_str(),
+                                                      checkData.m_privilege.c_str()););
     RUNNER_ASSERT_MSG(ret == expectedResult,
                          "Cache check returned unexpected value: "
                              << " returned value = " << ret << ","
@@ -101,11 +105,14 @@ void Client::checkCache(const CheckData &checkData, int expectedResult)
 void Client::createRequest(const CheckData &checkData, cynara_check_id &id,
                            const RequestEntity &callbackData, int expectedResult)
 {
-    int ret = cynara_async_create_request(m_cynara, checkData.m_client.c_str(),
-                                          checkData.m_session.c_str(), checkData.m_user.c_str(),
-                                          checkData.m_privilege.c_str(), &id,
-                                          RequestMonitor::updateResponse,
-                                          reinterpret_cast<void*>(&m_requestMonitor));
+    int ret;
+    RUNNER_DEFER_SCOPE(ret = cynara_async_create_request(m_cynara, checkData.m_client.c_str(),
+                                                         checkData.m_session.c_str(),
+                                                         checkData.m_user.c_str(),
+                                                         checkData.m_privilege.c_str(), &id,
+                                                         RequestMonitor::updateResponse,
+                                                         static_cast<void*>(
+                                                             &m_requestMonitor)););
     if (ret == CYNARA_API_SUCCESS)
         m_requestMonitor.registerRequest(id, callbackData);
 
@@ -140,19 +147,19 @@ void Client::process(int expectedResult,
         ret = TEMP_FAILURE_RETRY(select(fd + 1, &fds, &fds, NULL, &tv));
 
     if (ret == 0) {
-        RUNNER_ASSERT_ERRNO_MSG(timeoutExpectation != EXPECT_NO_TIMEOUT,
-                                   "Unexpected select timeout."
-                                   << " ret = " << ret);
+        RUNNER_ASSERT_MSG(timeoutExpectation != EXPECT_NO_TIMEOUT,
+                             "Unexpected select timeout."
+                             << " ret = " << ret);
         return;
     }
     RUNNER_ASSERT_ERRNO_MSG(ret > 0,
                                "Select returned error:"
                                << " ret = " << ret);
-    RUNNER_ASSERT_ERRNO_MSG(timeoutExpectation != EXPECT_TIMEOUT,
-                               "Select returned positive value, when timeout was expected."
-                               << " ret = " << ret);
+    RUNNER_ASSERT_MSG(timeoutExpectation != EXPECT_TIMEOUT,
+                         "Select returned positive value, when timeout was expected."
+                         << " ret = " << ret);
 
-    ret = cynara_async_process(m_cynara);
+    RUNNER_DEFER_SCOPE(ret = cynara_async_process(m_cynara););
     RUNNER_ASSERT_MSG(ret == expectedResult,
                          "cynara_async_process returned unexpected value: "
                              << " returned value = " << ret << ","
@@ -161,7 +168,8 @@ void Client::process(int expectedResult,
 
 void Client::cancel(cynara_check_id id, int expectedResult)
 {
-    int ret = cynara_async_cancel_request(m_cynara, id);
+    int ret;
+    RUNNER_DEFER_SCOPE(ret = cynara_async_cancel_request(m_cynara, id););
     RUNNER_ASSERT_MSG(ret == expectedResult,
                          "Cancel request returned unexpected value: "
                              << " returned value = " << ret << ","
index ee08c7e..33244d0 100644 (file)
@@ -53,48 +53,50 @@ void RequestMonitor::registerRequest(cynara_check_id id, const RequestEntity &re
 void RequestMonitor::updateResponse(cynara_check_id checkId, cynara_async_call_cause cause,
                                     int response, void *data)
 {
-    RequestMonitor *monitor = reinterpret_cast<RequestMonitor*>(data);
-    if (!monitor) {
-        RUNNER_FAIL_MSG("Bad user data (nullptr) in response callback.");
-        return;
-    }
-
-    auto it = monitor->m_requests.find(checkId);
-    if (it == monitor->m_requests.end()) {
-        RUNNER_FAIL_MSG("Received unexpected callback for request:"
-                           << "id = " << checkId << ","
-                           << "response = " << response << ","
-                           << "cause = " << cause << ".");
-        return;
-    }
+    RUNNER_DEFER_TRYCATCH(
+        RequestMonitor *monitor = static_cast<RequestMonitor*>(data);
+        if (!monitor) {
+            RUNNER_FAIL_MSG("Bad user data (nullptr) in response callback.");
+            return;
+        }
 
-    //save request data and remove request from monitored requests
-    auto expectedResponse = it->second.m_expectedResponse;
-    auto expectedCause = it->second.m_expectedCause;
-    auto userFunction = it->second.m_userFunction;
-    monitor->m_requests.erase(it);
+        auto it = monitor->m_requests.find(checkId);
+        if (it == monitor->m_requests.end()) {
+            RUNNER_FAIL_MSG("Received unexpected callback for request:"
+                               << "id = " << checkId << ","
+                               << "response = " << response << ","
+                               << "cause = " << cause << ".");
+            return;
+        }
 
-    RUNNER_ASSERT_MSG(cause == expectedCause,
-                         "Unexpected cause in response callback:"
-                            << "id = " << checkId << ","
-                            << "received response = " << response << ","
-                            << "expected response = " << expectedResponse << ","
-                            << "received cause = " << cause << ","
-                            << "expected cause = " << expectedCause << ".");
+        //save request data and remove request from monitored requests
+        auto expectedResponse = it->second.m_expectedResponse;
+        auto expectedCause = it->second.m_expectedCause;
+        auto userFunction = it->second.m_userFunction;
+        monitor->m_requests.erase(it);
 
-    if (cause == CYNARA_CALL_CAUSE_ANSWER)
-    {
-        RUNNER_ASSERT_MSG(response == expectedResponse,
-                             "Unexpected response in response callback:"
+        RUNNER_ASSERT_MSG(cause == expectedCause,
+                             "Unexpected cause in response callback:"
                                 << "id = " << checkId << ","
                                 << "received response = " << response << ","
                                 << "expected response = " << expectedResponse << ","
                                 << "received cause = " << cause << ","
                                 << "expected cause = " << expectedCause << ".");
-    }
 
-    if (userFunction)
-        userFunction();
+        if (cause == CYNARA_CALL_CAUSE_ANSWER)
+        {
+            RUNNER_ASSERT_MSG(response == expectedResponse,
+                                 "Unexpected response in response callback:"
+                                    << "id = " << checkId << ","
+                                    << "received response = " << response << ","
+                                    << "expected response = " << expectedResponse << ","
+                                    << "received cause = " << cause << ","
+                                    << "expected cause = " << expectedCause << ".");
+        }
+
+        if (userFunction)
+            userFunction();
+    );
 }
 
 }// namespace CynaraTestClientAsync
index 2a2e0ae..5246178 100644 (file)
@@ -27,21 +27,23 @@ StatusMonitor::StatusMonitor(const StatusFunction &userFunction)
 
 void StatusMonitor::updateStatus(int oldFd, int newFd, cynara_async_status status, void *data)
 {
-    StatusMonitor *monitor = reinterpret_cast<StatusMonitor*>(data);
-    if (!monitor) {
-        RUNNER_FAIL_MSG("Bad user data (nullptr) in status callback.");
-        return;
-    }
+    RUNNER_DEFER_TRYCATCH(
+        StatusMonitor *monitor = static_cast<StatusMonitor*>(data);
+        if (!monitor) {
+            RUNNER_FAIL_MSG("Bad user data (nullptr) in status callback.");
+            return;
+        }
 
-    RUNNER_ASSERT_MSG(monitor->m_fd == oldFd,
-                         "fd value mismatch: "
-                             << " last saved fd = " << monitor->m_fd << ","
-                             << " callback oldFd = " << oldFd << ".");
+        RUNNER_ASSERT_MSG(monitor->m_fd == oldFd,
+                             "fd value mismatch: "
+                                 << " last saved fd = " << monitor->m_fd << ","
+                                 << " callback oldFd = " << oldFd << ".");
 
-    monitor->m_fd = newFd;
-    monitor->m_status = status;
-    if (monitor->m_userFunction)
-        monitor->m_userFunction(oldFd, newFd, status);
+        monitor->m_fd = newFd;
+        monitor->m_status = status;
+        if (monitor->m_userFunction)
+            monitor->m_userFunction(oldFd, newFd, status);
+    );
 }
 
 int StatusMonitor::getFd(void) const
index afeec79..8c2f5a1 100644 (file)
@@ -20,7 +20,7 @@
 #include <cynara_test_cynara_mask.h>
 
 #include <dpl/exception.h>
-#include <dpl/test/test_runner.h>
+#include <dpl/test/test_exception.h>
 
 #include <exception>
 
@@ -39,21 +39,19 @@ void environmentWrap(const char *testName, const std::function<void(void)> &func
 {
     CynaraTestEnv env(testName);
     env.save();
+    env.loadDefaultDatabase();
 
     try {
         func();
-    } catch (const DPL::Test::TestRunner::TestFailed &e) {
+    } catch (const DPL::Test::TestException &e) {
         env.restore();
-        throw e;
-    } catch (const DPL::Test::TestRunner::Ignored &e) {
-        env.restore();
-        throw e;
+        throw;
     } catch (const DPL::Exception &e) {
         env.restore();
-        throw e;
+        throw;
     } catch (const std::exception &e) {
         env.restore();
-        throw e;
+        throw;
     } catch (...) {
         env.restore();
         throw std::runtime_error("Unknown exception");
index 3185007..ba3350a 100644 (file)
@@ -29,6 +29,7 @@ CynaraTestEnv::CynaraTestEnv(const char *dirName)
     m_saveDir = TMP_DIR + "/" + dirName;
     m_dbSaveDir = m_saveDir + "/db";
     m_pluginsSaveDir = m_saveDir + "/plugins";
+    m_defaultDir = "/etc/security-tests/db_patterns/default";
 }
 
 CynaraTestEnv::~CynaraTestEnv()
@@ -74,3 +75,13 @@ void CynaraTestEnv::restore()
     removeDirIfExists(m_pluginsSaveDir);
     removeDirIfExists(m_saveDir);
 }
+
+void CynaraTestEnv::loadDefaultDatabase()
+{
+    CynaraMask mask;
+
+    if (m_dbPresent) {
+        removeDirFiles(CynaraTestConsts::DB_DIR);
+        copyCynaraFiles(m_defaultDir, CynaraTestConsts::DB_DIR);
+    }
+}
index 707e852..6c528f7 100644 (file)
@@ -27,11 +27,13 @@ public:
 
     void save();
     void restore();
+    void loadDefaultDatabase();
 
 private:
     std::string m_saveDir;
     std::string m_dbSaveDir;
     std::string m_pluginsSaveDir;
+    std::string m_defaultDir;
     bool m_dbPresent;
 };
 
index 0c27a26..1f7a5da 100644 (file)
@@ -95,6 +95,9 @@ void copyCynaraFile(const std::string &src, const std::string &dst)
 
     ret = sendfile(outFd, inFd, 0, statSrc.st_size);
     RUNNER_ASSERT_ERRNO_MSG(ret != -1, "sendfile failed");
+
+    ret = fsync(outFd);
+    RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fsync failed");
 }
 
 void copyCynaraFiles(const std::string &source, const std::string &destination)
@@ -114,12 +117,30 @@ void copyCynaraFiles(const std::string &source, const std::string &destination)
         std::string tempSrc = source + "/" + direntPtr->d_name;
         copyCynaraFile(tempSrc, tempDest);
     }
+
+    syncDir(destination);
+}
+
+void syncElem(const std::string &filename, int flags, mode_t mode)
+{
+    int fileFd = TEMP_FAILURE_RETRY(open(filename.c_str(), flags, mode));
+    RUNNER_ASSERT_ERRNO_MSG(fileFd != -1, "open failed name=" << filename);
+    FdUniquePtr fdPtr(&fileFd);
+
+    int ret = fsync(fileFd);
+    RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fsync failed name=" << filename);
+}
+
+void syncDir(const std::string &dirname, mode_t mode) {
+    syncElem(dirname, O_DIRECTORY, mode);
 }
 
 void makeDir(const std::string &directory)
 {
     RUNNER_ASSERT_ERRNO_MSG(!mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IRWXO),
                                "Unable to make " << directory << " test directory");
+
+    syncDir(directory);
 }
 
 void removeDirFiles(const std::string &dir)
@@ -127,6 +148,8 @@ void removeDirFiles(const std::string &dir)
     int ret = nftw(dir.c_str(), removeFile, 2, FTW_DEPTH | FTW_PHYS);
     if (ret == -1)
         RUNNER_ASSERT_ERRNO_MSG(errno == ENOENT, "nftw failed");
+    else
+        syncDir(dir);
 }
 
 void removeDirIfExists(const std::string &dir)
index fae2e09..d3acdb8 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef CYNARA_TEST_FILE_OPERATIONS_H
 #define CYNARA_TEST_FILE_OPERATIONS_H
 
+#include <fcntl.h>
 #include <string>
 
 namespace FileOperations
@@ -25,6 +26,8 @@ namespace FileOperations
 bool dirExists(const std::string &directory);
 void copyCynaraFile(const std::string &src, const std::string &dst);
 void copyCynaraFiles(const std::string &source, const std::string &destination);
+void syncElem(const std::string &filename, int flags = O_RDONLY, mode_t mode = S_IRUSR | S_IWUSR);
+void syncDir(const std::string &dirname, mode_t mode = S_IRUSR | S_IWUSR);
 void makeDir(const std::string &directory);
 void removeDirFiles(const std::string &dir);
 void removeDirIfExists(const std::string &dir);
diff --git a/src/cynara-tests/db_patterns/default/checksum b/src/cynara-tests/db_patterns/default/checksum
new file mode 100644 (file)
index 0000000..9998a60
--- /dev/null
@@ -0,0 +1,2 @@
+buckets;$1$$6ZlVs5lw2nZgVmiw0BdY21
+_;$1$$qRPK7m23GJusamGpoGLby/
diff --git a/src/cynara-tests/db_patterns/defaultAllowed/checksum b/src/cynara-tests/db_patterns/defaultAllowed/checksum
new file mode 100644 (file)
index 0000000..90c581c
--- /dev/null
@@ -0,0 +1,2 @@
+buckets;$1$$UYHKvrIkGoSTO5hIgvCLg0
+_;$1$$qRPK7m23GJusamGpoGLby/
diff --git a/src/cynara-tests/db_patterns/nonEmptyDatabase/checksum b/src/cynara-tests/db_patterns/nonEmptyDatabase/checksum
new file mode 100644 (file)
index 0000000..ebaaf4c
--- /dev/null
@@ -0,0 +1,2 @@
+buckets;$1$$6ZlVs5lw2nZgVmiw0BdY21
+_;$1$$nssatAXP6yl4N8gjldhxf0
diff --git a/src/cynara-tests/test_cases_agent.cpp b/src/cynara-tests/test_cases_agent.cpp
new file mode 100644 (file)
index 0000000..51fab54
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2015 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_cases_agent.cpp
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @author      Radoslaw Bartosiak <r.bartosiak@samsung.com>
+ * @version     1.0
+ * @brief       Tests for libcynara-agent
+ */
+
+#include <chrono>
+#include <string>
+
+#include <cynara-error.h>
+#include <cynara-admin-types.h>
+#include <cynara-client-async.h>
+
+#include <dpl/test/test_runner.h>
+#include <cynara_test_admin.h>
+#include <cynara_test_agent.h>
+#include <cynara_test_agent_request.h>
+#include <cynara_test_agent_response.h>
+#include <cynara_test_client_async_client.h>
+#include <cynara_test_commons.h>
+#include <cynara_test_env.h>
+#include <service_manager.h>
+#include <timeout.h>
+
+using namespace CynaraTestAdmin;
+using namespace CynaraTestAgent;
+using namespace CynaraTestClientAsync;
+using namespace CynaraTestPlugins;
+
+void loadAgentPlugin()
+{
+    DirectoryPaths paths;
+    paths.push_back(TEST_PLUGIN_PATH + TEST_AGENT);
+    loadServicePlugins(paths);
+}
+
+void setAgentPolicy(int expectedResult = CYNARA_API_SUCCESS)
+{
+    const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+    const char *wildcard = CYNARA_ADMIN_WILDCARD;
+    const char *extra = nullptr;
+// collection of policy descriptions defined by plugin that causes use of TestAgent
+    auto testAgentPolicies = POLICY_DESCRIPTIONS.at(TEST_AGENT);
+// any policy type from above collection
+    auto policyType = testAgentPolicies[0].type;
+
+    CynaraPoliciesContainer cp;
+    cp.add(bucket, wildcard, wildcard, wildcard, policyType, extra);
+
+    Admin admin;
+    admin.setPolicies(cp, expectedResult);
+}
+
+void restartCynara()
+{
+    ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+    serviceManager.restartService();
+}
+
+void getAgentRequest(Agent &agent, AgentRequest &request, Client &client,
+                     int expectedResult = CYNARA_API_SUCCESS,
+                     Timeout::ExpectMode expectTimeoutMode = Timeout::ExpectMode::TIMEOUT)
+{
+    auto timeLimit = std::chrono::seconds(2);
+    auto hangOnGetRequest = [&agent, &request, &expectedResult]() {
+        agent.getRequest(request, expectedResult);
+    };
+    Timeout::CancelFunction sendClientRequest = [&client]() {
+        client.process();
+        client.assertStatus(READ);
+    };
+
+    Timeout::callAndWait(timeLimit, expectTimeoutMode,
+                         sendClientRequest, hangOnGetRequest);
+}
+
+void tcag01_set_agent_type_policy_without_plugin_func()
+{
+    loadServicePlugins(DirectoryPaths());
+    setAgentPolicy(CYNARA_API_INVALID_PARAM);
+}
+
+void tcag02_set_agent_type_policy_with_plugin_loaded_func()
+{
+    loadAgentPlugin();
+    setAgentPolicy();
+}
+
+void tcag03_check_with_no_agent_func()
+{
+    std::string testNo("03");
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_DENIED,
+                                  CYNARA_CALL_CAUSE_ANSWER};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Client client;
+    client.createRequest({testNo}, id, callbackData);
+    client.assertStatus(READWRITE);
+
+    //send requests
+    client.process();
+    client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+}
+
+void tcag04_agent_initialize_func()
+{
+    Agent();
+}
+
+void tcag05_agent_request_timeout_func()
+{
+    Agent agent;
+    AgentRequest request;
+
+    auto testTimeLimit = std::chrono::seconds(2);
+    auto hangOnGetRequest = [&agent, &request]() {
+        agent.getRequest(request, CYNARA_API_SERVICE_NOT_AVAILABLE);
+    };
+
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::TIMEOUT,
+                         restartCynara, hangOnGetRequest);
+}
+
+void tcag06_check_with_unregistered_agent_func()
+{
+    std::string testNo("06");
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_DENIED,
+                                  CYNARA_CALL_CAUSE_ANSWER};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+
+    Client client;
+    client.createRequest({testNo}, id, callbackData);
+    client.assertStatus(READWRITE);
+
+    //send requests
+    client.process();
+    client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+}
+
+void tcag07_get_request_func()
+{
+    std::string testNo("07");
+    CheckData data(testNo);
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_ALLOWED,
+                                  CYNARA_CALL_CAUSE_ANSWER};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+    AgentRequest agentRequest;
+    Client client;
+    client.createRequest(data, id, callbackData);
+    client.assertStatus(READWRITE);
+
+    auto testTimeLimit = std::chrono::seconds(5);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+
+    agentRequest.assertAction(data.m_client, data.m_user, data.m_privilege);
+    agent.putResponse(AgentResponse::createAllow(agentRequest.id()));
+    client.process();
+}
+
+void tcag08_get_request_and_respond_with_wrong_id_func()
+{
+    std::string testNo("08");
+    CheckData data(testNo);
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_SUCCESS,
+                                  CYNARA_CALL_CAUSE_FINISH};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+    AgentRequest agentRequest;
+    Client client;
+    client.createRequest(data, id, callbackData);
+    client.assertStatus(READWRITE);
+
+    auto testTimeLimit = std::chrono::seconds(5);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    agentRequest.assertAction(data.m_client, data.m_user, data.m_privilege);
+    agent.putResponse(AgentResponse::createAllow(agentRequest.id() + 1));
+    client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::EXPECT_TIMEOUT, 2);
+}
+
+void tcag09_get_request_and_correct_responded_id_func()
+{
+    std::string testNo("09");
+    CheckData data(testNo);
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_ALLOWED,
+                                  CYNARA_CALL_CAUSE_ANSWER};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+    AgentRequest agentRequest;
+    Client client;
+    client.createRequest(data, id, callbackData);
+    client.assertStatus(READWRITE);
+
+    auto testTimeLimit = std::chrono::seconds(5);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    agentRequest.assertAction(data.m_client, data.m_user, data.m_privilege);
+    agent.putResponse(AgentResponse::createAllow(agentRequest.id() + 1));
+    client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::EXPECT_TIMEOUT, 2);
+    agent.putResponse(AgentResponse::createAllow(agentRequest.id()));
+    client.process();
+}
+
+void tcag10_cancel_request_func()
+{
+    std::string testNo("10");
+    CheckData data(testNo);
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_ALLOWED,
+                                  CYNARA_CALL_CAUSE_CANCEL};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+    AgentRequest agentRequest;
+
+    Client client;
+    client.createRequest(data, id, callbackData);
+    client.assertStatus(READWRITE);
+
+    auto testTimeLimit = std::chrono::seconds(5);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    agentRequest.assertAction(data.m_client, data.m_user, data.m_privilege);
+    client.cancel(id);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    agentRequest.assertCancel();
+    agent.putResponse(AgentResponse::createCancel(id));
+    client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::EXPECT_NO_TIMEOUT, 2);
+}
+
+void tcag11_cancel_processed_request_func()
+{
+    std::string testNo("11");
+    CheckData data(testNo);
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_ALLOWED,
+                                  CYNARA_CALL_CAUSE_CANCEL};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+    AgentRequest agentRequest;
+
+    Client client;
+    client.createRequest(data, id, callbackData);
+    client.assertStatus(READWRITE);
+
+    auto testTimeLimit = std::chrono::seconds(5);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    agentRequest.assertAction(data.m_client, data.m_user, data.m_privilege);
+    agent.putResponse(AgentResponse::createCancel(id));
+    client.cancel(id);
+    // we do not expect getting the cancel request in the agent
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::TIMEOUT,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                         std::ref(client), CYNARA_API_SERVICE_NOT_AVAILABLE, Timeout::ExpectMode::TIMEOUT);
+    client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::EXPECT_NO_TIMEOUT, 2);
+}
+
+void tcag12_create_two_requests_func()
+{
+    std::string testNo("12");
+    CheckData data1(testNo, 1), data2(testNo, 2);
+    cynara_check_id id1, id2;
+    RequestEntity callbackData1 = {RequestFunction(),
+                                   CYNARA_API_ACCESS_DENIED,
+                                   CYNARA_CALL_CAUSE_ANSWER};
+    RequestEntity callbackData2 = {RequestFunction(),
+                                   CYNARA_API_ACCESS_ALLOWED,
+                                   CYNARA_CALL_CAUSE_CANCEL};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+    AgentRequest agentRequest1, agentRequest2, agentRequest3;
+    Client client;
+    client.createRequest(data1, id1, callbackData1);
+    client.assertStatus(READWRITE);
+    client.createRequest(data2, id2, callbackData2);
+    client.assertStatus(READWRITE);
+
+    auto testTimeLimit = std::chrono::seconds(5);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest1),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest2),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::IGNORE);
+    client.cancel(id2);
+    client.assertStatus(READWRITE);
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequest, std::ref(agent), std::ref(agentRequest3),
+                         std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    agentRequest1.assertAction(data1.m_client, data1.m_user, data1.m_privilege);
+    agentRequest2.assertAction(data2.m_client, data2.m_user, data2.m_privilege);
+    agentRequest3.assertCancel();
+
+    agent.putResponse(AgentResponse::createDeny(id1));
+    agent.putResponse(AgentResponse::createCancel(id2));
+
+    client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::EXPECT_NO_TIMEOUT, 3);
+    client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::IGNORE_TIMEOUT, 1);
+}
+
+void tcag13_create_many_requests_func()
+{
+    const int numberOfRequests = 4;
+    std::string testNo("13");
+    cynara_check_id ids[numberOfRequests];
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_DENIED,
+                                  CYNARA_CALL_CAUSE_ANSWER};
+    loadAgentPlugin();
+    setAgentPolicy();
+
+    Agent agent;
+    AgentRequest agentRequests[numberOfRequests];
+    Client client;
+    for (int i = 0; i < numberOfRequests; i++) {
+        CheckData data(testNo, i);
+        client.createRequest(data, ids[i], callbackData);
+        client.assertStatus(READWRITE);
+        auto testTimeLimit = std::chrono::seconds(5);
+        Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED, restartCynara,
+                             getAgentRequest, std::ref(agent), std::ref(agentRequests[i]),
+                             std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+        agentRequests[i].assertAction(data.m_client, data.m_user, data.m_privilege);
+    };
+    for (int i = numberOfRequests - 1; i >= 0; i--) {
+        agent.putResponse(AgentResponse::createDeny(ids[i]));
+        client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::EXPECT_NO_TIMEOUT, 2);
+    }
+}
+
+void tcag14_client_disconnects_func()
+{
+    std::string testNo("14");
+    CheckData data(testNo);
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_ALLOWED,
+                                  CYNARA_CALL_CAUSE_FINISH};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+    Agent agent;
+    AgentRequest agentRequest;
+    auto testTimeLimit = std::chrono::seconds(5);
+    {
+        Client client;
+        client.createRequest(data, id, callbackData);
+        client.assertStatus(READWRITE);
+        Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                             restartCynara, getAgentRequest, std::ref(agent),
+                             std::ref(agentRequest), std::ref(client),
+                             CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    };
+    auto getAgentRequestWrap = [&agent, &agentRequest]() {
+            agent.getRequest(agentRequest, CYNARA_API_SUCCESS);
+        };
+    Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED,
+                         restartCynara, getAgentRequestWrap);
+    agentRequest.assertCancel();
+}
+
+void tcag15_agent_disconnects_func()
+{
+    std::string testNo("15");
+    CheckData data(testNo);
+    cynara_check_id id;
+    RequestEntity callbackData = {RequestFunction(),
+                                  CYNARA_API_ACCESS_DENIED,
+                                  CYNARA_CALL_CAUSE_ANSWER};
+
+    loadAgentPlugin();
+    setAgentPolicy();
+    Client client;
+    client.createRequest(data, id, callbackData);
+    client.assertStatus(READWRITE);
+    AgentRequest agentRequest;
+    {
+        Agent agent;
+        auto testTimeLimit = std::chrono::seconds(5);
+        Timeout::callAndWait(testTimeLimit, Timeout::ExpectMode::FINISHED, restartCynara,
+                             getAgentRequest, std::ref(agent), std::ref(agentRequest),
+                             std::ref(client), CYNARA_API_SUCCESS, Timeout::ExpectMode::TIMEOUT);
+    };
+    client.process(CYNARA_API_SUCCESS, Client::TimeoutExpectation::EXPECT_NO_TIMEOUT, 2);
+}
+
+RUNNER_TEST_GROUP_INIT(cynara_agent_tests)
+
+RUN_CYNARA_TEST(tcag01_set_agent_type_policy_without_plugin)
+RUN_CYNARA_TEST(tcag02_set_agent_type_policy_with_plugin_loaded)
+RUN_CYNARA_TEST(tcag03_check_with_no_agent)
+RUN_CYNARA_TEST(tcag04_agent_initialize)
+RUN_CYNARA_TEST(tcag05_agent_request_timeout)
+RUN_CYNARA_TEST(tcag06_check_with_unregistered_agent)
+RUN_CYNARA_TEST(tcag07_get_request)
+RUN_CYNARA_TEST(tcag08_get_request_and_respond_with_wrong_id)
+RUN_CYNARA_TEST(tcag09_get_request_and_correct_responded_id)
+RUN_CYNARA_TEST(tcag10_cancel_request)
+RUN_CYNARA_TEST(tcag11_cancel_processed_request)
+RUN_CYNARA_TEST(tcag12_create_two_requests)
+RUN_CYNARA_TEST(tcag13_create_many_requests)
+RUN_CYNARA_TEST(tcag14_client_disconnects)
+RUN_CYNARA_TEST(tcag15_agent_disconnects)
index 6fe3202..16b3d91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -51,6 +51,7 @@ const std::string defDbAllow("defaultAllowed");
 const std::string nonEmptyDb("nonEmptyDatabase");
 const std::string cynaraTestPatternsPath("/etc/security-tests/db_patterns/");
 const std::string directoryWildcard("/*");
+const char directorySeparator('/');
 
 void createDbFile(const std::string &filename)
 {
@@ -108,19 +109,63 @@ size_t db_files_count(const std::string &source) {
     return dbFilesCount;
 }
 
+const std::set<std::string> dump_glob_filenames(const glob_t &globbuf) {
+    std::set<std::string> set;
+
+    for (unsigned i = 0; i < globbuf.gl_pathc; ++i) {
+        std::string filename(globbuf.gl_pathv[i]);
+        set.insert(filename.substr(filename.find_last_of(directorySeparator)+1));
+    }
+
+    return set;
+}
+
+const std::set<std::string> glob_filenames(const std::string &source, const std::string &wildcard) {
+    //for finding files matching pattern in directory
+    glob_t globbuf;
+    std::string pattern = source + wildcard;
+
+    //for freeing allocated memory
+    GlobPtr globbufPtr(&globbuf);
+
+    //actually find files matching pattern in directory - including dotfiles
+    RUNNER_ASSERT_MSG(0 == glob(pattern.c_str(), GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf),
+                      "Failed to search for requested pathnames in " << source << ".");
+
+    return dump_glob_filenames(globbuf);
+}
+
+const std::set<std::string> db_files_pathnames(const std::string &source) {
+    return glob_filenames(source, directoryWildcard);
+}
+
+std::ostream& operator<<(std::ostream& os, const std::set<std::string> &set)
+{
+    os << "{";
+    for (const auto &item : set) {
+        os << " " << item;
+    }
+    os << " }";
+    return os;
+}
+
 void compareDbs(const std::string &source)
 {
     //for accessing files in directory
     std::string patternDir = cynaraTestPatternsPath + source;
+    std::string resultDir = CynaraTestConsts::DB_DIR;
     DIR *patternDirPtr = nullptr;
     struct dirent *direntPtr;
 
     size_t patternFileCount = db_files_count(patternDir);
-    size_t resultFileCount = db_files_count(CynaraTestConsts::DB_DIR);
+    size_t resultFileCount = db_files_count(resultDir);
 
     //directories do not match if there is different number of files
     RUNNER_ASSERT_MSG(patternFileCount == resultFileCount,
-                      "No match in database and pattern directory file count");
+                      "No match in database and pattern directory file count: "
+                          << resultFileCount << " != " << patternFileCount << "." << std::endl
+                          << "Expected: " << db_files_pathnames(patternDir) << std::endl
+                          << "Actual:   " << db_files_pathnames(resultDir));
 
     //compare files in database directory with pattern directory
     RUNNER_ASSERT_ERRNO_MSG(patternDirPtr = opendir(patternDir.c_str()),
@@ -131,12 +176,12 @@ void compareDbs(const std::string &source)
         if (!strcmp(direntPtr->d_name, ".")
          || !strcmp(direntPtr->d_name, ".."))
             continue;
-        std::string patternName = patternDir + "/" + direntPtr->d_name;
-        std::string resultName = CynaraTestConsts::DB_DIR + "/" + direntPtr->d_name;
+        std::string patternName = patternDir + directorySeparator + direntPtr->d_name;
+        std::string resultName = CynaraTestConsts::DB_DIR + directorySeparator + direntPtr->d_name;
 
         //comparing file saved db dir with reference file from patterns dir
         RUNNER_ASSERT_MSG(true == unordered_files_match(patternName, resultName),
-                          "No match in stored file and pattern file");
+                          "No match in stored file and pattern file: " << resultName);
     }
 }
 
@@ -160,7 +205,7 @@ void tcdb01_lockdown_init_failure_func()
     const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
     const char *extra = nullptr;
 
-    const auto fakeBackupGuard = CynaraTestConsts::DB_DIR + "/guard";
+    const auto fakeBackupGuard = CynaraTestConsts::DB_DIR + directorySeparator + "guard";
 
     createDbFile(fakeBackupGuard);
     admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra, CYNARA_API_OPERATION_FAILED);
@@ -190,7 +235,7 @@ void tcdb02_write_to_backup_failure_func()
     const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
     const char *extra = nullptr;
 
-    const auto fakeBucketDumpFile = CynaraTestConsts::DB_DIR + "/_~";
+    const auto fakeBucketDumpFile = CynaraTestConsts::DB_DIR + directorySeparator + "_~";
 
     admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra);
     compareDbs(defDbAllow);
@@ -221,7 +266,7 @@ void tcdb03_invalid_and_valid_backup_removal_func()
     const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
     const char *extra = nullptr;
 
-    const auto defaultBucketDumpFile = CynaraTestConsts::DB_DIR + "/_~";
+    const auto defaultBucketDumpFile = CynaraTestConsts::DB_DIR + directorySeparator + "_~";
 
     createDbFile(defaultBucketDumpFile);
     admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra, CYNARA_API_OPERATION_FAILED);
@@ -280,7 +325,7 @@ void tcdb05_non_indexed_files_removal_func()
                                            "some-file-that-doesnt-belong-here" };
 
     for (const auto &filename : filenames) {
-        auto garbageFilename = CynaraTestConsts::DB_DIR + "/" + filename;
+        auto garbageFilename = CynaraTestConsts::DB_DIR + directorySeparator + filename;
         createDbFile(garbageFilename);
     }
 
index 411f09e..72b3d2c 100644 (file)
@@ -32,6 +32,7 @@ SET(DPL_FRAMEWORK_TEST_SOURCES
     ${PROJECT_SOURCE_DIR}/src/framework/src/dlog_log_provider.cpp
     ${PROJECT_SOURCE_DIR}/src/framework/src/log.cpp
     ${PROJECT_SOURCE_DIR}/src/framework/src/old_style_log_provider.cpp
+    ${PROJECT_SOURCE_DIR}/src/framework/src/test_failed.cpp
     ${PROJECT_SOURCE_DIR}/src/framework/src/test_results_collector.cpp
     ${PROJECT_SOURCE_DIR}/src/framework/src/test_results_collector_commons.cpp
     ${PROJECT_SOURCE_DIR}/src/framework/src/test_results_collector_console.cpp
diff --git a/src/framework/include/dpl/test/performance_result.h b/src/framework/include/dpl/test/performance_result.h
new file mode 100644 (file)
index 0000000..f15c0da
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015 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        performance_result.h
+ * @author      Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version     1.0
+ * @brief       Header file with declaration of PerformanceResult class
+ */
+
+#ifndef DPL_TEST_PERFORMANCE_RESULT_H
+#define DPL_TEST_PERFORMANCE_RESULT_H
+
+#include <dpl/binary_queue.h>
+
+#include <chrono>
+#include <memory>
+
+namespace DPL {
+namespace Test {
+
+class PerformanceResult;
+
+typedef std::shared_ptr<PerformanceResult> PerformanceResultPtr;
+typedef std::shared_ptr<const PerformanceResult> ConstPerformanceResultPtr;
+
+class PerformanceResult
+{
+public:
+    PerformanceResult(const std::chrono::system_clock::duration& maxDuration)
+        : m_startTime(std::chrono::system_clock::now())
+        , m_duration(std::chrono::microseconds::zero())
+        , m_maxDuration(maxDuration < std::chrono::microseconds::zero()
+                            ? std::chrono::microseconds::zero()
+                            : maxDuration) {}
+
+    PerformanceResult(BinaryQueue &queue)
+        : m_startTime(std::chrono::system_clock::now())
+        , m_duration(std::chrono::microseconds::zero())
+        , m_maxDuration(std::chrono::microseconds::zero()) {
+        queue.FlattenConsume(const_cast<std::chrono::system_clock::time_point*>(&m_startTime),
+                             sizeof(std::chrono::system_clock::time_point));
+        queue.FlattenConsume(const_cast<std::chrono::system_clock::duration*>(&m_duration),
+                             sizeof(std::chrono::system_clock::duration));
+        queue.FlattenConsume(const_cast<std::chrono::system_clock::duration*>(&m_maxDuration),
+                             sizeof(std::chrono::system_clock::duration));
+    }
+
+    bool IsMaxDuration() const {
+        return m_maxDuration > std::chrono::microseconds::zero();
+    }
+
+    bool IsDurationOk() const {
+        return m_duration <= m_maxDuration;
+    }
+
+    const std::chrono::system_clock::duration &GetDuration() const {
+        return m_duration;
+    }
+
+    const std::chrono::system_clock::duration &GetMaxDuration() const {
+        return m_maxDuration;
+    }
+
+    void Finish() {
+        if (m_duration == std::chrono::microseconds::zero())
+            m_duration = std::chrono::system_clock::now() - m_startTime;
+    }
+
+    const std::string ToBinaryString() const {
+        std::string strStartTime(reinterpret_cast<const char*>(&m_startTime), sizeof(m_startTime));
+        std::string strDuration(reinterpret_cast<const char*>(&m_duration), sizeof(m_duration));
+        std::string strMaxDuration(reinterpret_cast<const char*>(&m_maxDuration),
+                                   sizeof(m_maxDuration));
+        return strStartTime + strDuration + strMaxDuration;
+    }
+
+private:
+    const std::chrono::system_clock::time_point m_startTime;
+    std::chrono::system_clock::duration m_duration;
+    const std::chrono::system_clock::duration m_maxDuration;
+};
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_PERFORMANCE_RESULT_H
index fe550bd..4990ffd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -27,7 +27,7 @@
 #include <cstddef>
 
 #include <dpl/assert.h>
-#include <dpl/test/test_results_collector.h>
+#include <dpl/test/test_result.h>
 
 namespace DPL {
 namespace Test {
@@ -42,15 +42,15 @@ class Statistic
         m_count(0)
     {}
 
-    void AddTest(TestResultsCollectorBase::FailStatus status)
+    void AddTest(TestResult::FailStatus status)
     {
         ++m_count;
         switch (status) {
-        case TestResultsCollectorBase::FailStatus::FAILED:   ++m_failed;
+        case TestResult::FailStatus::FAILED:   ++m_failed;
             break;
-        case TestResultsCollectorBase::FailStatus::IGNORED:  ++m_ignored;
+        case TestResult::FailStatus::IGNORED:  ++m_ignored;
             break;
-        case TestResultsCollectorBase::FailStatus::NONE:     ++m_passed;
+        case TestResult::FailStatus::NONE:     ++m_passed;
             break;
         default:
             Assert(false && "Bad FailStatus");
diff --git a/src/framework/include/dpl/test/test_exception.h b/src/framework/include/dpl/test/test_exception.h
new file mode 100644 (file)
index 0000000..49e4739
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 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_exception.h
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file is the header file of test_exception base class
+ */
+
+#ifndef DPL_TEST_EXCEPTION_H
+#define DPL_TEST_EXCEPTION_H
+
+#include <string>
+
+namespace DPL {
+namespace Test {
+
+class TestException
+{
+    public:
+        std::string GetMessage() const
+        {
+            return m_message;
+        }
+
+    protected:
+        std::string m_message;
+
+        TestException() {}
+        TestException(const std::string &message) :
+            m_message(message) {}
+
+};
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_EXCEPTION_H
diff --git a/src/framework/include/dpl/test/test_failed.h b/src/framework/include/dpl/test/test_failed.h
new file mode 100644 (file)
index 0000000..f446094
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 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_failed.h
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file is the header file of TestFailed class
+ */
+
+#ifndef DPL_TEST_FAILED_H
+#define DPL_TEST_FAILED_H
+
+#include <string>
+
+#include <dpl/test/test_exception.h>
+
+namespace DPL {
+namespace Test {
+
+class TestFailed : public TestException
+{
+    public:
+        TestFailed() = default;
+
+        //! \brief Failed test message creator
+        //!
+        //! \param[in] aTest string for tested expression
+        //! \param[in] aFile source file name
+        //! \param[in] aLine source file line
+        //! \param[in] aMessage error message
+        TestFailed(const char* aTest,
+                   const char* aFile,
+                   int aLine,
+                   const std::string &aMessage);
+
+        TestFailed(const std::string &message) :
+            TestException(message)
+        {}
+};
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_FAILED_H
diff --git a/src/framework/include/dpl/test/test_ignored.h b/src/framework/include/dpl/test/test_ignored.h
new file mode 100644 (file)
index 0000000..17a5c0a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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_ignored.h
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file is the header file of TestIgnored class
+ */
+
+#ifndef DPL_TEST_IGNORED_H
+#define DPL_TEST_IGNORED_H
+
+#include <string>
+
+#include <dpl/test/test_exception.h>
+
+namespace DPL {
+namespace Test {
+
+class TestIgnored : public TestException
+{
+    public:
+        TestIgnored() = default;
+
+        TestIgnored(const std::string &message) :
+            TestException(message)
+        {}
+};
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_IGNORED_H
diff --git a/src/framework/include/dpl/test/test_result.h b/src/framework/include/dpl/test/test_result.h
new file mode 100644 (file)
index 0000000..e2810d6
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015 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_result.h
+ * @author      Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
+ * @version     1.0
+ * @brief       Header file with declaration of TestResult class
+ */
+
+#ifndef DPL_TEST_RESULT_H
+#define DPL_TEST_RESULT_H
+
+#include <dpl/test/performance_result.h>
+
+#include <string>
+
+namespace DPL {
+namespace Test {
+
+class TestResult
+{
+public:
+    enum class FailStatus
+    {
+        NONE,
+        FAILED,
+        IGNORED
+    };
+
+    TestResult(FailStatus status,
+               const std::string& reason = std::string(),
+               ConstPerformanceResultPtr performanceResult = nullptr)
+        : m_failStatus(status)
+        , m_reason(reason)
+        , m_performanceResult(performanceResult) {}
+
+    FailStatus GetFailStatus() const {
+        return m_failStatus;
+    }
+
+    const std::string& GetReason() const {
+        return m_reason;
+    }
+
+    ConstPerformanceResultPtr GetPerformanceResult() const {
+        return m_performanceResult;
+    }
+
+private:
+    const FailStatus m_failStatus;
+    const std::string m_reason;
+    ConstPerformanceResultPtr m_performanceResult;
+};
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_RESULT_H
index cfd9227..60a926f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -15,6 +15,7 @@
  */
 /*
  * @file        test_results_collector.h
+ * @author      Marcin Niesluchowski (m.niesluchow@samsung.com)
  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
  * @version     1.0
  * @brief       Header file with declaration of TestResultsCollectorBase
 #define DPL_TEST_RESULTS_COLLECTOR_H
 
 #include <dpl/noncopyable.h>
+#include <dpl/test/test_result.h>
+
 #include <vector>
 #include <list>
 #include <map>
-#include <chrono>
 #include <string>
 #include <memory>
 
@@ -43,12 +45,6 @@ class TestResultsCollectorBase :
   public:
     typedef TestResultsCollectorBase* (*CollectorConstructorFunc)();
     typedef std::list<std::string> TestCaseIdList;
-    enum class FailStatus
-    {
-        NONE,
-        FAILED,
-        IGNORED
-    };
 
     virtual ~TestResultsCollectorBase() {}
 
@@ -61,13 +57,7 @@ class TestResultsCollectorBase :
     virtual void CollectCurrentTestGroupName(const std::string& /*groupName*/)
     {}
 
-    virtual void CollectTestsCasesList(const TestCaseIdList& /*list*/) {}
-    virtual void CollectResult(const std::string& id,
-                               const FailStatus status = FailStatus::NONE,
-                               const std::string& reason = "",
-                               const bool& isPerformanceTest = false,
-                               const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
-                               const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero()) = 0;
+    virtual void CollectResult(const std::string& id, const TestResult &result) = 0;
     virtual std::string CollectorSpecificHelp() const
     {
         return "";
index 6961f4e..8fc98c1 100644 (file)
@@ -41,10 +41,14 @@ namespace Test {
     "[%s%s%s] %s[elapsed: %0.3fms, expected < %0.3fms]%s\n", BOLD_GREEN_BEGIN, \
     "   OK   ", BOLD_GREEN_END, BOLD_RED_BEGIN, elapsed, max, BOLD_RED_END
 
+extern const std::string COLLECTOR_NO_VERBOSE_HELP;
+
 // Get duration as a fraction of millisecond (max precision is 1 microsecond)
 double get_milliseconds (const std::chrono::system_clock::duration& performanceTime);
 
+std::string CollectorFileHelp(const std::string &defaultFilename);
 bool ParseCollectorFileArg(const std::string &arg, std::string &filename);
+bool ParseCollectorNoVerboseArg(const std::string &arg, bool &verbosity);
 
 } // namespace Test
 } // namespace DPL
index 332763b..8f43d75 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -40,28 +40,20 @@ public:
 private:
     ConsoleCollector();
 
+    virtual bool ParseCollectorSpecificArg(const std::string& arg);
+    virtual std::string CollectorSpecificHelp() const;
     virtual void CollectCurrentTestGroupName(const std::string& name);
-    virtual void CollectResult(const std::string& id,
-                               const FailStatus status = FailStatus::NONE,
-                               const std::string& reason = "",
-                               const bool& isPerformanceTest = true,
-                               const std::chrono::system_clock::duration& performanceTime
-                                   = std::chrono::microseconds::zero(),
-                               const std::chrono::system_clock::duration& performanceMaxTime
-                                   = std::chrono::microseconds::zero());
+    virtual void CollectResult(const std::string& id, const TestResult &result);
     virtual void Finish();
 
-    void PrintfErrorMessage(const char* type,
-                            const std::string& message,
-                            bool verbosity);
-    void PrintfIgnoredMessage(const char* type,
-                              const std::string& message,
-                              bool verbosity);
+    void PrintfErrorMessage(const char* type, const std::string& message);
+    void PrintfIgnoredMessage(const char* type, const std::string& message);
     void PrintStats(const std::string& title, const Statistic& stats);
 
     Statistic m_stats;
     std::map<std::string, Statistic> m_groupsStats;
     std::string m_currentGroup;
+    bool m_verbosity;
 };
 
 } // namespace Test
index 90d635e..122d3f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -46,22 +46,11 @@ private:
     virtual bool Configure();
     virtual void Start();
     virtual void CollectCurrentTestGroupName(const std::string& name);
-    virtual void CollectResult(const std::string& id,
-                               const FailStatus status = FailStatus::NONE,
-                               const std::string& reason = "",
-                               const bool& isPerformanceTest = false,
-                               const std::chrono::system_clock::duration& performanceTime
-                                   = std::chrono::microseconds::zero(),
-                               const std::chrono::system_clock::duration& performanceMaxTime
-                                   = std::chrono::microseconds::zero());
+    virtual void CollectResult(const std::string& id, const TestResult &result);
     virtual void Finish();
 
-    void PrintfErrorMessage(const char* type,
-                            const std::string& message,
-                            bool verbosity);
-    void PrintfIgnoredMessage(const char* type,
-                              const std::string& message,
-                              bool verbosity);
+    void PrintfErrorMessage(const char* type, const std::string& message);
+    void PrintfIgnoredMessage(const char* type, const std::string& message);
     void PrintStats(const std::string& name, const Statistic& stats);
 
     std::string m_filename;
@@ -69,6 +58,7 @@ private:
     Statistic m_stats;
     std::string m_currentGroup;
     std::map<std::string, Statistic> m_groupsStats;
+    bool m_verbosity;
 };
 
 } // namespace Test
index f0edfcc..8f83a71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -45,14 +45,7 @@ private:
     virtual std::string CollectorSpecificHelp() const;
     virtual bool ParseCollectorSpecificArg(const std::string& arg);
     virtual void Start();
-    virtual void CollectResult(const std::string& id,
-                               const FailStatus status = FailStatus::NONE,
-                               const std::string& reason = "",
-                               const bool& isPerformanceTest = false,
-                               const std::chrono::system_clock::duration& performanceTime
-                                   = std::chrono::microseconds::zero(),
-                               const std::chrono::system_clock::duration& performanceMaxTime
-                                   = std::chrono::microseconds::zero());
+    virtual void CollectResult(const std::string& id, const TestResult &result);
     virtual void Finish();
 
     void writeStats(bool segfault);
index 01b9802..60e8aca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -44,14 +44,7 @@ private:
     virtual bool Configure();
     virtual void Start();
     virtual void CollectCurrentTestGroupName(const std::string& name);
-    virtual void CollectResult(const std::string& id,
-                               const FailStatus status = FailStatus::NONE,
-                               const std::string& reason = "",
-                               const bool& isPerformanceTest = false,
-                               const std::chrono::system_clock::duration& performanceTime
-                                   = std::chrono::microseconds::zero(),
-                               const std::chrono::system_clock::duration& performanceMaxTime
-                                   = std::chrono::microseconds::zero());
+    virtual void CollectResult(const std::string& id, const TestResult &result);
     virtual void Finish();
 
     void GroupStart(const std::size_t pos, const std::string& name);
@@ -65,12 +58,8 @@ private:
                                 const std::string& value);
     std::string UIntToString(const unsigned int value);
     void GroupFinish(const std::size_t groupPosition);
-    void PrintfErrorMessage(const char* type,
-                            const std::string& message,
-                            bool verbosity);
-    void PrintfIgnoredMessage(const char* type,
-                              const std::string& message,
-                              bool verbosity);
+    void PrintfErrorMessage(const char* type, const std::string& message);
+    void PrintfIgnoredMessage(const char* type, const std::string& message);
     void FlushOutput();
     std::string EscapeSpecialCharacters(std::string s);
 
@@ -79,6 +68,7 @@ private:
     Statistic m_stats;
     std::string m_outputBuffer;
     std::string m_resultBuffer;
+    bool m_verbosity;
 };
 
 } // namespace Test
index 373b319..ee1d7c3 100644 (file)
@@ -25,6 +25,7 @@
 #define DPL_TEST_RUNNER_H
 
 #include <chrono>
+#include <cstdlib>
 #include <cstring>
 #include <exception>
 #include <iostream>
 #include <dpl/colors.h>
 #include <dpl/gdbbacktrace.h>
 #include <dpl/singleton.h>
+#include <dpl/test/performance_result.h>
+#include <dpl/test/test_exception.h>
+#include <dpl/test/test_failed.h>
+#include <dpl/test/test_ignored.h>
+#include <dpl/test/test_result.h>
 #include <dpl/test/test_results_collector.h>
 
 namespace DPL {
@@ -61,16 +67,14 @@ class TestRunner
         m_currentTestCase(nullptr)
       , m_terminate(false)
       , m_allowChildLogs(false)
+      , m_deferDeepness(0U)
+      , m_firstDeferredExceptionType(DeferredExceptionType::DEFERRED_FAILED)
     {}
 
-    void beginPerformanceTestTime(std::chrono::system_clock::duration maxTimeInMicroseconds);
-    void endPerformanceTestTime();
-    void getCurrentTestCasePerformanceResult(bool& isPerformanceTest,
-                                             std::chrono::system_clock::duration& result,
-                                             std::chrono::system_clock::duration& resultMax);
-    void setCurrentTestCasePerformanceResult(bool isPerformanceTest,
-                                             std::chrono::system_clock::duration result,
-                                             std::chrono::system_clock::duration resultMax);
+    void beginPerformance(std::chrono::system_clock::duration maxDurationInMicroseconds);
+    void endPerformance();
+    void setCurrentTestCasePerformanceResult(const PerformanceResultPtr &performance);
+    ConstPerformanceResultPtr getCurrentTestCasePerformanceResult();
 
     void addFailReason(const std::string &reason);
 
@@ -81,11 +85,7 @@ class TestRunner
     {
         std::string name;
         TestCase proc;
-
-        bool m_isPerformanceTest;
-        std::chrono::system_clock::time_point m_performanceTestStartTime;
-        std::chrono::system_clock::duration m_performanceTestDurationTime;
-        std::chrono::system_clock::duration m_performanceMaxTime;
+        PerformanceResultPtr performance;
 
         bool operator <(const TestCaseStruct &other) const
         {
@@ -99,8 +99,7 @@ class TestRunner
 
         TestCaseStruct(const std::string &n, TestCase p) :
             name(n),
-            proc(p),
-            m_isPerformanceTest(false)
+            proc(p)
         {}
     };
 
@@ -110,14 +109,8 @@ class TestRunner
 
     TestCaseStruct * m_currentTestCase;
 
-    typedef std::set<std::string> SelectedTestNameSet;
-    SelectedTestNameSet m_selectedTestNamesSet;
-    typedef std::set<std::string> SelectedTestGroupSet;
-    SelectedTestGroupSet m_selectedTestGroupSet;
     std::string m_currentGroup;
 
-    DPL::Atomic m_totalAssertions;
-
     // Terminate without any logs.
     // Some test requires to call fork function.
     // Child process must not produce any logs and should die quietly.
@@ -132,9 +125,7 @@ class TestRunner
     bool filterByXML(std::map<std::string, bool> & casesMap);
     void normalizeXMLTag(std::string& str, const std::string& testcase);
 
-    enum Status { FAILED, IGNORED, PASS };
-
-    Status RunTestCase(const TestCaseStruct& testCase);
+    void RunTestCase(const TestCaseStruct& testCase);
 
     void setCurrentTestCase(TestCaseStruct* testCase);
     TestCaseStruct *getCurrentTestCase();
@@ -143,74 +134,33 @@ class TestRunner
 
     std::string getConcatedFailReason(const std::string &reason);
 
-    void CollectResult(const std::string& id,
-                       const TestResultsCollectorBase::FailStatus status
-                           = TestResultsCollectorBase::FailStatus::NONE,
-                       const std::string& reason = std::string(),
-                       const bool& isPerformanceTest = false,
-                       const std::chrono::system_clock::duration& performanceTime = std::chrono::microseconds::zero(),
-                       const std::chrono::system_clock::duration& performanceMaxTime = std::chrono::microseconds::zero());
+    void CollectResult(const std::string& id, const TestResult &result);
 
   public:
-    class TestFailed
-    {
-      private:
-        std::string m_message;
-
-      public:
-        TestFailed()
-        {}
-
-        //! \brief Failed test message creator
-        //!
-        //! \param[in] aTest string for tested expression
-        //! \param[in] aFile source file name
-        //! \param[in] aLine source file line
-        //! \param[in] aMessage error message
-        TestFailed(const char* aTest,
-                   const char* aFile,
-                   int aLine,
-                   const std::string &aMessage);
-
-        TestFailed(const std::string &message);
-
-        std::string GetMessage() const
-        {
-            return m_message;
-        }
-    };
-
-    class Ignored
-    {
-      private:
-        std::string m_message;
-
-      public:
-        Ignored()
-        {}
-
-        Ignored(const std::string &message) :
-            m_message(message)
-        {}
-
-        std::string GetMessage() const
-        {
-            return m_message;
-        }
-    };
-
-    void MarkAssertion();
-
     void RegisterTest(const char *testName, TestCase proc);
     void InitGroup(const char* name);
 
     int ExecTestRunner(int argc, char *argv[]);
     typedef std::vector<std::string> ArgsList;
     int ExecTestRunner(ArgsList args);
-    bool getRunIgnored() const;
     // The runner will terminate as soon as possible (after current test).
     void Terminate();
     bool GetAllowChildLogs();
+
+    void deferFailedException(const DPL::Test::TestFailed &ex);
+    void deferIgnoredException(const DPL::Test::TestIgnored &ex);
+    void deferBegin();
+    void deferEnd();
+
+private:
+    std::vector<std::string> m_deferredExceptionsMessages;
+    std::size_t m_deferDeepness;
+    enum DeferredExceptionType {
+        DEFERRED_FAILED,
+        DEFERRED_IGNORED,
+    } m_firstDeferredExceptionType;
+    DPL::Test::TestFailed m_firstDeferredFail;
+    DPL::Test::TestIgnored m_firstDeferredIgnore;
 };
 
 typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
@@ -247,16 +197,14 @@ typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
 #define RUNNER_ASSERT_MSG(test, message)                                              \
     do                                                                                \
     {                                                                                 \
-        DPL::Test::TestRunnerSingleton::Instance().MarkAssertion();                   \
-                                                                                      \
         if (!(test))                                                                  \
         {                                                                             \
             std::ostringstream assertMsg;                                             \
             assertMsg << message << DPL::gdbbacktrace();                              \
-            DPL::Test::TestRunner::TestFailed e(#test,                                \
-                                                __FILE__,                             \
-                                                __LINE__,                             \
-                                                assertMsg.str());                     \
+            DPL::Test::TestFailed e(#test,                                            \
+                                    __FILE__,                                         \
+                                    __LINE__,                                         \
+                                    assertMsg.str());                                 \
             if (!std::uncaught_exception())                                           \
                 throw e;                                                              \
             DPL::Test::TestRunnerSingleton::Instance().addFailReason(e.GetMessage()); \
@@ -266,8 +214,6 @@ typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
 #define RUNNER_ASSERT_ERRNO_MSG(test, message)                                        \
     do                                                                                \
     {                                                                                 \
-        DPL::Test::TestRunnerSingleton::Instance().MarkAssertion();                   \
-                                                                                      \
         if (!(test))                                                                  \
         {                                                                             \
             const char *err = strerror(errno);                                        \
@@ -276,10 +222,10 @@ typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
             if (!assertMsg.str().empty())                                             \
                 assertMsg << ". ";                                                    \
             assertMsg << err << DPL::gdbbacktrace();                                  \
-            DPL::Test::TestRunner::TestFailed e(#test,                                \
-                                                __FILE__,                             \
-                                                __LINE__,                             \
-                                                assertMsg.str());                     \
+            DPL::Test::TestFailed e(#test,                                            \
+                                    __FILE__,                                         \
+                                    __LINE__,                                         \
+                                    assertMsg.str());                                 \
             if (!std::uncaught_exception())                                           \
                 throw e;                                                              \
             DPL::Test::TestRunnerSingleton::Instance().addFailReason(e.GetMessage()); \
@@ -303,12 +249,12 @@ typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
  * body.
  */
 
-#define RUNNER_IGNORED_MSG(message)                            \
-    do                                                         \
-    {                                                          \
-        std::ostringstream assertMsg;                          \
-        assertMsg << message;                                  \
-        throw DPL::Test::TestRunner::Ignored(assertMsg.str()); \
+#define RUNNER_IGNORED_MSG(message)                    \
+    do                                                 \
+    {                                                  \
+        std::ostringstream assertMsg;                  \
+        assertMsg << message;                          \
+        throw DPL::Test::TestIgnored(assertMsg.str()); \
     } while (0)
 
 /**
@@ -331,13 +277,13 @@ typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
 
 #define RUNNER_PERF_TEST_BEGIN(maxTime)                                                \
     do {                                                                               \
-        DPL::Test::TestRunnerSingleton::Instance().beginPerformanceTestTime(           \
+        DPL::Test::TestRunnerSingleton::Instance().beginPerformance(                   \
             std::chrono::microseconds{static_cast<long long int>(maxTime*1000000.0)}); \
     } while (0)
 
-#define RUNNER_PERF_TEST_END()                                                \
-    do {                                                                      \
-        DPL::Test::TestRunnerSingleton::Instance().endPerformanceTestTime();  \
+#define RUNNER_PERF_TEST_END()                                       \
+    do {                                                             \
+        DPL::Test::TestRunnerSingleton::Instance().endPerformance(); \
     } while (0)
 
 /**
@@ -352,4 +298,39 @@ typedef DPL::Singleton<TestRunner> TestRunnerSingleton;
                   << DPL::Colors::Text::RED_END << std::endl; \
     } while (0)
 
+/**
+ * DEFER MACROS
+ *
+ * Use them to defer fails and ignores in test cases.
+ * Some code constructions disallow to throw. Such places can be surrounded
+ * with RUNNER_DEFER_SCOPE macro. RUNNER_DEFER_TRYCATCH macro can be used to catch possibly thrown
+ * exceptions within such scope. Possibly catched exceptions will be rethrown
+ * when leaving RUNNER_DEFER_SCOPE scope.
+ * Macros can be safely nested.
+ */
+
+
+#define RUNNER_DEFER_TRYCATCH(scope)                                              \
+    do {                                                                          \
+        try                                                                       \
+        {                                                                         \
+            scope                                                                 \
+        }                                                                         \
+        catch (const DPL::Test::TestFailed &ex)                                   \
+        {                                                                         \
+            DPL::Test::TestRunnerSingleton::Instance().deferFailedException(ex);  \
+        }                                                                         \
+        catch (const DPL::Test::TestIgnored &ex)                                  \
+        {                                                                         \
+            DPL::Test::TestRunnerSingleton::Instance().deferIgnoredException(ex); \
+        }                                                                         \
+    } while (0)                                                                   \
+
+#define RUNNER_DEFER_SCOPE(scope)                                \
+    do {                                                         \
+        DPL::Test::TestRunnerSingleton::Instance().deferBegin(); \
+        scope                                                    \
+        DPL::Test::TestRunnerSingleton::Instance().deferEnd();   \
+    } while (0)                                                  \
+
 #endif // DPL_TEST_RUNNER_H
index d1e4b1c..8c52600 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2013-2015 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.
@@ -50,15 +50,11 @@ class PipeWrapper : DPL::Noncopyable
     virtual ~PipeWrapper();
 
     Status send(int code, std::string &message);
-    Status sendTime(int code,
-                    std::chrono::system_clock::duration time,
-                    std::chrono::system_clock::duration timeMax);
+    Status sendPerformance(const ConstPerformanceResultPtr &performance);
 
     Status receive(int &code,
-                   int &msgType,
                    std::string &data,
-                   std::chrono::system_clock::duration &time,
-                   std::chrono::system_clock::duration &timeMax,
+                   PerformanceResultPtr &performance,
                    time_t deadline);
 
     void closeAll();
@@ -66,7 +62,6 @@ class PipeWrapper : DPL::Noncopyable
   protected:
 
     std::string toBinaryString(int data);
-    std::string toBinaryString(std::chrono::system_clock::duration data);
 
     void closeHelp(int desc);
 
diff --git a/src/framework/src/test_failed.cpp b/src/framework/src/test_failed.cpp
new file mode 100644 (file)
index 0000000..c8de070
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 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_failed.cpp
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version     1.0
+ * @brief       This file is the implementation file of TestFailed class
+ */
+
+#include <cstdlib>
+#include <cstring>
+#include <libgen.h>
+#include <memory>
+#include <sstream>
+
+#include <dpl/test/test_failed.h>
+
+namespace DPL {
+namespace Test {
+namespace // anonymous
+{
+std::string BaseName(const std::string &aPath)
+{
+    std::unique_ptr<char, decltype(free)*> path(strdup(aPath.c_str()), free);
+    if (!path)
+        throw std::bad_alloc();
+
+    return basename(path.get());
+}
+} // namespace anonymous
+
+//! \brief Failed test message creator
+//!
+//! \param[in] aTest string for tested expression
+//! \param[in] aFile source file name
+//! \param[in] aLine source file line
+//! \param[in] aMessage error message
+TestFailed::TestFailed(const char* aTest,
+                       const char* aFile,
+                       int aLine,
+                       const std::string &aMessage)
+{
+    std::ostringstream assertMsg;
+    assertMsg << "[" << BaseName(aFile) << ":" << aLine
+              << "] Assertion failed ("
+              << aTest << ") " << aMessage;
+    m_message = assertMsg.str();
+}
+
+} // namespace Test
+} // namespace DPL
index e821f16..013bde2 100644 (file)
 namespace DPL {
 namespace Test {
 
+namespace {
+
+const std::string NO_VERBOSE_ARG = "--no-verbose";
+
+} // namespace
+
+const std::string COLLECTOR_NO_VERBOSE_HELP =
+        NO_VERBOSE_ARG                          + " - turns off verbosity\n" +
+        std::string(NO_VERBOSE_ARG.size(), ' ') + "   verbosity turned on by default\n";
+
 double get_milliseconds (const std::chrono::system_clock::duration& performanceTime)
 {
     return (static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>
             (performanceTime).count()))/1000.0;
 }
 
+std::string CollectorFileHelp(const std::string &defaultFilename)
+{
+    return "--file=<filename> - name of file for output\n"
+           "                    default - " + defaultFilename + "\n";
+}
+
 bool ParseCollectorFileArg(const std::string &arg, std::string &filename)
 {
     const std::string argname = "--file=";
@@ -43,6 +59,14 @@ bool ParseCollectorFileArg(const std::string &arg, std::string &filename)
     return false;
 }
 
+bool ParseCollectorNoVerboseArg(const std::string &arg, bool &verbosity)
+{
+    if (arg != NO_VERBOSE_ARG)
+        return false;
+    verbosity=false;
+    return true;
+}
+
 } // namespace Test
 } // namespace DPL
 
index 09030a8..dab84f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -34,6 +34,7 @@ namespace DPL {
 namespace Test {
 
 ConsoleCollector::ConsoleCollector()
+    : m_verbosity(true)
 {
 }
 
@@ -42,6 +43,16 @@ TestResultsCollectorBase* ConsoleCollector::Constructor()
     return new ConsoleCollector();
 }
 
+bool ConsoleCollector::ParseCollectorSpecificArg(const std::string& arg)
+{
+    return ParseCollectorNoVerboseArg(arg, m_verbosity);
+}
+
+std::string ConsoleCollector::CollectorSpecificHelp() const
+{
+    return COLLECTOR_NO_VERBOSE_HELP;
+}
+
 void ConsoleCollector::CollectCurrentTestGroupName(const std::string& name)
 {
     printf("Starting group %s\n", name.c_str());
@@ -59,92 +70,79 @@ void ConsoleCollector::Finish()
     PrintStats("All tests together", m_stats);
 }
 
-void ConsoleCollector::CollectResult(const std::string& id,
-                                     const FailStatus status,
-                                     const std::string& reason,
-                                     const bool& isPerformanceTest,
-                                     const std::chrono::system_clock::duration& performanceTime,
-                                     const std::chrono::system_clock::duration& performanceMaxTime)
+void ConsoleCollector::CollectResult(const std::string& id, const TestResult &result)
 {
     using namespace DPL::Colors::Text;
     std::string tmp = "'" + id + "' ...";
 
     printf("Running test case %-60s", tmp.c_str());
-    switch (status) {
-    case FailStatus::NONE:
-        if (isPerformanceTest) {
-            if (performanceMaxTime <= std::chrono::microseconds::zero()) {
-                printf(GREEN_RESULT_OK_TIME,
-                        get_milliseconds(performanceTime));
-                break;
-            }
-            else {
-                if (performanceTime > performanceMaxTime)
-                    printf(GREEN_RESULT_OK_TIME_TOO_LONG(
-                            get_milliseconds(performanceTime),
-                            get_milliseconds(performanceMaxTime)));
-                else
-                    printf(GREEN_RESULT_OK_TIME_MAX(
-                            get_milliseconds(performanceTime),
-                            get_milliseconds(performanceMaxTime)));
-                break;
-            }
+
+    ConstPerformanceResultPtr performanceResult;
+    switch (result.GetFailStatus()) {
+    case TestResult::FailStatus::NONE:
+        performanceResult = result.GetPerformanceResult();
+        if (!performanceResult) {
+            printf(GREEN_RESULT_OK);
+            break;
+        }
+        if (!performanceResult->IsMaxDuration()) {
+            printf(GREEN_RESULT_OK_TIME,
+                   get_milliseconds(performanceResult->GetDuration()));
+            break;
+        }
+        if (!performanceResult->IsDurationOk()) {
+            printf(GREEN_RESULT_OK_TIME_TOO_LONG(
+                       get_milliseconds(performanceResult->GetDuration()),
+                       get_milliseconds(performanceResult->GetMaxDuration())));
+            break;
         }
-        printf(GREEN_RESULT_OK);
+        printf(GREEN_RESULT_OK_TIME_MAX(
+                   get_milliseconds(performanceResult->GetDuration()),
+                   get_milliseconds(performanceResult->GetMaxDuration())));
         break;
-    case FailStatus::FAILED:
-        PrintfErrorMessage(" FAILED ", reason, true);
+    case TestResult::FailStatus::FAILED:
+        PrintfErrorMessage(" FAILED ", result.GetReason());
         break;
-    case FailStatus::IGNORED:
-        PrintfIgnoredMessage("Ignored ", reason, true);
+    case TestResult::FailStatus::IGNORED:
+        PrintfIgnoredMessage("Ignored ", result.GetReason());
         break;
     default:
         Assert(false && "Bad status");
     }
-    m_stats.AddTest(status);
-    m_groupsStats[m_currentGroup].AddTest(status);
+    m_stats.AddTest(result.GetFailStatus());
+    m_groupsStats[m_currentGroup].AddTest(result.GetFailStatus());
 }
 
-void ConsoleCollector::PrintfErrorMessage(const char* type,
-                                          const std::string& message,
-                                          bool verbosity)
+void ConsoleCollector::PrintfErrorMessage(const char* type, const std::string& message)
 {
     using namespace DPL::Colors::Text;
-    if (verbosity) {
-        printf("[%s%s%s] %s%s%s\n",
-               BOLD_RED_BEGIN,
-               type,
-               BOLD_RED_END,
+    printf("[%s%s%s]",
+           BOLD_RED_BEGIN,
+           type,
+           BOLD_RED_END);
+    if (m_verbosity) {
+        printf(" %s%s%s",
                BOLD_YELLOW_BEGIN,
                message.c_str(),
                BOLD_YELLOW_END);
-    } else {
-        printf("[%s%s%s]\n",
-               BOLD_RED_BEGIN,
-               type,
-               BOLD_RED_END);
     }
+    printf("\n");
 }
 
-void ConsoleCollector::PrintfIgnoredMessage(const char* type,
-                                            const std::string& message,
-                                            bool verbosity)
+void ConsoleCollector::PrintfIgnoredMessage(const char* type, const std::string& message)
 {
     using namespace DPL::Colors::Text;
-    if (verbosity) {
-        printf("[%s%s%s] %s%s%s\n",
-               CYAN_BEGIN,
-               type,
-               CYAN_END,
+    printf("[%s%s%s]",
+           CYAN_BEGIN,
+           type,
+           CYAN_END);
+    if (m_verbosity) {
+        printf(" %s%s%s",
                BOLD_GOLD_BEGIN,
                message.c_str(),
                BOLD_GOLD_END);
-    } else {
-        printf("[%s%s%s]\n",
-               CYAN_BEGIN,
-               type,
-               CYAN_END);
     }
+    printf("\n");
 }
 
 void ConsoleCollector::PrintStats(const std::string& title, const Statistic& stats)
index 93698cc..86fce37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -39,7 +39,8 @@ const char *DEFAULT_HTML_FILE_NAME = "index.html";
 }
 
 HtmlCollector::HtmlCollector()
-    : m_filename(DEFAULT_HTML_FILE_NAME)
+    : m_filename(DEFAULT_HTML_FILE_NAME),
+      m_verbosity(true)
 {
 }
 
@@ -66,8 +67,7 @@ bool HtmlCollector::Configure()
 
 std::string HtmlCollector::CollectorSpecificHelp() const
 {
-    return "--file=<filename> - name of file for output\n"
-           "                    default - index.html\n";
+    return CollectorFileHelp(DEFAULT_HTML_FILE_NAME) + COLLECTOR_NO_VERBOSE_HELP;
 }
 
 void HtmlCollector::Start()
@@ -102,99 +102,87 @@ void HtmlCollector::Finish()
 
 bool HtmlCollector::ParseCollectorSpecificArg(const std::string& arg)
 {
-    return ParseCollectorFileArg(arg, m_filename);
+    return ParseCollectorFileArg(arg, m_filename) || ParseCollectorNoVerboseArg(arg, m_verbosity);
 }
 
-void HtmlCollector::CollectResult(const std::string& id,
-                                  const FailStatus status,
-                                  const std::string& reason,
-                                  const bool& isPerformanceTest,
-                                  const std::chrono::system_clock::duration& performanceTime,
-                                  const std::chrono::system_clock::duration& performanceMaxTime)
+void HtmlCollector::CollectResult(const std::string& id, const TestResult &result)
 {
     using namespace DPL::Colors::Html;
     std::string tmp = "'" + id + "' ...";
 
     fprintf(m_fp.Get(), "Running test case %-100s", tmp.c_str());
-    switch (status) {
-    case FailStatus::NONE:
-        if (isPerformanceTest) {
-            if (performanceMaxTime <= std::chrono::microseconds::zero()) {
-                fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME,
-                        get_milliseconds(performanceTime));
-                break;
-            } else {
-                if (performanceTime > performanceMaxTime)
-                    fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_TOO_LONG(
-                            get_milliseconds(performanceTime),
-                            get_milliseconds(performanceMaxTime)));
-                else
-                    fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_MAX(
-                            get_milliseconds(performanceTime),
-                            get_milliseconds(performanceMaxTime)));
-                break;
-            }
+
+    ConstPerformanceResultPtr performanceResult;
+    switch (result.GetFailStatus()) {
+    case TestResult::FailStatus::NONE:
+        performanceResult = result.GetPerformanceResult();
+        if (!performanceResult) {
+            fprintf(m_fp.Get(), GREEN_RESULT_OK);
+            break;
+        }
+        if (!performanceResult->IsMaxDuration()) {
+            fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME,
+                    get_milliseconds(performanceResult->GetDuration()));
+            break;
         }
-        fprintf(m_fp.Get(), GREEN_RESULT_OK);
+        if (!performanceResult->IsDurationOk()) {
+            fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_TOO_LONG(
+                                    get_milliseconds(performanceResult->GetDuration()),
+                                    get_milliseconds(performanceResult->GetMaxDuration())));
+            break;
+        }
+        fprintf(m_fp.Get(), GREEN_RESULT_OK_TIME_MAX(
+                                get_milliseconds(performanceResult->GetDuration()),
+                                get_milliseconds(performanceResult->GetMaxDuration())));
         break;
-    case FailStatus::FAILED:
-        PrintfErrorMessage(" FAILED ", reason, true);
+    case TestResult::FailStatus::FAILED:
+        PrintfErrorMessage(" FAILED ", result.GetReason());
         break;
-    case FailStatus::IGNORED:
-        PrintfIgnoredMessage("Ignored ", reason, true);
+    case TestResult::FailStatus::IGNORED:
+        PrintfIgnoredMessage("Ignored ", result.GetReason());
         break;
     default:
         Assert(false && "Bad status");
     }
-    m_groupsStats[m_currentGroup].AddTest(status);
-    m_stats.AddTest(status);
+    m_groupsStats[m_currentGroup].AddTest(result.GetFailStatus());
+    m_stats.AddTest(result.GetFailStatus());
 }
 
-void HtmlCollector::PrintfErrorMessage(const char* type,
-                                       const std::string& message,
-                                       bool verbosity)
+void HtmlCollector::PrintfErrorMessage(const char* type, const std::string& message)
 {
     using namespace DPL::Colors::Html;
-    if (verbosity) {
+    fprintf(m_fp.Get(),
+            "[%s%s%s]",
+            BOLD_RED_BEGIN,
+            type,
+            BOLD_RED_END);
+    if (m_verbosity) {
         fprintf(m_fp.Get(),
-                "[%s%s%s] %s%s%s\n",
-                BOLD_RED_BEGIN,
-                type,
-                BOLD_RED_END,
+                " %s%s%s",
                 BOLD_YELLOW_BEGIN,
                 message.c_str(),
                 BOLD_YELLOW_END);
-    } else {
-        fprintf(m_fp.Get(),
-                "[%s%s%s]\n",
-                BOLD_RED_BEGIN,
-                type,
-                BOLD_RED_END);
     }
+    fprintf(m_fp.Get(), "\n");
 }
 
-void HtmlCollector::PrintfIgnoredMessage(const char* type,
-                                         const std::string& message,
-                                         bool verbosity)
+void HtmlCollector::PrintfIgnoredMessage(const char* type, const std::string& message)
 {
     using namespace DPL::Colors::Html;
 
-    if (verbosity) {
+    fprintf(m_fp.Get(),
+            "[%s%s%s]",
+            CYAN_BEGIN,
+            type,
+            CYAN_END);
+    if (m_verbosity) {
         fprintf(m_fp.Get(),
-                "[%s%s%s] %s%s%s\n",
-                CYAN_BEGIN,
-                type,
-                CYAN_END,
+                " %s%s%s",
                 BOLD_GOLD_BEGIN,
                 message.c_str(),
                 BOLD_GOLD_END);
-    } else {
-        fprintf(m_fp.Get(),
-                "[%s%s%s]\n",
-                CYAN_BEGIN,
-                type,
-                CYAN_END);
     }
+    fprintf(m_fp.Get(), "\n");
 }
 
 void HtmlCollector::PrintStats(const std::string& name, const Statistic& stats)
index 74cb680..efcaa31 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -48,8 +48,7 @@ TestResultsCollectorBase* SummaryCollector::Constructor()
 
 std::string SummaryCollector::CollectorSpecificHelp() const
 {
-    return "--file=<filename> - name of file for output\n"
-           "                    default - " + DEFAULT_SUMMARY_FILE_NAME + "\n";
+    return CollectorFileHelp(DEFAULT_SUMMARY_FILE_NAME);
 }
 
 bool SummaryCollector::ParseCollectorSpecificArg(const std::string& arg)
@@ -62,20 +61,11 @@ void SummaryCollector::Start()
     writeStats(true);
 }
 
-void SummaryCollector::CollectResult(const std::string& id,
-                                     const FailStatus status,
-                                     const std::string& reason,
-                                     const bool& isPerformanceTest,
-                                     const std::chrono::system_clock::duration& performanceTime,
-                                     const std::chrono::system_clock::duration& performanceMaxTime)
+void SummaryCollector::CollectResult(const std::string& id, const TestResult &result)
 {
     DPL_UNUSED_PARAM(id);
-    DPL_UNUSED_PARAM(reason);
-    DPL_UNUSED_PARAM(isPerformanceTest);
-    DPL_UNUSED_PARAM(performanceTime);
-    DPL_UNUSED_PARAM(performanceMaxTime);
 
-    m_stats.AddTest(status);
+    m_stats.AddTest(result.GetFailStatus());
     writeStats(true);
 }
 
index 7eea2b7..6ad2fce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -42,7 +42,7 @@ const char *DEFAULT_XML_FILE_NAME = "results.xml";
 }
 
 XmlCollector::XmlCollector()
-    : m_filename(DEFAULT_XML_FILE_NAME)
+    : m_filename(DEFAULT_XML_FILE_NAME), m_verbosity(true)
 {
 }
 
@@ -99,8 +99,7 @@ bool XmlCollector::Configure()
 
 std::string XmlCollector::CollectorSpecificHelp() const
 {
-    return "--file=<filename> - name of file for output\n"
-           "                    default - results.xml\n";
+    return CollectorFileHelp(DEFAULT_XML_FILE_NAME) + COLLECTOR_NO_VERBOSE_HELP;
 }
 
 void XmlCollector::Start()
@@ -122,54 +121,49 @@ void XmlCollector::Finish()
 
 bool XmlCollector::ParseCollectorSpecificArg(const std::string& arg)
 {
-    return ParseCollectorFileArg(arg, m_filename);
+    return ParseCollectorFileArg(arg, m_filename) || ParseCollectorNoVerboseArg(arg, m_verbosity);
 }
 
-void XmlCollector::CollectResult(const std::string& id,
-                                 const FailStatus status,
-                                 const std::string& reason,
-                                 const bool& isPerformanceTest,
-                                 const std::chrono::system_clock::duration& performanceTime,
-                                 const std::chrono::system_clock::duration& performanceMaxTime)
+void XmlCollector::CollectResult(const std::string& id, const TestResult &result)
 {
     m_resultBuffer.erase();
     m_resultBuffer.append("\t\t<testcase name=\"");
     m_resultBuffer.append(EscapeSpecialCharacters(id));
     m_resultBuffer.append("\"");
-    switch (status) {
-    case FailStatus::NONE:
-        if (isPerformanceTest) {
-            if (performanceMaxTime <= std::chrono::microseconds::zero()) {
-                m_resultBuffer.append(" status=\"OK\" time=\"");
-                std::ostringstream ostr;
-                ostr << performanceTime.count();
-                m_resultBuffer.append(ostr.str());
-                m_resultBuffer.append("\"/>\n");
-                break;
-            } else {
-                m_resultBuffer.append(" status=\"OK\" time=\"");
-                std::ostringstream ostr;
-                ostr << performanceTime.count();
-                m_resultBuffer.append(ostr.str());
-                m_resultBuffer.append("\" time_expected=\"");
-                ostr.str("");
-                ostr << performanceMaxTime.count();
-                m_resultBuffer.append(ostr.str());
-                m_resultBuffer.append("\"/>\n");
-                break;
-            }
+
+    std::ostringstream ostr;
+    ConstPerformanceResultPtr performanceResult;
+    switch (result.GetFailStatus()) {
+    case TestResult::FailStatus::NONE:
+        performanceResult = result.GetPerformanceResult();
+        if (!performanceResult) {
+            m_resultBuffer.append(" status=\"OK\"/>\n");
+            break;
         }
-        m_resultBuffer.append(" status=\"OK\"/>\n");
+        if (!performanceResult->IsMaxDuration()) {
+            m_resultBuffer.append(" status=\"OK\" time=\"");
+            ostr << performanceResult->GetDuration().count();
+            m_resultBuffer.append(ostr.str());
+            m_resultBuffer.append("\"/>\n");
+            break;
+        }
+        m_resultBuffer.append(" status=\"OK\" time=\"");
+        ostr << performanceResult->GetDuration().count();
+        m_resultBuffer.append(ostr.str());
+        m_resultBuffer.append("\" time_expected=\"");
+        ostr.str("");
+        ostr << performanceResult->GetMaxDuration().count();
+        m_resultBuffer.append(ostr.str());
+        m_resultBuffer.append("\"/>\n");
         break;
-    case FailStatus::FAILED:
+    case TestResult::FailStatus::FAILED:
         m_resultBuffer.append(" status=\"FAILED\">\n");
-        PrintfErrorMessage("FAILED", EscapeSpecialCharacters(reason), true);
+        PrintfErrorMessage("FAILED", EscapeSpecialCharacters(result.GetReason()));
         m_resultBuffer.append("\t\t</testcase>\n");
         break;
-    case FailStatus::IGNORED:
+    case TestResult::FailStatus::IGNORED:
         m_resultBuffer.append(" status=\"Ignored\">\n");
-        PrintfIgnoredMessage("Ignored", EscapeSpecialCharacters(
-                                 reason), true);
+        PrintfIgnoredMessage("Ignored", EscapeSpecialCharacters(result.GetReason()));
         m_resultBuffer.append("\t\t</testcase>\n");
         break;
     default:
@@ -188,7 +182,7 @@ void XmlCollector::CollectResult(const std::string& id,
     }
     m_outputBuffer.insert(last_case_pos - 2, m_resultBuffer);
 
-    m_stats.AddTest(status);
+    m_stats.AddTest(result.GetFailStatus());
 
     UpdateGroupHeader(group_pos,
                       m_stats.GetTotal() + 1, // include SegFault
@@ -300,38 +294,26 @@ void XmlCollector::FlushOutput()
     }
 }
 
-void XmlCollector::PrintfErrorMessage(const char* type,
-                                      const std::string& message,
-                                      bool verbosity)
+void XmlCollector::PrintfErrorMessage(const char* type, const std::string& message)
 {
-    if (verbosity) {
-        m_resultBuffer.append("\t\t\t<failure type=\"");
-        m_resultBuffer.append(EscapeSpecialCharacters(type));
+    m_resultBuffer.append("\t\t\t<failure type=\"");
+    m_resultBuffer.append(EscapeSpecialCharacters(type));
+    if (m_verbosity) {
         m_resultBuffer.append("\" message=\"");
         m_resultBuffer.append(EscapeSpecialCharacters(message));
-        m_resultBuffer.append("\"/>\n");
-    } else {
-        m_resultBuffer.append("\t\t\t<failure type=\"");
-        m_resultBuffer.append(EscapeSpecialCharacters(type));
-        m_resultBuffer.append("\"/>\n");
     }
+    m_resultBuffer.append("\"/>\n");
 }
 
-void XmlCollector::PrintfIgnoredMessage(const char* type,
-                                        const std::string& message,
-                                        bool verbosity)
+void XmlCollector::PrintfIgnoredMessage(const char* type, const std::string& message)
 {
-    if (verbosity) {
-        m_resultBuffer.append("\t\t\t<skipped type=\"");
-        m_resultBuffer.append(EscapeSpecialCharacters(type));
+    m_resultBuffer.append("\t\t\t<skipped type=\"");
+    m_resultBuffer.append(EscapeSpecialCharacters(type));
+    if (m_verbosity) {
         m_resultBuffer.append("\" message=\"");
         m_resultBuffer.append(EscapeSpecialCharacters(message));
-        m_resultBuffer.append("\"/>\n");
-    } else {
-        m_resultBuffer.append("\t\t\t<skipped type=\"");
-        m_resultBuffer.append(EscapeSpecialCharacters(type));
-        m_resultBuffer.append("\"/>\n");
     }
+    m_resultBuffer.append("\"/>\n");
 }
 
 std::string XmlCollector::EscapeSpecialCharacters(std::string s)
index ae9bbc5..95e1698 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -13,7 +13,7 @@
  *    See the License for the specific language governing permissions and
  *    limitations under the License.
  */
-/*
+/**
  * @file        test_runner.cpp
  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
@@ -21,6 +21,8 @@
  * @brief       This file is the implementation file of test runner
  */
 #include <stddef.h>
+#include <dpl/test/test_failed.h>
+#include <dpl/test/test_ignored.h>
 #include <dpl/test/test_runner.h>
 #include <dpl/test/test_results_collector.h>
 #include <dpl/exception.h>
@@ -31,9 +33,6 @@
 #include <algorithm>
 #include <cstdio>
 #include <memory.h>
-#include <libgen.h>
-#include <cstring>
-#include <cstdlib>
 
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
@@ -59,42 +58,6 @@ std::string getXMLNode(xmlNodePtr node)
 
 namespace DPL {
 namespace Test {
-namespace // anonymous
-{
-std::string BaseName(std::string aPath)
-{
-    ScopedFree<char> path(strdup(aPath.c_str()));
-    if (nullptr == path.Get()) {
-        throw std::bad_alloc();
-    }
-    char* baseName = basename(path.Get());
-    std::string retValue = baseName;
-    return retValue;
-}
-} // namespace anonymous
-
-//! \brief Failed test message creator
-//!
-//! \param[in] aTest string for tested expression
-//! \param[in] aFile source file name
-//! \param[in] aLine source file line
-//! \param[in] aMessage error message
-TestRunner::TestFailed::TestFailed(const char* aTest,
-                                   const char* aFile,
-                                   int aLine,
-                                   const std::string &aMessage)
-{
-    std::ostringstream assertMsg;
-    assertMsg << "[" << BaseName(aFile) << ":" << aLine
-              << "] Assertion failed ("
-              << aTest << ") " << aMessage;
-    m_message = assertMsg.str();
-}
-
-TestRunner::TestFailed::TestFailed(const std::string &message)
-{
-    m_message = message;
-}
 
 void TestRunner::RegisterTest(const char *testName, TestCase proc)
 {
@@ -243,57 +206,50 @@ bool TestRunner::filterByXML(std::map<std::string, bool> & casesMap)
     return true;
 }
 
-TestRunner::Status TestRunner::RunTestCase(const TestCaseStruct& testCase)
+void TestRunner::RunTestCase(const TestCaseStruct& testCase)
 {
     setCurrentTestCase(&(const_cast<TestCaseStruct &>(testCase)));
+    m_deferDeepness = 0U;
     try {
         testCase.proc();
     } catch (const TestFailed &e) {
         // Simple test failure
         CollectResult(testCase.name,
-                      TestResultsCollectorBase::FailStatus::FAILED,
-                      getConcatedFailReason(e.GetMessage()));
+                      TestResult(TestResult::FailStatus::FAILED,
+                                 getConcatedFailReason(e.GetMessage())));
 
         setCurrentTestCase(nullptr);
-        return FAILED;
-    } catch (const Ignored &e) {
+        return;
+    } catch (const TestIgnored &e) {
         if (m_runIgnored) {
             // Simple test have to be implemented
             CollectResult(testCase.name,
-                          TestResultsCollectorBase::FailStatus::IGNORED,
-                          e.GetMessage());
+                          TestResult(TestResult::FailStatus::IGNORED, e.GetMessage()));
         }
 
         setCurrentTestCase(nullptr);
-        return IGNORED;
+        return;
     } catch (const std::exception &) {
         // std exception failure
         CollectResult(testCase.name,
-                      TestResultsCollectorBase::FailStatus::FAILED,
-                      "std exception");
+                      TestResult(TestResult::FailStatus::FAILED, "std exception"));
 
         setCurrentTestCase(nullptr);
-        return FAILED;
+        return;
     } catch (...) {
         // Unknown exception failure
         CollectResult(testCase.name,
-                      TestResultsCollectorBase::FailStatus::FAILED,
-                      "unknown exception");
-
+                      TestResult(TestResult::FailStatus::FAILED, "unknown exception"));
         setCurrentTestCase(nullptr);
-        return FAILED;
+        return;
     }
 
+    // Everything OK
     CollectResult(testCase.name,
-                  TestResultsCollectorBase::FailStatus::NONE,
-                  "",
-                  testCase.m_isPerformanceTest,
-                  testCase.m_performanceTestDurationTime,
-                  testCase.m_performanceMaxTime);
+                  TestResult(TestResult::FailStatus::NONE,
+                             std::string(),
+                             testCase.performance));
     setCurrentTestCase(nullptr);
-
-    // Everything OK
-    return PASS;
 }
 
 void TestRunner::RunTests()
@@ -360,56 +316,41 @@ void TestRunner::setCurrentTestCase(TestCaseStruct* testCase)
     m_currentTestCase = testCase;
 }
 
-void TestRunner::beginPerformanceTestTime(std::chrono::system_clock::duration maxTimeInMicroseconds)
+void TestRunner::beginPerformance(std::chrono::system_clock::duration maxDurationInMicroseconds)
 {
     TestCaseStruct* testCase = getCurrentTestCase();
     if (!testCase)
         return;
 
-    testCase->m_isPerformanceTest = true;
-    testCase->m_performanceMaxTime = maxTimeInMicroseconds;
-    testCase->m_performanceTestStartTime = std::chrono::system_clock::now();
-
-    // Set result to 0 microseconds. Display 0ms result when end macro is missing.
-    testCase->m_performanceTestDurationTime = std::chrono::microseconds::zero();
+    if (!testCase->performance)
+        testCase->performance.reset(new PerformanceResult(maxDurationInMicroseconds));
 }
 
-void TestRunner::endPerformanceTestTime()
+void TestRunner::endPerformance()
 {
     TestCaseStruct* testCase = getCurrentTestCase();
     if (!testCase)
         return;
 
-    testCase->m_performanceTestDurationTime = std::chrono::system_clock::now() -
-            testCase->m_performanceTestStartTime;
+    testCase->performance->Finish();
 }
 
-void TestRunner::getCurrentTestCasePerformanceResult(bool& isPerformanceTest,
-                                                     std::chrono::system_clock::duration& result,
-                                                     std::chrono::system_clock::duration& resultMax)
+ConstPerformanceResultPtr TestRunner::getCurrentTestCasePerformanceResult()
 {
     TestCaseStruct* testCase = getCurrentTestCase();
-    if (!testCase || !(testCase->m_isPerformanceTest)){
-        isPerformanceTest = false;
-        return;
-    }
+    if (!testCase)
+        return nullptr;
 
-    isPerformanceTest = testCase->m_isPerformanceTest;
-    result = testCase->m_performanceTestDurationTime;
-    resultMax = testCase->m_performanceMaxTime;
+    return testCase->performance;
 }
 
-void TestRunner::setCurrentTestCasePerformanceResult(bool isPerformanceTest,
-                                                     std::chrono::system_clock::duration result,
-                                                     std::chrono::system_clock::duration resultMax)
+void TestRunner::setCurrentTestCasePerformanceResult(const PerformanceResultPtr &performance)
 {
     TestCaseStruct* testCase = getCurrentTestCase();
     if (!testCase)
         return;
 
-    testCase->m_isPerformanceTest = isPerformanceTest;
-    testCase->m_performanceTestDurationTime = result;
-    testCase->m_performanceMaxTime = resultMax;
+    testCase->performance = performance;
 }
 
 void TestRunner::addFailReason(const std::string &reason)
@@ -428,24 +369,13 @@ std::string TestRunner::getConcatedFailReason(const std::string &reason)
     return reason + ret;
 }
 
-void TestRunner::CollectResult(
-    const std::string& id,
-    const TestResultsCollectorBase::FailStatus status,
-    const std::string& reason,
-    const bool& isPerformanceTest,
-    const std::chrono::system_clock::duration& performanceTestDurationTime,
-    const std::chrono::system_clock::duration& performanceMaxTime)
+void TestRunner::CollectResult(const std::string& id, const TestResult& result)
 {
     std::for_each(m_collectors.begin(),
                   m_collectors.end(),
                   [&](const TestResultsCollectors::value_type & collector)
                   {
-                      collector.second->CollectResult(id,
-                                                      status,
-                                                      reason,
-                                                      isPerformanceTest,
-                                                      performanceTestDurationTime,
-                                                      performanceMaxTime);
+                      collector.second->CollectResult(id, result);
                   });
 }
 
@@ -532,11 +462,6 @@ int TestRunner::ExecTestRunner(int argc, char *argv[])
     return ExecTestRunner(args);
 }
 
-void TestRunner::MarkAssertion()
-{
-    ++m_totalAssertions;
-}
-
 int TestRunner::ExecTestRunner(ArgsList args)
 {
     m_runIgnored = false;
@@ -742,11 +667,6 @@ int TestRunner::ExecTestRunner(ArgsList args)
     return 0;
 }
 
-bool TestRunner::getRunIgnored() const
-{
-    return m_runIgnored;
-}
-
 void TestRunner::Terminate()
 {
     m_terminate = true;
@@ -757,5 +677,60 @@ bool TestRunner::GetAllowChildLogs()
     return m_allowChildLogs;
 }
 
+void TestRunner::deferFailedException(const DPL::Test::TestFailed &ex)
+{
+    if (m_deferDeepness <= 0)
+        throw ex;
+
+    if (m_deferredExceptionsMessages.empty()) {
+        m_firstDeferredFail = ex;
+        m_firstDeferredExceptionType = DeferredExceptionType::DEFERRED_FAILED;
+    }
+    m_deferredExceptionsMessages.push_back(ex.GetMessage());
 }
+
+void TestRunner::deferIgnoredException(const DPL::Test::TestIgnored &ex)
+{
+    if (m_deferDeepness <= 0)
+        throw ex;
+
+    if (m_deferredExceptionsMessages.empty()) {
+        m_firstDeferredIgnore = ex;
+        m_firstDeferredExceptionType = DeferredExceptionType::DEFERRED_IGNORED;
+    }
+    m_deferredExceptionsMessages.push_back(ex.GetMessage());
+}
+
+void TestRunner::deferBegin()
+{
+    m_deferDeepness++;
+}
+
+void TestRunner::deferEnd()
+{
+    if (m_deferDeepness > 0)
+        m_deferDeepness--;
+
+    if (m_deferDeepness > 0)
+        return;
+
+    bool oops = std::uncaught_exception();
+    size_t additionalExceptions = oops ? 0 : 1;
+    for (size_t i = additionalExceptions; i < m_deferredExceptionsMessages.size(); ++i)
+        addFailReason(m_deferredExceptionsMessages[i]);
+
+    if (!oops && !m_deferredExceptionsMessages.empty())
+    {
+        m_deferredExceptionsMessages.clear();
+        switch (m_firstDeferredExceptionType) {
+            case DeferredExceptionType::DEFERRED_FAILED:
+                throw m_firstDeferredFail;
+            case DeferredExceptionType::DEFERRED_IGNORED:
+                throw m_firstDeferredIgnore;
+        }
+    }
+    m_deferredExceptionsMessages.clear();
+}
+
+} // namespace Test
 } // namespace DPL
index 19ed08c..e2efb02 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2013-2015 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.
  *    See the License for the specific language governing permissions and
  *    limitations under the License.
  */
-/*
+/**
  * @file        test_runner_child.cpp
  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
  * @version     1.0
  * @brief       This file is the implementation file of test runner
  */
 #include <stddef.h>
+#include <dpl/test/test_failed.h>
+#include <dpl/test/test_ignored.h>
 #include <dpl/test/test_runner.h>
 #include <dpl/test/test_runner_child.h>
 #include <dpl/test/test_results_collector.h>
@@ -47,9 +49,6 @@ const int CHILD_TEST_FAIL    = 0;
 const int CHILD_TEST_PASS    = 1;
 const int CHILD_TEST_IGNORED = 2;
 
-const int MSG_TYPE_MESSAGE   = 0; // sizeof(Message) + Message
-const int MSG_TYPE_PERF_TIME = 1; // perfTime + maxTime
-
 int closeOutput() {
     int devnull;
     int retcode = -1;
@@ -113,7 +112,6 @@ PipeWrapper::Status PipeWrapper::send(int code, std::string &message)
 
     std::ostringstream output;
     output << toBinaryString(code);
-    output << toBinaryString(MSG_TYPE_MESSAGE);
     output << toBinaryString(static_cast<int>(message.size()));
     output << message;
 
@@ -129,21 +127,16 @@ PipeWrapper::Status PipeWrapper::send(int code, std::string &message)
     return SUCCESS;
 }
 
-PipeWrapper::Status PipeWrapper::sendTime(int code,
-                                          std::chrono::system_clock::duration time,
-                                          std::chrono::system_clock::duration timeMax)
+PipeWrapper::Status PipeWrapper::sendPerformance(const ConstPerformanceResultPtr &performance)
 {
+    int foo = 0;
     if (m_pipefd[1] == PIPE_CLOSED) {
         return ERROR;
     }
+    if (!performance)
+        return writeHelp(&foo, sizeof(int));
 
-    std::ostringstream output;
-    output << toBinaryString(code);
-    output << toBinaryString(MSG_TYPE_PERF_TIME);
-    output << toBinaryString(time);
-    output << toBinaryString(timeMax);
-
-    std::string binary = output.str();
+    std::string binary = performance->ToBinaryString();
     int size = binary.size();
 
     if ((writeHelp(&size,
@@ -156,10 +149,8 @@ PipeWrapper::Status PipeWrapper::sendTime(int code,
 }
 
 PipeWrapper::Status PipeWrapper::receive(int &code,
-                                         int &msgType,
                                          std::string &data,
-                                         std::chrono::system_clock::duration &time,
-                                         std::chrono::system_clock::duration &timeMax,
+                                         PerformanceResultPtr &performance,
                                          time_t deadline)
 {
     if (m_pipefd[0] == PIPE_CLOSED) {
@@ -185,24 +176,34 @@ PipeWrapper::Status PipeWrapper::receive(int &code,
         queue.AppendCopy(&buffer[0], size);
 
         queue.FlattenConsume(&code, sizeof(int));
-        queue.FlattenConsume(&msgType, sizeof(int));
-
-        switch (msgType) {
-        case MSG_TYPE_MESSAGE:
-            queue.FlattenConsume(&size, sizeof(int));
-
-            buffer.resize(size);
-
-            queue.FlattenConsume(&buffer[0], size);
-            data.assign(buffer.begin(), buffer.end());
-            break;
-        case MSG_TYPE_PERF_TIME:
-            queue.FlattenConsume(&time, sizeof(std::chrono::system_clock::duration));
-            queue.FlattenConsume(&timeMax, sizeof(std::chrono::system_clock::duration));
-            break;
-        default:
-            return ERROR;
+        queue.FlattenConsume(&size, sizeof(int));
+
+        buffer.resize(size);
+
+        queue.FlattenConsume(&buffer[0], size);
+        data.assign(buffer.begin(), buffer.end());
+
+        if (code != CHILD_TEST_PASS)
+            return SUCCESS;
+
+        if ((ret = readHelp(&size, sizeof(int), deadline)) != SUCCESS) {
+            return ret;
         }
+
+        if (size == 0) {
+            performance = nullptr;
+            return SUCCESS;
+        }
+
+        buffer.resize(size);
+
+        if ((ret = readHelp(buffer.data(), size, deadline)) != SUCCESS) {
+            return ret;
+        }
+
+        queue.AppendCopy(buffer.data(), size);
+
+        performance.reset(new PerformanceResult(queue));
     } catch (DPL::BinaryQueue::Exception::Base &e) {
         return ERROR;
     }
@@ -222,13 +223,6 @@ std::string PipeWrapper::toBinaryString(int data)
     return std::string(buffer, buffer + sizeof(int));
 }
 
-std::string PipeWrapper::toBinaryString(std::chrono::system_clock::duration data)
-{
-    char buffer[sizeof(std::chrono::system_clock::duration)];
-    memcpy(buffer, &data, sizeof(std::chrono::system_clock::duration));
-    return std::string(buffer, buffer + sizeof(std::chrono::system_clock::duration));
-}
-
 void PipeWrapper::closeHelp(int desc)
 {
     if (m_pipefd[desc] != PIPE_CLOSED) {
@@ -297,13 +291,13 @@ void RunChildProc(TestRunner::TestCase procChild)
 {
     PipeWrapper pipe;
     if (!pipe.isReady()) {
-        throw TestRunner::TestFailed("Pipe creation failed");
+        throw TestFailed("Pipe creation failed");
     }
 
     pid_t pid = fork();
 
     if (pid == -1) {
-        throw TestRunner::TestFailed("Child creation failed");
+        throw TestFailed("Child creation failed");
     }
 
     if (pid != 0) {
@@ -311,12 +305,10 @@ void RunChildProc(TestRunner::TestCase procChild)
         pipe.setUsage(PipeWrapper::READONLY);
 
         int code;
-        int msgType;
-        std::chrono::system_clock::duration time_m;
-        std::chrono::system_clock::duration timeMax_m;
         std::string message;
+        PerformanceResultPtr performance;
 
-        int pipeReturn = pipe.receive(code, msgType, message, time_m, timeMax_m, time(0) + 10);
+        int pipeReturn = pipe.receive(code, message, performance, time(0) + 10);
 
         if (pipeReturn != PipeWrapper::SUCCESS) { // Timeout or reading error
             pipe.closeAll();
@@ -327,23 +319,19 @@ void RunChildProc(TestRunner::TestCase procChild)
         waitpid(pid, &status, 0);
 
         if (pipeReturn == PipeWrapper::TIMEOUT) {
-            throw TestRunner::TestFailed("Timeout");
+            throw TestFailed("Timeout");
         }
 
         if (pipeReturn == PipeWrapper::ERROR) {
-            throw TestRunner::TestFailed("Reading pipe error");
+            throw TestFailed("Reading pipe error");
         }
 
-        if (code == CHILD_TEST_PASS && msgType == MSG_TYPE_PERF_TIME) {
-            DPL::Test::TestRunnerSingleton::Instance().setCurrentTestCasePerformanceResult(true,
-                                                                                           time_m,
-                                                                                           timeMax_m);
-        }
+        TestRunnerSingleton::Instance().setCurrentTestCasePerformanceResult(performance);
 
         if (code == CHILD_TEST_FAIL) {
-            throw TestRunner::TestFailed(message);
+            throw TestFailed(message);
         } else if (code == CHILD_TEST_IGNORED) {
-            throw TestRunner::Ignored(message);
+            throw TestIgnored(message);
         }
     } else {
         // child code
@@ -353,9 +341,6 @@ void RunChildProc(TestRunner::TestCase procChild)
 
         int code = CHILD_TEST_PASS;
         std::string msg;
-        bool isPerformanceTest;
-        std::chrono::system_clock::duration time_m;
-        std::chrono::system_clock::duration timeMax_m;
 
         bool allowLogs = TestRunnerSingleton::Instance().GetAllowChildLogs();
 
@@ -368,10 +353,10 @@ void RunChildProc(TestRunner::TestCase procChild)
 
         try {
             procChild();
-        } catch (const DPL::Test::TestRunner::TestFailed &e) {
+        } catch (const DPL::Test::TestFailed &e) {
             msg = e.GetMessage();
             code = CHILD_TEST_FAIL;
-        } catch (const DPL::Test::TestRunner::Ignored &e) {
+        } catch (const DPL::Test::TestIgnored &e) {
             msg = e.GetMessage();
             code = CHILD_TEST_IGNORED;
         } catch (...) { // catch all exception generated by "user" code
@@ -383,16 +368,10 @@ void RunChildProc(TestRunner::TestCase procChild)
             closeOutput();
         }
 
-        DPL::Test::TestRunnerSingleton::Instance().getCurrentTestCasePerformanceResult(isPerformanceTest,
-                                                                                       time_m,
-                                                                                       timeMax_m);
-
-        if (code == CHILD_TEST_PASS && isPerformanceTest){
-            pipe.sendTime(code,
-                    time_m,
-                    timeMax_m);
-        } else {
-            pipe.send(code, msg);
+        pipe.send(code, msg);
+        if (code == CHILD_TEST_PASS){
+            pipe.sendPerformance(TestRunnerSingleton::Instance() \
+                 .getCurrentTestCasePerformanceResult());
         }
     }
 }
index 989654a..55e889b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2015 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.
@@ -13,7 +13,7 @@
  *    See the License for the specific language governing permissions and
  *    limitations under the License.
  */
-/*
+/**
  * @file        test_runner_multiprocess.cpp
  * @author      Marcin Niesluchowski (m.niesluchow@samsung.com)
  * @version     1.0
@@ -22,6 +22,8 @@
 
 #include <sys/file.h>
 #include <dpl/exception.h>
+#include <dpl/test/test_failed.h>
+#include <dpl/test/test_ignored.h>
 #include <dpl/test/test_runner.h>
 #include <dpl/test/test_runner_child.h>
 #include <dpl/test/test_runner_multiprocess.h>
@@ -141,16 +143,16 @@ void RunMultiProc(TestRunner::TestCase procMulti)
     pid_t top_pid = getpid();
 
     if (!pipe.isReady()) {
-        throw TestRunner::TestFailed("Pipe creation failed");
+        throw TestFailed("Pipe creation failed");
     }
     // pipe
 
     try {
         procMulti();
-    } catch (const TestRunner::TestFailed &e) {
+    } catch (const TestFailed &e) {
         code = MULTI_TEST_FAILED;
         msg = e.GetMessage();
-    } catch (const TestRunner::Ignored &e) {
+    } catch (const TestIgnored &e) {
         code = MULTI_TEST_IGNORED;
         msg = e.GetMessage();
     } catch (const std::exception &) {
@@ -180,10 +182,10 @@ void RunMultiProc(TestRunner::TestCase procMulti)
                         }
                         if (pipeReturn == PipeWrapper::ERROR) {
                             pipe.closeAll();
-                            throw TestRunner::TestFailed("Reading pipe error");
+                            throw TestFailed("Reading pipe error");
                         } else if (pipeReturn == PipeWrapper::TIMEOUT) {
                             pipe.closeAll();
-                            throw TestRunner::TestFailed("Timeout error");
+                            throw TestFailed("Timeout error");
                         }
                         msg = msg + "\n" + recMsg;
                     }
@@ -193,11 +195,11 @@ void RunMultiProc(TestRunner::TestCase procMulti)
                     case MULTI_TEST_PASS:
                         return;
                     case MULTI_TEST_FAILED:
-                        throw TestRunner::TestFailed(msg);
+                        throw TestFailed(msg);
                     case MULTI_TEST_IGNORED:
-                        throw TestRunner::Ignored(msg);
+                        throw TestIgnored(msg);
                     default:
-                        throw TestRunner::TestFailed(msg);
+                        throw TestFailed(msg);
                     }
                 } else {
                     pipe.setUsage(PipeWrapper::WRITEONLY);
index a1fe677..653971a 100644 (file)
@@ -54,7 +54,7 @@ function printSummary
 
 runTest smack
 runTest smack-dbus
-#runTest libprivilege-control
+runTest libprivilege-control
 #runTest ss-clientsmack
 #runTest ss-server
 #runTest ss-password
@@ -62,6 +62,7 @@ runTest smack-dbus
 #runTest ss-stress
 runTest security-manager
 runTest cynara
+runTest ckm
 
 printSummary
 
index db3221c..f99127b 100644 (file)
@@ -88,13 +88,19 @@ case $1 in
     echo
     cynara-test "${@:2}"
     ;;
+"ckm")
+    echo "========================================================================="
+    echo "KEY MANAGER TESTS"
+    echo
+    ckm-tests "${@:2}"
+    ;;
 *)
     echo "Correct using:"
     echo "    security_test.sh <module> <args_for_module>"
     echo
     echo "modules: smack, smack-dbus, libprivilege-control, ss-clientsmack"
     echo "         ss-server, ss-api-speed, ss-password, ss-stress"
-    echo "         ss-privilege, security-manager, cynara"
+    echo "         ss-privilege, security-manager, cynara, ckm"
     ;;
 
 esac
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b1b4d87
--- /dev/null
@@ -0,0 +1,63 @@
+# Copyright (c) 2015 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.
+#
+
+cmake_minimum_required(VERSION 2.8.3)
+
+INCLUDE(FindPkgConfig)
+SET(INNER_TARGET_TEST "security-tests-inner-test")
+
+PKG_CHECK_MODULES(INNER_TARGET_DEP
+    REQUIRED
+    glib-2.0
+    )
+
+#files to compile
+SET(INNER_TARGET_TEST_SOURCES
+    ${PROJECT_SOURCE_DIR}/tests/inner-test.cpp
+    ${PROJECT_SOURCE_DIR}/tests/common/test_cases_timeout.cpp
+    ${PROJECT_SOURCE_DIR}/tests/framework/test_cases_deferred.cpp
+    )
+
+#header directories
+INCLUDE_DIRECTORIES(SYSTEM
+    ${INNER_TARGET_DEP_INCLUDE_DIRS}
+    )
+
+INCLUDE_DIRECTORIES(
+    ${PROJECT_SOURCE_DIR}/src/framework/include/
+    ${PROJECT_SOURCE_DIR}/src/
+    )
+
+#output format
+ADD_EXECUTABLE(${INNER_TARGET_TEST} ${INNER_TARGET_TEST_SOURCES})
+
+#linker directories
+TARGET_LINK_LIBRARIES(${INNER_TARGET_TEST}
+    ${INNER_TARGET_DEP_LIBRARIES}
+    tests-common
+    dpl-test-framework
+    )
+
+#place for output file
+INSTALL(TARGETS ${INNER_TARGET_TEST}
+    DESTINATION /usr/bin
+    PERMISSIONS OWNER_READ
+                OWNER_WRITE
+                OWNER_EXECUTE
+                GROUP_READ
+                GROUP_EXECUTE
+                WORLD_READ
+                WORLD_EXECUTE
+    )
diff --git a/tests/common/test_cases_timeout.cpp b/tests/common/test_cases_timeout.cpp
new file mode 100644 (file)
index 0000000..f11ad41
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015 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_cases_timeout.cpp
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version     1.0
+ * @brief       Inner tests for timeout mechanism
+ */
+
+#include <chrono>
+#include <string>
+#include <thread>
+
+#include <dpl/test/test_runner.h>
+#include <common/timeout.h>
+
+RUNNER_TEST_GROUP_INIT(TIMEOUT)
+
+void timeout_test_ret(int waitDuration, int functionDuration, Timeout::ExpectMode expect) {
+    float fRet = 3.1415;
+    auto ret = Timeout::callAndWait(std::chrono::seconds(waitDuration), expect,
+                         Timeout::CancelFunction(),
+                         ([fRet](int sec) -> float {
+                             std::this_thread::sleep_for(std::chrono::seconds(sec));
+                             return fRet;
+                         }), functionDuration);
+    RUNNER_ASSERT_MSG(ret == fRet,
+                         "Function returned = " << ret << " while expected value was " << fRet);
+}
+
+RUNNER_TEST(it01_expected_timeout)
+{
+    timeout_test_ret(3, 5, Timeout::ExpectMode::TIMEOUT);
+}
+
+RUNNER_TEST(it02_unexpected_finish)
+{
+    bool thrown = false;
+    try {
+        timeout_test_ret(3, 5, Timeout::ExpectMode::FINISHED);
+    } catch (const DPL::Test::TestException&) {
+        thrown = true;
+    }
+    RUNNER_ASSERT_MSG(thrown,
+                         "Test should throw DPL::Test::TestException");
+}
+
+RUNNER_TEST(it03_ignored_timeout)
+{
+    timeout_test_ret(3, 5, Timeout::ExpectMode::IGNORE);
+}
+
+RUNNER_TEST(it04_expected_finish)
+{
+    timeout_test_ret(5, 3, Timeout::ExpectMode::FINISHED);
+}
+
+RUNNER_TEST(it05_unexpected_timeout)
+{
+    bool thrown = false;
+    try {
+        timeout_test_ret(5, 3, Timeout::ExpectMode::TIMEOUT);
+    } catch (const DPL::Test::TestException&) {
+        thrown = true;
+    }
+    RUNNER_ASSERT_MSG(thrown,
+                         "Test should throw DPL::Test::TestException");
+}
+
+RUNNER_TEST(it06_ignored_finish)
+{
+    timeout_test_ret(5, 3, Timeout::ExpectMode::IGNORE);
+}
+
+void timeout_test_throw(int waitDuration, int functionDuration, Timeout::ExpectMode expect) {
+    std::string exceptionString("exceptionString");
+    bool thrown = false;
+    try {
+        Timeout::callAndWait(std::chrono::seconds(waitDuration), expect,
+                             Timeout::CancelFunction(),
+                             ([exceptionString](int sec) -> float {
+                                 std::this_thread::sleep_for(std::chrono::seconds(sec));
+                                 throw exceptionString;
+                             }), functionDuration);
+    } catch (const std::string &str) {
+        RUNNER_ASSERT_MSG(str == exceptionString,
+                             "Function thrown = " << str
+                             << " while expected value was " << exceptionString);
+        thrown = true;
+    }
+    RUNNER_ASSERT_MSG(thrown,
+                         "Test should throw std::string(" << exceptionString << ")");
+}
+
+RUNNER_TEST(it07_throw_expected_timeout)
+{
+    timeout_test_throw(3, 5, Timeout::ExpectMode::TIMEOUT);
+}
+
+RUNNER_TEST(it08_throw_unexpected_finish)
+{
+    bool thrown = false;
+    try {
+        timeout_test_throw(3, 5, Timeout::ExpectMode::FINISHED);
+    } catch (const DPL::Test::TestException&) {
+        thrown = true;
+    }
+    RUNNER_ASSERT_MSG(thrown,
+                         "Test should throw DPL::Test::TestException");
+}
+
+RUNNER_TEST(it09_throw_ignored_timeout)
+{
+    timeout_test_throw(3, 5, Timeout::ExpectMode::IGNORE);
+}
+
+RUNNER_TEST(it10_throw_expected_finish)
+{
+    timeout_test_throw(5, 3, Timeout::ExpectMode::FINISHED);
+}
+
+RUNNER_TEST(it11_throw_unexpected_timeout)
+{
+    bool thrown = false;
+    try {
+        timeout_test_throw(5, 3, Timeout::ExpectMode::TIMEOUT);
+    } catch (const DPL::Test::TestException&) {
+        thrown = true;
+    }
+    RUNNER_ASSERT_MSG(thrown,
+                         "Test should throw DPL::Test::TestException");
+}
+
+RUNNER_TEST(it12_throw_ignored_finish)
+{
+    timeout_test_throw(5, 3, Timeout::ExpectMode::IGNORE);
+}
diff --git a/tests/framework/test_cases_deferred.cpp b/tests/framework/test_cases_deferred.cpp
new file mode 100644 (file)
index 0000000..036bc0f
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015 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_cases_deferred.cpp
+ * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version     1.0
+ * @brief       Inner tests for defer macros mechanism
+ */
+
+#include <dpl/test/test_exception.h>
+#include <dpl/test/test_runner.h>
+
+#define EXPECT_EXCEPTION(expectedCatch, F) {                           \
+    bool catched = false;                                              \
+    try {                                                              \
+        F;                                                             \
+    } catch (const DPL::Test::TestException & ex) {                    \
+        catched = true;                                                \
+    }                                                                  \
+    RUNNER_ASSERT_MSG(catched == expectedCatch,                        \
+                         "Exception catched = " << catched             \
+                         << " while expected is = " << expectedCatch); \
+}
+
+#define FILTER(F) { \
+    try {           \
+        F;          \
+    } catch (...) { \
+    }               \
+}
+
+#define TRYCATCH(F) {      \
+    RUNNER_DEFER_TRYCATCH( \
+        F;                 \
+    );                     \
+}
+
+#define SCOPE(F) {      \
+    RUNNER_DEFER_SCOPE( \
+        F;              \
+    );                  \
+}
+
+void fail(void)
+{
+    RUNNER_FAIL_MSG("Oops!");
+}
+
+void pass(void)
+{
+}
+
+RUNNER_TEST_GROUP_INIT(DEFERRED)
+
+RUNNER_TEST(id01_simple_fail)
+{
+    EXPECT_EXCEPTION(true, fail());
+}
+
+RUNNER_TEST(id02_filtred_fail)
+{
+    EXPECT_EXCEPTION(false, FILTER(fail()));
+}
+
+RUNNER_TEST(id03_saved_filtred_rethrown_fail)
+{
+    EXPECT_EXCEPTION(true, SCOPE(FILTER(TRYCATCH(fail()))));
+}
+
+RUNNER_TEST(id04_saved_filtred_fail)
+{
+    EXPECT_EXCEPTION(false, FILTER(TRYCATCH(fail())));
+}
+
+RUNNER_TEST(id05_filtred_rethrown_fail)
+{
+    EXPECT_EXCEPTION(false, SCOPE(FILTER(fail())));
+}
+
+RUNNER_TEST(id06_saved_rethrown_fail)
+{
+    EXPECT_EXCEPTION(true, SCOPE(TRYCATCH(fail())));
+}
+
+RUNNER_TEST(id07_saved_fail)
+{
+    EXPECT_EXCEPTION(true, TRYCATCH(fail()));
+}
+
+RUNNER_TEST(id08_rethrown_fail)
+{
+    EXPECT_EXCEPTION(true, SCOPE(fail()));
+}
+
+RUNNER_TEST(id09_nested_scope)
+{
+    EXPECT_EXCEPTION(true, SCOPE(SCOPE(SCOPE(FILTER(TRYCATCH(fail()))))));
+}
+
+RUNNER_TEST(id10_nested_scope2)
+{
+    EXPECT_EXCEPTION(true, SCOPE(SCOPE(FILTER(SCOPE(TRYCATCH(fail()))))));
+}
+
+RUNNER_TEST(id11_saved_filtred_rethrown_pass)
+{
+    EXPECT_EXCEPTION(false, SCOPE(FILTER(TRYCATCH(pass()))));
+}
diff --git a/tests/inner-test.cpp b/tests/inner-test.cpp
new file mode 100644 (file)
index 0000000..052acfa
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+#include <dpl/test/test_runner.h>
+
+int main (int argc, char *argv[])
+{
+    int status = DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
+    return status;
+}