############################# subdirectories ##################################
ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(tests)
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:
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
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"
/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
${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
/*
- * 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.
*
* 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);
* @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);
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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_
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();
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))
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ * 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
#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 {
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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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_
${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
)
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: "
{
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();
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.");
{
bool oops = std::uncaught_exception();
try {
- cynara_async_finish(m_cynara);
+ RUNNER_DEFER_SCOPE(cynara_async_finish(m_cynara););
assertStatus(DISCONNECTED);
} catch (...) {
if (!oops)
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 << ","
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);
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 << ","
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 << ","
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
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
#include <cynara_test_cynara_mask.h>
#include <dpl/exception.h>
-#include <dpl/test/test_runner.h>
+#include <dpl/test/test_exception.h>
#include <exception>
{
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");
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()
removeDirIfExists(m_pluginsSaveDir);
removeDirIfExists(m_saveDir);
}
+
+void CynaraTestEnv::loadDefaultDatabase()
+{
+ CynaraMask mask;
+
+ if (m_dbPresent) {
+ removeDirFiles(CynaraTestConsts::DB_DIR);
+ copyCynaraFiles(m_defaultDir, CynaraTestConsts::DB_DIR);
+ }
+}
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;
};
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)
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)
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)
#ifndef CYNARA_TEST_FILE_OPERATIONS_H
#define CYNARA_TEST_FILE_OPERATIONS_H
+#include <fcntl.h>
#include <string>
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);
--- /dev/null
+buckets;$1$$6ZlVs5lw2nZgVmiw0BdY21
+_;$1$$qRPK7m23GJusamGpoGLby/
--- /dev/null
+buckets;$1$$UYHKvrIkGoSTO5hIgvCLg0
+_;$1$$qRPK7m23GJusamGpoGLby/
--- /dev/null
+buckets;$1$$6ZlVs5lw2nZgVmiw0BdY21
+_;$1$$nssatAXP6yl4N8gjldhxf0
--- /dev/null
+/*
+ * 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)
/*
- * 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.
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)
{
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()),
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);
}
}
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);
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);
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);
"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);
}
${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
--- /dev/null
+/*
+ * 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
/*
- * 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.
#include <cstddef>
#include <dpl/assert.h>
-#include <dpl/test/test_results_collector.h>
+#include <dpl/test/test_result.h>
namespace DPL {
namespace Test {
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");
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
/*
- * 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.
*/
/*
* @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>
public:
typedef TestResultsCollectorBase* (*CollectorConstructorFunc)();
typedef std::list<std::string> TestCaseIdList;
- enum class FailStatus
- {
- NONE,
- FAILED,
- IGNORED
- };
virtual ~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 "";
"[%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
/*
- * 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.
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
/*
- * 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.
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;
Statistic m_stats;
std::string m_currentGroup;
std::map<std::string, Statistic> m_groupsStats;
+ bool m_verbosity;
};
} // namespace Test
/*
- * 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.
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);
/*
- * 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.
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);
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);
Statistic m_stats;
std::string m_outputBuffer;
std::string m_resultBuffer;
+ bool m_verbosity;
};
} // namespace Test
#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 {
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);
{
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
{
TestCaseStruct(const std::string &n, TestCase p) :
name(n),
- proc(p),
- m_isPerformanceTest(false)
+ proc(p)
{}
};
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.
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();
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;
#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()); \
#define RUNNER_ASSERT_ERRNO_MSG(test, message) \
do \
{ \
- DPL::Test::TestRunnerSingleton::Instance().MarkAssertion(); \
- \
if (!(test)) \
{ \
const char *err = strerror(errno); \
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()); \
* 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)
/**
#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)
/**
<< 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
/*
- * 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.
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();
protected:
std::string toBinaryString(int data);
- std::string toBinaryString(std::chrono::system_clock::duration data);
void closeHelp(int desc);
--- /dev/null
+/*
+ * 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
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=";
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
/*
- * 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.
namespace Test {
ConsoleCollector::ConsoleCollector()
+ : m_verbosity(true)
{
}
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());
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)
/*
- * 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.
}
HtmlCollector::HtmlCollector()
- : m_filename(DEFAULT_HTML_FILE_NAME)
+ : m_filename(DEFAULT_HTML_FILE_NAME),
+ m_verbosity(true)
{
}
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()
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)
/*
- * 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.
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)
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);
}
/*
- * 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.
}
XmlCollector::XmlCollector()
- : m_filename(DEFAULT_XML_FILE_NAME)
+ : m_filename(DEFAULT_XML_FILE_NAME), m_verbosity(true)
{
}
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()
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:
}
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
}
}
-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)
/*
- * 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.
* 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)
* @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>
#include <algorithm>
#include <cstdio>
#include <memory.h>
-#include <libgen.h>
-#include <cstring>
-#include <cstdlib>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
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)
{
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()
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)
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);
});
}
return ExecTestRunner(args);
}
-void TestRunner::MarkAssertion()
-{
- ++m_totalAssertions;
-}
-
int TestRunner::ExecTestRunner(ArgsList args)
{
m_runIgnored = false;
return 0;
}
-bool TestRunner::getRunIgnored() const
-{
- return m_runIgnored;
-}
-
void TestRunner::Terminate()
{
m_terminate = true;
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
/*
- * 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>
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;
std::ostringstream output;
output << toBinaryString(code);
- output << toBinaryString(MSG_TYPE_MESSAGE);
output << toBinaryString(static_cast<int>(message.size()));
output << 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,
}
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) {
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;
}
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) {
{
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) {
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();
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
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();
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
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());
}
}
}
/*
- * 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.
* 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
#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>
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 &) {
}
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;
}
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);
runTest smack
runTest smack-dbus
-#runTest libprivilege-control
+runTest libprivilege-control
#runTest ss-clientsmack
#runTest ss-server
#runTest ss-password
#runTest ss-stress
runTest security-manager
runTest cynara
+runTest ckm
printSummary
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
--- /dev/null
+# 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
+ )
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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()))));
+}
--- /dev/null
+/*
+ * 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;
+}