one_shot(bind(vsm_create_domain, _1, argv[pos + 1], nullptr));
}
+void destroy_domain(int pos, int argc, const char** argv)
+{
+ using namespace std::placeholders;
+
+ if (argc <= pos + 1) {
+ throw runtime_error("Not enough parameters");
+ }
+
+ one_shot(bind(vsm_destroy_domain, _1, argv[pos + 1], 1));
+}
+
void lock_domain(int pos, int argc, const char** argv)
{
using namespace std::placeholders;
void create_domain(int pos, int argc, const char** argv);
/**
+ * Parses command line arguments and call vsm_destroy_domain
+ *
+ * @see vsm_destroy_domain
+ */
+void destroy_domain(int pos, int argc, const char** argv);
+
+/**
* Parses command line arguments and call vsm_lock_domain
*
* @see vsm_lock_domain
}
},
{
+ "destroy_domain", {
+ destroy_domain,
+ "destroy_domain container_id",
+ "Destroy container",
+ {{"container_id", "id container name"}}
+ }
+ },
+ {
"lock_domain", {
lock_domain,
"lock_domain container_id",
}
GVariant* args_in = g_variant_new("(s)", id);
- return callMethod(HOST_INTERFACE, api::host::METHOD_ADD_CONTAINER, args_in);
+ return callMethod(HOST_INTERFACE, api::host::METHOD_CREATE_CONTAINER, args_in);
}
-VsmStatus Client::vsm_destroy_domain(const char*) noexcept
+VsmStatus Client::vsm_destroy_domain(const char* id) noexcept
{
- mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
- return vsm_get_status();
+ assert(id);
+ GVariant* args_in = g_variant_new("(s)", id);
+ return callMethod(HOST_INTERFACE, api::host::METHOD_DESTROY_CONTAINER, args_in);
}
VsmStatus Client::vsm_shutdown_domain(const char*) noexcept
return getClient(client).vsm_create_domain(id, tname);
}
-API VsmStatus vsm_destroy_domain(VsmClient client, const char* id)
+API VsmStatus vsm_destroy_domain(VsmClient client, const char* id, int /*force*/)
{
return getClient(client).vsm_destroy_domain(id);
}
* @param[in] force if 0 data will be kept, otherwise data will be lost
* @return status of this function call
*/
-VsmStatus vsm_destroy_domain(VsmStatus clent, const char* id, int force);
+VsmStatus vsm_destroy_domain(VsmClient clent, const char* id, int force);
/**
* Shutdown domain
namespace api {
const std::string ERROR_FORBIDDEN = "org.tizen.containers.Error.Forbidden";
const std::string ERROR_FORWARDED = "org.tizen.containers.Error.Forwarded";
-const std::string ERROR_UNKNOWN_ID = "org.tizen.containers.Error.UnknownId";
+const std::string ERROR_INVALID_ID = "org.tizen.containers.Error.InvalidId";
const std::string ERROR_INTERNAL = "org.tizen.containers.Error.Internal";
const std::string METHOD_PROXY_CALL = "ProxyCall";
{
LOGD(mId << ": Destroying ContainerAdmin object...");
+ if (mDestroyOnExit) {
+ if (!mDom.stop()) {
+ LOGE(mId << ": Failed to stop the container");
+ }
+ if (!mDom.destroy()) {
+ LOGE(mId << ": Failed to destroy the container");
+ }
+ }
+
if (!mDetachOnExit) {
// Try to forcefully stop
if (!mDom.stop()) {
mDetachOnExit = true;
}
+void ContainerAdmin::setDestroyOnExit()
+{
+ mDestroyOnExit = true;
+}
+
std::int64_t ContainerAdmin::getSchedulerQuota()
{
// assert(mDom);
void setDetachOnExit();
/**
+ * Set if container should be destroyed on exit.
+ */
+ void setDestroyOnExit();
+
+ /**
* @return Scheduler CFS quota,
* TODO: this function is only for UNIT TESTS
*/
lxc::LxcDomain mDom;
const std::string mId;
bool mDetachOnExit;
+ bool mDestroyOnExit;
void setSchedulerParams(std::uint64_t cpuShares, std::uint64_t vcpuPeriod, std::int64_t vcpuQuota);
};
}
}
+void Container::setDestroyOnExit()
+{
+ Lock lock(mReconnectMutex);
+ mAdmin->setDestroyOnExit();
+}
+
bool Container::isRunning()
{
Lock lock(mReconnectMutex);
void setDetachOnExit();
/**
+ * Set if container should be destroyed on exit.
+ */
+ void setDestroyOnExit();
+
+ /**
* @return Is the container running?
*/
bool isRunning();
mHostConnection.setSetActiveContainerCallback(bind(&ContainersManager::handleSetActiveContainerCall,
this, _1, _2));
- mHostConnection.setAddContainerCallback(bind(&ContainersManager::handleAddContainerCall,
- this, _1, _2));
+ mHostConnection.setCreateContainerCallback(bind(&ContainersManager::handleCreateContainerCall,
+ this, _1, _2));
+
+ mHostConnection.setDestroyContainerCallback(bind(&ContainersManager::handleDestroyContainerCall,
+ this, _1, _2));
for (auto& containerConfig : mConfig.containerConfigs) {
- addContainer(containerConfig);
+ createContainer(containerConfig);
}
// check if default container exists, throw ContainerOperationException if not found
LOGD("ContainersManager object destroyed");
}
-void ContainersManager::addContainer(const std::string& containerConfig)
+void ContainersManager::createContainer(const std::string& containerConfig)
{
std::string baseConfigPath = utils::dirName(mConfigPath);
std::string containerConfigPath = utils::getAbsolutePath(containerConfig, baseConfigPath);
mContainers.insert(ContainerMap::value_type(id, std::move(c)));
}
+void ContainersManager::destroyContainer(const std::string& containerId)
+{
+ // TODO mutex for mContainers access
+ auto it = mContainers.find(containerId);
+ if (it == mContainers.end()) {
+ LOGE("Failed to destroy container " << containerId << ": no such container");
+ throw ContainerOperationException("No such container");
+ }
+
+ // TODO give back the focus
+ it->second->setDestroyOnExit();
+ mContainers.erase(it);
+}
+
void ContainersManager::focus(const std::string& containerId)
{
/* try to access the object first to throw immediately if it doesn't exist */
ContainerMap::const_iterator targetIter = mContainers.find(target);
if (targetIter == mContainers.end()) {
LOGE("Target container '" << target << "' not found");
- result->setError(api::ERROR_UNKNOWN_ID, "Unknown proxy call target");
+ result->setError(api::ERROR_INVALID_ID, "Unknown proxy call target");
return;
}
LOGI("GetContainerInfo call");
if (mContainers.count(id) == 0) {
LOGE("No container with id=" << id);
- result->setError(api::ERROR_UNKNOWN_ID, "No such container id");
+ result->setError(api::ERROR_INVALID_ID, "No such container id");
return;
}
const auto& container = mContainers[id];
auto container = mContainers.find(id);
if (container == mContainers.end()){
LOGE("No container with id=" << id );
- result->setError(api::ERROR_UNKNOWN_ID, "No such container id");
+ result->setError(api::ERROR_INVALID_ID, "No such container id");
return;
}
fs::perms::others_read);
}
-void ContainersManager::handleAddContainerCall(const std::string& id,
- dbus::MethodResultBuilder::Pointer result)
+void ContainersManager::handleCreateContainerCall(const std::string& id,
+ dbus::MethodResultBuilder::Pointer result)
{
if (id.empty()) {
LOGE("Failed to add container - invalid name.");
- result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
- "Failed to add container - invalid name.");
+ result->setError(api::ERROR_INVALID_ID, "Invalid name");
return;
}
- LOGI("Adding container " << id);
+ LOGI("Creating container " << id);
// TODO: This solution is temporary. It utilizes direct access to config files when creating new
// containers. Update this handler when config database will appear.
namespace fs = boost::filesystem;
- boost::system::error_code ec;
- const std::string containerPathStr = utils::createFilePath(mConfig.containersPath, "/", id, "/");
-
// check if container does not exist
if (mContainers.find(id) != mContainers.end()) {
LOGE("Cannot create " << id << " container - already exists!");
- result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
- "Cannot create " + id + " container - already exists!");
+ result->setError(api::ERROR_INVALID_ID, "Already exists");
return;
}
+ const std::string containerPathStr = utils::createFilePath(mConfig.containersPath, "/", id, "/");
+
// copy container image if config contains path to image
LOGT("Image path: " << mConfig.containerImagePath);
if (!mConfig.containerImagePath.empty()) {
if (!utils::launchAsRoot(copyImageContentsWrapper)) {
LOGE("Failed to copy container image.");
- result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
- "Failed to copy container image.");
+ result->setError(api::ERROR_INTERNAL, "Failed to copy container image.");
return;
}
}
std::string configPath = utils::createFilePath(templateDir, "/", CONTAINER_TEMPLATE_CONFIG_PATH);
std::string newConfigPath = utils::createFilePath(configDir, "/containers/", id + ".conf");
- auto removeAllWrapper = [](const std::string& path) {
+ auto removeAllWrapper = [](const std::string& path) -> bool {
try {
LOGD("Removing copied data");
fs::remove_all(fs::path(path));
generateNewConfig(id, configPath, newConfigPath);
} catch (SecurityContainersException& e) {
- LOGE(e.what());
+ LOGE("Generate config failed: " << e.what());
utils::launchAsRoot(std::bind(removeAllWrapper, containerPathStr));
- result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED, e.what());
+ result->setError(api::ERROR_INTERNAL, "Failed to generate config");
return;
}
- LOGT("Adding new container");
+ LOGT("Creating new container");
try {
- addContainer(newConfigPath);
+ createContainer(newConfigPath);
} catch (SecurityContainersException& e) {
- LOGE(e.what());
+ LOGE("Creating new container failed: " << e.what());
utils::launchAsRoot(std::bind(removeAllWrapper, containerPathStr));
- result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED, e.what());
+ result->setError(api::ERROR_INTERNAL, "Failed to create container");
return;
}
} else {
LOGE("Failed to start container.");
// TODO removeContainer
- result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
- "Failed to start container.");
+ result->setError(api::ERROR_INTERNAL, "Failed to start container");
}
};
mContainers[id]->startAsync(resultCallback);
}
+void ContainersManager::handleDestroyContainerCall(const std::string& id,
+ dbus::MethodResultBuilder::Pointer result)
+{
+ if (mContainers.find(id) == mContainers.end()) {
+ LOGE("Failed to destroy container - no such container id: " << id);
+ result->setError(api::ERROR_INVALID_ID, "No such container id");
+ return;
+ }
+
+ LOGI("Destroying container " << id);
+
+ auto destroyer = [id, result, this] {
+ try {
+ destroyContainer(id);
+ } catch (const SecurityContainersException& e) {
+ LOGE("Error during container destruction: " << e.what());
+ result->setError(api::ERROR_INTERNAL, "Failed to destroy container");
+ return;
+ }
+ result->setVoid();
+ };
+
+ std::thread thread(destroyer);
+ thread.detach(); //TODO fix it
+}
+
} // namespace security_containers
~ContainersManager();
/**
- * Add new container.
+ * Create new container.
*
* @param containerConfig config of new container
*/
- void addContainer(const std::string& containerConfig);
+ void createContainer(const std::string& containerConfig);
+
+ /**
+ * Destroy container.
+ *
+ * @param containerId id of the container
+ */
+ void destroyContainer(const std::string& containerId);
/**
* Focus this container, put it to the foreground.
void handleGetContainerInfoCall(const std::string& id, dbus::MethodResultBuilder::Pointer result);
void handleSetActiveContainerCall(const std::string& id,
dbus::MethodResultBuilder::Pointer result);
- void handleAddContainerCall(const std::string& id,
- dbus::MethodResultBuilder::Pointer result);
+ void handleCreateContainerCall(const std::string& id,
+ dbus::MethodResultBuilder::Pointer result);
+ void handleDestroyContainerCall(const std::string& id,
+ dbus::MethodResultBuilder::Pointer result);
};
mSetActiveContainerCallback = callback;
}
-void HostConnection::setAddContainerCallback(const AddContainerCallback& callback)
+void HostConnection::setCreateContainerCallback(const CreateContainerCallback& callback)
{
- mAddContainerCallback = callback;
+ mCreateContainerCallback = callback;
+}
+
+void HostConnection::setDestroyContainerCallback(const DestroyContainerCallback& callback)
+{
+ mDestroyContainerCallback = callback;
}
void HostConnection::onMessageCall(const std::string& objectPath,
return;
}
- if (methodName == api::host::METHOD_ADD_CONTAINER) {
+ if (methodName == api::host::METHOD_CREATE_CONTAINER) {
+ const gchar* id = NULL;
+ g_variant_get(parameters, "(&s)", &id);
+
+ if (mCreateContainerCallback){
+ mCreateContainerCallback(id, result);
+ }
+ }
+
+ if (methodName == api::host::METHOD_DESTROY_CONTAINER) {
const gchar* id = NULL;
g_variant_get(parameters, "(&s)", &id);
- if (mAddContainerCallback){
- mAddContainerCallback(id, result);
+ if (mDestroyContainerCallback){
+ mDestroyContainerCallback(id, result);
}
}
}
)> SetActiveContainerCallback;
typedef std::function<void(const std::string& id,
dbus::MethodResultBuilder::Pointer result
- )> AddContainerCallback;
+ )> CreateContainerCallback;
+ typedef std::function<void(const std::string& id,
+ dbus::MethodResultBuilder::Pointer result
+ )> DestroyContainerCallback;
/**
* Register proxy call callback
/**
* Register a callback called to create new container
*/
- void setAddContainerCallback(const AddContainerCallback& callback);
+ void setCreateContainerCallback(const CreateContainerCallback& callback);
+
+ /**
+ * Register a callback called to destroy container
+ */
+ void setDestroyContainerCallback(const DestroyContainerCallback& callback);
/**
* Make a proxy call
GetActiveContainerIdCallback mGetActiveContainerIdCallback;
GetContainerInfoCallback mGetContainerInfoCallback;
SetActiveContainerCallback mSetActiveContainerCallback;
- AddContainerCallback mAddContainerCallback;
+ CreateContainerCallback mCreateContainerCallback;
+ DestroyContainerCallback mDestroyContainerCallback;
void onNameAcquired();
void onNameLost();
const std::string INTERFACE = "org.tizen.containers.host.manager";
const std::string ERROR_CONTAINER_STOPPED = "org.tizen.containers.host.Error.ContainersStopped";
-const std::string ERROR_CONTAINER_CREATE_FAILED = "org.tizen.containers.host.Error.ContainerCreateFailed";
const std::string METHOD_GET_CONTAINER_DBUSES = "GetContainerDbuses";
const std::string METHOD_GET_CONTAINER_ID_LIST = "GetContainerIds";
const std::string METHOD_GET_ACTIVE_CONTAINER_ID = "GetActiveContainerId";
const std::string METHOD_GET_CONTAINER_INFO = "GetContainerInfo";
const std::string METHOD_SET_ACTIVE_CONTAINER = "SetActiveContainer";
-const std::string METHOD_ADD_CONTAINER = "AddContainer";
+const std::string METHOD_CREATE_CONTAINER = "CreateContainer";
+const std::string METHOD_DESTROY_CONTAINER = "DestroyContainer";
const std::string SIGNAL_CONTAINER_DBUS_STATE = "ContainerDbusState";
" <method name='" + METHOD_SET_ACTIVE_CONTAINER + "'>"
" <arg type='s' name='id' direction='in'/>"
" </method>"
- " <method name='" + METHOD_ADD_CONTAINER + "'>"
+ " <method name='" + METHOD_CREATE_CONTAINER + "'>"
+ " <arg type='s' name='id' direction='in'/>"
+ " </method>"
+ " <method name='" + METHOD_DESTROY_CONTAINER + "'>"
" <arg type='s' name='id' direction='in'/>"
" </method>"
" <signal name='" + SIGNAL_CONTAINER_DBUS_STATE + "'>"
vsm_client_free(client);
}
-BOOST_AUTO_TEST_CASE(AddContainerTest)
+BOOST_AUTO_TEST_CASE(CreateContainerTest)
{
const std::string newActiveContainerId = "";
FILE(GLOB manager_manager_CONF ut-containers-manager/*.conf)
FILE(GLOB manager_container_CONF ut-containers-manager/containers/*.conf)
-FILE(GLOB manager_admin_TEMPLATE ut-containers-manager/templates/*.conf)
FILE(GLOB container_CONF ut-container/*.conf)
FILE(GLOB container_container_CONF ut-container/containers/*.conf)
${CMAKE_BINARY_DIR}/ut-containers-manager/buggy-foreground-daemon.conf @ONLY)
CONFIGURE_FILE(ut-containers-manager/test-dbus-daemon.conf.in
${CMAKE_BINARY_DIR}/ut-containers-manager/test-dbus-daemon.conf @ONLY)
+CONFIGURE_FILE(ut-containers-manager/empty-dbus-daemon.conf.in
+ ${CMAKE_BINARY_DIR}/ut-containers-manager/empty-dbus-daemon.conf @ONLY)
FILE(GLOB manager_manager_CONF_GEN ${CMAKE_BINARY_DIR}/ut-containers-manager/*.conf)
CONFIGURE_FILE(ut-containers-manager/containers/console1-dbus.conf.in
${CMAKE_BINARY_DIR}/ut-containers-manager/containers/console3-dbus.conf @ONLY)
FILE(GLOB manager_container_CONF_GEN ${CMAKE_BINARY_DIR}/ut-containers-manager/containers/*.conf)
+CONFIGURE_FILE(ut-containers-manager/templates/template.conf.in
+ ${CMAKE_BINARY_DIR}/ut-containers-manager/templates/template.conf @ONLY)
+FILE(GLOB manager_container_TEMPLATE_GEN ${CMAKE_BINARY_DIR}/ut-containers-manager/templates/*.conf)
+
## Install #####################################################################
INSTALL(FILES ${server_manager_CONF}
DESTINATION ${SC_TEST_CONFIG_INSTALL_DIR}/server/ut-containers-manager/containers)
INSTALL(FILES ${manager_container_CONF_GEN}
DESTINATION ${SC_TEST_CONFIG_INSTALL_DIR}/server/ut-containers-manager/containers)
-INSTALL(FILES ${manager_admin_TEMPLATE}
+INSTALL(FILES ${manager_container_TEMPLATE_GEN}
DESTINATION ${SC_TEST_CONFIG_INSTALL_DIR}/server/ut-containers-manager/templates)
INSTALL(FILES ${container_CONF}
--- /dev/null
+{
+ "containerConfigs" : [],
+ "foregroundId" : "",
+ "defaultId" : "",
+ "containersPath" : "/tmp/ut-containers",
+ "containerImagePath" : "",
+ "containerTemplatePath" : "templates",
+ "containerNewConfigPrefix" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-containers-manager/",
+ "runMountPointPrefix" : "",
+ "lxcTemplatePrefix" : "@SC_TEST_LXC_TEMPLATES_INSTALL_DIR@",
+ "inputConfig" : {"enabled" : false,
+ "device" : "/dev/doesnotexist",
+ "code" : 139,
+ "numberOfEvents" : 2,
+ "timeWindowMs" : 500},
+ "proxyCallRules" : [{"caller" : "*",
+ "target" : "*",
+ "targetBusName" : "org.tizen.containers.tests",
+ "targetObjectPath" : "*",
+ "targetInterface" : "*",
+ "targetMethod" : "*"}]
+}
+++ /dev/null
-{
- "privilege" : 20,
- "vt" : -1,
- "switchToDefaultAfterTimeout" : true,
- "cpuQuotaForeground" : -1,
- "cpuQuotaBackground" : 1000,
- "runMountPoint" : "/tmp/ut-containers-manager/~NAME~-dbus",
- "enableDbusIntegration" : true,
- "permittedToSend" : [ "/tmp/.*" ],
- "permittedToRecv" : [ "/tmp/.*" ]
-}
--- /dev/null
+{
+ "name" : "~NAME~",
+ "lxcTemplate" : "minimal-dbus1.sh",
+ "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; /usr/bin/dbus-daemon --config-file=@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-containers-manager/ut-dbus.conf --fork; read"],
+ "ipv4Gateway" : "",
+ "ipv4" : "",
+ "privilege" : 20,
+ "vt" : -1,
+ "switchToDefaultAfterTimeout" : true,
+ "enableDbusIntegration" : true,
+ "cpuQuotaForeground" : -1,
+ "cpuQuotaBackground" : 1000,
+ "runMountPoint" : "/tmp/ut-run1",
+ "permittedToSend" : [ "/tmp/.*" ],
+ "permittedToRecv" : [ "/tmp/.*" ]
+}
const std::string TEST_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/test-daemon.conf";
const std::string TEST_DBUS_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/test-dbus-daemon.conf";
+const std::string EMPTY_DBUS_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/empty-dbus-daemon.conf";
const std::string BUGGY_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-daemon.conf";
const std::string BUGGY_FOREGROUND_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-foreground-daemon.conf";
const std::string BUGGY_DEFAULTID_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-default-daemon.conf";
typedef std::function<void(const std::string& argument,
MethodResultBuilder::Pointer result
)> TestApiMethodCallback;
- typedef std::function<void()> AddContainerResultCallback;
+ typedef std::function<void()> VoidResultCallback;
typedef std::map<std::string, std::string> Dbuses;
}
- void callAsyncMethodAddContainer(const std::string& id,
- const AddContainerResultCallback& result)
+ void callAsyncMethodCreateContainer(const std::string& id,
+ const VoidResultCallback& result)
{
auto asyncResult = [result](dbus::AsyncMethodCallResult& asyncMethodCallResult) {
BOOST_CHECK(g_variant_is_of_type(asyncMethodCallResult.get(), G_VARIANT_TYPE_UNIT));
mClient->callMethodAsync(api::host::BUS_NAME,
api::host::OBJECT_PATH,
api::host::INTERFACE,
- api::host::METHOD_ADD_CONTAINER,
+ api::host::METHOD_CREATE_CONTAINER,
+ parameters,
+ "()",
+ asyncResult);
+ }
+
+ void callAsyncMethodDestroyContainer(const std::string& id,
+ const VoidResultCallback& result)
+ {
+ auto asyncResult = [result](dbus::AsyncMethodCallResult& asyncMethodCallResult) {
+ BOOST_CHECK(g_variant_is_of_type(asyncMethodCallResult.get(), G_VARIANT_TYPE_UNIT));
+ result();
+ };
+
+ assert(isHost());
+ GVariant* parameters = g_variant_new("(s)", id.c_str());
+ mClient->callMethodAsync(api::host::BUS_NAME,
+ api::host::OBJECT_PATH,
+ api::host::INTERFACE,
+ api::host::METHOD_DESTROY_CONTAINER,
parameters,
"()",
asyncResult);
DbusException);
}
-//TODO fix it
-//BOOST_AUTO_TEST_CASE(AddContainerTest)
-//{
-// const std::string newContainerId = "test1234";
-// const std::vector<std::string> newContainerConfigs = {
-// TEST_CONTAINER_CONF_PATH + newContainerId + ".conf",
-// };
-// FileCleanerRAII cleaner(newContainerConfigs);
-//
-// ContainersManager cm(TEST_DBUS_CONFIG_PATH);
-// cm.startAll();
-//
-// Latch callDone;
-// auto resultCallback = [&]() {
-// callDone.set();
-// };
-//
-// DbusAccessory dbus(DbusAccessory::HOST_ID);
-//
-// // create new container
-// dbus.callAsyncMethodAddContainer(newContainerId, resultCallback);
-// callDone.wait(EVENT_TIMEOUT);
-//
-// // focus new container
-// cm.focus(newContainerId);
-// BOOST_CHECK(cm.getRunningForegroundContainerId() == newContainerId);
-//}
+BOOST_AUTO_TEST_CASE(CreateDestroyContainerTest)
+{
+ const std::string newContainerId = "test1234";
+
+ ContainersManager cm(EMPTY_DBUS_CONFIG_PATH);
+ cm.startAll();
+
+ Latch callDone;
+ auto resultCallback = [&]() {
+ callDone.set();
+ };
+
+ DbusAccessory dbus(DbusAccessory::HOST_ID);
+
+ // create new container
+ dbus.callAsyncMethodCreateContainer(newContainerId, resultCallback);
+ BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+
+ // focus new container
+ cm.focus(newContainerId);
+ BOOST_CHECK(cm.getRunningForegroundContainerId() == newContainerId);
+
+ // destroy container
+ dbus.callAsyncMethodDestroyContainer(newContainerId, resultCallback);
+ BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+
+ BOOST_CHECK(cm.getRunningForegroundContainerId() == "");
+}
BOOST_AUTO_TEST_SUITE_END()