atspi-2
capi-ui-efl-util
efl-extension
+ gobject-2.0
+ eldbus
)
SET(COMMON_FLAGS "-fdiagnostics-color=always -fPIC")
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(efl-extension)
BuildRequires: pkgconfig(capi-ui-efl-util)
+BuildRequires: pkgconfig(gobject-2.0)
+BuildRequires: pkgconfig(eldbus)
#Required for tests
BuildRequires: net-config
--- /dev/null
+#include "Atspi.hpp"
+
+#include <Eldbus.h>
+#include <functional>
+
+#define GERROR_CHECK(error) \
+ if (error) \
+ { \
+ ERROR("Error: %s", error->message); \
+ g_error_free(error); \
+ error = nullptr; \
+ }
+
+namespace
+{
+ template<class ReturnType, class GetValueFunctionType, class InterfaceType>
+ Optional<ReturnType> getValueTemplateFunction(GetValueFunctionType getValueFunction, InterfaceType interface)
+ {
+ GError *error = nullptr;
+ ReturnType value = getValueFunction(interface, &error);
+ if (!error)
+ return value;
+ else {
+ GERROR_CHECK(error);
+ return {};
+ }
+ }
+
+ bool _dbus_set_property_bool(Eldbus_Connection_Type connection_type,
+ const char *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ bool value)
+ {
+ eldbus_init();
+
+ Eldbus_Connection *conn = eldbus_connection_get(connection_type);
+ if (!conn) {
+ ERROR("Connection to dbus failed");
+ return false;
+ }
+
+ Eldbus_Object *dobj = eldbus_object_get(conn, bus, path);
+ eldbus_connection_unref(conn);
+ if (!dobj) {
+ ERROR("Failed to create eldbus object");
+ eldbus_shutdown();
+ return false;
+ }
+
+ Eldbus_Proxy *proxy = eldbus_proxy_get(dobj, "org.freedesktop.DBus.Properties");
+ eldbus_object_unref(dobj);
+ if (!proxy) {
+ ERROR("Failed to create proxy object for 'org.freedesktop.DBus.Properties'");
+ eldbus_shutdown();
+ return false;
+ }
+
+ Eldbus_Message *req = eldbus_proxy_method_call_new(proxy, "Set");
+ if (!req) {
+ ERROR("Failed to create method call on org.freedesktop.DBus.Properties.Set");
+ eldbus_shutdown();
+ return false;
+ }
+ eldbus_message_ref(req);
+ bool ret = false;
+ if (eldbus_message_arguments_append(req, "ss", interface, property)) {
+ Eldbus_Message_Iter *iter = eldbus_message_iter_container_new(eldbus_message_iter_get(req), 'v', "b");
+ if (iter) {
+ if (eldbus_message_iter_arguments_append(iter, "b", value)) {
+ if (eldbus_message_iter_container_close(eldbus_message_iter_get(req), iter)) {
+ eldbus_proxy_send(proxy, req, NULL, NULL, -1.0);
+ ret = true;
+ } else
+ ERROR("Failed to close variant iterator");
+ } else
+ ERROR("Unable to append to variant iterator");
+ } else
+ ERROR("Unable to create variant iterator");
+ } else
+ ERROR("Failed to append message args");
+ eldbus_message_unref(req);
+
+ eldbus_shutdown();
+ return ret;
+ }
+}
+
+bool Atspi::ConnectAtClient()
+{
+ auto error = atspi_init();
+ if (error != 0 || error != 1) {
+ ERROR("Error code %d", error);
+ return false;
+ }
+
+ auto dbusStatus = _dbus_set_property_bool(ELDBUS_CONNECTION_TYPE_SESSION, "org.a11y.Bus", "/org/a11y/bus", "org.a11y.Status", "IsEnabled", true);
+ if (!dbusStatus) {
+ ERROR("IsEnabled flag set to true procedure failed");
+ return false;
+ }
+
+ if (error == 1)
+ DEBUG("Atspi already initialized");
+ return true;
+}
+
+bool Atspi::DisconnectAtClient()
+{
+ auto dbusStatus = _dbus_set_property_bool(ELDBUS_CONNECTION_TYPE_SESSION, "org.a11y.Bus", "/org/a11y/bus", "org.a11y.Status", "IsEnabled", false);
+ if (!dbusStatus)
+ ERROR("IsEnabled flag set to false procedure failed");
+
+ auto error = atspi_exit();
+ if (error) {
+ ERROR("Memory leak detected. Error code %d", error);
+ return false;
+ }
+ return true;
+}
+
+Optional<std::shared_ptr<AtspiAction>> Atspi::getActionInterface(std::shared_ptr<AtspiAccessible> accessibleObj)
+{
+ auto action = atspi_accessible_get_action_iface(accessibleObj.get());
+ if (action)
+ return std::shared_ptr<AtspiAction> {action, g_object_unref};
+ DEBUG("Action interface is not available");
+ return {};
+}
+
+bool Atspi::doAction(std::shared_ptr<AtspiAction> accessibleObj, int action)
+{
+ GError *error = nullptr;
+ auto status = atspi_action_do_action(accessibleObj.get(), action, &error);
+ GERROR_CHECK(error);
+ if (status)
+ return true;
+
+ DEBUG("Action execution failure");
+ return false;
+}
+
+bool Atspi::doActionName(std::shared_ptr<AtspiAction> accessibleObj, const std::string &action)
+{
+ GError *error = nullptr;
+ auto status = atspi_action_do_action_name(accessibleObj.get(), action.c_str(), &error);
+ GERROR_CHECK(error)
+ if (status)
+ return true;
+
+ DEBUG("Action by name execution failure");
+ return false;
+}
+
+Optional<std::shared_ptr<AtspiAccessible>> Atspi::getObjectInRelation(std::shared_ptr<AtspiAccessible> accessibleObj, AtspiRelationType searchType)
+{
+ if (!accessibleObj) {
+ ERROR("accessibleObj is nullptr");
+ return {};
+ }
+
+ GError *error = nullptr;
+ auto relations = atspi_accessible_get_relation_set(accessibleObj.get(), &error);
+ GERROR_CHECK(error);
+ if (!relations) {
+ DEBUG("Relation set do not exist");
+ return {};
+ }
+
+ DEBUG("Relations found: %d", relations->len);
+ AtspiAccessible *relationObj = nullptr;
+ for (unsigned i = 0; i < relations->len; ++i) {
+ AtspiRelation *relation = g_array_index(relations, AtspiRelation *, i);
+ auto type = atspi_relation_get_relation_type(relation);
+ DEBUG("Relation type: %d", type);
+
+ if (type == searchType) {
+ DEBUG("Searched relation found");
+ relationObj = atspi_relation_get_target(relation, 0);
+ break;
+ }
+ }
+ g_array_free(relations, TRUE);
+ if (relationObj)
+ return std::shared_ptr<AtspiAccessible> {relationObj, g_object_unref};
+ return {};
+}
+
+Optional<std::shared_ptr<AtspiValue>> Atspi::getValueInterface(std::shared_ptr<AtspiAccessible> accessibleObj)
+{
+ auto valueInterface = atspi_accessible_get_value_iface(accessibleObj.get());
+ if (valueInterface)
+ return std::shared_ptr<AtspiValue> {valueInterface, g_object_unref};
+ else {
+ DEBUG("Object %p do not has value interface", accessibleObj.get());
+ return {};
+ }
+}
+
+Optional<double> Atspi::getCurrentValue(std::shared_ptr<AtspiValue> valueInterface)
+{
+ return getValueTemplateFunction<double>(atspi_value_get_current_value, valueInterface.get());
+}
+
+bool Atspi::setCurrentValue(std::shared_ptr<AtspiValue> valueInterface, double newValue)
+{
+ GError *error = nullptr;
+ auto isSuccessful = atspi_value_set_current_value(valueInterface.get(), newValue, &error);
+ GERROR_CHECK(error);
+ if (isSuccessful)
+ return true;
+ else
+ return false;
+}
+
+Optional<double> Atspi::getMinimumIncrement(std::shared_ptr<AtspiValue> valueInterface)
+{
+ return getValueTemplateFunction<double>(atspi_value_get_minimum_increment, valueInterface.get());
+}
+
+Optional<double> Atspi::getMaximumValue(std::shared_ptr<AtspiValue> valueInterface)
+{
+ return getValueTemplateFunction<double>(atspi_value_get_maximum_value, valueInterface.get());
+}
+
+Optional<double> Atspi::getMinimumValue(std::shared_ptr<AtspiValue> valueInterface)
+{
+ return getValueTemplateFunction<double>(atspi_value_get_minimum_value, valueInterface.get());
+}
--- /dev/null
+#ifndef ATSPI_ADAPTER_HPP
+#define ATSTI_ADAPTER_HPP
+
+#include "Optional.hpp"
+
+#include <atspi/atspi.h>
+#include <memory>
+
+namespace Atspi
+{
+ bool ConnectAtClient();
+ bool DisconnectAtClient();
+
+ Optional<std::shared_ptr<AtspiAction>> getActionInterface(std::shared_ptr<AtspiAccessible> accessibleObj);
+ bool doAction(std::shared_ptr<AtspiAction> accessibleObj, int action);
+ bool doActionName(std::shared_ptr<AtspiAction> accessibleObj, const std::string &action);
+
+ Optional<std::shared_ptr<AtspiAccessible>> getObjectInRelation(std::shared_ptr<AtspiAccessible> accessibleObj, AtspiRelationType searchType);
+
+ Optional<std::shared_ptr<AtspiValue>> getValueInterface(std::shared_ptr<AtspiAccessible> accessibleObj);
+ Optional<double> getCurrentValue(std::shared_ptr<AtspiValue> valueInterface);
+ bool setCurrentValue(std::shared_ptr<AtspiValue> valueInterface, double newValue);
+ Optional<double> getMinimumIncrement(std::shared_ptr<AtspiValue> valueInterface);
+ Optional<double> getMaximumValue(std::shared_ptr<AtspiValue> valueInterface);
+ Optional<double> getMinimumValue(std::shared_ptr<AtspiValue> valueInterface);
+}
+
+#endif
ActivityChangeRequest.cpp
AutoScanOnActivity.cpp
MenuBuilder.cpp
+ Atspi.cpp
)
ADD_LIBRARY(universal-switch-obj OBJECT ${SRCS})
--- /dev/null
+#ifndef OPTIONAL_HPP
+#define OPTIONAL_HPP
+
+/*
+ * After project conversion to C++17 standard this template class will be deleted
+ *
+ * Allowed operations (note, to make code simplier, than original, value class must have accessible copy and move constructor):
+ * - constructing empty (valueless) object
+ * - copying Optional (with and without value)
+ * - moving Optional (with and without value)
+ * - querying, if Optional has value (via explicit operator bool), for example:
+ * Optional<int> v = ...;
+ * if (v) ... // if v has value, then do something
+ * - accessing value (via operator *), for example:
+ * Optional<int> v = ...;
+ * auto z = *v; // z now has the same int, as v (copied)
+ * auto &y = *v; // y now has REFERENCe to int inside v, so modying y modifies v
+ */
+
+#include "UniversalSwitchLog.hpp"
+
+#include <new>
+#include <utility>
+#include <type_traits>
+
+template <typename A>
+class Optional
+{
+ union {
+ A place;
+ };
+ bool hasValue = false;
+public:
+ Optional() {}
+
+ template < typename U = A, typename std::enable_if <
+ std::is_convertible < U &&, A >::value &&
+ std::is_constructible < A, U && >::value &&
+ !std::is_same<typename std::decay<U>::type, Optional<A>>::value
+ , int * >::type = nullptr > constexpr Optional(U && a)
+ : place(std::forward<U>(a)), hasValue(true)
+ {
+ }
+
+ template < typename U = A, typename std::enable_if <
+ !std::is_convertible < U &&, A >::value &&
+ std::is_constructible < A, U && >::value &&
+ !std::is_same<typename std::decay<U>::type, Optional<A>>::value
+ , int * >::type = nullptr > explicit constexpr Optional(U && a)
+ : place(std::forward<U>(a)), hasValue(true)
+ {
+ }
+
+ Optional(const Optional &v) : place(v.place), hasValue(v.hasValue)
+ {
+ }
+
+ Optional(Optional &&v) : place(std::move(v.place)), hasValue(v.hasValue)
+ {
+ }
+
+ ~Optional()
+ {
+ if (hasValue) {
+ place.~A();
+ }
+ }
+
+ explicit operator bool () const
+ {
+ return hasValue;
+ }
+
+ A &operator * ()
+ {
+ ASSERT(hasValue, "Object is not initialized");
+ return place;
+ }
+
+ const A &operator * () const
+ {
+ ASSERT(hasValue, "Object is not initialized");
+ return place;
+ }
+
+ A *operator -> ()
+ {
+ ASSERT(hasValue, "Object is not initialized");
+ return &place;
+ }
+
+ const A *operator -> () const
+ {
+ ASSERT(hasValue, "Object is not initialized");
+ return &place;
+ }
+
+ Optional &operator = (const Optional &v)
+ {
+ if (this != &v) {
+ if (hasValue != v.hasValue) {
+ if (v.hasValue) new (&place) A(v.place);
+ else place.~A();
+ hasValue = v.hasValue;
+ } else if (hasValue) {
+ place.~A();
+ new (&place) A(v.place);
+ }
+ }
+ return *this;
+ }
+
+ Optional &operator = (Optional &&v)
+ {
+ if (this != &v) {
+ if (hasValue != v.hasValue) {
+ if (v.hasValue) new (&place) A(std::move(v.place));
+ else place.~A();
+ hasValue = v.hasValue;
+ } else if (hasValue) {
+ place.~A();
+ new (&place) A(std::move(v.place));
+ }
+ }
+ return *this;
+ }
+
+ template <typename U = A>
+ typename std::enable_if <
+ !std::is_same<typename std::decay<U>::type, Optional<A>>::value &&
+ std::is_constructible<A, U>::value &&
+ std::is_assignable<A &, U>::value &&
+ (!std::is_scalar<A>::value || !std::is_same<typename std::decay<U>, A>::value)
+ , Optional & >::type operator = (U && a)
+ {
+ if (hasValue)
+ place.~A();
+ else
+ hasValue = true;
+ new (&place) A(std::forward<U>(a));
+ return *this;
+ }
+};
+
+#endif
#include "UniversalSwitchLog.hpp"
#include "Window.hpp"
#include "ScreenScannerManager.hpp"
+#include "Atspi.hpp"
#include <tizen.h>
#include <app.h>
#include <Elementary.h>
-#include <vconf.h>
-
static void _setting_time_lang_changed(app_event_info_h event_info, void *data)
{
bool app_create(void *data)
{
DEBUG("App create");
+ Atspi::ConnectAtClient();
return true;
}
void app_terminate(void *data)
{
DEBUG("app termination procedure");
+ Atspi::DisconnectAtClient();
return;
}
INSTALL(PROGRAMS VConf_init.sh DESTINATION ${TESTS_INSTALL_DIR})
CREATE_TEST(VConfImplTests.cpp)
+CREATE_TEST(OptionalTests.cpp)
CREATE_TEST(ConfigurationTests.cpp)
CREATE_TEST(ActivityProcessingTests.cpp)
CREATE_TEST(MenuBuilderTests.cpp)
-
--- /dev/null
+#include "Optional.hpp"
+
+#include <gtest/gtest.h>
+
+class OptionalTestsFixture : public ::testing::Test
+{
+public:
+ struct AA {
+ AA() = default;
+ int value = 10;
+ };
+
+ class ClassWithCounters
+ {
+ public:
+ ClassWithCounters(int a)
+ : value(std::move(a))
+ {
+ ++constructorCallsCount;
+ }
+
+ ClassWithCounters(const ClassWithCounters &other)
+ : value(other.value)
+ {
+ ++constructorCallsCount;
+ }
+
+ ClassWithCounters(ClassWithCounters &&other)
+ : value(std::move(other.value))
+ {
+ ++constructorCallsCount;
+ }
+
+ ClassWithCounters(const Optional<ClassWithCounters> &other)
+ {
+ ++constructorCallsCount;
+ if (other)
+ value = other->value;
+ }
+
+ explicit ClassWithCounters(const AA &other)
+ {
+ ++constructorCallsCount;
+ value = other.value;
+ }
+
+ ~ClassWithCounters()
+ {
+ ++destructorCallsCount;
+ }
+
+ ClassWithCounters &operator = (const ClassWithCounters &other)
+ {
+ if (this != &other) {
+ value = other.value;
+ }
+ return *this;
+ }
+
+ static int constructorCallsCount;
+ static int destructorCallsCount;
+ int value = 0;
+ };
+
+ void SetUp()
+ {
+ ClassWithCounters::constructorCallsCount = 0;
+ ClassWithCounters::destructorCallsCount = 0;
+ }
+
+ void SetExpects(int constructorCalls, int destructorCalls)
+ {
+ EXPECT_EQ(ClassWithCounters::constructorCallsCount, constructorCalls) << "Wrong number of constructor calls";
+ EXPECT_EQ(ClassWithCounters::destructorCallsCount, destructorCalls) << "Wrong number of destructor calls";
+ }
+
+};
+int OptionalTestsFixture::ClassWithCounters::constructorCallsCount = 0;
+int OptionalTestsFixture::ClassWithCounters::destructorCallsCount = 0;
+
+TEST(OptionalTests, OptionalToBoolConversionChecking)
+{
+ auto emptyOptional = Optional<int> {};
+ EXPECT_FALSE(emptyOptional) << "Optional should return false if not initialized";
+ auto notEmptyOptional = Optional<int> {5};
+ EXPECT_TRUE(notEmptyOptional) << "Optional should return true if initialized";
+}
+
+TEST(OptionalTests, ValueStorageChecking)
+{
+ auto a = Optional<int> {5};
+ EXPECT_EQ(*a, 5);
+ const auto b = Optional<int> {5};
+ EXPECT_EQ(*b, 5);
+ auto c = Optional<double> {5.0};
+ EXPECT_EQ(*c, 5.0);
+ auto d = Optional<std::string> {"TIZEN"};
+ EXPECT_EQ(*d, "TIZEN");
+}
+
+TEST(OptionalTests, ConstructorChecking_FromValue)
+{
+ Optional<int> a{5};
+ ASSERT_TRUE(a);
+ EXPECT_EQ(*a, 5);
+}
+
+TEST_F(OptionalTestsFixture, ConstructorChecking_FromTypeWithoutCast)
+{
+ auto u = AA {};
+ Optional<ClassWithCounters> a{u};
+ EXPECT_EQ(u.value, 10);
+ ASSERT_TRUE(a);
+ EXPECT_EQ(a->value, 10);
+ SetExpects(1, 0);
+}
+
+TEST(OptionalTests, CopyConstructorChecking_FromEmptyOptional)
+{
+ auto original = Optional<int> {};
+ auto copy = original;
+ ASSERT_FALSE(original);
+ ASSERT_FALSE(copy);
+}
+
+TEST(OptionalTests, CopyConstructorChecking_FromValidOptional)
+{
+ auto original = Optional<int> {5};
+ auto copy = original;
+ ASSERT_TRUE(original);
+ EXPECT_EQ(*original, 5);
+ ASSERT_TRUE(copy);
+ EXPECT_EQ(*copy, 5);
+}
+
+TEST(OptionalTests, MoveConstructorChecking_FromEmptyOptional)
+{
+ auto original = Optional<int> {};
+ auto copy{std::move(original)};
+ ASSERT_FALSE(original);
+ ASSERT_FALSE(copy);
+}
+
+TEST(OptionalTests, MoveConstructorChecking_FromValidOptional)
+{
+ auto original = Optional<int> {5};
+ auto copy{std::move(original)};
+ ASSERT_TRUE(copy);
+ ASSERT_EQ(*copy, 5);
+}
+
+TEST_F(OptionalTestsFixture, DestructorChecking_EmptyOptional)
+{
+ auto a = Optional<ClassWithCounters> {};
+ a.~Optional();
+ SetExpects(0, 0);
+}
+
+TEST_F(OptionalTestsFixture, DestructorChecking_ValidOptional)
+{
+ auto a = Optional<ClassWithCounters> {5};
+ a.~Optional();
+ SetExpects(1, 1);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentOperatorChecking_SameObjectEmptyOptional)
+{
+ auto a = Optional<ClassWithCounters> {};
+ a = a;
+ ASSERT_FALSE(a);
+ SetExpects(0, 0);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentOperatorChecking_SameObjectValidOptional)
+{
+ auto a = Optional<ClassWithCounters> {5};
+ a = a;
+ ASSERT_TRUE(a);
+ EXPECT_EQ(a->value, 5);
+ SetExpects(1, 0);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentOperatorChecking_FromEmptyToValid)
+{
+ auto a = Optional<ClassWithCounters> {};
+ auto b = Optional<ClassWithCounters> {7};
+ b = a;
+ ASSERT_FALSE(a);
+ ASSERT_FALSE(b);
+ SetExpects(1, 1);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentOperatorChecking_FromValidToValid)
+{
+ auto a = Optional<ClassWithCounters> {5};
+ auto b = Optional<ClassWithCounters> {7};
+ SetExpects(2, 0);
+ b = a;
+ ASSERT_TRUE(a);
+ EXPECT_EQ(a->value, 5);
+ ASSERT_TRUE(b);
+ EXPECT_EQ(b->value, 5);
+ SetExpects(3, 1);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentOperatorChecking_FromValidToEmpty)
+{
+ auto a = Optional<ClassWithCounters> {5};
+ auto b = Optional<ClassWithCounters> {};
+ b = a;
+ ASSERT_TRUE(a);
+ EXPECT_EQ(a->value, 5);
+ ASSERT_TRUE(b);
+ EXPECT_EQ(b->value, 5);
+ SetExpects(2, 0);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentMoveOperatorChecking_SameObjectEmptyOptional)
+{
+ auto a = Optional<ClassWithCounters> {};
+ a = std::move(a);
+ ASSERT_FALSE(a);
+ SetExpects(0, 0);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentMoveOperatorChecking_SameObjectValidOptional)
+{
+ auto a = Optional<ClassWithCounters> {5};
+ a = std::move(a);
+ ASSERT_TRUE(a);
+ EXPECT_EQ(a->value, 5);
+ SetExpects(1, 0);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentMoveOperatorChecking_FromEmptyToValid)
+{
+ auto a = Optional<ClassWithCounters> {};
+ auto b = Optional<ClassWithCounters> {7};
+ b = std::move(a);
+ ASSERT_FALSE(a);
+ ASSERT_FALSE(b);
+ SetExpects(1, 1);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentMoveOperatorChecking_FromValidToValid)
+{
+ auto a = Optional<ClassWithCounters> {5};
+ auto b = Optional<ClassWithCounters> {7};
+ b = std::move(a);
+ ASSERT_TRUE(a);
+ EXPECT_EQ(a->value, 5);
+ ASSERT_TRUE(b);
+ EXPECT_EQ(b->value, 5);
+ SetExpects(3, 1);
+}
+
+TEST_F(OptionalTestsFixture, AssignmentMoveOperatorChecking_FromValidToEmpty)
+{
+ auto a = Optional<ClassWithCounters> {5};
+ auto b = Optional<ClassWithCounters> {};
+ b = std::move(a);
+ EXPECT_TRUE(a);
+ EXPECT_EQ(a->value, 5);
+ EXPECT_TRUE(b);
+ EXPECT_EQ(b->value, 5);
+ SetExpects(2, 0);
+}
+
+TEST_F(OptionalTestsFixture, ValueAssignmentOperatorChecking_FromValidToEmpty)
+{
+ auto a = ClassWithCounters {5};
+ auto b = Optional<ClassWithCounters> {};
+ b = a;
+ EXPECT_EQ(a.value, 5);
+ EXPECT_TRUE(b);
+ EXPECT_EQ(b->value, 5);
+ SetExpects(2, 0);
+}
+
+TEST_F(OptionalTestsFixture, ValueAssignmentOperatorChecking_FromValidToValid)
+{
+ auto a = ClassWithCounters {5};
+ auto b = Optional<ClassWithCounters> {7};
+ b = a;
+ EXPECT_EQ(a.value, 5);
+ EXPECT_TRUE(b);
+ EXPECT_EQ(b->value, 5);
+ SetExpects(3, 1);
+}