#include <memory>
+#include "component_based/common/exception.h"
#include "component_based/app_control/component_based_app_control.h"
#include "component_based/app_control/component_based_app_control_implementation.h"
return *this;
}
-AppControl AppControl::Builder::Build() {
+app_control_h AppControl::Builder::BuildNative() {
app_control_h handle = nullptr;
app_control_create(&handle);
+ if (handle == nullptr)
+ return nullptr;
+
+ std::unique_ptr<std::remove_pointer<app_control_h>::type,
+ decltype(app_control_destroy)*> ptr(handle, app_control_destroy);
if (!appid_.empty()) {
- app_control_set_app_id(handle, appid_.c_str());
+ if (app_control_set_app_id(handle, appid_.c_str()) !=
+ APP_CONTROL_ERROR_NONE)
+ return nullptr;
}
if (!op_.empty()) {
- app_control_set_operation(handle, op_.c_str());
+ if (app_control_set_operation(handle, op_.c_str()) !=
+ APP_CONTROL_ERROR_NONE)
+ return nullptr;
}
if (!mime_.empty()) {
- app_control_set_mime(handle, mime_.c_str());
+ if (app_control_set_mime(handle, mime_.c_str()) !=
+ APP_CONTROL_ERROR_NONE)
+ return nullptr;
}
- app_control_set_uri(handle, uri_.Encode().c_str());
+ if (app_control_set_uri(handle, uri_.Encode().c_str()) !=
+ APP_CONTROL_ERROR_NONE)
+ return nullptr;
for (auto& data : extra_) {
- app_control_add_extra_data(handle, data.first.c_str(),
- data.second.c_str());
+ if (app_control_add_extra_data(handle, data.first.c_str(),
+ data.second.c_str()) !=
+ APP_CONTROL_ERROR_NONE)
+ return nullptr;
}
- app_control_set_launch_mode(handle,
- static_cast<app_control_launch_mode_e>(mode_));
+ if (app_control_set_launch_mode(handle,
+ static_cast<app_control_launch_mode_e>(mode_)) !=
+ APP_CONTROL_ERROR_NONE)
+ return nullptr;
if (!comp_id_.empty()) {
- app_control_set_component_id(handle, comp_id_.c_str());
+ if (app_control_set_component_id(handle, comp_id_.c_str()) !=
+ APP_CONTROL_ERROR_NONE)
+ return nullptr;
}
+ return ptr.release();
+}
+AppControl AppControl::Builder::Build() {
+ app_control_h handle = BuildNative();
+ if (handle == nullptr) {
+ THROW(Exception::ErrorCodes::IOError);
+ }
return AppControl(handle);
}
AppControl::AppControl(const AppControl& control) {
app_control_h handle = nullptr;
- app_control_clone(&handle, control.impl_->handle_);
+ if (app_control_clone(&handle, control.impl_->handle_) !=
+ APP_CONTROL_ERROR_NONE) {
+ THROW(Exception::ErrorCodes::OutOfMemory);
+ }
impl_ = std::unique_ptr<Impl>(new Impl(this, handle));
}
AppControl& AppControl::operator=(const AppControl& control) {
if (this != &control) {
app_control_h handle = nullptr;
- app_control_clone(&handle, control.impl_->handle_);
+ if (app_control_clone(&handle, control.impl_->handle_) !=
+ APP_CONTROL_ERROR_NONE) {
+ THROW(Exception::ErrorCodes::OutOfMemory);
+ }
impl_->handle_ = handle;
}
return *this;
return AppControl::LaunchMode::SINGLE;
app_control_launch_mode_e launch_mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
- app_control_get_launch_mode(impl_->handle_, &launch_mode);
+ if (app_control_get_launch_mode(impl_->handle_, &launch_mode) !=
+ APP_CONTROL_ERROR_NONE) {
+ THROW(Exception::ErrorCodes::InvalidParameter);
+ }
return static_cast<AppControl::LaunchMode>(launch_mode);
}
Builder& SetComponentID(std::string comp_id);
AppControl Build();
+ private:
+ app_control_h BuildNative();
+
private:
std::string appid_;
std::string op_;
* limitations under the License.
*/
+#include <dlog.h>
+
#include <memory>
#include <string>
+#include "component_based/common/exception.h"
#include "component_based/base/action_internal.h"
namespace component_based {
Action::Action(std::string name, Action::IEventListener* ev)
: ev_(ev) {
- app_control_add_action_handler(name.c_str(), OnActionCB, ev_, &handle_);
+ if (app_control_add_action_handler(name.c_str(), OnActionCB, ev_, &handle_)
+ != APP_CONTROL_ERROR_NONE) {
+ THROW(Exception::ErrorCodes::InvalidParameter);
+ }
}
Action::~Action() {
void Action::OnActionCB(const char* action, app_control_h app_control,
void* user_data) {
IEventListener* ev = static_cast<IEventListener*>(user_data);
- ev->OnAction(std::string(action), AppControl(app_control));
+ try {
+ ev->OnAction(std::string(action), AppControl(app_control));
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ }
}
} // namespace internal
#include <memory>
+#include "component_based/common/exception.h"
#include "component_based/base/application_base_implementation.h"
#include "component_based/base/application_base.h"
#include "component_based/base/component_manager_internal.h"
LOGD("");
char* id = nullptr;
int r = app_get_id(&id);
- if (r != APP_ERROR_NONE) {
- LOGE("Failed to get application ID");
- return;
- }
+ if (r != APP_ERROR_NONE)
+ THROW(Exception::ErrorCodes::IOError);
auto p = std::unique_ptr<char, decltype(std::free)*>(id, std::free);
app_id_ = std::string(p.get());
auto comp_id = i->first;
auto factory = std::move(i->second);
auto& mgr = internal::ComponentManager::GetInst();
- mgr.RegisterComponent(std::move(comp_id), std::move(factory));
+ try {
+ mgr.RegisterComponent(std::move(comp_id), std::move(factory));
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ throw;
+ }
}
return true;
#include <memory>
+#include "component_based/common/exception.h"
#include "component_based/base/component.h"
#include "component_based/base/component_implementation.h"
#include "component_based/base/dlog_internal.h"
}
bool Component::Impl::OnCreate() {
- aul_comp_notify_start(inst_id_.c_str());
+ int ret = aul_comp_notify_start(inst_id_.c_str());
+ if (ret != AUL_R_OK) {
+ LOGE("Fail to start notify (%d)", ret);
+ return false;
+ }
if (parent_->GetType() == Component::Type::Frame) {
FrameComponent* component = static_cast<FrameComponent*>(parent_);
LOGE("OnCreate() returns nullptr");
return false;
}
+
auto& mgr = internal::ComponentManager::GetInst();
- mgr.Bind(component->GetInstanceID(), std::move(win));
- aul_comp_status_update(inst_id_.c_str(), STATUS_CREATED);
+ if (!mgr.Bind(component->GetInstanceID(), std::move(win))) {
+ LOGE("Bind window fail");
+ return false;
+ }
+
+ ret = aul_comp_status_update(inst_id_.c_str(), STATUS_CREATED);
+ if (ret != AUL_R_OK) {
+ LOGE("Fail to update status (%d)", ret);
+ return false;
+ }
+
} else {
ServiceComponent* component = static_cast<ServiceComponent*>(parent_);
bool r = component->OnCreate();
}
void Component::Impl::OnDestroy() {
- aul_comp_status_update(inst_id_.c_str(), STATUS_DYING);
+ int ret = aul_comp_status_update(inst_id_.c_str(), STATUS_DYING);
+ if (ret != AUL_R_OK) {
+ LOGE("Fail to update status (%d)", ret);
+ return;
+ }
+
state_ = State::Dying;
if (parent_->GetType() == Component::Type::Frame) {
FrameComponent* component = static_cast<FrameComponent*>(parent_);
return;
}
- act_map_[app_control_name] = std::unique_ptr<internal::Action>(
- new internal::Action(app_control_name, this));
+ try {
+ std::unique_ptr<internal::Action> action = std::unique_ptr<internal::Action>(
+ new (std::nothrow) internal::Action(app_control_name, this));
+ if (action.get() == nullptr)
+ THROW(Exception::ErrorCodes::OutOfMemory);
+ act_map_[app_control_name] = std::move(action);
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ throw;
+ }
}
-void Component::Impl::DeregisterAction(std::string app_control_name) {
+bool Component::Impl::DeregisterAction(std::string app_control_name) {
auto act_iter = act_map_.find(app_control_name);
if (act_iter == act_map_.end()) {
LOGW("Not found");
- return;
+ return false;
}
act_map_.erase(app_control_name);
+ return true;
}
void Component::Impl::OnAppControlReply(app_control_h request,
app_control_clone(&request_handle, request);
app_control_h reply_handle = nullptr;
app_control_clone(&reply_handle, reply);
- ev->OnReplyReceived(AppControl(request_handle), AppControl(reply_handle),
- static_cast<AppControl::Result>(result));
+ try {
+ ev->OnReplyReceived(AppControl(request_handle), AppControl(reply_handle),
+ static_cast<AppControl::Result>(result));
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ }
}
void Component::Impl::OnAppControlResult(app_control_h request,
static_cast<AppControl::IEventListener*>(user_data);
app_control_h request_handle = nullptr;
app_control_clone(&request_handle, request);
- ev->OnResultReceived(AppControl(request_handle),
- static_cast<AppControl::Error>(result));
+ try {
+ ev->OnResultReceived(AppControl(request_handle),
+ static_cast<AppControl::Error>(result));
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ }
}
void Component::Impl::SendAsync(AppControl control,
AppControl::IEventListener* ev) {
- if (ev == nullptr) {
- LOGE("Invalid parameter");
- return;
- }
+ if (ev == nullptr)
+ THROW(Exception::ErrorCodes::InvalidParameter);
app_control_h handle = control.GetHandle();
- if (handle == nullptr) {
- LOGE("Invalid parameter");
- return;
- }
+ if (handle == nullptr)
+ THROW(Exception::ErrorCodes::InvalidParameter);
int r = app_control_set_caller_instance_id(handle, inst_id_.c_str());
if (r != APP_CONTROL_ERROR_NONE) {
LOGE("Failed to set caller instance(%s)", inst_id_.c_str());
- return;
+ THROW(Exception::ErrorCodes::InvalidParameter);
}
r = app_control_send_launch_request_async(handle,
OnAppControlResult, OnAppControlReply, ev);
if (r != APP_CONTROL_ERROR_NONE) {
LOGE("Failed to send launch request async. err(%d)", r);
- return;
+ THROW(Exception::ErrorCodes::InvalidParameter);
}
}
AppControl Component::Impl::Send(AppControl control) {
app_control_h reply = nullptr;
app_control_h handle = control.GetHandle();
- if (handle == nullptr) {
- LOGE("Invalid parameter");
- return AppControl(reply);
- }
+ if (handle == nullptr)
+ THROW(Exception::ErrorCodes::InvalidParameter);
int r = app_control_set_caller_instance_id(handle, inst_id_.c_str());
if (r != APP_CONTROL_ERROR_NONE) {
LOGE("Failed to set caller instance(%s)", inst_id_.c_str());
- return AppControl(reply);
+ THROW(Exception::ErrorCodes::InvalidParameter);
}
app_control_result_e result;
r = app_control_send_launch_request_sync(handle, &reply, &result);
if (r != APP_CONTROL_ERROR_NONE) {
LOGE("Failed to send launch request sync. err(%d)", r);
- return AppControl(nullptr);
+ THROW(Exception::ErrorCodes::IOError);
+ }
+
+ try {
+ AppControl control(reply);
+ return control;
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ throw;
}
- LOGI("result(%d)", result);
- return AppControl(reply);
}
Component::Component(Component::Type type, std::string comp_id,
}
void Component::RegisterAction(std::string app_control_name) {
- impl_->RegisterAction(std::move(app_control_name));
+ try {
+ impl_->RegisterAction(std::move(app_control_name));
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ throw;
+ }
}
-void Component::DeregisterAction(std::string app_control_name) {
- impl_->DeregisterAction(std::move(app_control_name));
+bool Component::DeregisterAction(std::string app_control_name) {
+ return impl_->DeregisterAction(std::move(app_control_name));
}
void Component::SendAsync(AppControl control, AppControl::IEventListener* ev) {
- impl_->SendAsync(std::move(control), ev);
+ try {
+ impl_->SendAsync(std::move(control), ev);
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ throw;
+ }
}
AppControl Component::Send(AppControl control) {
- return impl_->Send(std::move(control));
+ try {
+ return impl_->Send(std::move(control));
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ throw;
+ }
}
} // namespace component_based
void Finish();
Type GetType();
void RegisterAction(std::string app_control_name);
- void DeregisterAction(std::string app_control_name);
+ bool DeregisterAction(std::string app_control_name);
void SendAsync(AppControl control, AppControl::IEventListener* ev);
AppControl Send(AppControl control);
void OnSuspendedStateChanged(SuspendedState::State state) override;
void RegisterAction(std::string app_control_name);
- void DeregisterAction(std::string app_control_name);
+ bool DeregisterAction(std::string app_control_name);
const Component::Type& GetType() {
return type_;
#include <memory>
#include <string>
+#include "component_based/common/exception.h"
#include "component_based/base/component_manager_internal.h"
#include "component_based/base/dlog_internal.h"
appcore_multiwindow_base_class cls =
appcore_multiwindow_base_class_get_default();
cls.id = strdup(comp_id.c_str());
+ if (cls.id == nullptr)
+ throw std::bad_alloc();
cls.data = this;
cls.create = OnCreateCB;
cls.terminate = OnTerminateCB;
}
std::unique_ptr<Component> component = fac_map_[comp_id]->Create(comp_id,
inst_id);
+ if (component == nullptr || component.get() == nullptr) {
+ LOGE("Fail to create component");
+ return;
+ }
inst_map_[inst_id] = std::move(component);
appcore_multiwindow_base_instance_run(comp_id.c_str(), inst_id.c_str(),
nullptr);
app_control_h handle = nullptr;
app_control_create_event(b, &handle);
- AppControl control(handle);
- ev_map_[inst_id]->OnStart(control, restarted);
+ try {
+ AppControl control(handle);
+ ev_map_[inst_id]->OnStart(control, restarted);
+ } catch(Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ }
}
void ComponentManager::Resume(std::string inst_id) {
}
}
-void ComponentManager::Bind(std::string inst_id, std::unique_ptr<IWindow> win) {
+bool ComponentManager::Bind(std::string inst_id, std::unique_ptr<IWindow> win) {
appcore_multiwindow_base_instance_h context =
appcore_multiwindow_base_instance_find(inst_id.c_str());
if (!context) {
LOGE("Failed to find instance(%s)", inst_id.c_str());
- return;
+ return false;
}
win_map_[inst_id] = std::move(win);
Ecore_Wl2_Window* wl_win = GetWl2Window(inst_id);
if (!wl_win) {
LOGE("Failed to get wayland window(%s)", inst_id.c_str());
- return;
+ return false;
}
appcore_multiwindow_base_window_bind(context, wl_win);
LOGI("Bind instance(%s)", inst_id.c_str());
+ return true;
}
void ComponentManager::Unbind(std::string inst_id) {
void Exit(std::string inst_id);
void ExitAll();
- void Bind(std::string inst_id, std::unique_ptr<IWindow> win);
+ bool Bind(std::string inst_id, std::unique_ptr<IWindow> win);
void Unbind(std::string inst_id);
std::string GetInstanceID(int win_id);
const IWindow* GetWindow(std::string inst_id);
+++ /dev/null
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
- *
- * 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.
- */
-
-#ifndef COMPONENT_BASED_BASE_EXCEPTION_H_
-#define COMPONENT_BASED_BASE_EXCEPTION_H_
-
-#include <app_types.h>
-
-#include <exception>
-#include <string>
-
-#define THROW(error_code) throw Exception(error_code, __FILE__, __LINE__)
-
-namespace component_based {
-
-class Exception : public std::exception {
- public:
- explicit Exception(int error_code, std::string file = __FILE__,
- int line = __LINE__ ) {
- error_code_ = error_code;
- message_ = file.substr(file.find_last_of("/") + 1) + ":"
- + std::to_string(line) + GetErrorString(error_code);
- }
- virtual ~Exception() {}
- virtual const char *what(void) const noexcept {
- return message_.c_str();
- }
- int GetErrorCode() {
- return error_code_;
- }
-
- private:
- int error_code_;
- std::string message_;
- std::string GetErrorString(int error_code) {
- switch (error_code) {
- case APP_ERROR_INVALID_PARAMETER:
- return ": INVALID_PARAMETER";
- case APP_ERROR_OUT_OF_MEMORY:
- return ": OUT_OF_MEMORY";
- case APP_ERROR_INVALID_CONTEXT:
- return ": INVALID_CONTEXT";
- case APP_ERROR_NO_SUCH_FILE:
- return ": NO_SUCH_FILE";
- case APP_ERROR_NOT_SUPPORTED:
- return ": NOT_SUPPORTED";
- case APP_ERROR_ALREADY_RUNNING:
- return ": ALREADY_RUNNING";
- case APP_ERROR_PERMISSION_DENIED:
- return ": PERMISSION_DENIED";
- default:
- return "";
- }
- }
-};
-
-} // namespace component_based
-
-#endif // COMPONENT_BASED_BASE_EXCEPTION_H_
std::unique_ptr<Component> Create(std::string comp_id,
std::string inst_id) override {
return std::unique_ptr<Component>(
- new FrameComponent(std::move(comp_id), std::move(inst_id)));
+ new (std::nothrow) FrameComponent(
+ std::move(comp_id), std::move(inst_id)));
}
};
std::unique_ptr<Component> Create(std::string comp_id,
std::string inst_id) override {
return std::unique_ptr<Component>(
- new ServiceComponent(std::move(comp_id), std::move(inst_id)));
+ new (std::nothrow) ServiceComponent(
+ std::move(comp_id), std::move(inst_id)));
}
};
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef COMPONENT_BASED_COMMON_EXCEPTION_H_
+#define COMPONENT_BASED_COMMON_EXCEPTION_H_
+
+#include <exception>
+#include <string>
+
+#define THROW(error_code) throw Exception(error_code, __FILE__, __LINE__)
+
+namespace component_based {
+
+class Exception : public std::exception {
+ public:
+ enum class ErrorCodes {
+ InvalidParameter,
+ OutOfMemory,
+ IOError,
+ };
+ explicit Exception(ErrorCodes error_code, std::string file = __FILE__,
+ int line = __LINE__ ) {
+ error_code_ = error_code;
+ message_ = file.substr(file.find_last_of("/") + 1) + ":"
+ + std::to_string(line) + GetErrorString(error_code);
+ }
+ virtual ~Exception() {}
+ virtual const char *what(void) const noexcept {
+ return message_.c_str();
+ }
+ ErrorCodes GetErrorCode() {
+ return error_code_;
+ }
+
+ private:
+ ErrorCodes error_code_;
+ std::string message_;
+ std::string GetErrorString(ErrorCodes error_code) {
+ switch (error_code) {
+ case ErrorCodes::InvalidParameter:
+ return ": INVALID_PARAMETER";
+ case ErrorCodes::OutOfMemory:
+ return ": OUT_OF_MEMORY";
+ case ErrorCodes::IOError:
+ return ": ERROR_IO_ERROR";
+ default:
+ return "";
+ }
+ }
+};
+
+} // namespace component_based
+
+#endif // COMPONENT_BASED_COMMON_EXCEPTION_H_
#include "component_based/efl_base/api/service_component.h"
#include "component_based/efl_base/api/component_based_app.h"
+#include "component_based/common/exception.h"
#include "component_based/efl_base/application.h"
#include "component_based/efl_base/elm_window.h"
std::map<std::string, std::unique_ptr<component_based::Component::Factory>>
OnCreate() override {
std::map<std::string, std::unique_ptr<component_based::Component::Factory>> facs;
- component_class_h h = nullptr;;
+ component_class_h h = nullptr;
if (cb_.create)
h = cb_.create(user_data_);
std::unique_ptr<component_based::Component> Create(std::string comp_id,
std::string inst_id) override {
return std::unique_ptr<component_based::Component>(
- new StubFrameComponent(std::move(comp_id), std::move(inst_id),
- cb_, user_data_));
+ new (std::nothrow) StubFrameComponent(
+ std::move(comp_id), std::move(inst_id), cb_, user_data_));
}
private:
std::unique_ptr<component_based::Component> Create(std::string comp_id,
std::string inst_id) override {
return std::unique_ptr<component_based::Component>(
- new StubServiceComponent(std::move(comp_id), std::move(inst_id),
- cb_, user_data_));
+ new (std::nothrow) StubServiceComponent(std::move(comp_id),
+ std::move(inst_id), cb_, user_data_));
}
private:
::ComponentClass* handle;
if (comp_class == nullptr) {
- handle = new ::ComponentClass();
+ handle = new (std::nothrow) ::ComponentClass();
if (handle == nullptr) {
LOGE("Out of memory");
set_last_result(APP_ERROR_OUT_OF_MEMORY);
component_based::Component* component =
static_cast<component_based::Component*>(h);
- component->RegisterAction(action);
+ try {
+ component->RegisterAction(action);
+ } catch (component_based::Exception& ex) {
+ LOGE("Exception occurred (%s)", ex.what());
+ return COMPONENT_ERROR_INVALID_CONTEXT;
+ }
return COMPONENT_ERROR_NONE;
}
component_based::Component* component =
static_cast<component_based::Component*>(h);
- component->DeregisterAction(action);
+ if (!component->DeregisterAction(action)) {
+ LOGE("Deregister fail");
+ return COMPONENT_ERROR_INVALID_PARAMETER;
+ }
return COMPONENT_ERROR_NONE;
}
r = app_control_send_launch_request_sync(app_control, reply, result);
if (r != APP_CONTROL_ERROR_NONE) {
- LOGE("Failed to send launch request async. error(%d)", r);
+ LOGE("Failed to send launch request sync. error(%d)", r);
return __app_control_error_convert(r);
}
void TearDown() override {}
};
+class TestListener : public component_based::AppControl::IEventListener {
+ public:
+ void OnResultReceived(component_based::AppControl request,
+ component_based::AppControl::Error error) {
+ }
+ void OnReplyReceived(component_based::AppControl request,
+ component_based::AppControl reply,
+ component_based::AppControl::Result result) {
+ }
+};
+
int __fake_app_get_display_state(app_display_state_e* state) {
*state = APP_DISPLAY_STATE_ON;
return 0;
builder->SetComponentID("ElmFrame");
component_based::AppControl ctrl = builder->Build();
- component_based::AppControl::IEventListener* ev = nullptr;
- fc->SendAsync(ctrl, ev);
+ std::unique_ptr<TestListener> listener =
+ std::unique_ptr<TestListener>(new TestListener());
+ fc->SendAsync(ctrl, listener.get());
fc->Send(ctrl);
}