--- /dev/null
- uint32_t ServiceManager::getUIntProperty(const std::string &interface, const std::string &property)
+/*
+ * Copyright (c) 2013-2014 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 service_manager.cpp
+ * @author Zbigniew Jasinski <z.jasinski@samsung.com>
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @author Marcin Niesluchowski <m.niesluchow@samsung.com>
+ * @version 1.1
+ * @brief Definition of service control class using dbus interface to communicate with systemd
+ */
+
+#include <service_manager.h>
+
+#include <dpl/test/test_runner.h>
+
+#include <sstream>
+#include <unistd.h>
+#include <vector>
+
+namespace {
+
+const std::string DBUS_CLIENT_NAME("tests.dbus.client");
+const std::string DBUS_PROPERTIES_INTERFACE("org.freedesktop.DBus.Properties");
+const std::string SYSTEMD_DESTINATION("org.freedesktop.systemd1");
+const std::string SYSTEMD_PATH("/org/freedesktop/systemd1");
+const std::string SYSTEMD_MANAGER_INTERFACE("org.freedesktop.systemd1.Manager");
+const std::string SYSTEMD_SERVICE_INTERFACE("org.freedesktop.systemd1.Service");
+
+const std::string MATCH_JOB_REMOVED("JobRemoved");
+const std::string MATCH_JOB_NEW("JobNew");
+const std::string MATCH_RELOADING("Reloading");
+
+}
+
+ServiceManager::ServiceManager(const std::string &serviceName)
+ : m_connection(DBUS_BUS_SYSTEM, true)
+ , m_serviceName(serviceName)
+{
+ addBusMatch(MATCH_JOB_REMOVED);
+ addBusMatch(MATCH_JOB_NEW);
+ addBusMatch(MATCH_RELOADING);
+ m_connection.flush();
+ m_connection.addFilter(messageHandler,
+ reinterpret_cast<void*>(this));
+ subscribeSignals();
+ m_connection.requestName(DBUS_CLIENT_NAME);
+ getUnitPath();
+}
+
+void ServiceManager::addBusMatch(const std::string &member)
+{
+ std::ostringstream rule;
+ rule << "type='signal',"
+ << "sender='" << SYSTEMD_DESTINATION << "',"
+ << "interface='" << SYSTEMD_MANAGER_INTERFACE << "',"
+ << "member='" << member << "',"
+ << "path='" << SYSTEMD_PATH << "'";
+
+ m_connection.addMatch(rule.str());
+}
+
+void ServiceManager::subscribeSignals()
+{
+ DBus::MessageOut messageOut = newMethodCall("Subscribe");
+ m_connection.sendWithReplyAndBlock(messageOut);
+}
+
+void ServiceManager::reloadDbusManager()
+{
+ DBus::MessageOut messageOut = newMethodCall("Reload");
+ m_connection.sendWithReplyAndBlock(messageOut);
+ m_runningJobs.insert(MATCH_RELOADING);
+}
+
+void ServiceManager::getUnitPath()
+{
+ DBus::MessageOut messageOut = newMethodCall("GetUnit");
+ messageOut.append(m_serviceName);
+ DBus::MessageIn messageIn = m_connection.sendWithReplyAndBlock(messageOut);
+ m_unitPath = handleObjectPathMsgReply(messageIn);
+}
+
+DBus::MessageOut ServiceManager::newMethodCall(const std::string &method)
+{
+ return DBus::MessageOut(SYSTEMD_DESTINATION.c_str(),
+ SYSTEMD_PATH.c_str(),
+ SYSTEMD_MANAGER_INTERFACE.c_str(),
+ method.c_str());
+}
+
+std::string ServiceManager::handleObjectPathMsgReply(DBus::MessageIn &messageIn)
+{
+ DBus::MessageIn::Iterator iterator = messageIn.iterInit();
+ iterator.expectArgType(DBUS_TYPE_OBJECT_PATH);
+ return iterator.getArgString();
+}
+
+uint32_t ServiceManager::handleVariantUIntMsgReply(DBus::MessageIn &messageIn)
+{
+ DBus::MessageIn::Iterator iterator = messageIn.iterInit();
+ iterator.expectArgType(DBUS_TYPE_VARIANT);
+ DBus::MessageIn::Iterator iteratorSub = iterator.recurse();
+ iteratorSub.expectArgType(DBUS_TYPE_UINT32);
+ return iteratorSub.getArgUint32();
+}
+
++uint64_t ServiceManager::handleVariantUInt64MsgReply(DBus::MessageIn &messageIn)
++{
++ DBus::MessageIn::Iterator iterator = messageIn.iterInit();
++ iterator.expectArgType(DBUS_TYPE_VARIANT);
++ DBus::MessageIn::Iterator iteratorSub = iterator.recurse();
++ iteratorSub.expectArgType(DBUS_TYPE_UINT64);
++ return iteratorSub.getArgUint64();
++}
++
+void ServiceManager::sendToService(const std::string &method)
+{
+ DBus::MessageOut messageOut = newMethodCall(method);
+ messageOut.append(m_serviceName);
+ messageOut.append("fail");
+ DBus::MessageIn messageIn = m_connection.sendWithReplyAndBlock(messageOut);
+ m_runningJobs.insert(handleObjectPathMsgReply(messageIn));
+}
+
+void ServiceManager::sendMaskToService()
+{
+ const std::vector<std::string> mask(1, m_serviceName);
+ DBus::MessageOut messageOut = newMethodCall("MaskUnitFiles");
+ messageOut.append(mask);
+ messageOut.append(true);
+ messageOut.append(true);
+ m_connection.sendWithReplyAndBlock(messageOut);
+}
+
+void ServiceManager::sendUnmaskToService()
+{
+ const std::vector<std::string> mask(1, m_serviceName);
+ DBus::MessageOut messageOut = newMethodCall("UnmaskUnitFiles");
+ messageOut.append(mask);
+ messageOut.append(true);
+ m_connection.sendWithReplyAndBlock(messageOut);
+}
+
- DBus::MessageOut messageOut(SYSTEMD_DESTINATION.c_str(),
- SYSTEMD_PATH.c_str(),
- DBUS_PROPERTIES_INTERFACE.c_str(),
- "Get");
++DBus::MessageIn ServiceManager::sendPropertyGetMsg(const std::string &interface,
++ const std::string &property)
+{
- DBus::MessageIn messageIn = m_connection.sendWithReplyAndBlock(messageOut);
++ DBus::MessageOut messageOut(SYSTEMD_DESTINATION,
++ m_unitPath,
++ DBUS_PROPERTIES_INTERFACE,
++ "Get");
+ messageOut.append(interface);
+ messageOut.append(property);
++ return m_connection.sendWithReplyAndBlock(messageOut);
++}
++
++uint32_t ServiceManager::getUIntProperty(const std::string &interface,
++ const std::string &property)
++{
++ DBus::MessageIn messageIn = sendPropertyGetMsg(interface, property);
+ return handleVariantUIntMsgReply(messageIn);
+}
+
++uint64_t ServiceManager::getUInt64Property(const std::string &interface,
++ const std::string &property)
++{
++ DBus::MessageIn messageIn = sendPropertyGetMsg(interface, property);
++ return handleVariantUInt64MsgReply(messageIn);
++}
++
+void ServiceManager::sendResetFailedToService()
+{
+ DBus::MessageOut messageOut = newMethodCall("ResetFailedUnit");
+ messageOut.append(m_serviceName);
+ m_connection.sendWithReplyAndBlock(messageOut);
+}
+
+DBusHandlerResult ServiceManager::messageHandler(DBusConnection *conn, DBusMessage *msg, void *t)
+{
+ (void) conn;
+ ServiceManager* self = reinterpret_cast<ServiceManager*>(t);
+
+ DBus::MessageIn messageIn(msg, true);
+ if (messageIn.isSignal(SYSTEMD_MANAGER_INTERFACE, MATCH_JOB_REMOVED))
+ self->signalJobRemovedHandler(messageIn);
+ else if(messageIn.isSignal(SYSTEMD_MANAGER_INTERFACE, MATCH_JOB_NEW))
+ self->signalJobNewHandler(messageIn);
+ else if(messageIn.isSignal(SYSTEMD_MANAGER_INTERFACE, MATCH_RELOADING))
+ self->signalReloadingHandler(messageIn);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+void ServiceManager::signalJobRemovedHandler(DBus::MessageIn &messageIn)
+{
+ DBus::MessageIn::Iterator iterator = messageIn.iterInit();
+
+ iterator.expectArgType(DBUS_TYPE_UINT32);
+ uint32_t id = iterator.getArgUint32();
+ iterator.expectNext();
+
+ iterator.expectArgType(DBUS_TYPE_OBJECT_PATH);
+ std::string path = iterator.getArgString();
+ iterator.expectNext();
+
+ iterator.expectArgType(DBUS_TYPE_STRING);
+ std::string unit = iterator.getArgString();
+ iterator.expectNext();
+
+ iterator.expectArgType(DBUS_TYPE_STRING);
+ std::string result = iterator.getArgString();
+
+ if(m_serviceName == unit) {
+ RUNNER_ASSERT_MSG(result == "done" || result == "canceled",
+ "RemoveJob signal delivered bad news. Job wasn't completed successfully: "
+ << "expected job results = {done, canceled}, "
+ << "received job result = " << result << ", "
+ << "for job with id = " << id << ", "
+ << "and path = " << path);
+ m_runningJobs.erase(path);
+ }
+}
+
+void ServiceManager::signalJobNewHandler(DBus::MessageIn &messageIn)
+{
+ DBus::MessageIn::Iterator iterator = messageIn.iterInit();
+
+ iterator.expectArgTypeValid();
+ iterator.expectNext();
+
+ iterator.expectArgType(DBUS_TYPE_OBJECT_PATH);
+ std::string path = iterator.getArgString();
+ iterator.expectNext();
+
+ iterator.expectArgType(DBUS_TYPE_STRING);
+ std::string unit = iterator.getArgString();
+
+ if(m_serviceName == unit)
+ m_runningJobs.insert(path);
+}
+
+void ServiceManager::signalReloadingHandler(DBus::MessageIn &messageIn)
+{
+ DBus::MessageIn::Iterator iterator = messageIn.iterInit();
+
+ iterator.expectArgType(DBUS_TYPE_BOOLEAN);
+ bool active = iterator.getArgBool();
+
+ if (active)
+ m_runningJobs.insert(MATCH_RELOADING);
+ else
+ m_runningJobs.erase(MATCH_RELOADING);
+}
+
+void ServiceManager::waitForRunningJobsFinish()
+{
+ while (!m_runningJobs.empty())
+ m_connection.readWriteDispatch();
+}
+
+void ServiceManager::startService()
+{
+ sendToService("StartUnit");
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+void ServiceManager::stopService()
+{
+ sendToService("StopUnit");
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+void ServiceManager::restartService()
+{
+ sendToService("RestartUnit");
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+pid_t ServiceManager::getServicePid()
+{
+ return static_cast<pid_t>(getUIntProperty(SYSTEMD_SERVICE_INTERFACE, "MainPID"));
+}
+
++timeval ServiceManager::getServiceStartTimestamp() {
++ uint64_t timestamp = getUInt64Property(SYSTEMD_SERVICE_INTERFACE,
++ "ExecMainStartTimestamp");
++ return {static_cast<long>(timestamp / 1000000), static_cast<long>(timestamp % 1000000)};
++}
++
+void ServiceManager::maskService()
+{
+ sendMaskToService();
+ reloadDbusManager();
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+void ServiceManager::unmaskService()
+{
+ sendUnmaskToService();
+ reloadDbusManager();
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013-2014 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 service_manager.h
+ * @author Zbigniew Jasinski <z.jasinski@samsung.com>
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @author Marcin Niesluchowski <m.niesluchow@samsungcom>
+ * @version 1.1
+ * @brief Declaration of service control class using dbus interface to communicate with systemd
+ */
+
+#ifndef COMMON_SERVICE_MANAGER_H
+#define COMMON_SERVICE_MANAGER_H
+
+#include <dbus/dbus.h>
+
+#include <dbus_connection.h>
+#include <dbus_message_in.h>
+#include <dbus_message_out.h>
+
+#include <cstdint>
+#include <set>
+#include <string>
+
+class ServiceManager {
+public:
+ ServiceManager() = delete;
+ ServiceManager(const std::string &serviceName);
+ ~ServiceManager() = default;
+
+ void startService();
+ void stopService();
+ void restartService();
+ pid_t getServicePid();
++ timeval getServiceStartTimestamp();
+ void maskService();
+ void unmaskService();
+
+private:
+ void addBusMatch(const std::string &member);
+ void subscribeSignals();
+ void reloadDbusManager();
+ void getUnitPath();
+ DBus::MessageOut newMethodCall(const std::string &method);
+ std::string handleObjectPathMsgReply(DBus::MessageIn &messageIn);
+ uint32_t handleVariantUIntMsgReply(DBus::MessageIn &messageIn);
++ uint64_t handleVariantUInt64MsgReply(DBus::MessageIn &messageIn);
+
+ void sendToService(const std::string &method);
+ void sendMaskToService();
+ void sendUnmaskToService();
++ DBus::MessageIn sendPropertyGetMsg(const std::string &interface, const std::string &property);
+ uint32_t getUIntProperty(const std::string &interface, const std::string &property);
++ uint64_t getUInt64Property(const std::string &interface, const std::string &property);
+ void sendResetFailedToService();
+
+ static DBusHandlerResult messageHandler(DBusConnection *conn, DBusMessage *msg, void *t);
+ void signalJobRemovedHandler(DBus::MessageIn &messageIn);
+ void signalJobNewHandler(DBus::MessageIn &messageIn);
+ void signalReloadingHandler(DBus::MessageIn &messageIn);
+ void waitForRunningJobsFinish();
+
+ DBus::Connection m_connection;
+
+ const std::string m_serviceName;
+ std::string m_unitPath;
+
+ std::set<std::string> m_runningJobs;
+};
+
+#endif // COMMON_SERVICE_MANAGER_H
--- /dev/null
-CynaraMask::CynaraMask() : m_dbusAccess(CynaraTestConsts::SERVICE.c_str())
+ /*
+ * 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 cynara_test_cynara_mask.cpp
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version 1.0
+ * @brief Implementation of scoped cynara service masker
+ */
+
+ #include <exception>
+
+ #include <cynara_test_commons.h>
+ #include <dpl/test/test_runner.h>
+
+ #include <cynara_test_cynara_mask.h>
+
- m_dbusAccess.maskService();
- m_dbusAccess.stopService();
++CynaraMask::CynaraMask() : m_serviceManager(CynaraTestConsts::SERVICE)
+ {
- m_dbusAccess.unmaskService();
- m_dbusAccess.startService();
++ m_serviceManager.maskService();
++ m_serviceManager.stopService();
+ }
+
+ CynaraMask::~CynaraMask() noexcept(false)
+ {
+ bool oops = std::uncaught_exception();
+ try {
++ m_serviceManager.unmaskService();
++ m_serviceManager.startService();
+ } catch (...) {
+ if (!oops)
+ throw;
+ RUNNER_ERROR_MSG("Error: more exceptions thrown while releasing CynaraMask.");
+ }
+ }
--- /dev/null
-#include <dbus_access.h>
+ /*
+ * 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 cynara_test_cynara_mask.h
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version 1.0
+ * @brief Definition of scoped cynara service masker
+ */
+
+ #ifndef CYNARA_TEST_CYNARA_MASK_H_
+ #define CYNARA_TEST_CYNARA_MASK_H_
+
- DBusAccess m_dbusAccess;
++#include <service_manager.h>
+
+ class CynaraMask
+ {
+ public:
+ CynaraMask();
+ ~CynaraMask() noexcept(false);
+
+ private:
++ ServiceManager m_serviceManager;
+ };
+
+ #endif // CYNARA_TEST_CYNARA_MASK_H_
* limitations under the License.
*/
- #include <cynara_test_env.h>
+ #include <cynara_test_commons.h>
+ #include <cynara_test_cynara_mask.h>
+ #include <cynara_test_file_operations.h>
-#include <dbus_access.h>
#include <tests_common.h>
- #include <service_manager.h>
- #include <memory.h>
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/sendfile.h>
- #include <unistd.h>
- #include <errno.h>
- #include <ftw.h>
- #include <fcntl.h>
- #include <pwd.h>
- #include <dirent.h>
-
- namespace
- {
-
- typedef CStringPtr PwBufPtr;
-
- DEFINE_SMARTPTR(closedir, DIR, DirPtr);
-
- const std::string cynaraDbDir = CYNARA_DB_DIR;
- const std::string tmpDir = "/tmp/";
- const std::string cynaraUser = "cynara";
- const std::string cynaraLabel = "System";
-
- int removeContents(const char *fpath, const struct stat * /*sb*/,
- int tflag, struct FTW * /*ftwbuf*/)
- {
- if (tflag == FTW_F)
- RUNNER_ASSERT_ERRNO_MSG(!unlink(fpath), "Unable to unlink " << fpath << " file");
- else
- RUNNER_ASSERT_MSG(tflag == FTW_DP, "Visited file should not exist. Path: " << fpath);
- return 0;
- }
-
- void copyFile(const std::string &src, const std::string &dst)
- {
- int inFd = TEMP_FAILURE_RETRY(open(src.c_str(), O_RDONLY));
- RUNNER_ASSERT_ERRNO_MSG(inFd > 0, "Opening " << src << " file failed");
- FdUniquePtr inFdPtr(&inFd);
-
- int outFd = TEMP_FAILURE_RETRY(creat(dst.c_str(), 0700));
- RUNNER_ASSERT_ERRNO_MSG(outFd > 0, "Creating " << dst << " file failed");
- FdUniquePtr outFdPtr(&outFd);
-
- long int len = sysconf(_SC_GETPW_R_SIZE_MAX);
- RUNNER_ASSERT_MSG(len != -1, "No suggested buflen");
- size_t buflen = len;
- char *buf = static_cast<char*>(malloc(buflen));
-
- PwBufPtr pwBufPtr(buf);
-
- struct passwd pwbuf, *pwbufp = nullptr;
- int ret = TEMP_FAILURE_RETRY(getpwnam_r(cynaraUser.c_str(),
- &pwbuf, buf, buflen, &pwbufp));
- RUNNER_ASSERT_ERRNO_MSG(ret == 0, "getpwnam_r failed on " << cynaraUser << " user");
- RUNNER_ASSERT_MSG(pwbufp, "User " << cynaraUser << " does not exist");
-
- ret = fchown(outFd, pwbufp->pw_uid, pwbufp->pw_gid);
- RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fchown failed");
-
- ret = smack_fsetlabel(outFd, cynaraLabel.c_str(), SMACK_LABEL_ACCESS);
- RUNNER_ASSERT_MSG(ret == 0, "Setting smack label failed");
-
- struct stat statSrc;
- ret = fstat(inFd, &statSrc);
- RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fstat failed");
- ret = sendfile(outFd, inFd, 0, statSrc.st_size);
- RUNNER_ASSERT_ERRNO_MSG(ret != -1, "sendfile failed");
- }
-
- void copyDir(const std::string &source, const std::string &destination)
- {
- DIR *dirPtr = nullptr;
- struct dirent *direntPtr;
-
- RUNNER_ASSERT_ERRNO_MSG(dirPtr = opendir(source.c_str()),
- "opening " << source << " dir failed");
- DirPtr dirScopedPtr(dirPtr);
-
- while((direntPtr = readdir(dirPtr)) != nullptr) {
- if (!strcmp(direntPtr->d_name, ".")
- || !strcmp(direntPtr->d_name, ".."))
- continue;
- std::string tempDest = destination + "/" + direntPtr->d_name;
- std::string tempSrc = source + "/" + direntPtr->d_name;
- copyFile(tempSrc, tempDest);
- }
- }
-
- void clear(const std::string &dir)
- {
- int ret = nftw(dir.c_str(), removeContents, 2, FTW_DEPTH | FTW_PHYS);
- if (ret == -1)
- RUNNER_ASSERT_ERRNO_MSG(errno == ENOENT, "nftw failed");
- }
-
- void removeDirIfExists(const std::string &dir)
- {
- RUNNER_ASSERT_ERRNO_MSG(!rmdir(dir.c_str()) || errno == ENOENT,
- "Removing " << dir << " dir failed");
- }
-
- bool cynaraDbExists()
- {
- struct stat st;
- int ret = stat(cynaraDbDir.c_str(), &st);
- if (ret == -1 && errno == ENOENT) {
- return false;
- } else if (ret == -1) {
- RUNNER_ASSERT_ERRNO_MSG(false, "Cannot stat " << cynaraDbDir
- << " not due to its nonexistence");
- }
- RUNNER_ASSERT_MSG(st.st_mode & S_IFDIR, cynaraDbDir << " is not a directory");
- return true;
- }
+ #include <cynara_test_env.h>
- }
+ using namespace FileOperations;
CynaraTestEnv::CynaraTestEnv(const char *dirName)
: m_dbPresent(false)
#include <cynara_test_commons.h>
#include <cynara_test_client_async_client.h>
-#include <dbus_access.h>
++#include <service_manager.h>
#include <dpl/test/test_runner.h>
#include <cynara-client-async.h>
client.assertStatus(READWRITE);
}
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
+ void tca04_request_and_process_func()
+ {
+ std::string testNo("04");
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+
+ Client client;
+
+ client.createRequest({testNo}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ //send request
+ client.process();
+ client.assertStatus(READ);
+
+ //get answer
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca05_request_and_cancel1_func()
+ {
+ std::string testNo("05");
+ int subtest = 1;
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_CANCEL};
+
+ Client client;
+
+ client.createRequest({testNo, subtest}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ client.cancel(id);
+ client.assertStatus(READWRITE);
+
+ //send request and cancel
+ client.process();
+ client.assertStatus(READ);
+
+ //get answer
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca05_request_and_cancel2_func()
+ {
+ std::string testNo("05");
+ int subtest = 2;
+ cynara_check_id id1, id2;
+ Client client;
+
+ RequestEntity callbackData1 = {[&]()->void {client.cancel(id2);},
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+ RequestEntity callbackData2 = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_CANCEL};
+
+ client.createRequest({testNo, subtest}, id1, callbackData1);
+ client.createRequest({testNo, subtest}, id2, callbackData2);
+ client.assertStatus(READWRITE);
+
+ //send requests
+ client.process();
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca05_request_and_cancel3_func()
+ {
+ std::string testNo("05");
+ int subtest = 3;
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+
+ Client client;
+
+ client.createRequest({testNo, subtest}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ //send request
+ client.process();
+ client.assertStatus(READ);
+
+ //get answer
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.assertStatus(READ);
+
+ client.cancel(id, CYNARA_API_INVALID_PARAM);
+ }
+
+ void tca06_cancel_fail_func()
+ {
+ cynara_check_id id = 0xDEAD;
+
+ Client client;
+
+ client.cancel(id, CYNARA_API_INVALID_PARAM);
+ }
+
+ void tca07_request_with_data_insertion_func()
+ {
+ std::string testNo("07");
+ Admin admin;
+ const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+ const int resultAllow = CYNARA_ADMIN_ALLOW;
+ CheckData data[2] = {{testNo, 1}, {testNo, 2}};
+ RequestEntity callbackAllow = {RequestFunction(),
+ CYNARA_API_ACCESS_ALLOWED,
+ CYNARA_CALL_CAUSE_ANSWER};
+ RequestEntity callbackDeny = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+ cynara_check_id id;
+ Client client;
+
+ client.checkCache(data[0], CYNARA_API_CACHE_MISS);
+ client.checkCache(data[1], CYNARA_API_CACHE_MISS);
+
+ client.createRequest(data[0], id, callbackDeny);
+ client.assertStatus(READWRITE);
+ client.process();
+ client.assertStatus(READ);
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.assertStatus(READ);
+
+ client.checkCache(data[0], CYNARA_API_ACCESS_DENIED);
+ client.checkCache(data[1], CYNARA_API_CACHE_MISS);
+
+ {
+ CynaraPoliciesContainer cp;
+ cp.add(bucket, data[0].toAdminPolicy(), resultAllow);
+ admin.setPolicies(cp);
+ }
+
+ client.checkCache(data[0], CYNARA_API_CACHE_MISS);
+ client.checkCache(data[1], CYNARA_API_CACHE_MISS);
+
+ client.createRequest(data[0], id, callbackAllow);
+ client.assertStatus(READWRITE);
+ client.process();
+ client.assertStatus(READ);
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.assertStatus(READ);
+
+ client.checkCache(data[0], CYNARA_API_ACCESS_ALLOWED);
+ client.checkCache(data[1], CYNARA_API_CACHE_MISS);
+ }
+
+ void tca08_disconnect1_func()
+ {
+ std::string testNo("08");
+ int subtest = 1;
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+ Client client;
+
+ client.createRequest({testNo, subtest}, id, callbackData);
+ client.assertStatus(READWRITE);
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++ serviceManager.restartService();
+
+ client.process();
+ client.assertStatus(READ);
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca08_disconnect2_func()
+ {
+ std::string testNo("08");
+ int subtest = 2;
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+ Client client;
+
+ client.createRequest({testNo, subtest}, id, callbackData);
+ client.assertStatus(READWRITE);
+
- dbusAccess.restartService();
++ serviceManager.restartService();
+
+ client.process();
+ client.assertStatus(READ);
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
- dbusAccess.restartService();
++ serviceManager.restartService();
+
+ client.process();
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca08_disconnect3_func()
+ {
+ std::string testNo("08");
+ int subtest = 2;
+ cynara_check_id id;
+ RequestEntity callbackData = {[&](){
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
++ serviceManager.restartService();
+ },
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+ Client client;
+
+ client.createRequest({testNo, subtest}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ client.process();
+ client.assertStatus(READ);
+
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca09_disconnect_and_cancel1_func()
+ {
+ std::string testNo("09");
+ int subtest = 1;
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_CANCEL};
+
+ Client client;
+
+ client.createRequest({testNo, subtest}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ //send request
+ client.process();
+ client.assertStatus(READ);
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++ serviceManager.restartService();
+
+ client.cancel(id);
+ client.assertStatus(READWRITE);
+
+ //send cancel
+ client.process();
+ client.assertStatus(READ);
+
+ //get answer
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.assertStatus(READ);
+ }
+
+ void tca09_disconnect_and_cancel2_func()
+ {
+ std::string testNo("09");
+ int subtest = 2;
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_CANCEL};
+
+ Client client;
+
+ client.createRequest({testNo, subtest}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ //send request
+ client.process();
+ client.assertStatus(READ);
+
+ client.cancel(id);
+ client.assertStatus(READWRITE);
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
- dbusAccess.restartService();
++ serviceManager.restartService();
+
+ //handle reconnect
+ client.process();
+ client.assertStatus(READ);
+
+ //get answer
+ client.process(CYNARA_API_SUCCESS, Client::EXPECT_TIMEOUT);
+ client.assertStatus(READ);
+ }
+
+ void tca10_double_request_func()
+ {
+ std::string testNo("10");
+ cynara_check_id id, id2;
+ Client client;
+
+ RequestEntity callbackData2 = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+
+ RequestEntity callbackData = {[&](){client.createRequest({testNo}, id2, callbackData2);},
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+
+
+ client.createRequest({testNo}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ client.process();
+ client.process();
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca11_double_request_with_restart_func()
+ {
+ std::string testNo("11");
+ cynara_check_id id, id2;
+ Client client;
+
+ RequestEntity callbackData2 = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+
+ RequestEntity callbackData = {[&](){
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
- pid_t before = dbusAccess.getServicePid();
- timeval beforeTimestamp = dbusAccess.getServiceStartTimestamp();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
++ serviceManager.restartService();
+ client.createRequest({testNo}, id2, callbackData2);
+ },
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_ANSWER};
+
+
+ client.createRequest({testNo}, id, callbackData);
+ client.assertStatus(READWRITE);
+
+ client.process();
+ client.process();
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ client.process(CYNARA_API_SUCCESS, Client::IGNORE_TIMEOUT);
+ }
+
+ void tca12_multiple_connections_without_requests_func()
+ {
+ std::string testNo("12");
+
+ cynara_check_id id;
+ RequestEntity callbackData = {RequestFunction(),
+ CYNARA_API_ACCESS_DENIED,
+ CYNARA_CALL_CAUSE_FINISH};
+
- pid_t after = dbusAccess.getServicePid();
- timeval afterTimestamp = dbusAccess.getServiceStartTimestamp();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
++ pid_t before = serviceManager.getServicePid();
++ timeval beforeTimestamp = serviceManager.getServiceStartTimestamp();
+
+ for (int i = 0; i < 10; ++i)
+ {
+ Client client;
+ client.createRequest({testNo}, id, callbackData);
+ client.assertStatus(READWRITE);
+ }
+
+ //wait until cynara possibly restarts
+ sleep(3);
+
++ pid_t after = serviceManager.getServicePid();
++ timeval afterTimestamp = serviceManager.getServiceStartTimestamp();
+ RUNNER_ASSERT_MSG(after != 0,
+ "cynara service not running. After = " << after << ".");
+ RUNNER_ASSERT_MSG(before == after
+ && beforeTimestamp.tv_sec == afterTimestamp.tv_sec
+ && beforeTimestamp.tv_usec == afterTimestamp.tv_usec,
+ "cynara service was restarted during the test. Before pid / timestamp = "
+ << before << " / " << beforeTimestamp.tv_sec << "."
+ << beforeTimestamp.tv_usec << " and after pid / timestamp = "
+ << after << " / " << afterTimestamp.tv_sec << "."
+ << afterTimestamp.tv_usec);
+ }
+
RUNNER_TEST_GROUP_INIT(cynara_async_tests)
RUN_CYNARA_TEST(tca01_initialize)
--- /dev/null
-#include <dbus_access.h>
+ /*
+ * Copyright (c) 2012 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_db.cpp
+ * @author Pawel Wieczorek <p.wieczorek2@samsung.com>
+ * @version 0.1
+ * @brief Tests for Cynara's mechanism assuring integrity of database
+ */
+
+ #include <cynara_test_admin.h>
+ #include <cynara_test_client.h>
+ #include <cynara_test_commons.h>
+ #include <cynara_test_env.h>
+ #include <dpl/test/test_runner.h>
+ #include <sys/smack.h>
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++#include <service_manager.h>
+ #include <dirent.h>
+ #include <fcntl.h>
+ #include <fstream>
+ #include <glob.h>
+ #include <iterator>
+ #include <memory.h>
+ #include <set>
+ #include <string>
+ #include <unistd.h>
+ #include <vector>
+
+ using namespace CynaraTestAdmin;
+ using namespace CynaraTestClient;
+
+ namespace
+ {
+
+ const std::string defDb("default");
+ const std::string defDbAllow("defaultAllowed");
+ const std::string nonEmptyDb("nonEmptyDatabase");
+ const std::string cynaraTestPatternsPath("/etc/security-tests/db_patterns/");
+ const std::string directoryWildcard("/*");
+
+ void createDbFile(const std::string &filename)
+ {
+ int fileFd = TEMP_FAILURE_RETRY(creat(filename.c_str(), 0000));
+ RUNNER_ASSERT_ERRNO_MSG(fileFd > 0, "Creating " << filename << " file failed");
+ FdUniquePtr fileFdPtr(&fileFd);
+
+ int ret = smack_fsetlabel(fileFd, CynaraTestConsts::LABEL.c_str(), SMACK_LABEL_ACCESS);
+ RUNNER_ASSERT_MSG(ret == 0, "Setting smack label failed");
+ }
+
+ void deleteDbFile(const std::string &filename)
+ {
+ RUNNER_ASSERT_ERRNO_MSG(!unlink(filename.c_str()), "Unable to unlink " << filename << " file");
+ }
+
+ bool unordered_files_match(const std::string &patternFilePath, const std::string &resultFilePath) {
+ std::ifstream patternFile(patternFilePath, std::ifstream::in | std::ifstream::binary);
+ std::ifstream resultFile(resultFilePath, std::ifstream::in | std::ifstream::binary);
+
+ RUNNER_ASSERT_MSG(patternFile.is_open(), "Failed to open " << patternFile << ".");
+ RUNNER_ASSERT_MSG(resultFile.is_open(), "Failed to open " << resultFile << ".");
+
+ auto patternRecords = std::multiset<std::string>(std::istream_iterator<std::string>(patternFile),
+ std::istream_iterator<std::string>());
+
+ auto resultRecords = std::multiset<std::string>(std::istream_iterator<std::string>(resultFile),
+ std::istream_iterator<std::string>());
+
+ return patternRecords == resultRecords;
+ }
+
+ size_t glob_count(const std::string &source, const std::string &wildcard) {
+ //for counting files in directory
+ glob_t globbuf;
+ std::string pattern = source + wildcard;
+
+ //for freeing allocated memory
+ GlobPtr globbufPtr(&globbuf);
+
+ //actually count files 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 globbuf.gl_pathc;
+ }
+
+ size_t db_files_count(const std::string &source) {
+ size_t dbFilesCount = 0;
+
+ //database directory must not be empty
+ RUNNER_ASSERT_MSG(0 != (dbFilesCount = glob_count(source, directoryWildcard)),
+ "Unexpected condition: " << source << " was empty.");
+
+ return dbFilesCount;
+ }
+
+ void compareDbs(const std::string &source)
+ {
+ //for accessing files in directory
+ std::string patternDir = cynaraTestPatternsPath + source;
+ DIR *patternDirPtr = nullptr;
+ struct dirent *direntPtr;
+
+ size_t patternFileCount = db_files_count(patternDir);
+ size_t resultFileCount = db_files_count(CynaraTestConsts::DB_DIR);
+
+ //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");
+
+ //compare files in database directory with pattern directory
+ RUNNER_ASSERT_ERRNO_MSG(patternDirPtr = opendir(patternDir.c_str()),
+ "Opening " << patternDir << " directory failed");
+ DirPtr patternDirScopedPtr(patternDirPtr);
+
+ while ((direntPtr = readdir(patternDirPtr)) != nullptr) {
+ 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;
+
+ //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");
+ }
+ }
+
+ } // anonymous namespace
+
+ /**
+ * @brief Lockdown initialization failure caused by fake guard existence
+ * @test Expected result: refuse to write data to storage as long as guard file creation fails
+ * 1. Create fake guard file with 0000 attributes in policy database
+ * 2. Try to make a change (ALLOW) in default bucket (data dump should fail)
+ * 3. Delete fake guard file from policy database
+ * 4. Retry to make a change (ALLOW) in default bucket (data dump should proceed)
+ * 5. Check if database is saved correctly
+ */
+ void tcdb01_lockdown_init_failure_func()
+ {
+ Admin admin;
+ Client cynara;
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+
+ const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+ const char *extra = nullptr;
+
+ const auto fakeBackupGuard = CynaraTestConsts::DB_DIR + "/guard";
+
+ createDbFile(fakeBackupGuard);
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra, CYNARA_API_OPERATION_FAILED);
+
+ deleteDbFile(fakeBackupGuard);
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra);
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++ serviceManager.restartService();
+ compareDbs(defDbAllow);
+ }
+
+ /**
+ * @brief Failure during writing to backup (before lockdown)
+ * @test Expected result: read from primary policy database
+ * 1. Write ALLOW to default bucket
+ * 2. Check if data is saved correctly
+ * 3. Create fake backup file with 0000 attributes in policy database
+ * 4. Try to make a change (DENY) in default bucket (data dump should fail)
+ * 5. Reload Cynara - policies loaded from default bucket should still be ALLOW
+ */
+ void tcdb02_write_to_backup_failure_func()
+ {
+ Admin admin;
+ Client cynara;
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+
+ const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+ const char *extra = nullptr;
+
+ const auto fakeBucketDumpFile = CynaraTestConsts::DB_DIR + "/_~";
+
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra);
+ compareDbs(defDbAllow);
+
+ createDbFile(fakeBucketDumpFile);
+ admin.setBucket(bucket, CYNARA_ADMIN_DENY, extra, CYNARA_API_OPERATION_FAILED);
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++ serviceManager.restartService();
+ compareDbs(defDbAllow);
+ }
+
+ /**
+ * @brief Check whether both invalid and valid backup databases are removed
+ * @test Expected result: no unnecessary backup files in policy database directory
+ * 1. Fail writing to backup database
+ * 2. Reload Cynara - policies should be loaded from primary (valid) database
+ * 3. Check if all backup files were removed
+ * 4. Successfully write changes to database
+ * 5. Reload Cynara - policies should be loaded from primary (revalidated) database
+ * 6. Check if all backup files were removed
+ */
+ void tcdb03_invalid_and_valid_backup_removal_func()
+ {
+ Admin admin;
+ Client cynara;
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+
+ const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+ const char *extra = nullptr;
+
+ const auto defaultBucketDumpFile = CynaraTestConsts::DB_DIR + "/_~";
+
+ createDbFile(defaultBucketDumpFile);
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra, CYNARA_API_OPERATION_FAILED);
+
- dbusAccess.restartService();
++ serviceManager.restartService();
+ compareDbs(defDb);
+
+ admin.setBucket(bucket, CYNARA_ADMIN_ALLOW, extra);
+
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++ serviceManager.restartService();
+ compareDbs(defDbAllow);
+ }
+
+ /**
+ * @brief Comparison between database modified by Cynara with expected one
+ * @test Expected result: no differences between those files
+ * 1. Write sample policy to database (and let it save to storage)
+ * 2. Compare freshly saved files with samples from test patterns directory
+ */
+ void tcdb04_dumped_file_binary_comparison_func()
+ {
+ Admin admin;
+ Client cynara;
- DBusAccess dbusAccess(CynaraTestConsts::SERVICE.c_str());
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+
+ const char *bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
+ const char *client = "client";
+ const char *user = "user";
+ const char *privilege = "privilege";
+ const char *extra = nullptr;
+
+ {
+ CynaraPoliciesContainer cp;
+ cp.add(bucket, client, user, privilege, CYNARA_ADMIN_DENY, extra);
+ admin.setPolicies(cp, CYNARA_API_SUCCESS);
+ }
+
+ compareDbs(nonEmptyDb);
+ }
+
+ /**
+ * @brief Invalid database files removal
+ * @test Expected result: no unnecessary files in policy database directory
+ * 1. Fill Cynara's policy database directory with garbage:
+ * - Sample backup file which should be removed earlier
+ * - Sample bucket file which is not mentioned in index (shouldn't exist at all)
+ * - Sample files which don't belong to database
+ * 2. Reload Cynara
+ * 3. Check if any of mentioned above files still remained
+ */
+ void tcdb05_non_indexed_files_removal_func()
+ {
- dbusAccess.restartService();
++ ServiceManager serviceManager(CynaraTestConsts::SERVICE);
+
+ std::vector<std::string> filenames = { "_broken-backup~", "_non-indexed-bucket",
+ "some-file-that-doesnt-belong-here" };
+
+ for (const auto &filename : filenames) {
+ auto garbageFilename = CynaraTestConsts::DB_DIR + "/" + filename;
+ createDbFile(garbageFilename);
+ }
+
++ serviceManager.restartService();
+ compareDbs(defDb);
+ }
+
+ RUNNER_TEST_GROUP_INIT(cynara_db_tests)
+
+ RUN_CYNARA_TEST(tcdb01_lockdown_init_failure)
+ RUN_CYNARA_TEST(tcdb02_write_to_backup_failure)
+ RUN_CYNARA_TEST(tcdb03_invalid_and_valid_backup_removal)
+ RUN_CYNARA_TEST(tcdb04_dumped_file_binary_comparison)
+ RUN_CYNARA_TEST(tcdb05_non_indexed_files_removal)
void RunTests();
+ std::string getConcatedFailReason(const std::string &reason);
+
void CollectResult(const std::string& id,
- const std::string& description,
const TestResultsCollectorBase::FailStatus status
= TestResultsCollectorBase::FailStatus::NONE,
const std::string& reason = std::string(),
* body. Failing assertion indicates failing test.
*/
- #define RUNNER_ASSERT_MSG(test, message) \
- do \
- { \
- DPL::Test::TestRunnerSingleton::Instance().MarkAssertion(); \
- \
- if (!(test)) \
- { \
- std::ostringstream assertMsg; \
- assertMsg << message << DPL::gdbbacktrace(); \
- throw DPL::Test::TestRunner::TestFailed(#test, \
- __FILE__, \
- __LINE__, \
- assertMsg.str()); \
- } \
+ #define RUNNER_ASSERT_MSG(test, message) \
+ do \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().MarkAssertion(); \
+ \
+ if (!(test)) \
+ { \
+ std::ostringstream assertMsg; \
- assertMsg << message << gdbbacktrace(); \
++ assertMsg << message << DPL::gdbbacktrace(); \
+ DPL::Test::TestRunner::TestFailed e(#test, \
+ __FILE__, \
+ __LINE__, \
+ assertMsg.str()); \
+ if (!std::uncaught_exception()) \
+ throw e; \
+ DPL::Test::TestRunnerSingleton::Instance().addFailReason(e.GetMessage()); \
+ } \
} while (0)
- #define RUNNER_ASSERT_ERRNO_MSG(test, message) \
- do \
- { \
- DPL::Test::TestRunnerSingleton::Instance().MarkAssertion(); \
- \
- if (!(test)) \
- { \
- const char *err = strerror(errno); \
- std::ostringstream assertMsg; \
- assertMsg << message; \
- if (!assertMsg.str().empty()) \
- assertMsg << ". "; \
- assertMsg << err << DPL::gdbbacktrace(); \
- throw DPL::Test::TestRunner::TestFailed(#test, \
- __FILE__, \
- __LINE__, \
- assertMsg.str()); \
- } \
+ #define RUNNER_ASSERT_ERRNO_MSG(test, message) \
+ do \
+ { \
+ DPL::Test::TestRunnerSingleton::Instance().MarkAssertion(); \
+ \
+ if (!(test)) \
+ { \
+ const char *err = strerror(errno); \
+ std::ostringstream assertMsg; \
+ assertMsg << message; \
+ if (!assertMsg.str().empty()) \
+ assertMsg << ". "; \
- assertMsg << err << gdbbacktrace(); \
++ assertMsg << err << DPL::gdbbacktrace(); \
+ DPL::Test::TestRunner::TestFailed e(#test, \
+ __FILE__, \
+ __LINE__, \
+ assertMsg.str()); \
+ if (!std::uncaught_exception()) \
+ throw e; \
+ DPL::Test::TestRunnerSingleton::Instance().addFailReason(e.GetMessage()); \
+ } \
} while (0)
#define RUNNER_ASSERT_ERRNO(test) \
} catch (const TestFailed &e) {
// Simple test failure
CollectResult(testCase.name,
- "",
TestResultsCollectorBase::FailStatus::FAILED,
- e.GetMessage());
+ getConcatedFailReason(e.GetMessage()));
setCurrentTestCase(nullptr);
return FAILED;