Client library with C interface 07/25407/25
authorMateusz Malicki <m.malicki2@samsung.com>
Mon, 4 Aug 2014 13:33:25 +0000 (15:33 +0200)
committerPiotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
Mon, 18 Aug 2014 12:15:48 +0000 (05:15 -0700)
[Feature]      security-containers's client with c interface.
[Cause]        N/A
[Solution]     N/A
[Verification] Build, install, run test suite Client

Change-Id: Ic968e876806ce44751c95a9161ba8f497427aee8

20 files changed:
client/CMakeLists.txt
client/exception.hpp [deleted file]
client/main.cpp [deleted file]
client/security-containers-client-impl.cpp [new file with mode: 0644]
client/security-containers-client-impl.hpp [new file with mode: 0644]
client/security-containers-client.cpp [new file with mode: 0644]
client/security-containers-client.h
tests/unit_tests/CMakeLists.txt
tests/unit_tests/client/configs/CMakeLists.txt [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/containers/console1-dbus.conf [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/containers/console2-dbus.conf [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/containers/console3-dbus.conf [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/libvirt-config/console1-dbus.xml.in [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/libvirt-config/console2-dbus.xml.in [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/libvirt-config/console3-dbus.xml.in [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/libvirt-config/network1.xml [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/libvirt-config/network2.xml [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/libvirt-config/network3.xml [new file with mode: 0644]
tests/unit_tests/client/configs/ut-client/test-dbus-daemon.conf [new file with mode: 0644]
tests/unit_tests/client/ut-client.cpp [new file with mode: 0644]

index 8a34575..48cefea 100644 (file)
 #
 #
 # @file   CMakeLists.txt
-# @author Jan Olszak (j.olszak@samsung.com)
+# @author Mateusz Malicki (m.malicki2@samsung.com)
 #
 
 MESSAGE(STATUS "Generating makefile for the Client...")
-FILE(GLOB         project_SRCS *.cpp *.hpp)
-FILE(GLOB_RECURSE common_SRCS ${COMMON_FOLDER}/*.cpp ${COMMON_FOLDER}/*.hpp)
+FILE(GLOB project_SRCS *.cpp *.hpp *.h)
+FILE(GLOB common_SRCS ${COMMON_FOLDER}/utils/callback-guard.hpp
+                      ${COMMON_FOLDER}/utils/callback-guard.cpp
+                      ${COMMON_FOLDER}/utils/glib-loop.cpp
+                      ${COMMON_FOLDER}/utils/glib-loop.hpp)
 
 SET(_LIB_VERSION_ "0.0.1")
 SET(_LIB_SOVERSION_ "0")
 SET(PC_FILE "${PROJECT_NAME}.pc")
 
+## Set the default ELF image symbol visibility to hidden. Using this feature
+## can very substantially improve linking and load times of shared object
+## libraries, produce more optimized code, provide near-perfect API export
+## and prevent symbol clashes
+ADD_DEFINITIONS(-fvisibility=hidden)
+
 ## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${project_SRCS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${project_SRCS} ${common_SRCS})
 SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY SOVERSION ${_LIB_SOVERSION_})
 SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY   VERSION ${_LIB_VERSION_})
 
 
 ## Link libraries ##############################################################
+PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libSimpleDbus libLogger)
+INCLUDE_DIRECTORIES(SYSTEM ${LIB_DEPS_INCLUDE_DIRS})
 INCLUDE_DIRECTORIES(${COMMON_FOLDER})
-
+INCLUDE_DIRECTORIES(${SERVER_FOLDER})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_DEPS_LIBRARIES})
 
 ## Generate the pc file ########################################################
 CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_BINARY_DIR}/${PC_FILE} @ONLY)
diff --git a/client/exception.hpp b/client/exception.hpp
deleted file mode 100644 (file)
index b4420e8..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Contact: Lukasz Pawelczyk <l.pawelczyk@partner.samsung.com>
- *
- *  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
- * @author  Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com)
- * @brief   Exceptions for the client
- */
-
-
-#ifndef CLIENT_EXCEPTION_HPP
-#define CLIENT_EXCEPTION_HPP
-
-#include "base-exception.hpp"
-
-
-namespace security_containers {
-
-
-/**
- * @brief Base class for exceptions in Security Containers Client
- */
-struct ClientException: public SecurityContainersException {
-
-    ClientException(const std::string& error = "") : SecurityContainersException(error) {}
-};
-
-
-}
-
-
-#endif // CLIENT_EXCEPTION_HPP
diff --git a/client/main.cpp b/client/main.cpp
deleted file mode 100644 (file)
index 1c02567..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Contact: Jan Olszak <j.olszak@samsung.com>
- *
- *  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
- * @author  Jan Olszak (j.olszak@samsung.com)
- * @brief   Main file for the Security Containers Client
- */
-
-#include "config.hpp"
-
-#include "exception.hpp"
diff --git a/client/security-containers-client-impl.cpp b/client/security-containers-client-impl.cpp
new file mode 100644 (file)
index 0000000..87c30f8
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Mateusz Malicki <m.malicki2@samsung.com>
+ *
+ *  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
+ * @author  Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief   This file contains security-containers-server's client implementation
+ */
+
+#include <config.hpp>
+#include "security-containers-client-impl.hpp"
+#include <dbus/connection.hpp>
+#include <dbus/exception.hpp>
+#include <utils/glib-loop.hpp>
+#include <host-dbus-definitions.hpp>
+
+#include <memory>
+#include <cstring>
+#include <cassert>
+
+using namespace std;
+using namespace dbus;
+using namespace security_containers;
+using namespace security_containers::utils;
+
+namespace {
+
+const string SCCLIENT_SUCCESS_MSG;
+const string SCCLIENT_EXCEPTION_MSG = "unspecified exception";
+
+const DbusInterfaceInfo hostDbusInterfaceInfo(api::host::BUS_NAME,
+                                              api::host::OBJECT_PATH,
+                                              api::host::INTERFACE);
+
+unique_ptr<ScopedGlibLoop> loop;
+
+void toDict(GVariant* in, ScArrayString* keys, ScArrayString* values)
+{
+    assert(in);
+    assert(keys);
+    assert(values);
+
+    typedef char* key_type;
+    typedef char* value_type;
+
+    GVariantIter iter;
+    value_type value;
+    key_type key;
+    gsize size = g_variant_n_children(in);
+    key_type* outk = (key_type*)calloc(size + 1, sizeof(key_type));
+    value_type* outv = (value_type*)calloc(size + 1, sizeof(value_type));
+
+    g_variant_iter_init(&iter, in);
+    for (int i = 0; g_variant_iter_loop(&iter, "{ss}", &key, &value); i++) {
+        outk[i] = strdup(key);
+        outv[i] = strdup(value);
+    }
+    *keys = outk;
+    *values = outv;
+}
+
+ScStatus toStatus(const std::exception& ex)
+{
+    if (typeid(DbusCustomException) == typeid(ex)) {
+        return SCCLIENT_DBUS_CUSTOM_EXCEPTION;
+    } else if (typeid(DbusIOException) == typeid(ex)) {
+        return SCCLIENT_DBUS_IO_EXCEPTION;
+    } else if (typeid(DbusOperationException) == typeid(ex)) {
+        return SCCLIENT_DBUS_OPERATION_EXCEPTION;
+    } else if (typeid(DbusInvalidArgumentException) == typeid(ex)) {
+        return SCCLIENT_DBUS_INVALID_ARGUMENT_EXCEPTION;
+    } else if (typeid(DbusException) == typeid(ex)) {
+        return SCCLIENT_DBUS_EXCEPTION;
+    }
+    return SCCLIENT_RUNTIME_EXCEPTION;
+}
+
+} //namespace
+
+ScStatus Client::sc_start() noexcept
+{
+    try {
+        if (!loop) {
+            loop.reset(new ScopedGlibLoop());
+        }
+    } catch (const exception& ex) {
+        return toStatus(ex);
+    } catch (...) {
+        return SCCLIENT_EXCEPTION;
+    }
+
+    return SCCLIENT_SUCCESS;
+}
+
+ScStatus Client::sc_stop() noexcept
+{
+    try {
+        if (loop) {
+            loop.reset();
+        }
+    } catch (const exception& ex) {
+        return toStatus(ex);
+    } catch (...) {
+        return SCCLIENT_EXCEPTION;
+    }
+    return SCCLIENT_SUCCESS;
+}
+
+Client::Status::Status(ScStatus status)
+    : mScStatus(status)
+{
+    switch (status) {
+        case SCCLIENT_EXCEPTION:
+            mMsg = SCCLIENT_EXCEPTION_MSG;
+            break;
+        case SCCLIENT_SUCCESS:
+            mMsg = SCCLIENT_SUCCESS_MSG;
+            break;
+        default:
+            assert(!"Logic error. You must specify a message.");
+            mMsg = std::string();
+    }
+}
+
+Client::Status::Status(ScStatus status, const std::string& msg)
+    : mScStatus(status), mMsg(msg)
+{
+}
+
+Client::Client() noexcept
+    : mStatus(SCCLIENT_SUCCESS)
+{
+}
+
+Client::~Client() noexcept
+{
+}
+
+ScStatus Client::createSystem() noexcept
+{
+    try {
+        mConnection = DbusConnection::createSystem();
+        mStatus = Status(SCCLIENT_SUCCESS);
+    } catch (const exception& ex)  {
+        mStatus = Status(toStatus(ex), ex.what());
+    } catch (...) {
+        mStatus = Status(SCCLIENT_EXCEPTION);
+    }
+    return sc_get_status();
+}
+
+ScStatus Client::create(const string& address) noexcept
+{
+    try {
+        mConnection = DbusConnection::create(address);
+        mStatus = Status(SCCLIENT_SUCCESS);
+    } catch (const exception& ex)  {
+        mStatus = Status(toStatus(ex), ex.what());
+    } catch (...) {
+        mStatus = Status(SCCLIENT_EXCEPTION);
+    }
+    return sc_get_status();
+}
+
+ScStatus Client::callMethod(const DbusInterfaceInfo& info,
+                            const string& method,
+                            GVariant* args_in,
+                            const string& args_spec_out,
+                            GVariant** args_out)
+{
+    try {
+        GVariantPtr ret = mConnection->callMethod(info.busName,
+                                                  info.objectPath,
+                                                  info.interface,
+                                                  method,
+                                                  args_in,
+                                                  args_spec_out);
+        if (args_out != NULL) {
+            *args_out = ret.release();
+        }
+        mStatus = Status(SCCLIENT_SUCCESS);
+    } catch (const exception& ex)  {
+        mStatus = Status(toStatus(ex), ex.what());
+    } catch (...) {
+        mStatus = Status(SCCLIENT_EXCEPTION);
+    }
+    return sc_get_status();
+}
+
+const char* Client::sc_get_status_message() noexcept
+{
+    return mStatus.mMsg.c_str();
+}
+
+ScStatus Client::sc_get_status() noexcept
+{
+    return mStatus.mScStatus;
+}
+
+ScStatus Client::sc_get_container_dbuses(ScArrayString* keys, ScArrayString* values) noexcept
+{
+    assert(keys);
+    assert(values);
+
+    GVariant* out;
+    ScStatus ret = callMethod(hostDbusInterfaceInfo,
+                              api::host::METHOD_GET_CONTAINER_DBUSES,
+                              NULL,
+                              "(a{ss})",
+                              &out);
+    if (ret != SCCLIENT_SUCCESS) {
+        return ret;
+    }
+    GVariant* unpacked;
+    g_variant_get(out, "(*)", &unpacked);
+    toDict(unpacked, keys, values);
+    g_variant_unref(unpacked);
+    g_variant_unref(out);
+    return ret;
+}
diff --git a/client/security-containers-client-impl.hpp b/client/security-containers-client-impl.hpp
new file mode 100644 (file)
index 0000000..f823cd1
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Mateusz Malicki <m.malicki2@samsung.com>
+ *
+ *  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
+ * @author  Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief   This file contains security-containers-server's client definition
+ */
+
+#ifndef SECURITY_CONTAINERS_CLIENT_IMPL_HPP
+#define SECURITY_CONTAINERS_CLIENT_IMPL_HPP
+
+#include "security-containers-client.h"
+#include <dbus/connection.hpp>
+#include <exception>
+
+/**
+ * Structure which defines the dbus interface.
+ */
+struct DbusInterfaceInfo {
+    DbusInterfaceInfo(const std::string& busName,
+                      const std::string& objectPath,
+                      const std::string& interface)
+        : busName(busName),
+          objectPath(objectPath),
+          interface(interface) {}
+    const std::string busName;
+    const std::string objectPath;
+    const std::string interface;
+};
+
+/**
+ * security-containers's client definition.
+ *
+ * Client uses dbus API.
+ */
+class Client {
+private:
+    struct Status {
+        Status(ScStatus status);
+        Status(ScStatus status, const std::string& msg);
+        ScStatus mScStatus;
+        std::string mMsg;
+    };
+
+    dbus::DbusConnection::Pointer mConnection;
+    Status mStatus;
+
+    ScStatus callMethod(const DbusInterfaceInfo& info,
+                        const std::string& method,
+                        GVariant* args_in,
+                        const std::string& args_spec_out = std::string(),
+                        GVariant** args_out = NULL);
+
+public:
+    Client() noexcept;
+    ~Client() noexcept;
+
+    /**
+     * Create client with system dbus address.
+     *
+     * @return Status of this function call.
+     */
+    ScStatus createSystem() noexcept;
+
+    /**
+     * Create client.
+     *
+     * @param address Dbus socket address.
+     * @return Status of this function call.
+     */
+    ScStatus create(const std::string& address) noexcept;
+
+    /**
+     *  @see ::sc_get_status_message
+     */
+    const char* sc_get_status_message() noexcept;
+
+    /**
+     *  @see ::sc_get_status
+     */
+    ScStatus sc_get_status() noexcept;
+
+    /**
+     *  @see ::sc_get_container_dbuses
+     */
+    ScStatus sc_get_container_dbuses(ScArrayString* keys, ScArrayString* values) noexcept;
+
+    /**
+     *  @see ::sc_start
+     */
+    static ScStatus sc_start() noexcept;
+
+    /**
+     *  @see ::sc_stop
+     */
+    static ScStatus sc_stop() noexcept;
+};
+
+#endif /* SECURITY_CONTAINERS_CLIENT_IMPL_HPP */
diff --git a/client/security-containers-client.cpp b/client/security-containers-client.cpp
new file mode 100644 (file)
index 0000000..572f166
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Mateusz Malicki <m.malicki2@samsung.com>
+ *
+ *  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
+ * @author  Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief   This file contains the public API for Security Containers Client
+ */
+
+#include <config.hpp>
+#include "security-containers-client.h"
+#include "security-containers-client-impl.hpp"
+
+#include <cstdarg>
+#include <cassert>
+
+#ifndef API
+#define API __attribute__((visibility("default")))
+#endif // API
+
+using namespace std;
+
+namespace {
+
+typedef Client* ClientPtr;
+
+ClientPtr getClient(ScClient client)
+{
+    assert(client);
+    return reinterpret_cast<ClientPtr>(client);
+}
+
+} // namespace
+
+/* external */
+API ScStatus sc_start()
+{
+    return Client::sc_start();
+}
+
+API ScStatus sc_stop()
+{
+    return Client::sc_stop();
+}
+
+API ScStatus sc_get_client(ScClient* client, ScClientType type, ...)
+{
+    const char* address = NULL;
+    va_list vl;
+    va_start(vl, type);
+    if (type == SCCLIENT_CUSTOM_TYPE) {
+        address = va_arg(vl, const char*);
+        assert(address);
+    }
+    va_end(vl);
+
+    assert(client);
+    Client* clientPtr = new(nothrow) Client();
+    *client = reinterpret_cast<ScClient>(clientPtr);
+    if (clientPtr == NULL) {
+        return SCCLIENT_NOT_ENOUGH_MEMORY;
+    }
+
+    ScStatus status;
+    switch (type) {
+    case SCCLIENT_CUSTOM_TYPE:
+        status = clientPtr->create(address);
+        break;
+    case SCCLIENT_SYSTEM_TYPE:
+        status = clientPtr->createSystem();
+        break;
+    default:
+        assert(!"Logic error. No such ScClient type");
+        status = SCCLIENT_EXCEPTION;
+    }
+    return status;
+}
+
+API int sc_is_failed(ScStatus status)
+{
+    return status != SCCLIENT_SUCCESS ? 1 : 0;
+}
+
+API void sc_array_string_free(ScArrayString astring)
+{
+    if (!astring) {
+        return;
+    }
+    for (char** ptr = astring; *ptr; ++ptr) {
+        sc_string_free(*ptr);
+    }
+    free(astring);
+}
+
+API void sc_string_free(ScString string)
+{
+    free(string);
+}
+
+
+API void sc_client_free(ScClient client)
+{
+    if (client != NULL) {
+        delete getClient(client);
+    }
+}
+
+API const char* sc_get_status_message(ScClient client)
+{
+    return getClient(client)->sc_get_status_message();
+}
+
+API ScStatus sc_get_status(ScClient client)
+{
+    return getClient(client)->sc_get_status();
+}
+
+API ScStatus sc_get_container_dbuses(ScClient client, ScArrayString* keys, ScArrayString* values)
+{
+    return getClient(client)->sc_get_container_dbuses(keys, values);
+}
index b17b763..692df31 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
  *
- *  Contact: Jan Olszak <j.olszak@samsung.com>
+ *  Contact: Mateusz Malicki <m.malicki2@samsung.com>
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 
 /**
- * @file    security-containers-client.h
- * @author  Jan Olszak (j.olszak@samsung.com)
+ * @file
+ * @author  Mateusz Malicki (m.malicki2@samsung.com)
  * @brief   This file contains the public API for Security Containers Client
  */
 
 #ifndef SECURITY_CONTAINERS_CLIENT_H
 #define SECURITY_CONTAINERS_CLIENT_H
 
-#endif /*SECURITY_CONTAINERS_CLIENT_H*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * security-containers-server's client
+ */
+typedef void* ScClient;
+
+/**
+ * String type.
+ *
+ * NULL-terminated string.
+ */
+typedef char* ScString;
+
+/**
+ * Array of strings type.
+ *
+ * Array are NULL-terminated.
+ */
+typedef ScString* ScArrayString;
+
+/**
+ * Completion status of communication function.
+ */
+typedef enum {
+    SCCLIENT_DBUS_CUSTOM_EXCEPTION,
+    SCCLIENT_DBUS_IO_EXCEPTION,
+    SCCLIENT_DBUS_OPERATION_EXCEPTION,
+    SCCLIENT_DBUS_INVALID_ARGUMENT_EXCEPTION,
+    SCCLIENT_DBUS_EXCEPTION,
+    SCCLIENT_NOT_ENOUGH_MEMORY,
+    SCCLIENT_RUNTIME_EXCEPTION,
+    SCCLIENT_EXCEPTION,
+    SCCLIENT_SUCCESS
+} ScStatus;
+
+typedef enum {
+    SCCLIENT_SYSTEM_TYPE,
+    SCCLIENT_CUSTOM_TYPE
+} ScClientType;
+
+/**
+ * Initialize communication resources.
+ */
+ScStatus sc_start();
+
+/**
+ * Release communication resources.
+ *
+ * @return Status of this function call.
+ */
+ScStatus sc_stop();
+
+/**
+ * Create a security-containers-server's client.
+ *
+ * After calling this function a connection to security-containers-server is established.
+ *
+ * @param[out] client security-containers-server's client who will be returned.
+ *                    Client can be broken. To check this you must call sc_is_failed().
+ *                    Broken client can't be used to communicate with security-containers-server.
+ * @param[in] type Type of client.
+ * @param[in] @optional address Dbus socket address (significant only for type SCCLIENT_CUSTOM_TYPE).
+ * @return Status of this function call.
+ */
+ScStatus sc_get_client(ScClient* client, ScClientType type, /* const char* address */ ...);
+
+/**
+ * Release client resources.
+ *
+ * @param client security-containers-server's client.
+ */
+void sc_client_free(ScClient client);
+
+/**
+ * Get status message of the last security-containers-server communication.
+ *
+ * @param client security-containers-server's client.
+ * @return Last status message from security-containers-server communication.
+ */
+const char* sc_get_status_message(ScClient client);
+
+/**
+ * Get status code of last security-containers-server communication.
+ *
+ * @param client security-containers-server's client.
+ * @return Status of this function call.
+ */
+ScStatus sc_get_status(ScClient client);
+
+/**
+ * Check if security-containers-server communication function fail.
+ *
+ * @param status Value returned by security-containers-server communication function.
+ * @return 0 if succeeded otherwise 1.
+ */
+int sc_is_failed(ScStatus status);
+
+/**
+ * Release ScArrayString.
+ *
+ * @param astring ScArrayString.
+ */
+void sc_array_string_free(ScArrayString astring);
+
+/**
+ * Release ScString.
+ *
+ * @param string ScString.
+ */
+void sc_string_free(ScString string);
+
+
+/*************************************************************************************************
+ *
+ *  org.tizen.containers.host.manager interface
+ *
+ ************************************************************************************************/
+
+/**
+ * Get dbus address of each container.
+ *
+ * @param[in] client security-containers-server's client.
+ * @param[out] keys Array of containers name.
+ * @param[out] values Array of containers dbus address.
+ * @return Status of this function call.
+ * @post keys[i] corresponds to values[i].
+ */
+ScStatus sc_get_container_dbuses(ScClient client, ScArrayString* keys, ScArrayString* values);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SECRITY_CONTAINERS_CLIENT_H */
index a82075c..3bb265d 100644 (file)
@@ -21,6 +21,7 @@ MESSAGE(STATUS "Generating makefile for the Unit Tests...")
 FILE(GLOB_RECURSE project_SRCS *.cpp *.hpp)
 FILE(GLOB_RECURSE common_SRCS ${COMMON_FOLDER}/*.cpp ${COMMON_FOLDER}/*.hpp)
 FILE(GLOB         server_SRCS ${SERVER_FOLDER}/*.cpp ${SERVER_FOLDER}/*.hpp)
+FILE(GLOB         client_SRCS ${CLIENT_FOLDER}/*.cpp ${CLIENT_FOLDER}/*.h)
 
 FILE(GLOB         main_SRC ${SERVER_FOLDER}/main.cpp)
 LIST(REMOVE_ITEM server_SRCS ${main_SRC})
@@ -28,7 +29,7 @@ LIST(REMOVE_ITEM server_SRCS ${main_SRC})
 
 ## Setup target ################################################################
 SET(UT_SERVER_CODENAME "${PROJECT_NAME}-server-unit-tests")
-ADD_EXECUTABLE(${UT_SERVER_CODENAME} ${project_SRCS} ${common_SRCS} ${server_SRCS})
+ADD_EXECUTABLE(${UT_SERVER_CODENAME} ${project_SRCS} ${common_SRCS} ${server_SRCS} ${client_SRCS})
 
 
 ## Link libraries ##############################################################
@@ -36,7 +37,7 @@ FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem regex)
 
 PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED libvirt libvirt-glib-1.0 json gio-2.0
                   libsystemd-journal libcap-ng libLogger libSimpleDbus libConfig)
-INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER})
+INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER} ${CLIENT_FOLDER})
 INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
 TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES})
 
@@ -48,6 +49,7 @@ ADD_DEFINITIONS(-DSC_TEST_CONFIG_INSTALL_DIR="${SC_TEST_CONFIG_INSTALL_DIR}")
 ADD_SUBDIRECTORY(dbus/configs)
 ADD_SUBDIRECTORY(server/configs)
 ADD_SUBDIRECTORY(utils/configs)
+ADD_SUBDIRECTORY(client/configs)
 
 
 ## Install #####################################################################
diff --git a/tests/unit_tests/client/configs/CMakeLists.txt b/tests/unit_tests/client/configs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..112d979
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright (c) 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   CMakeLists.txt
+# @author Mateusz Malicki (m.malicki2@samsung.com)
+#
+
+MESSAGE(STATUS "Installing configs for the Client Unit Tests to " ${SC_CONFIG_INSTALL_DIR})
+
+FILE(GLOB client_manager_CONF       ut-client/*.conf)
+FILE(GLOB client_container_CONF     ut-client/containers/*.conf)
+FILE(GLOB client_admin_CONF         ut-client/libvirt-config/*.xml)
+
+## Generate ####################################################################
+CONFIGURE_FILE(ut-client/libvirt-config/console1-dbus.xml.in
+               ${CMAKE_BINARY_DIR}/ut-client/libvirt-config/console1-dbus.xml @ONLY)
+CONFIGURE_FILE(ut-client/libvirt-config/console2-dbus.xml.in
+               ${CMAKE_BINARY_DIR}/ut-client/libvirt-config/console2-dbus.xml @ONLY)
+CONFIGURE_FILE(ut-client/libvirt-config/console3-dbus.xml.in
+               ${CMAKE_BINARY_DIR}/ut-client/libvirt-config/console3-dbus.xml @ONLY)
+FILE(GLOB client_admin_CONF_GEN ${CMAKE_BINARY_DIR}/ut-client/libvirt-config/*.xml)
+
+
+## Install #####################################################################
+INSTALL(FILES        ${client_manager_CONF}
+        DESTINATION  ${SC_TEST_CONFIG_INSTALL_DIR}/client/ut-client)
+INSTALL(FILES        ${client_container_CONF}
+        DESTINATION  ${SC_TEST_CONFIG_INSTALL_DIR}/client/ut-client/containers)
+INSTALL(FILES        ${client_admin_CONF}
+        DESTINATION  ${SC_TEST_CONFIG_INSTALL_DIR}/client/ut-client/libvirt-config)
+INSTALL(FILES        ${client_admin_CONF_GEN}
+        DESTINATION  ${SC_TEST_CONFIG_INSTALL_DIR}/client/ut-client/libvirt-config)
diff --git a/tests/unit_tests/client/configs/ut-client/containers/console1-dbus.conf b/tests/unit_tests/client/configs/ut-client/containers/console1-dbus.conf
new file mode 100644 (file)
index 0000000..ef49f19
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "privilege" : 20,
+    "switchToDefaultAfterTimeout" : true,
+    "config" : "../libvirt-config/console1-dbus.xml",
+    "networkConfig" : "../libvirt-config/network1.xml",
+    "cpuQuotaForeground" : -1,
+    "cpuQuotaBackground" : 1000,
+    "runMountPoint" : "/tmp/ut-containers-manager/console1-dbus",
+    "permittedToSend" : [ "/tmp/.*", "/etc/secret2" ],
+    "permittedToRecv" : [ "/tmp/.*" ]
+}
diff --git a/tests/unit_tests/client/configs/ut-client/containers/console2-dbus.conf b/tests/unit_tests/client/configs/ut-client/containers/console2-dbus.conf
new file mode 100644 (file)
index 0000000..76c5e49
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "privilege" : 20,
+    "switchToDefaultAfterTimeout" : false,
+    "config" : "../libvirt-config/console2-dbus.xml",
+    "networkConfig" : "../libvirt-config/network2.xml",
+    "cpuQuotaForeground" : -1,
+    "cpuQuotaBackground" : 1000,
+    "runMountPoint" : "/tmp/ut-containers-manager/console2-dbus",
+    "permittedToSend" : [ "/tmp/.*" ],
+    "permittedToRecv" : [ "/tmp/.*", "/etc/secret1" ]
+}
diff --git a/tests/unit_tests/client/configs/ut-client/containers/console3-dbus.conf b/tests/unit_tests/client/configs/ut-client/containers/console3-dbus.conf
new file mode 100644 (file)
index 0000000..592cbfa
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "privilege" : 20,
+    "switchToDefaultAfterTimeout" : true,
+    "config" : "../libvirt-config/console3-dbus.xml",
+    "networkConfig" : "../libvirt-config/network3.xml",
+    "cpuQuotaForeground" : -1,
+    "cpuQuotaBackground" : 1000,
+    "runMountPoint" : "/tmp/ut-containers-manager/console3-dbus",
+    "permittedToSend" : [ "/tmp/.*" ],
+    "permittedToRecv" : [ "/tmp/.*" ]
+}
diff --git a/tests/unit_tests/client/configs/ut-client/libvirt-config/console1-dbus.xml.in b/tests/unit_tests/client/configs/ut-client/libvirt-config/console1-dbus.xml.in
new file mode 100644 (file)
index 0000000..3bce659
--- /dev/null
@@ -0,0 +1,15 @@
+<domain type="lxc">
+    <name>ut-containers-manager-console1-dbus</name>
+    <uuid>58184009-b278-4d01-975d-708393690084</uuid>
+    <memory>102400</memory>
+    <os>
+        <type>exe</type>
+        <init>/usr/bin/dbus-daemon</init>
+        <initarg>--nofork</initarg>
+        <initarg>--config-file=@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-containers-manager/ut-dbus.conf</initarg>
+        <initarg>--address=unix:path=/tmp/ut-containers-manager/console1-dbus/dbus/system_bus_socket</initarg>
+    </os>
+    <devices>
+        <console type="pty"/>
+    </devices>
+</domain>
diff --git a/tests/unit_tests/client/configs/ut-client/libvirt-config/console2-dbus.xml.in b/tests/unit_tests/client/configs/ut-client/libvirt-config/console2-dbus.xml.in
new file mode 100644 (file)
index 0000000..f98c9bd
--- /dev/null
@@ -0,0 +1,15 @@
+<domain type="lxc">
+    <name>ut-containers-manager-console2-dbus</name>
+    <uuid>3d18323e-4ada-4a1b-a907-836701891306</uuid>
+    <memory>102400</memory>
+    <os>
+        <type>exe</type>
+        <init>/usr/bin/dbus-daemon</init>
+        <initarg>--nofork</initarg>
+        <initarg>--config-file=@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-containers-manager/ut-dbus.conf</initarg>
+        <initarg>--address=unix:path=/tmp/ut-containers-manager/console2-dbus/dbus/system_bus_socket</initarg>
+    </os>
+    <devices>
+        <console type="pty"/>
+    </devices>
+</domain>
diff --git a/tests/unit_tests/client/configs/ut-client/libvirt-config/console3-dbus.xml.in b/tests/unit_tests/client/configs/ut-client/libvirt-config/console3-dbus.xml.in
new file mode 100644 (file)
index 0000000..8175bcf
--- /dev/null
@@ -0,0 +1,15 @@
+<domain type="lxc">
+    <name>ut-containers-manager-console3-dbus</name>
+    <uuid>71cb8511-7474-4e90-865a-3360b7f77254</uuid>
+    <memory>102400</memory>
+    <os>
+        <type>exe</type>
+        <init>/usr/bin/dbus-daemon</init>
+        <initarg>--nofork</initarg>
+        <initarg>--config-file=@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-containers-manager/ut-dbus.conf</initarg>
+        <initarg>--address=unix:path=/tmp/ut-containers-manager/console3-dbus/dbus/system_bus_socket</initarg>
+    </os>
+    <devices>
+        <console type="pty"/>
+    </devices>
+</domain>
diff --git a/tests/unit_tests/client/configs/ut-client/libvirt-config/network1.xml b/tests/unit_tests/client/configs/ut-client/libvirt-config/network1.xml
new file mode 100644 (file)
index 0000000..23a5edd
--- /dev/null
@@ -0,0 +1,4 @@
+<network>
+    <name>test-network-1</name>
+    <uuid>372720ef-258b-4b27-baf6-d08341b15353</uuid>
+</network>
diff --git a/tests/unit_tests/client/configs/ut-client/libvirt-config/network2.xml b/tests/unit_tests/client/configs/ut-client/libvirt-config/network2.xml
new file mode 100644 (file)
index 0000000..c3b4f04
--- /dev/null
@@ -0,0 +1,4 @@
+<network>
+    <name>test-network-2</name>
+    <uuid>95b9c647-ed3f-4586-886e-0a7b24e683a8</uuid>
+</network>
diff --git a/tests/unit_tests/client/configs/ut-client/libvirt-config/network3.xml b/tests/unit_tests/client/configs/ut-client/libvirt-config/network3.xml
new file mode 100644 (file)
index 0000000..7b3f730
--- /dev/null
@@ -0,0 +1,4 @@
+<network>
+    <name>test-network-3</name>
+    <uuid>962b061d-7f3e-410b-8990-3f1267d77656</uuid>
+</network>
diff --git a/tests/unit_tests/client/configs/ut-client/test-dbus-daemon.conf b/tests/unit_tests/client/configs/ut-client/test-dbus-daemon.conf
new file mode 100644 (file)
index 0000000..2a6ad35
--- /dev/null
@@ -0,0 +1,20 @@
+{
+    "containerConfigs" : ["containers/console1-dbus.conf",
+                          "containers/console2-dbus.conf",
+                          "containers/console3-dbus.conf"],
+    "foregroundId" : "ut-containers-manager-console1-dbus",
+    "defaultId" : "ut-containers-manager-console1-dbus",
+    "containersPath" : "/tmp",
+    "runMountPointPrefix" : "",
+    "inputConfig" : {"enabled" : false,
+                     "device" : "/dev/doesnotexist",
+                     "code" : 139,
+                     "numberOfEvents" : 2,
+                     "timeWindowMs" : 500},
+    "proxyCallRules" : [{"caller" : "*",
+                         "target" : "*",
+                         "targetBusName" : "org.tizen.containers.tests",
+                         "targetObjectPath" : "*",
+                         "targetInterface" : "*",
+                         "targetMethod" : "*"}]
+}
diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp
new file mode 100644 (file)
index 0000000..1755874
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Mateusz Malicki <m.malicki2@samsung.com>
+ *
+ *  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
+ * @author  Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief   Unit tests of the client C API
+ */
+
+#include <config.hpp>
+#include "ut.hpp"
+#include <security-containers-client.h>
+
+#include "containers-manager.hpp"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <memory>
+
+using namespace security_containers;
+
+namespace {
+
+const std::string TEST_DBUS_CONFIG_PATH =
+    SC_TEST_CONFIG_INSTALL_DIR "/client/ut-client/test-dbus-daemon.conf";
+
+struct Fixture {
+    Fixture() { sc_start(); };
+    ~Fixture() { sc_stop(); };
+};
+
+const std::map<std::string, std::string> EXPECTED_DBUSES_STARTED = {
+    {"ut-containers-manager-console1-dbus",
+     "unix:path=/tmp/ut-containers-manager/console1-dbus/dbus/system_bus_socket"},
+    {"ut-containers-manager-console2-dbus",
+     "unix:path=/tmp/ut-containers-manager/console2-dbus/dbus/system_bus_socket"},
+    {"ut-containers-manager-console3-dbus",
+     "unix:path=/tmp/ut-containers-manager/console3-dbus/dbus/system_bus_socket"}};
+
+void convertDictToMap(ScArrayString keys,
+                      ScArrayString values,
+                      std::map<std::string, std::string>& ret)
+{
+    char** iKeys;
+    char** iValues;
+    for (iKeys = keys, iValues = values; *iKeys && *iValues; iKeys++, iValues++) {
+        ret.insert(std::make_pair(*iKeys, *iValues));
+    }
+}
+
+int getArrayStringLength(ScArrayString astring, int max_len = -1)
+{
+    int i = 0;
+    for (i = 0; astring[i];  i++) {
+        if (i == max_len) {
+            return max_len;
+        }
+    }
+    return i;
+}
+
+} // namespace
+
+BOOST_FIXTURE_TEST_SUITE(Client, Fixture)
+
+BOOST_AUTO_TEST_CASE(NotRunningServerTest)
+{
+    ScClient client;
+    ScStatus status = sc_get_client(&client,
+                                    SCCLIENT_CUSTOM_TYPE,
+                                    EXPECTED_DBUSES_STARTED.begin()->second.c_str());
+    BOOST_CHECK(sc_is_failed(status));
+    sc_client_free(client);
+}
+
+BOOST_AUTO_TEST_CASE(GetContainerDbusesTest)
+{
+    std::unique_ptr<ContainersManager> cm;
+    BOOST_REQUIRE_NO_THROW(cm.reset(new ContainersManager(TEST_DBUS_CONFIG_PATH)));
+    cm->startAll();
+    ScClient client;
+    ScStatus status = sc_get_client(&client, SCCLIENT_SYSTEM_TYPE);
+    BOOST_REQUIRE(!sc_is_failed(status));
+    ScArrayString keys, values;
+    status = sc_get_container_dbuses(client, &keys, &values);
+    BOOST_REQUIRE(!sc_is_failed(status));
+
+    BOOST_CHECK_EQUAL(getArrayStringLength(keys, EXPECTED_DBUSES_STARTED.size() + 1),
+                      EXPECTED_DBUSES_STARTED.size());
+    BOOST_CHECK_EQUAL(getArrayStringLength(values, EXPECTED_DBUSES_STARTED.size() + 1),
+                      EXPECTED_DBUSES_STARTED.size());
+
+    std::map<std::string, std::string> containers;
+    convertDictToMap(keys, values, containers);
+    BOOST_CHECK(containers == EXPECTED_DBUSES_STARTED);
+    sc_array_string_free(keys);
+    sc_array_string_free(values);
+    sc_client_free(client);
+    BOOST_WARN_NO_THROW(cm.reset());
+}
+
+BOOST_AUTO_TEST_SUITE_END()