[Merge] lp:~boiko/telephony-service/non_phone_accounts_tests into lp:telephony-service

Tiago Salem Herrmann tiago.herrmann at canonical.com
Mon Mar 30 18:45:00 UTC 2015


Review: Needs Fixing



Diff comments:

> === modified file '.bzrignore'
> --- .bzrignore	2014-01-07 19:53:45 +0000
> +++ .bzrignore	2015-03-27 02:49:31 +0000
> @@ -32,19 +32,22 @@
>  handler/handleradaptor.*
>  indicator/*.desktop
>  indicator/*.service
> +indicator/NotificationsInterface.*
>  
>  Testing
> -Ubuntu/Telephony/tests/*Test
>  Ubuntu/Telephony/qmldir
> -libtelephonyservice/tests/*Test
>  CTestTestfile.cmake
>  test_*.xml
> +cmake_uninstall.cmake
>  
>  coverage*
>  
>  po/*.gmo
>  
> -handler/tests/HandlerTest
> -handler/tests/dbus-test-wrapper.sh
> -handler/tests/mock/mockconnectionadaptor.*
> -handler/tests/mock/telepathy-mock
> +tests/*/*Test
> +tests/common/dbus-test-wrapper.sh
> +tests/common/mock/mockconnectionadaptor.*
> +tests/common/mock/telepathy-mock
> +tests/Ubuntu.Telephony/ContactWatcherTest
> +tests/libtelephonyservice/GreeterContactsTestExe
> +tests/libtelephonyservice/GreeterContactsTestServerExe
> 
> === modified file 'CMakeLists.txt'
> --- CMakeLists.txt	2014-08-05 20:04:00 +0000
> +++ CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -9,23 +9,6 @@
>  include(CheckIncludeFileCXX)
>  include(CheckIncludeFile)
>  
> -include(EnableCoverageReport)
> -#####################################################################
> -# Enable code coverage calculation with gcov/gcovr/lcov
> -# Usage:
> -#  * Switch build type to coverage (use ccmake or cmake-gui)
> -#  * Invoke make, make test, make coverage
> -#  * Find html report in subdir coveragereport
> -#  * Find xml report feasible for jenkins in coverage.xml
> -#####################################################################
> -IF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE])
> -  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs" )
> -  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs" )
> -  SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -coverage" )
> -  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -coverage" )
> -  ENABLE_COVERAGE_REPORT(TARGETS ${PHONE_APP})
> -ENDIF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE])
> -
>  # Instruct CMake to run moc automatically when needed.
>  set(CMAKE_AUTOMOC ON)
>  
> @@ -36,8 +19,6 @@
>      add_definitions(-DUSE_UBUNTU_PLATFORM_API)
>  endif (USE_UBUNTU_PLATFORM_API)
>  
> -find_program(DBUS_RUNNER dbus-test-runner)
> -
>  set(TELEPHONY_SERVICE_DIR ${CMAKE_INSTALL_DATADIR}/telephony-service)
>  
>  configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)
> @@ -81,6 +62,14 @@
>      ${CMAKE_CURRENT_SOURCE_DIR}
>      )
>  
> +# generate a macro to make it easier to enable coverage support on targets
> +function(ENABLE_COVERAGE)
> +    get_directory_property(COVERAGE_TARGETS DIRECTORY ${CMAKE_SOURCE_DIR} COVERAGE_TARGETS)
> +    list(APPEND COVERAGE_TARGETS ${ARGN})
> +    MESSAGE(STATUS "Enabling coverage report for target(s): ${ARGN}")
> +    set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY COVERAGE_TARGETS ${COVERAGE_TARGETS})
> +endfunction()
> +
>  enable_testing()
>  
>  add_definitions(-std=c++11)
> @@ -98,3 +87,24 @@
>  add_subdirectory(tools)
>  add_subdirectory(icons)
>  add_subdirectory(po)
> +add_subdirectory(tests)
> +
> +include(EnableCoverageReport)
> +#####################################################################
> +# Enable code coverage calculation with gcov/gcovr/lcov
> +# Usage:
> +#  * Switch build type to coverage (use ccmake or cmake-gui)
> +#  * Invoke make, make test, make coverage
> +#  * Find html report in subdir coveragereport
> +#  * Find xml report feasible for jenkins in coverage.xml
> +#####################################################################
> +IF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE])
> +  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs" )
> +  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs" )
> +  SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -coverage" )
> +  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -coverage" )
> +  GET_DIRECTORY_PROPERTY(COVERAGE_TARGETS DIRECTORY ${CMAKE_SOURCE_DIR} COVERAGE_TARGETS)
> +  ENABLE_COVERAGE_REPORT(TARGETS ${COVERAGE_TARGETS})
> +ENDIF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE])
> +
> +
> 
> === modified file 'Ubuntu/Telephony/CMakeLists.txt'
> --- Ubuntu/Telephony/CMakeLists.txt	2014-04-23 20:55:13 +0000
> +++ Ubuntu/Telephony/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -19,10 +19,11 @@
>      telephonyservice
>      )
>  
> +enable_coverage(telephonyservice-qml)
> +
>  configure_file(qmldir.in ${CMAKE_CURRENT_BINARY_DIR}/qmldir)
>  set(PLUGIN_DIR ${QT_INSTALL_QML}/Ubuntu/Telephony)
>  install(TARGETS telephonyservice-qml DESTINATION ${PLUGIN_DIR})
>  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qmldir DESTINATION ${PLUGIN_DIR})
>  
>  add_subdirectory(PhoneNumber)
> -add_subdirectory(tests)
> 
> === modified file 'Ubuntu/Telephony/contactwatcher.cpp'
> --- Ubuntu/Telephony/contactwatcher.cpp	2015-03-27 02:49:31 +0000
> +++ Ubuntu/Telephony/contactwatcher.cpp	2015-03-27 02:49:31 +0000
> @@ -219,6 +219,10 @@
>  void ContactWatcher::setAddressableFields(const QStringList &fields)
>  {
>      mAddressableFields = fields;
> +    // if the addressable fields is empty, fall back to matching phone numbers
> +    if (mAddressableFields.isEmpty()) {
> +            mAddressableFields << "tel";
> +    }
>      Q_EMIT addressableFieldsChanged();
>  
>      startSearching();
> 
> === modified file 'approver/CMakeLists.txt'
> --- approver/CMakeLists.txt	2014-07-06 16:19:49 +0000
> +++ approver/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -25,6 +25,8 @@
>      telephonyservice
>      )
>  
> +enable_coverage(telephony-service-approver)
> +
>  configure_file(org.freedesktop.Telepathy.Client.TelephonyServiceApprover.service.in org.freedesktop.Telepathy.Client.TelephonyServiceApprover.service)
>  install(TARGETS telephony-service-approver RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
>  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.TelephonyServiceApprover.service DESTINATION share/dbus-1/services)
> 
> === added file 'cmake/modules/GenerateTest.cmake'
> --- cmake/modules/GenerateTest.cmake	1970-01-01 00:00:00 +0000
> +++ cmake/modules/GenerateTest.cmake	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,133 @@
> +#
> +# Copyright (C) 2015 Canonical, Ltd.
> +#
> +# Authors:
> +#  Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> +#
> +# This file is part of telephony-service.
> +#
> +# telephony-service is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; version 3.
> +#
> +# telephony-service is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +#
> +
> +include(CMakeParseArguments)
> +find_program(DBUS_RUNNER dbus-test-runner)
> +
> +function(generate_test TESTNAME)
> +    set(options USE_DBUS USE_UI)
> +    set(oneValueArgs TIMEOUT WORKING_DIRECTORY QML_TEST WAIT_FOR)
> +    set(multiValueArgs TASKS LIBRARIES QT5_MODULES SOURCES ENVIRONMENT)
> +    cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
> +
> +    MESSAGE(STATUS "Adding test: ${TESTNAME}")
> +
> +    # set reasonable defaults for the arguments
> +    if (NOT DEFINED ARG_WORKING_DIRECTORY)
> +        set(ARG_WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
> +    endif ()
> +
> +    if (NOT DEFINED ARG_TIMEOUT)
> +        set(ARG_TIMEOUT 30)
> +    endif ()
> +
> +    if (NOT DEFINED ARG_QT5_MODULES)
> +        set(ARG_QT5_MODULES Core Test)
> +    endif ()
> +
> +    if (${ARG_USE_UI})
> +        if (${ARG_USE_DBUS})
> +            set(PLATFORM -p -platform -p offscreen)
> +        else ()
> +            set(PLATFORM -platform offscreen)
> +        endif ()
> +    endif()
> +
> +    # Generate QML tests
> +    if (DEFINED ARG_QML_TEST)
> +        add_test(NAME ${TESTNAME}
> +            WORKING_DIRECTORY ${ARG_WORKING_DIRECTORY}
> +            COMMAND qmltestrunner -platform offscreen -import ${CMAKE_BINARY_DIR} -input ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_QML_TEST})
> +        set_tests_properties(${TESTNAME} PROPERTIES ENVIRONMENT "QT_QPA_FONTDIR=${CMAKE_BINARY_DIR}")
> +    else ()
> +        # For sanity checking, make sure DBUS_RUNNER is available for DBUS tests
> +        if (${ARG_USE_DBUS} AND "${DBUS_RUNNER}" STREQUAL "")
> +            message(WARNING "Test ${TESTNAME} disabled because dbus-test-runner was not found.")
> +            return()
> +        endif ()
> +
> +        # No QML test, regular binary compiled test.
> +        add_executable(${TESTNAME} ${ARG_SOURCES})
> +        qt5_use_modules(${TESTNAME} ${ARG_QT5_MODULES})
> +
> +        if (${ARG_USE_DBUS})
> +            execute_process(COMMAND mktemp -d OUTPUT_VARIABLE TMPDIR)
> +            string(REPLACE "\n" "" TMPDIR ${TMPDIR})
> +
> +            if (NOT DEFINED ARG_ENVIRONMENT)
> +                set(ARG_ENVIRONMENT HOME=${TMPDIR}
> +                                    HISTORY_SQLITE_DBPATH=:memory:
> +                                    MC_ACCOUNT_DIR=${TMPDIR}
> +                                    MC_MANAGER_DIR=${TMPDIR})
> +            endif ()
> +
> +            set(TEST_COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME} ${PLATFORM} -p -o -p -,txt -p -o -p ${CMAKE_BINARY_DIR}/test_${TESTNAME}.xml,xunitxml)
> +            if (DEFINED ARG_WAIT_FOR)
> +                SET(TEST_COMMAND ${TEST_COMMAND} --wait-for ${ARG_WAIT_FOR})
> +            endif ()
> +
> +            add_test(${TESTNAME} ${DBUS_RUNNER} --keep-env --dbus-config=${CMAKE_BINARY_DIR}/tests/common/dbus-session.conf --max-wait=${ARG_TIMEOUT}
> +                                                ${ARG_TASKS} --task ${TEST_COMMAND} --task-name ${TESTNAME})
> +        else ()
> +            add_test(${TESTNAME} ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME} ${PLATFORM} -o -,txt -o ${CMAKE_BINARY_DIR}/test_${TESTNAME}.xml,xunitxml)
> +        endif()
> +
> +        set_tests_properties(${TESTNAME} PROPERTIES
> +                             ENVIRONMENT "${ARG_ENVIRONMENT}"
> +                             TIMEOUT ${ARG_TIMEOUT})
> +        if (DEFINED ARG_LIBRARIES)
> +            target_link_libraries(${TESTNAME}
> +                                  ${ARG_LIBRARIES})
> +        endif ()
> +
> +        enable_coverage(${TESTNAME})
> +    endif ()
> +endfunction(generate_test)
> +
> +function(generate_telepathy_test TESTNAME)
> +    set(options "")
> +    set(oneValueArgs "")
> +    set(multiValueArgs TASKS LIBRARIES QT5_MODULES)
> +    cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
> +
> +    set(TASKS --task gnome-keyring-daemon -p -r -p -d --task-name gnome-keyring --ignore-return
> +              --task /usr/lib/dconf/dconf-service --task-name dconf-service --ignore-return
> +              --task dconf -p write -p /org/gnome/empathy/use-conn -p false --task-name dconf-write --wait-for ca.desrt.dconf --ignore-return
> +              --task /usr/lib/telepathy/mission-control-5 --task-name mission-control --wait-for ca.desrt.dconf --ignore-return
> +              --task ${CMAKE_BINARY_DIR}/tests/common/mock/telepathy-mock --task-name telepathy-mock --wait-for org.freedesktop.Telepathy.MissionControl5 --ignore-return
> +              # FIXME: maybe it would be better to decide whether to run the handler in a per-test basis?
> +              --task ${CMAKE_BINARY_DIR}/handler/telephony-service-handler --task-name telephony-service-handler --wait-for org.freedesktop.Telepathy.ConnectionManager.mock --ignore-return
> +              ${ARG_TASKS})
> +
> +    if (NOT DEFINED ARG_LIBRARIES)
> +        set(ARG_LIBRARIES ${TP_QT5_LIBRARIES} telephonyservice mockcontroller telepathytest)
> +    endif(NOT DEFINED ARG_LIBRARIES)
> +
> +    if (NOT DEFINED ARG_QT5_MODULES)
> +        set(ARG_QT5_MODULES Core DBus Test Qml)
> +    endif (NOT DEFINED ARG_QT5_MODULES)
> +    generate_test(${TESTNAME} ${ARGN}
> +                  TASKS ${TASKS}
> +                  LIBRARIES ${ARG_LIBRARIES} 
> +                  QT5_MODULES ${ARG_QT5_MODULES} 
> +                  USE_DBUS USE_UI 
> +                  WAIT_FOR org.freedesktop.Telepathy.Client.TelephonyServiceHandler)
> +endfunction(generate_telepathy_test)
> 
> === modified file 'handler/CMakeLists.txt'
> --- handler/CMakeLists.txt	2014-08-05 20:04:00 +0000
> +++ handler/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -26,6 +26,8 @@
>      telephonyservice
>      )
>  
> +enable_coverage(telephony-service-handler)
> +
>  configure_file(com.canonical.TelephonyServiceHandler.service.in com.canonical.TelephonyServiceHandler.service)
>  configure_file(org.freedesktop.Telepathy.Client.TelephonyServiceHandler.service.in org.freedesktop.Telepathy.Client.TelephonyServiceHandler.service)
>  
> @@ -33,9 +35,3 @@
>  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.TelephonyServiceHandler.service DESTINATION share/dbus-1/services)
>  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/com.canonical.TelephonyServiceHandler.service DESTINATION share/dbus-1/services)
>  install(FILES TelephonyServiceHandler.client DESTINATION share/telepathy/clients)
> -
> -if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc*")
> -    message(STATUS "Tests disabled on ppc")
> -else()
> -    add_subdirectory(tests)
> -endif()
> 
> === modified file 'handler/handler.cpp'
> --- handler/handler.cpp	2015-02-09 20:32:32 +0000
> +++ handler/handler.cpp	2015-03-27 02:49:31 +0000
> @@ -97,6 +97,7 @@
>      specList << TelepathyHelper::audioConferenceSpec();
>      specList << Tp::ChannelClassSpec::audioCall();
>      specList << Tp::ChannelClassSpec::textChat();
> +    specList << Tp::ChannelClassSpec::unnamedTextChat();
>  
>      return specList;
>  }
> 
> === removed file 'handler/tests/dbus-test-wrapper.sh.in'
> --- handler/tests/dbus-test-wrapper.sh.in	2014-03-27 13:26:31 +0000
> +++ handler/tests/dbus-test-wrapper.sh.in	1970-01-01 00:00:00 +0000
> @@ -1,35 +0,0 @@
> -#!/bin/sh -x
> -
> -# export the home folder to somewhere in /tmp
> -TMPDIR=/tmp/telephony_service_test_home
> -rm -rf $TMPDIR
> -mkdir -p $TMPDIR
> -export HOME=$TMPDIR
> -
> -# now run gnome-keyring
> -gnome-keyring-daemon -r -d
> -
> -# we need to set this otherwise mission-control doesn't work properly
> -dconf write /org/gnome/empathy/use-conn false
> -
> -# start the mock connection manager
> - at CMAKE_CURRENT_BINARY_DIR@/mock/telepathy-mock &
> -MOCK_PID=$!
> -
> -# wait 1 sec for the mock to start up
> -sleep 1
> -
> -mc-tool add mock/mock account0
> -
> - at CMAKE_CURRENT_BINARY_DIR@/../telephony-service-handler &
> -
> -HANDLER_PID=$!
> -
> -$@
> -RESULT=$?
> -
> -# FIXME: check the variables and things that should not be started
> -kill -9 $HANDLER_PID
> -kill -9 $MOCK_PID
> -
> -return $RESULT
> 
> === removed file 'handler/tests/telepathyhelper.cpp'
> --- handler/tests/telepathyhelper.cpp	2014-01-07 19:53:45 +0000
> +++ handler/tests/telepathyhelper.cpp	1970-01-01 00:00:00 +0000
> @@ -1,279 +0,0 @@
> -/**
> - * Copyright (C) 2013 Canonical, Ltd.
> - *
> - * This program is free software: you can redistribute it and/or modify it under
> - * the terms of the GNU General Public License version 3, as published by
> - * the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but WITHOUT
> - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> - *
> - * Authors: 
> - *  Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> - *  Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> - */
> -
> -#include "telepathyhelper.h"
> -#include <TelepathyQt/AbstractClient>
> -#include <TelepathyQt/AccountSet>
> -#include <TelepathyQt/ClientRegistrar>
> -#include <TelepathyQt/PendingReady>
> -#include <TelepathyQt/PendingAccount>
> -
> -TelepathyHelper::TelepathyHelper(QObject *parent)
> -    : QObject(parent),
> -      //mChannelObserver(0),
> -      mFirstTime(true),
> -      mConnected(false),
> -      mHandlerInterface(0)
> -{
> -    Tp::registerTypes();
> -
> -    mAccountFeatures << Tp::Account::FeatureCore;
> -    mContactFeatures << Tp::Contact::FeatureAlias
> -                     << Tp::Contact::FeatureAvatarData
> -                     << Tp::Contact::FeatureAvatarToken
> -                     << Tp::Contact::FeatureCapabilities
> -                     << Tp::Contact::FeatureSimplePresence;
> -    mConnectionFeatures << Tp::Connection::FeatureCore
> -                        << Tp::Connection::FeatureSelfContact
> -                        << Tp::Connection::FeatureSimplePresence;
> -
> -    Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus());
> -    channelFactory->addCommonFeatures(Tp::Channel::FeatureCore);
> -
> -    mAccountManager = Tp::AccountManager::create(
> -            Tp::AccountFactory::create(QDBusConnection::sessionBus(), mAccountFeatures),
> -            Tp::ConnectionFactory::create(QDBusConnection::sessionBus(), mConnectionFeatures),
> -            channelFactory,
> -            Tp::ContactFactory::create(mContactFeatures));
> -
> -    connect(mAccountManager->becomeReady(Tp::AccountManager::FeatureCore),
> -            SIGNAL(finished(Tp::PendingOperation*)),
> -            SLOT(onAccountManagerReady(Tp::PendingOperation*)));
> -
> -    mClientRegistrar = Tp::ClientRegistrar::create(mAccountManager);
> -}
> -
> -TelepathyHelper::~TelepathyHelper()
> -{
> -}
> -
> -TelepathyHelper *TelepathyHelper::instance()
> -{
> -    static TelepathyHelper* helper = new TelepathyHelper();
> -    return helper;
> -}
> -
> -QString TelepathyHelper::accountId() const
> -{
> -    if (mAccount) {
> -        return mAccount->uniqueIdentifier();
> -    }
> -    return QString();
> -}
> -
> -Tp::AccountPtr TelepathyHelper::account() const
> -{
> -    return mAccount;
> -}
> -
> -/*
> -ChannelObserver *TelepathyHelper::channelObserver() const
> -{
> -    return mChannelObserver;
> -}
> -*/
> -
> -bool TelepathyHelper::connected() const
> -{
> -    return mConnected;
> -}
> -
> -/*
> -void TelepathyHelper::registerChannelObserver(const QString &observerName)
> -{
> -    QString name = observerName;
> -
> -    if (name.isEmpty()) {
> -        name = "TelephonyPluginObserver";
> -    }
> -
> -    if (mChannelObserver) {
> -        mChannelObserver->deleteLater();
> -    }
> -
> -    mChannelObserver = new ChannelObserver(this);
> -    registerClient(mChannelObserver, name);
> -
> -    // messages
> -    connect(mChannelObserver, SIGNAL(textChannelAvailable(Tp::TextChannelPtr)),
> -            ChatManager::instance(), SLOT(onTextChannelAvailable(Tp::TextChannelPtr)));
> -
> -    // calls
> -    connect(mChannelObserver, SIGNAL(callChannelAvailable(Tp::CallChannelPtr)),
> -            CallManager::instance(), SLOT(onCallChannelAvailable(Tp::CallChannelPtr)));
> -
> -    Q_EMIT channelObserverCreated(mChannelObserver);
> -}
> -
> -void TelepathyHelper::unregisterChannelObserver()
> -{
> -    Tp::AbstractClientPtr clientPtr(mChannelObserver);
> -    if (clientPtr) {
> -        mClientRegistrar->unregisterClient(clientPtr);
> -    }
> -    mChannelObserver->deleteLater();
> -    mChannelObserver = NULL;
> -    Q_EMIT channelObserverUnregistered();
> -}
> -*/
> -
> -QStringList TelepathyHelper::supportedProtocols() const
> -{
> -    QStringList protocols;
> -    protocols << "mock";
> -    return protocols;
> -}
> -
> -void TelepathyHelper::initializeAccount()
> -{
> -    // watch for account state and connection changes
> -    connect(mAccount.data(),
> -            SIGNAL(stateChanged(bool)),
> -            SLOT(onAccountStateChanged(bool)));
> -    connect(mAccount.data(),
> -            SIGNAL(connectionChanged(const Tp::ConnectionPtr&)),
> -            SLOT(onAccountConnectionChanged(const Tp::ConnectionPtr&)));
> -
> -    // and make sure it is enabled and connected
> -    if (!mAccount->isEnabled()) {
> -        ensureAccountEnabled();
> -    } else {
> -        ensureAccountConnected();
> -    }
> -}
> -
> -void TelepathyHelper::ensureAccountEnabled()
> -{
> -    mAccount->setConnectsAutomatically(true);
> -    connect(mAccount->setEnabled(true),
> -            SIGNAL(finished(Tp::PendingOperation*)),
> -            SLOT(onAccountEnabled(Tp::PendingOperation*)));
> -}
> -
> -void TelepathyHelper::ensureAccountConnected()
> -{
> -    // if the account is not connected, request it to connect
> -    if (!mAccount->connection() || mAccount->connectionStatus() != Tp::ConnectionStatusConnected) {
> -        Tp::Presence presence(Tp::ConnectionPresenceTypeAvailable, "available", "online");
> -        mAccount->setRequestedPresence(presence);
> -    } else {
> -        watchSelfContactPresence();
> -    }
> -
> -    if (mFirstTime) {
> -        Q_EMIT accountReady();
> -        mFirstTime = false;
> -    }
> -}
> -
> -void TelepathyHelper::watchSelfContactPresence()
> -{
> -    if (mAccount.isNull() || mAccount->connection().isNull()) {
> -        return;
> -    }
> -
> -    connect(mAccount->connection()->selfContact().data(),
> -            SIGNAL(presenceChanged(Tp::Presence)),
> -            SLOT(onPresenceChanged(Tp::Presence)));
> -    onPresenceChanged(mAccount->connection()->selfContact()->presence());
> -}
> -
> -void TelepathyHelper::registerClient(Tp::AbstractClient *client, QString name)
> -{
> -    Tp::AbstractClientPtr clientPtr(client);
> -    bool succeeded = mClientRegistrar->registerClient(clientPtr, name);
> -    if (!succeeded) {
> -        name.append("%1");
> -        int count = 0;
> -        // limit the number of registered clients to 20, that should be a safe margin
> -        while (!succeeded && count < 20) {
> -            succeeded = mClientRegistrar->registerClient(clientPtr, name.arg(++count));
> -            if (succeeded) {
> -                name = name.arg(count);
> -            }
> -        }
> -    }
> -
> -    if (succeeded) {
> -        QObject *object = dynamic_cast<QObject*>(client);
> -        if (object) {
> -            object->setProperty("clientName", TP_QT_IFACE_CLIENT + "." + name );
> -        }
> -    }
> -}
> -
> -void TelepathyHelper::onAccountManagerReady(Tp::PendingOperation *op)
> -{
> -    Q_UNUSED(op)
> -
> -    Tp::AccountSetPtr accountSet;
> -    // try to find an account of the one of supported protocols
> -    Q_FOREACH(const QString &protocol, supportedProtocols()) {
> -        accountSet = mAccountManager->accountsByProtocol(protocol);
> -        if (accountSet->accounts().count() > 0) {
> -            break;
> -        }
> -    }
> -
> -    if (accountSet->accounts().count() == 0) {
> -        qCritical() << "No compatible telepathy account found!";
> -        return;
> -    }
> -
> -    mAccount = accountSet->accounts()[0];
> -
> -    // in case we have more than one account, the first one to show on the list is going to be used
> -    if (accountSet->accounts().count() > 1) {
> -        qWarning() << "There are more than just one account of type" << mAccount->protocolName();
> -    }
> -
> -    Q_EMIT accountIdChanged();
> -
> -    initializeAccount();
> -}
> -
> -void TelepathyHelper::onAccountEnabled(Tp::PendingOperation *op)
> -{
> -    // we might need to do more stuff once the account is enabled, but making sure it is connected is a good start
> -    ensureAccountConnected();
> -}
> -
> -void TelepathyHelper::onAccountStateChanged(bool enabled)
> -{
> -    if (!enabled) {
> -        ensureAccountEnabled();
> -    }
> -}
> -
> -void TelepathyHelper::onAccountConnectionChanged(const Tp::ConnectionPtr &connection)
> -{
> -    if (connection.isNull()) {
> -        ensureAccountConnected();
> -    } else {
> -        watchSelfContactPresence();
> -    }
> -    Q_EMIT connectionChanged();
> -}
> -
> -void TelepathyHelper::onPresenceChanged(const Tp::Presence &presence)
> -{
> -    mConnected = (presence.type() == Tp::ConnectionPresenceTypeAvailable);
> -    Q_EMIT connectedChanged();
> -}
> 
> === removed file 'handler/tests/telepathyhelper.h'
> --- handler/tests/telepathyhelper.h	2014-06-27 17:45:58 +0000
> +++ handler/tests/telepathyhelper.h	1970-01-01 00:00:00 +0000
> @@ -1,95 +0,0 @@
> -/**
> - * Copyright (C) 2013 Canonical, Ltd.
> - *
> - * This program is free software: you can redistribute it and/or modify it under
> - * the terms of the GNU General Public License version 3, as published by
> - * the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but WITHOUT
> - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> - *
> - * Authors: 
> - *  Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> - *  Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> - */
> -
> -#ifndef TELEPATHYHELPER_H
> -#define TELEPATHYHELPER_H
> -
> -#include <QObject>
> -#include <TelepathyQt/AccountManager>
> -#include <TelepathyQt/Contact>
> -#include <TelepathyQt/Connection>
> -#include <TelepathyQt/ConnectionManager>
> -#include <TelepathyQt/Types>
> -//#include "channelobserver.h"
> -
> -#define CANONICAL_TELEPHONY_VOICEMAIL_IFACE "com.canonical.Telephony.Voicemail"
> -#define CANONICAL_TELEPHONY_SPEAKER_IFACE "com.canonical.Telephony.Speaker"
> -#define CANONICAL_TELEPHONY_EMERGENCYMODE_IFACE "com.canonical.Telephony.EmergencyMode"
> -
> -class TelepathyHelper : public QObject
> -{
> -    Q_OBJECT
> -    Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
> -    Q_PROPERTY(QString accountId READ accountId NOTIFY accountIdChanged)
> -
> -public:
> -    ~TelepathyHelper();
> -
> -    static TelepathyHelper *instance();
> -    Tp::AccountPtr account() const;
> -    //ChannelObserver *channelObserver() const;
> -
> -    bool connected() const;
> -    QString accountId() const;
> -
> -    void registerClient(Tp::AbstractClient *client, QString name);
> -
> -Q_SIGNALS:
> -    //void channelObserverCreated(ChannelObserver *observer);
> -    //void channelObserverUnregistered();
> -    void accountReady();
> -    void connectionChanged();
> -    void connectedChanged();
> -    void accountIdChanged();
> -
> -public Q_SLOTS:
> -    //Q_INVOKABLE void registerChannelObserver(const QString &observerName = QString::null);
> -    //Q_INVOKABLE void unregisterChannelObserver();
> -
> -protected:
> -    QStringList supportedProtocols() const;
> -    void initializeAccount();
> -    void ensureAccountEnabled();
> -    void ensureAccountConnected();
> -    void watchSelfContactPresence();
> -
> -private Q_SLOTS:
> -    void onAccountManagerReady(Tp::PendingOperation *op);
> -    void onAccountEnabled(Tp::PendingOperation *op);
> -    void onAccountStateChanged(bool enabled);
> -    void onAccountConnectionChanged(const Tp::ConnectionPtr &connection);
> -    void onPresenceChanged(const Tp::Presence &presence);
> -
> -private:
> -    explicit TelepathyHelper(QObject *parent = 0);
> -    Tp::AccountManagerPtr mAccountManager;
> -    Tp::Features mAccountManagerFeatures;
> -    Tp::Features mAccountFeatures;
> -    Tp::Features mContactFeatures;
> -    Tp::Features mConnectionFeatures;
> -    Tp::ClientRegistrarPtr mClientRegistrar;
> -    Tp::AccountPtr mAccount;
> -    //ChannelObserver *mChannelObserver;
> -    bool mFirstTime;
> -    bool mConnected;
> -    QDBusInterface *mHandlerInterface;
> -};
> -
> -#endif // TELEPATHYHELPER_H
> 
> === modified file 'indicator/CMakeLists.txt'
> --- indicator/CMakeLists.txt	2014-04-07 19:21:14 +0000
> +++ indicator/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -47,6 +47,8 @@
>      telephonyservice
>      )
>  
> +enable_coverage(telephony-service-indicator)
> +
>  configure_file(org.freedesktop.Telepathy.Client.TelephonyServiceIndicator.service.in org.freedesktop.Telepathy.Client.TelephonyServiceIndicator.service)
>  install(TARGETS telephony-service-indicator RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
>  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.TelephonyServiceIndicator.service DESTINATION share/dbus-1/services)
> 
> === modified file 'libtelephonyservice/CMakeLists.txt'
> --- libtelephonyservice/CMakeLists.txt	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -38,4 +38,4 @@
>  
>  qt5_use_modules(telephonyservice Contacts Core DBus Feedback Multimedia Qml Quick)
>  
> -add_subdirectory(tests)
> +enable_coverage(telephonyservice)
> 
> === modified file 'libtelephonyservice/accountentry.cpp'
> --- libtelephonyservice/accountentry.cpp	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/accountentry.cpp	2015-03-27 02:49:31 +0000
> @@ -41,7 +41,8 @@
>  
>  bool AccountEntry::active() const
>  {
> -    return (!mAccount->connection().isNull() &&
> +    return (!mAccount.isNull() &&
> +            !mAccount->connection().isNull() &&
>              !mAccount->connection()->selfContact().isNull() &&
>               mAccount->connection()->selfContact()->presence().type() != Tp::ConnectionPresenceTypeOffline);
>  }
> @@ -70,10 +71,7 @@
>          return QString::null;
>      }
>      Tp::Presence presence = mAccount->connection()->selfContact()->presence();
> -    if (presence.type() == Tp::ConnectionPresenceTypeAvailable) {
> -        return presence.statusMessage();
> -    }
> -    return QString::null;
> +    return presence.statusMessage();
>  }
>  
>  QString AccountEntry::selfContactId() const
> @@ -147,6 +145,10 @@
>              SIGNAL(connectionChanged(Tp::ConnectionPtr)),
>              SLOT(onConnectionChanged()));
>  
> +    connect(this,
> +            SIGNAL(connectedChanged()),
> +            SIGNAL(activeChanged()));
> +
>      // and make sure it is enabled and connected
>      if (!mAccount->isEnabled()) {
>          QTimer::singleShot(0, this, SLOT(ensureEnabled()));
> @@ -203,15 +205,12 @@
>      Q_EMIT statusMessageChanged();
>      Q_EMIT connectedChanged();
>      Q_EMIT selfContactIdChanged();
> -    Q_EMIT activeChanged();
>  }
>  
>  void AccountEntry::onConnectionChanged()
>  {
>      if (!mAccount->connection()) {
> -
> -
> -        // and ensure the account gets connected
> +        // ensure the account gets connected
>          ensureConnected();
>      } else {
>          mConnectionInfo.busName = mAccount->connection()->busName();
> @@ -226,5 +225,4 @@
>  
>      Q_EMIT connectedChanged();
>      Q_EMIT selfContactIdChanged();
> -    Q_EMIT activeChanged();
>  }
> 
> === modified file 'libtelephonyservice/accountentryfactory.cpp'
> --- libtelephonyservice/accountentryfactory.cpp	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/accountentryfactory.cpp	2015-03-27 02:49:31 +0000
> @@ -25,7 +25,7 @@
>  
>  AccountEntry *AccountEntryFactory::createEntry(const Tp::AccountPtr &account, QObject *parent)
>  {
> -    QString protocol = account->protocolName();
> +    QString protocol = account.isNull() ? "" : account->protocolName();
>  
>      // FIXME: check what other accounts need extra properties/methods
>      if (protocol == "ofono") {
> @@ -34,7 +34,3 @@
>  
>      return new AccountEntry(account, parent);
>  }
> -
> -AccountEntryFactory::AccountEntryFactory()
> -{
> -}
> 
> === modified file 'libtelephonyservice/accountentryfactory.h'
> --- libtelephonyservice/accountentryfactory.h	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/accountentryfactory.h	2015-03-27 02:49:31 +0000
> @@ -31,8 +31,6 @@
>  public:
>      static AccountEntry *createEntry(const Tp::AccountPtr &account, QObject *parent = 0);
>  
> -private:
> -    explicit AccountEntryFactory();
>  };
>  
>  #endif // ACCOUNTENTRYFACTORY_H
> 
> === modified file 'libtelephonyservice/channelobserver.cpp'
> --- libtelephonyservice/channelobserver.cpp	2015-02-09 20:32:32 +0000
> +++ libtelephonyservice/channelobserver.cpp	2015-03-27 02:49:31 +0000
> @@ -38,6 +38,7 @@
>      specList << TelepathyHelper::audioConferenceSpec();
>      specList << Tp::ChannelClassSpec::audioCall();
>      specList << Tp::ChannelClassSpec::textChat();
> +    specList << Tp::ChannelClassSpec::unnamedTextChat();
>  
>      return specList;
>  }
> 
> === modified file 'libtelephonyservice/chatmanager.cpp'
> --- libtelephonyservice/chatmanager.cpp	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/chatmanager.cpp	2015-03-27 02:49:31 +0000
> @@ -26,6 +26,7 @@
>  #include "dbustypes.h"
>  #include "accountentry.h"
>  
> +#include <TelepathyQt/Contact>
>  #include <TelepathyQt/ContactManager>
>  #include <TelepathyQt/PendingContacts>
>  #include <QDBusArgument>
> @@ -114,6 +115,7 @@
>  
>  void ChatManager::sendMessage(const QStringList &recipients, const QString &message, const QString &accountId)
>  {
> +    // FIXME: this probably should be handle internally by telepathy-ofono
>      if (recipients.size() > 1 && TelepathyHelper::instance()->mmsGroupChat()) {
>          sendMMS(recipients, message, QVariant(), accountId);
>          return;
> @@ -173,9 +175,12 @@
>          return;
>      }
>  
> -    if (!channel->targetContact().isNull()) {
> -        Q_EMIT messageSent(channel->targetContact()->id(), sentMessage.text());
> +    QStringList recipients;
> +    Q_FOREACH(const Tp::ContactPtr &contact, channel->groupContacts(false)) {
> +        recipients << contact->id();
>      }
> +
> +    Q_EMIT messageSent(recipients, sentMessage.text());
>  }
>  
>  void ChatManager::acknowledgeMessage(const QStringList &recipients, const QString &messageId, const QString &accountId)
> 
> === modified file 'libtelephonyservice/chatmanager.h'
> --- libtelephonyservice/chatmanager.h	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/chatmanager.h	2015-03-27 02:49:31 +0000
> @@ -38,8 +38,8 @@
>      Q_INVOKABLE void sendMMS(const QStringList &recipients, const QString &message, const QVariant &attachments, const QString &accountId = QString:: null);
>  
>  Q_SIGNALS:
> -    void messageReceived(const QString &recipient, const QString &message, const QDateTime &timestamp, const QString &messageId, bool unread);
> -    void messageSent(const QString &recipient, const QString &message);
> +    void messageReceived(const QString &sender, const QString &message, const QDateTime &timestamp, const QString &messageId, bool unread);
> +    void messageSent(const QStringList &recipients, const QString &message);
>  
>  public Q_SLOTS:
>      void onTextChannelAvailable(Tp::TextChannelPtr channel);
> 
> === modified file 'libtelephonyservice/ofonoaccountentry.cpp'
> --- libtelephonyservice/ofonoaccountentry.cpp	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/ofonoaccountentry.cpp	2015-03-27 02:49:31 +0000
> @@ -203,6 +203,5 @@
>          mSerial = ussdIface.property("Serial").toString();
>      }
>  
> -    Q_EMIT simLockedChanged();
>      Q_EMIT serialChanged();
>  }
> 
> === modified file 'libtelephonyservice/telepathyhelper.cpp'
> --- libtelephonyservice/telepathyhelper.cpp	2015-03-27 02:49:31 +0000
> +++ libtelephonyservice/telepathyhelper.cpp	2015-03-27 02:49:31 +0000
> @@ -247,10 +247,7 @@
>  
>  void TelepathyHelper::unregisterChannelObserver()
>  {
> -    Tp::AbstractClientPtr clientPtr(mChannelObserver);
> -    if (clientPtr) {
> -        mClientRegistrar->unregisterClient(clientPtr);
> -    }
> +    unregisterClient(mChannelObserver);
>      mChannelObserver->deleteLater();
>      mChannelObserver = NULL;
>      Q_EMIT channelObserverUnregistered();
> @@ -315,6 +312,15 @@
>      return succeeded;
>  }
>  
> +bool TelepathyHelper::unregisterClient(Tp::AbstractClient *client)
> +{
> +    Tp::AbstractClientPtr clientPtr(client);
> +    if (clientPtr) {
> +        return mClientRegistrar->unregisterClient(clientPtr);
> +    }
> +    return false;
> +}
> +
>  AccountEntry *TelepathyHelper::accountForConnection(const Tp::ConnectionPtr &connection) const
>  {
>      if (connection.isNull()) {
> @@ -401,7 +407,7 @@
>      Q_FOREACH(AccountEntry *account, mAccounts) {
>          QString modemObjName = account->account()->parameters().value("modem-objpath").toString();
>          if (modemObjName.isEmpty()) {
> -            sortedOtherAccounts[account->displayName()] = account;
> +            sortedOtherAccounts[account->accountId()] = account;
>          } else {
>              sortedOfonoAccounts[modemObjName] = account;
>          }
> 
> === modified file 'libtelephonyservice/telepathyhelper.h'
> --- libtelephonyservice/telepathyhelper.h	2015-02-09 20:32:32 +0000
> +++ libtelephonyservice/telepathyhelper.h	2015-03-27 02:49:31 +0000
> @@ -87,6 +87,7 @@
>      Q_INVOKABLE void unlockSimCards() const;
>  
>      bool registerClient(Tp::AbstractClient *client, QString name);
> +    bool unregisterClient(Tp::AbstractClient *client);
>  
>      // pre-populated channel class specs for conferences
>      static Tp::ChannelClassSpec audioConferenceSpec();
> 
> === added directory 'tests'
> === added file 'tests/CMakeLists.txt'
> --- tests/CMakeLists.txt	1970-01-01 00:00:00 +0000
> +++ tests/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,6 @@
> +include (GenerateTest)
> +
> +add_subdirectory(common)
> +add_subdirectory(handler)
> +add_subdirectory(libtelephonyservice)
> +add_subdirectory(Ubuntu.Telephony)
> 
> === renamed directory 'Ubuntu/Telephony/tests' => 'tests/Ubuntu.Telephony'
> === modified file 'tests/Ubuntu.Telephony/CMakeLists.txt'
> --- Ubuntu/Telephony/tests/CMakeLists.txt	2014-07-11 21:30:21 +0000
> +++ tests/Ubuntu.Telephony/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -1,35 +1,19 @@
>  include_directories(
>      ${CMAKE_CURRENT_BINARY_DIR}
>      ${CMAKE_SOURCE_DIR}/Ubuntu/Telephony
> -    )
> -
> -macro(generate_tests)
> -    foreach(test ${ARGN})
> -        add_executable(${test} ${test}.cpp)
> -        qt5_use_modules(${test} Contacts Core DBus Qml Test)
> -        target_link_libraries(${test}
> -            telephonyservice-qml
> -            )
> -        add_test(${test} ${CMAKE_CURRENT_BINARY_DIR}/${test} -platform offscreen -xunitxml -o ${CMAKE_BINARY_DIR}/test_${test}.xml)
> -    endforeach(test)
> -endmacro(generate_tests)
> -
> -macro(DECLARE_QML_TEST TST_NAME TST_QML_FILE)
> -    add_test(NAME ${TST_NAME}
> -        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
> -        COMMAND xvfb-run -a -s "-screen 0 1024x768x24" qmltestrunner -import ${CMAKE_BINARY_DIR} -input ${CMAKE_CURRENT_SOURCE_DIR}/${TST_QML_FILE}
> -    )
> -endmacro()
> -
> -
> -generate_tests(
> -    ContactWatcherTest
> -    )
> -
> -declare_qml_test("context_properties" tst_contextProperties.qml)
> -declare_qml_test("phonenumber_field" tst_PhoneNumberField.qml)
> -declare_qml_test("phonenumber_input" tst_PhoneNumberInput.qml)
> -declare_qml_test("phonenumber_utils" tst_PhoneNumberPhoneUtils.qml)
> +    ${CMAKE_SOURCE_DIR}/libtelephonyservice
> +    )
> +
> +set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/Ubuntu/Telephony)
> +generate_test(ContactWatcherTest USE_UI
> +              SOURCES ContactWatcherTest.cpp
> +              LIBRARIES telephonyservice-qml
> +              QT5_MODULES Contacts Core DBus Qml Test)
> +
> +generate_test(context_properties QML_TEST tst_contextProperties.qml)
> +generate_test(phonenumber_field QML_TEST tst_PhoneNumberField.qml)
> +generate_test(phonenumber_input QML_TEST tst_PhoneNumberInput.qml)
> +generate_test(phonenumber_utils QML_TEST tst_PhoneNumberPhoneUtils.qml)
>  
>  # make the files visible on qtcreator
>  file(GLOB QML_TESTS *.qml *.js)
> 
> === modified file 'tests/Ubuntu.Telephony/ContactWatcherTest.cpp'
> --- Ubuntu/Telephony/tests/ContactWatcherTest.cpp	2015-03-27 02:49:31 +0000
> +++ tests/Ubuntu.Telephony/ContactWatcherTest.cpp	2015-03-27 02:49:31 +0000
> @@ -438,6 +438,11 @@
>      watcher.setAddressableFields(addressableFields);
>      QCOMPARE(addressableFieldsSpy.count(), 1);
>      QCOMPARE(watcher.addressableFields(), addressableFields);
> +
> +    // set the addressable fields to an empty value and make sure it falls back to "tel"
> +    watcher.setAddressableFields(QStringList());
> +    QCOMPARE(watcher.addressableFields().count(), 1);
> +    QCOMPARE(watcher.addressableFields()[0], QString("tel"));
>  }
>  
>  void ContactWatcherTest::testExtendedFieldMatch()
> 
> === added directory 'tests/common'
> === added file 'tests/common/CMakeLists.txt'
> --- tests/common/CMakeLists.txt	1970-01-01 00:00:00 +0000
> +++ tests/common/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,14 @@
> +include_directories(${TP_QT5_INCLUDE_DIRS}
> +                    ${CMAKE_SOURCE_DIR}/libtelephonyservice)
> +
> +configure_file(dbus-session.conf.in ${CMAKE_CURRENT_BINARY_DIR}/dbus-session.conf)
> +
> +add_library(mockcontroller STATIC mockcontroller.cpp mockcontroller.h)
> +qt5_use_modules(mockcontroller Core DBus)
> +
> +add_library(telepathytest STATIC telepathytest.cpp telepathytest.h)
> +qt5_use_modules(telepathytest Core DBus)
> +target_link_libraries(telepathytest telephonyservice ${TP_QT5_LIBRARIES})
> +
> +add_subdirectory(mock)
> +add_subdirectory(dbus-services)
> 
> === added directory 'tests/common/dbus-services'
> === added file 'tests/common/dbus-services/CMakeLists.txt'
> --- tests/common/dbus-services/CMakeLists.txt	1970-01-01 00:00:00 +0000
> +++ tests/common/dbus-services/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,9 @@
> +# copy the services we want to use
> +set(DBUS_SERVICES_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/dbus-1/services)
> +
> +file(COPY ${DBUS_SERVICES_DIR}/org.freedesktop.Telepathy.MissionControl5.service
> +     DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
> +file(COPY ${DBUS_SERVICES_DIR}/org.freedesktop.Telepathy.AccountManager.service
> +     DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
> +file(COPY ${DBUS_SERVICES_DIR}/ca.desrt.dconf.service
> +     DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
> 
> === added file 'tests/common/dbus-session.conf.in'
> --- tests/common/dbus-session.conf.in	1970-01-01 00:00:00 +0000
> +++ tests/common/dbus-session.conf.in	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,42 @@
> +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
> + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
> +<busconfig>
> +  <type>session</type>
> +
> +  <!-- If we fork, keep the user's original umask to avoid affecting
> +       the behavior of child processes. -->
> +  <keep_umask/>
> +
> +  <listen>unix:tmpdir=/tmp</listen>
> +
> +  <servicedir>@CMAKE_CURRENT_BINARY_DIR@/dbus-services</servicedir>
> +
> +  <policy context="default">
> +    <!-- Allow everything to be sent -->
> +    <allow send_destination="*" eavesdrop="true"/>
> +    <!-- Allow everything to be received -->
> +    <allow eavesdrop="true"/>
> +    <!-- Allow anyone to own anything -->
> +    <allow own="*"/>
> +  </policy>
> +
> +  <!-- raise the service start timeout to 40 seconds as it can timeout
> +       on the live cd on slow machines -->
> +  <limit name="service_start_timeout">60000</limit>
> +
> +  <!-- the memory limits are 1G instead of say 4G because they can't exceed 32-bit signed int max -->
> +  <limit name="max_incoming_bytes">1000000000</limit>
> +  <limit name="max_outgoing_bytes">1000000000</limit>
> +  <limit name="max_message_size">1000000000</limit>
> +  <limit name="service_start_timeout">120000</limit>  
> +  <limit name="auth_timeout">240000</limit>
> +  <limit name="max_completed_connections">100000</limit>  
> +  <limit name="max_incomplete_connections">10000</limit>
> +  <limit name="max_connections_per_user">100000</limit>
> +  <limit name="max_pending_service_starts">10000</limit>
> +  <limit name="max_names_per_connection">50000</limit>
> +  <limit name="max_match_rules_per_connection">50000</limit>
> +  <limit name="max_replies_per_connection">50000</limit>
> +  <limit name="reply_timeout">300000</limit>
> +
> +</busconfig>
> 
> === renamed directory 'handler/tests/mock' => 'tests/common/mock'
> === modified file 'tests/common/mock/CMakeLists.txt'
> --- handler/tests/mock/CMakeLists.txt	2014-03-13 17:11:09 +0000
> +++ tests/common/mock/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -4,11 +4,14 @@
>      ${Qt5DBus_INCLUDE_DIRS}
>      ${CMAKE_CURRENT_BINARY_DIR}
>      ${CMAKE_CURRENT_SOURCE_DIR}
> +    ${CMAKE_SOURCE_DIR}/libtelephonyservice
>      )
>  
>  find_library(TELEPATHY_QT5_SERVICE_LIBRARIES telepathy-qt5-service)
>  
> -set(mock_SRCS main.cpp protocol.cpp connection.cpp textchannel.cpp callchannel.cpp conferencecallchannel.cpp mockconnectiondbus.cpp speakeriface.cpp)
> +set(mock_SRCS main.cpp protocol.cpp connection.cpp textchannel.cpp callchannel.cpp
> +              conferencecallchannel.cpp mockconnectiondbus.cpp speakeriface.cpp
> +              emergencymodeiface.cpp ussdiface.cpp voicemailiface.cpp)
>  qt5_add_dbus_adaptor(mock_SRCS MockConnection.xml mockconnectiondbus.h MockConnectionDBus)
>  
>  add_executable(telepathy-mock ${mock_SRCS})
> 
> === modified file 'tests/common/mock/MockConnection.xml'
> --- handler/tests/mock/MockConnection.xml	2014-03-20 21:03:26 +0000
> +++ tests/common/mock/MockConnection.xml	2015-03-27 02:49:31 +0000
> @@ -38,6 +38,55 @@
>              <arg name="phoneNumber" type="s" direction="in"/>
>              <arg name="status" type="s" direction="in"/>
>          </method>
> +        <method name="SetOnline">
> +            <dox:d><![CDATA[
> +                Set the account online/offline
> +            ]]></dox:d>
> +            <arg name="online" type="b" direction="in"/>
> +        </method>
> +        <method name="SetPresence">
> +            <dox:d><![CDATA[
> +                Set the requested presence
> +            ]]></dox:d>
> +            <arg name="status" type="s" direction="in"/>
> +            <arg name="statusMessage" type="s" direction="in"/>
> +        </method>
> +        <method name="SetVoicemailIndicator">
> +            <dox:d><![CDATA[
> +                Set the voicemail indicator on/off
> +            ]]></dox:d>
> +            <arg name="active" type="b" direction="in"/>
> +        </method>
> +        <method name="SetVoicemailNumber">
> +            <dox:d><![CDATA[
> +                Set the voicemail number
> +            ]]></dox:d>
> +            <arg name="number" type="s" direction="in"/>
> +        </method>
> +        <method name="SetVoicemailCount">
> +            <dox:d><![CDATA[
> +                Set the voicemail count
> +            ]]></dox:d>
> +            <arg name="count" type="i" direction="in"/>
> +        </method>
> +        <method name="SetEmergencyNumbers">
> +            <dox:d><![CDATA[
> +                Set the emergency numbers
> +            ]]></dox:d>
> +            <arg name="numbers" type="as" direction="in"/>
> +        </method>
> +        <method name="Serial">
> +            <dox:d><![CDATA[
> +                Set the USSD serial

Get instead of Set?

> +            ]]></dox:d>
> +            <arg name="value" type="s" direction="out"/>
> +        </method>
> +        <signal name="MessageRead">
> +            <dox:d><![CDATA[
> +                A message was acknowledged
> +            ]]></dox:d>
> +            <arg name="messageId" type="s"/>
> +        </signal>
>          <signal name="MessageSent">
>              <dox:d><![CDATA[
>                  A message was sent from the client.
> @@ -45,6 +94,7 @@
>              <arg name="message" type="s"/>
>              <arg name="properties" type="a{sv}"/>
>              <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
> +            <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
>          </signal>
>          <signal name="CallReceived">
>              <dox:d><![CDATA[
> @@ -84,5 +134,15 @@
>              ]]></dox:d>
>              <arg name="objectPath" type="s"/>
>          </signal>
> +        <signal name="Disconnected">
> +            <dox:d><![CDATA[
> +                The account was disconnected
> +            ]]></dox:d>
> +        </signal>
> +        <signal name="Destroyed">
> +            <dox:d><![CDATA[
> +                The connection object was destroyed
> +            ]]></dox:d>
> +        </signal>
>      </interface>
>  </node>
> 
> === modified file 'tests/common/mock/callchannel.cpp'
> --- handler/tests/mock/callchannel.cpp	2014-03-20 21:03:26 +0000
> +++ tests/common/mock/callchannel.cpp	2015-03-27 02:49:31 +0000
> @@ -172,7 +172,7 @@
>  {
>      qDebug() << "call channel closed";
>      // TODO - for some reason the object is not being removed
> -    mConnection->dbusConnection().unregisterObject(mObjPath, QDBusConnection::UnregisterTree);
> +    mConnection->dbusConnection().unregisterObject(mBaseChannel->objectPath(), QDBusConnection::UnregisterTree);
>  }
>  
>  Tp::BaseChannelPtr MockCallChannel::baseChannel()
> 
> === modified file 'tests/common/mock/connection.cpp'
> --- handler/tests/mock/connection.cpp	2014-04-03 16:38:01 +0000
> +++ tests/common/mock/connection.cpp	2015-03-27 02:49:31 +0000
> @@ -36,7 +36,7 @@
>                              const QString &protocolName,
>                              const QVariantMap &parameters) :
>      Tp::BaseConnection(dbusConnection, cmName, protocolName, parameters),
> -    mHandleCount(0), mConferenceCall(0)
> +    mConferenceCall(0), mVoicemailIndicator(false), mVoicemailCount(0)
>  {
>      setSelfHandle(newHandle("<SelfHandle>"));
>  
> @@ -54,6 +54,7 @@
>      text.fixedProperties[TP_QT_IFACE_CHANNEL+".TargetHandleType"]  = Tp::HandleTypeContact;
>      text.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetHandle");
>      text.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetID");
> +    text.allowedProperties.append(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles"));
>  
>      // set requestable call channel properties
>      Tp::RequestableChannelClass call;
> @@ -77,26 +78,41 @@
>      // init presence interface
>      simplePresenceIface = Tp::BaseConnectionSimplePresenceInterface::create();
>      simplePresenceIface->setSetPresenceCallback(Tp::memFun(this,&MockConnection::setPresence));
> +    simplePresenceIface->setMaxmimumStatusMessageLength(255);
>      plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(simplePresenceIface));
>  
>      // Set Presence
>      Tp::SimpleStatusSpec presenceOnline;
>      presenceOnline.type = Tp::ConnectionPresenceTypeAvailable;
>      presenceOnline.maySetOnSelf = true;
> -    presenceOnline.canHaveMessage = false;
> +    presenceOnline.canHaveMessage = true;
>  
>      Tp::SimpleStatusSpec presenceOffline;
>      presenceOffline.type = Tp::ConnectionPresenceTypeOffline;
> -    presenceOffline.maySetOnSelf = false;
> -    presenceOffline.canHaveMessage = false;
> -
> -    Tp::SimpleStatusSpecMap statuses;
> -    statuses.insert(QLatin1String("available"), presenceOnline);
> -    statuses.insert(QLatin1String("offline"), presenceOffline);
> -
> -    simplePresenceIface->setStatuses(statuses);
> +    presenceOffline.maySetOnSelf = true;
> +    presenceOffline.canHaveMessage = true;
> +
> +    Tp::SimpleStatusSpec presenceAway;
> +    presenceAway.type = Tp::ConnectionPresenceTypeAway;
> +    presenceAway.maySetOnSelf = true;
> +    presenceAway.canHaveMessage = true;
> +
> +    mStatuses.insert(QLatin1String("available"), presenceOnline);
> +    mStatuses.insert(QLatin1String("offline"), presenceOffline);
> +    mStatuses.insert(QLatin1String("away"), presenceAway);
> +    mStatuses.insert(QLatin1String("simlocked"), presenceAway);
> +    mStatuses.insert(QLatin1String("flightmode"), presenceOffline);
> +    mStatuses.insert(QLatin1String("nosim"), presenceOffline);
> +    mStatuses.insert(QLatin1String("nomodem"), presenceOffline);
> +    mStatuses.insert(QLatin1String("registered"), presenceOnline);
> +    mStatuses.insert(QLatin1String("roaming"), presenceOnline);
> +    mStatuses.insert(QLatin1String("unregistered"), presenceAway);
> +    mStatuses.insert(QLatin1String("denied"), presenceAway);
> +    mStatuses.insert(QLatin1String("unknown"), presenceAway);
> +    mStatuses.insert(QLatin1String("searching"), presenceAway);
> +
> +    simplePresenceIface->setStatuses(mStatuses);
>      mSelfPresence.type = Tp::ConnectionPresenceTypeOffline;
> -    mRequestedSelfPresence.type = Tp::ConnectionPresenceTypeOffline;
>  
>      contactsIface = Tp::BaseConnectionContactsInterface::create();
>      contactsIface->setGetContactAttributesCallback(Tp::memFun(this,&MockConnection::getContactAttributes));
> @@ -105,9 +121,40 @@
>                                                   << TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE);
>      plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(contactsIface));
>  
> +    // init custom emergency mode interface (not provided by telepathy
> +    emergencyModeIface = BaseConnectionEmergencyModeInterface::create();
> +    emergencyModeIface->setEmergencyNumbersCallback(Tp::memFun(this,&MockConnection::emergencyNumbers));
> +    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(emergencyModeIface));
> +    mEmergencyNumbers << "123" << "456" << "789";
> +    emergencyModeIface->setEmergencyNumbers(mEmergencyNumbers);
> +
> +    // init custom voicemail interface (not provided by telepathy)
> +    voicemailIface = BaseConnectionVoicemailInterface::create();
> +    voicemailIface->setVoicemailCountCallback(Tp::memFun(this,&MockConnection::voicemailCount));
> +    voicemailIface->setVoicemailIndicatorCallback(Tp::memFun(this,&MockConnection::voicemailIndicator));
> +    voicemailIface->setVoicemailNumberCallback(Tp::memFun(this,&MockConnection::voicemailNumber));
> +    voicemailIface->setVoicemailNumber(mVoicemailNumber);
> +    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(voicemailIface));
> +    voicemailIface->setVoicemailCount(mVoicemailCount);
> +    voicemailIface->setVoicemailIndicator(mVoicemailIndicator);
> +    mVoicemailNumber = "555";
> +
> +    supplementaryServicesIface = BaseConnectionUSSDInterface::create();
> +    supplementaryServicesIface->setInitiateCallback(Tp::memFun(this,&MockConnection::USSDInitiate));
> +    supplementaryServicesIface->setRespondCallback(Tp::memFun(this,&MockConnection::USSDRespond));
> +    supplementaryServicesIface->setCancelCallback(Tp::memFun(this,&MockConnection::USSDCancel));
> +
> +    static int serial = 0;
> +    serial++;
> +    supplementaryServicesIface->setSerial(QString("accountserial%1").arg(QString::number(serial)));
> +
> +    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(supplementaryServicesIface));
> +
>      mDBus = new MockConnectionDBus(this);
> +}
>  
> -    setOnline(true);
> +MockConnection::~MockConnection()
> +{
>  }
>  
>  void MockConnection::addMMSToService(const QString &path, const QVariantMap &properties, const QString &servicePath)
> @@ -143,16 +190,45 @@
>  #endif
>  }
>  
> -MockConnection::~MockConnection()
> +MockTextChannel *MockConnection::textChannelForRecipients(const QStringList &recipients)
>  {
> +    Q_FOREACH(MockTextChannel *channel, mTextChannels) {
> +        QStringList channelRecipients = channel->recipients();
> +        if (channelRecipients.length() != recipients.length()) {
> +            continue;
> +        }
> +
> +        bool ok = true;
> +        Q_FOREACH(const QString &recipient, recipients) {
> +            if (!channelRecipients.contains(recipient)) {
> +                ok = false;
> +                break;
> +            }
> +        }
> +
> +        if (ok) {
> +            return channel;
> +        }
> +    }
> +    return 0;
>  }
>  
>  uint MockConnection::setPresence(const QString& status, const QString& statusMessage, Tp::DBusError *error)
>  {
> -    qDebug() << "setPresence" << status;
> -    if (status == "available") {
> -        mRequestedSelfPresence.type = Tp::ConnectionPresenceTypeAvailable;
> +    qDebug() << "setPresence" << status << statusMessage;
> +    Tp::SimpleContactPresences presences;
> +    if (!mStatuses.contains(status) || !mStatuses[status].maySetOnSelf) {
> +        error->set(TP_QT_ERROR_INVALID_ARGUMENT, "Status not supported or cannot be set");
> +        return selfHandle();
>      }
> +
> +    Tp::SimpleStatusSpec spec = mStatuses[status];
> +    mSelfPresence.status = status;
> +    mSelfPresence.type = spec.type;
> +    mSelfPresence.statusMessage = spec.canHaveMessage ? statusMessage : "";
> +
> +    presences[selfHandle()] = mSelfPresence;
> +    simplePresenceIface->setPresences(presences);
>      return selfHandle();
>  }
>  
> @@ -190,8 +266,9 @@
>  
>  uint MockConnection::newHandle(const QString &identifier)
>  {
> -    mHandles[++mHandleCount] = identifier;
> -    return mHandleCount;
> +    static int handleCount = 0;
> +    mHandles[++handleCount] = identifier;
> +    return handleCount;
>  }
>  
>  QMap<QString, MockCallChannel *> MockConnection::callChannels()
> @@ -248,29 +325,44 @@
>  }
>  
>  Tp::BaseChannelPtr MockConnection::createTextChannel(uint targetHandleType,
> -                                               uint targetHandle, Tp::DBusError *error)
> +                                                     uint targetHandle,
> +                                                     const QVariantMap &hints,
> +                                                     Tp::DBusError *error)
>  {
>      Q_UNUSED(targetHandleType);
>      Q_UNUSED(error);
>  
> -    QString requestedId = mHandles.value(targetHandle);
> -
> -    if (mTextChannels.contains(requestedId)) {
> -        return mTextChannels[requestedId]->baseChannel();
> -    }
> -
> -    MockTextChannel *channel = new MockTextChannel(this, requestedId, targetHandle);
> +    if (hints.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles")) &&
> +            targetHandleType == Tp::HandleTypeNone && targetHandle == 0) {
> +
> +    }
> +
> +    QStringList recipients;
> +    bool flash;
> +    if (hints.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles"))) {
> +        recipients << inspectHandles(Tp::HandleTypeContact, qdbus_cast<Tp::UIntList>(hints[TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles")]), error);
> +    } else {
> +        recipients << mHandles.value(targetHandle);
> +    }
> +
> +    if (hints.contains(TP_QT_IFACE_CHANNEL_INTERFACE_SMS + QLatin1String(".Flash"))) {
> +        flash = hints[TP_QT_IFACE_CHANNEL_INTERFACE_SMS + QLatin1String(".Flash")].toBool();
> +    }
> +
> +    // FIXME: test flash messages
> +    MockTextChannel *channel = new MockTextChannel(this, recipients, targetHandle);
>      QObject::connect(channel, SIGNAL(messageRead(QString)), SLOT(onMessageRead(QString)));
>      QObject::connect(channel, SIGNAL(destroyed()), SLOT(onTextChannelClosed()));
>      QObject::connect(channel, SIGNAL(messageSent(QString,QVariantMap)), SIGNAL(messageSent(QString,QVariantMap)));
>      qDebug() << channel;
> -    mTextChannels[requestedId] = channel;
> +    mTextChannels << channel;
>      return channel->baseChannel();
>  }
>  
>  void MockConnection::onMessageRead(const QString &id)
>  {
> -    // FIXME: implement
> +    // FIXME: check what else to do
> +    Q_EMIT messageRead(id);
>  }
>  
>  void MockConnection::onConferenceCallChannelClosed()
> @@ -355,7 +447,7 @@
>      }
>  
>      if (channelType == TP_QT_IFACE_CHANNEL_TYPE_TEXT) {
> -        return createTextChannel(targetHandleType, targetHandle, error);
> +        return createTextChannel(targetHandleType, targetHandle, hints, error);
>      } else if (channelType == TP_QT_IFACE_CHANNEL_TYPE_CALL) {
>          return createCallChannel(targetHandleType, targetHandle, hints, error);
>      } else {
> @@ -367,33 +459,36 @@
>  
>  void MockConnection::placeIncomingMessage(const QString &message, const QVariantMap &info)
>  {
> -    const QString sender = info["Sender"].toString();
> -    // check if there is an open channel for this sender and use it
> -    Q_FOREACH(const QString &id, mTextChannels.keys()) {
> -        if (id == sender) {
> -            mTextChannels[id]->messageReceived(message, info);
> -            return;
> -        }
> -    }
> -
> -    Tp::DBusError error;
> -    bool yours;
> -    uint handle = newHandle(sender);
> -    ensureChannel(TP_QT_IFACE_CHANNEL_TYPE_TEXT,Tp::HandleTypeContact, handle, yours, handle, false, QVariantMap(), &error);
> -    if(error.isValid()) {
> -        qWarning() << "Error creating channel for incoming message" << error.name() << error.message();
> -        return;
> -    }
> -    mTextChannels[sender]->messageReceived(message, info);
> +    QString sender = info["Sender"].toString();
> +    QStringList recipients = info["Recipients"].toStringList();
> +
> +    MockTextChannel *channel = textChannelForRecipients(recipients);
> +    if (!channel) {
> +        // request the channel
> +        Tp::DBusError error;
> +        bool yours;
> +        uint handle = newHandle(sender);
> +        ensureChannel(TP_QT_IFACE_CHANNEL_TYPE_TEXT,Tp::HandleTypeContact, handle, yours, handle, false, QVariantMap(), &error);
> +        if(error.isValid()) {
> +            qWarning() << "Error creating channel for incoming message" << error.name() << error.message();
> +            return;
> +        }
> +
> +        channel = textChannelForRecipients(recipients);
> +        if (!channel) {
> +            return;
> +        }
> +    }
> +
> +    channel->messageReceived(message, info);
>  }
>  
>  void MockConnection::onTextChannelClosed()
>  {
>      MockTextChannel *channel = static_cast<MockTextChannel*>(sender());
>      if (channel) {
> -        QString key = mTextChannels.key(channel);
> -        qDebug() << "text channel closed for number " << key;
> -        mTextChannels.remove(key);
> +        qDebug() << "text channel closed for recipients " << channel->recipients();
> +        mTextChannels.removeAll(channel);
>      }
>  }
>  
> @@ -469,6 +564,76 @@
>      return channel->objectPath();
>  }
>  
> +QStringList MockConnection::emergencyNumbers(Tp::DBusError *error)
> +{
> +    return mEmergencyNumbers;
> +}
> +
> +void MockConnection::setEmergencyNumbers(const QStringList &emergencyNumbers)
> +{
> +    mEmergencyNumbers = emergencyNumbers;
> +    emergencyModeIface->setEmergencyNumbers(emergencyNumbers);
> +}
> +
> +bool MockConnection::voicemailIndicator(Tp::DBusError *error)
> +{
> +    return mVoicemailIndicator;
> +}
> +
> +void MockConnection::setVoicemailIndicator(bool visible)
> +{
> +    mVoicemailIndicator = visible;
> +    voicemailIface->setVoicemailIndicator(visible);
> +}
> +
> +QString MockConnection::voicemailNumber(Tp::DBusError *error)
> +{
> +    return mVoicemailNumber;
> +}
> +
> +void MockConnection::setVoicemailNumber(const QString &number)
> +{
> +    mVoicemailNumber = number;
> +    voicemailIface->setVoicemailNumber(mVoicemailNumber);
> +}
> +
> +uint MockConnection::voicemailCount(Tp::DBusError *error)
> +{
> +    return mVoicemailCount;
> +}
> +
> +void MockConnection::setVoicemailCount(int count)
> +{
> +    mVoicemailCount = count;
> +    voicemailIface->setVoicemailCount(mVoicemailCount);
> +}
> +
> +void MockConnection::USSDInitiate(const QString &command, Tp::DBusError *error)
> +{
> +    // FIXME: implement
> +}
> +
> +void MockConnection::USSDRespond(const QString &reply, Tp::DBusError *error)
> +{
> +    // FIXME: implement
> +}
> +
> +void MockConnection::USSDCancel(Tp::DBusError *error)
> +{
> +    // FIXME: implement
> +}
> +
> +QString MockConnection::serial()
> +{
> +    return supplementaryServicesIface->serial();
> +}
> +
> +QString MockConnection::uniqueName() const
> +{
> +    static int count = 0;
> +    return QString("connection%1%2").arg((quintptr) this, 0, 16).arg(count++, 0, 16);
> +}
> +
>  void MockConnection::hangupCall(const QString &callerId)
>  {
>      if (!mCallChannels.contains(callerId)) {
> 
> === modified file 'tests/common/mock/connection.h'
> --- handler/tests/mock/connection.h	2014-03-20 21:03:26 +0000
> +++ tests/common/mock/connection.h	2015-03-27 02:49:31 +0000
> @@ -34,6 +34,9 @@
>  #include "textchannel.h"
>  #include "callchannel.h"
>  #include "dbustypes.h"
> +#include "emergencymodeiface.h"
> +#include "ussdiface.h"
> +#include "voicemailiface.h"
>  
>  class MockTextChannel;
>  class MockCallChannel;
> @@ -65,9 +68,16 @@
>      uint newHandle(const QString &identifier);
>      QMap<QString, MockCallChannel*> callChannels();
>  
> +    // phone custom interfaces
> +    BaseConnectionEmergencyModeInterfacePtr emergencyModeIface;
> +    BaseConnectionVoicemailInterfacePtr voicemailIface;
> +    BaseConnectionUSSDInterfacePtr supplementaryServicesIface;
> +
>      uint ensureHandle(const QString &id);
>      Tp::BaseChannelPtr createTextChannel(uint targetHandleType,
> -                                         uint targetHandle, Tp::DBusError *error);
> +                                         uint targetHandle,
> +                                         const QVariantMap &hints,
> +                                         Tp::DBusError *error);
>      Tp::BaseChannelPtr createCallChannel(uint targetHandleType,
>                                           uint targetHandle,
>                                           const QVariantMap &hints,
> @@ -76,7 +86,27 @@
>      ~MockConnection();
>  
>      QString placeCall(const QVariantMap &properties);
> +
> +    QStringList emergencyNumbers(Tp::DBusError *error);
> +    void setEmergencyNumbers(const QStringList &emergencyNumbers);
> +
> +    bool voicemailIndicator(Tp::DBusError *error);
> +    void setVoicemailIndicator(bool visible);
> +    QString voicemailNumber(Tp::DBusError *error);
> +    void setVoicemailNumber(const QString &number);
> +    uint voicemailCount(Tp::DBusError *error);
> +    void setVoicemailCount(int count);
> +    void USSDInitiate(const QString &command, Tp::DBusError *error);
> +    void USSDRespond(const QString &reply, Tp::DBusError *error);
> +    void USSDCancel(Tp::DBusError *error);
> +    QString serial();
> +
> +    // FIXME: there is a problem in telepathy-qt that connection object paths and services are not properly unregistered
> +    // and thus if we gain the same memory address (and thus the same pointer) every time we reconnect, there might be some problems
> +    QString uniqueName() const;
> +
>  Q_SIGNALS:
> +    void messageRead(const QString &messageId);
>      void messageSent(const QString &message, const QVariantMap &info);
>      void callReceived(const QString &callerId);
>      void callEnded(const QString &callerId);
> @@ -102,20 +132,27 @@
>  
>  private:
>      void addMMSToService(const QString &path, const QVariantMap &properties, const QString &servicePath);
> +
> +    MockTextChannel *textChannelForRecipients(const QStringList &recipients);
> +
>      QMap<uint, QString> mHandles;
> +    Tp::SimpleStatusSpecMap mStatuses;
>  
> -    QMap<QString, MockTextChannel*> mTextChannels;
> +    QList<MockTextChannel*> mTextChannels;
>      QMap<QString, MockCallChannel*> mCallChannels;
>      QMap<QString, QString> mInitialCallStatus;
>  
>      QStringList mModems;
> -    uint mHandleCount;
>      Tp::SimplePresence mSelfPresence;
> -    Tp::SimplePresence mRequestedSelfPresence;
>  
>      MockConnectionDBus *mDBus;
>      QStringList mIncomingCalls;
>      MockConferenceCallChannel *mConferenceCall;
> +
> +    QStringList mEmergencyNumbers;
> +    int mVoicemailCount;
> +    bool mVoicemailIndicator;
> +    QString mVoicemailNumber;
>  };
>  
>  #endif
> 
> === added file 'tests/common/mock/emergencymodeiface.cpp'
> --- tests/common/mock/emergencymodeiface.cpp	1970-01-01 00:00:00 +0000
> +++ tests/common/mock/emergencymodeiface.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,133 @@
> +/**
> + * Copyright (C) 2013-2015 Canonical, Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors: Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> +            Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> + */
> +
> +#include <QDebug>
> +
> +#include <TelepathyQt/Constants>
> +#include <TelepathyQt/DBusObject>
> +
> +#include "emergencymodeiface.h"
> +
> +BaseConnectionEmergencyModeInterface::Adaptee::Adaptee(BaseConnectionEmergencyModeInterface *interface)
> +    : QObject(interface),
> +      mInterface(interface)
> +{
> +}
> +
> +
> +struct TP_QT_NO_EXPORT BaseConnectionEmergencyModeInterface::Private {
> +    Private(BaseConnectionEmergencyModeInterface *parent)
> +        : adaptee(new BaseConnectionEmergencyModeInterface::Adaptee(parent)) {
> +    }
> +    EmergencyNumbersCallback emergencyNumbersCB;
> +    BaseConnectionEmergencyModeInterface::Adaptee *adaptee;
> +    QString fakeEmergencyNumber;
> +};
> +
> +BaseConnectionEmergencyModeInterface::Adaptee::~Adaptee()
> +{
> +}
> +
> +void BaseConnectionEmergencyModeInterface::Adaptee::emergencyNumbers(const ConnectionInterfaceEmergencyModeAdaptor::EmergencyNumbersContextPtr &context)
> +{
> +    if (!mInterface->mPriv->emergencyNumbersCB.isValid()) {
> +        context->setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"));
> +        return;
> +    }
> +    Tp::DBusError error;
> +    QStringList numbers = mInterface->mPriv->emergencyNumbersCB(&error);
> +    if (error.isValid()) {
> +        context->setFinishedWithError(error.name(), error.message());
> +        return;
> +    }
> +    if (mInterface->mPriv->fakeEmergencyNumber.isEmpty()) {
> +        context->setFinished(numbers);
> +    } else {
> +        context->setFinished(QStringList() << numbers << mInterface->mPriv->fakeEmergencyNumber);
> +    }
> +}
> +
> +BaseConnectionEmergencyModeInterface::BaseConnectionEmergencyModeInterface()
> +    : AbstractConnectionInterface(TP_QT_IFACE_CONNECTION_EMERGENCYMODE),
> +      mPriv(new Private(this))
> +{
> +}
> +
> +BaseConnectionEmergencyModeInterface::~BaseConnectionEmergencyModeInterface()
> +{
> +    delete mPriv;
> +}
> +
> +void BaseConnectionEmergencyModeInterface::setEmergencyNumbersCallback(const EmergencyNumbersCallback &cb)
> +{
> +    mPriv->emergencyNumbersCB = cb;
> +}
> +
> +void BaseConnectionEmergencyModeInterface::setEmergencyNumbers(const QStringList &numbers)
> +{
> +    QStringList finalEmergencyList(numbers);
> +
> +    if (!mPriv->fakeEmergencyNumber.isEmpty()) {
> +        finalEmergencyList << mPriv->fakeEmergencyNumber;
> +    }
> +
> +    Q_EMIT mPriv->adaptee->emergencyNumbersChanged(finalEmergencyList);
> +}
> +
> +void BaseConnectionEmergencyModeInterface::setFakeEmergencyNumber(const QString &fakeEmergencyNumber)
> +{
> +    mPriv->fakeEmergencyNumber = fakeEmergencyNumber;
> +}
> +
> +QVariantMap BaseConnectionEmergencyModeInterface::immutableProperties() const
> +{
> +    QVariantMap map;
> +    return map;
> +}
> +
> +void BaseConnectionEmergencyModeInterface::createAdaptor()
> +{
> +    (void) new ConnectionInterfaceEmergencyModeAdaptor(dbusObject()->dbusConnection(),
> +            mPriv->adaptee, dbusObject());
> +}
> +
> +
> +ConnectionInterfaceEmergencyModeAdaptor::ConnectionInterfaceEmergencyModeAdaptor(const QDBusConnection& bus, QObject* adaptee, QObject* parent)
> +    : Tp::AbstractAdaptor(bus, adaptee, parent)
> +{
> +    connect(adaptee, SIGNAL(emergencyNumbersChanged(QStringList)), SIGNAL(EmergencyNumbersChanged(QStringList)));
> +}
> +
> +ConnectionInterfaceEmergencyModeAdaptor::~ConnectionInterfaceEmergencyModeAdaptor()
> +{
> +}
> +
> +QStringList ConnectionInterfaceEmergencyModeAdaptor::EmergencyNumbers(const QDBusMessage& dbusMessage)
> +{
> +    if (!adaptee()->metaObject()->indexOfMethod("emergencyNumbers(ConnectionInterfaceEmergencyModeAdaptor::EmergencyNumbersContextPtr)") == -1) {
> +        dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented")));
> +        return QStringList();
> +    }
> +
> +    EmergencyNumbersContextPtr ctx = EmergencyNumbersContextPtr(
> +            new Tp::MethodInvocationContext< QStringList >(dbusConnection(), dbusMessage));
> +    QMetaObject::invokeMethod(adaptee(), "emergencyNumbers",
> +        Q_ARG(ConnectionInterfaceEmergencyModeAdaptor::EmergencyNumbersContextPtr, ctx));
> +    return QStringList();
> +}
> 
> === added file 'tests/common/mock/emergencymodeiface.h'
> --- tests/common/mock/emergencymodeiface.h	1970-01-01 00:00:00 +0000
> +++ tests/common/mock/emergencymodeiface.h	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,121 @@
> +/**
> + * Copyright (C) 2013-2015 Canonical, Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors: Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> +            Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> + */
> +
> +#ifndef OFONOEMERGENCYMODEIFACE_H
> +#define OFONOEMERGENCYMODEIFACE_H
> +
> +// telepathy-qt
> +#include <TelepathyQt/Constants>
> +#include <TelepathyQt/BaseConnection>
> +#include <TelepathyQt/AbstractAdaptor>
> +#include <TelepathyQt/DBusError>
> +#include <TelepathyQt/Callbacks>
> +
> +class BaseConnectionEmergencyModeInterface;
> +
> +typedef Tp::SharedPtr<BaseConnectionEmergencyModeInterface> BaseConnectionEmergencyModeInterfacePtr;
> +
> +#define TP_QT_IFACE_CONNECTION_EMERGENCYMODE "com.canonical.Telephony.EmergencyMode"
> +
> +class TP_QT_EXPORT BaseConnectionEmergencyModeInterface : public Tp::AbstractConnectionInterface
> +{
> +    Q_OBJECT
> +    Q_DISABLE_COPY(BaseConnectionEmergencyModeInterface)
> +
> +public:
> +    static BaseConnectionEmergencyModeInterfacePtr create() {
> +        return BaseConnectionEmergencyModeInterfacePtr(new BaseConnectionEmergencyModeInterface());
> +    }
> +    template<typename BaseConnectionEmergencyModeInterfaceSubclass>
> +    static Tp::SharedPtr<BaseConnectionEmergencyModeInterfaceSubclass> create() {
> +        return Tp::SharedPtr<BaseConnectionEmergencyModeInterfaceSubclass>(
> +                   new BaseConnectionEmergencyModeInterfaceSubclass());
> +    }
> +    QVariantMap immutableProperties() const;
> +    virtual ~BaseConnectionEmergencyModeInterface();
> +
> +    typedef Tp::Callback1<QStringList, Tp::DBusError*> EmergencyNumbersCallback;
> +    void setEmergencyNumbersCallback(const EmergencyNumbersCallback &cb);
> +    void setFakeEmergencyNumber(const QString &fakeEmergencyNumber);
> +
> +public Q_SLOTS:
> +    void setEmergencyNumbers(const QStringList &numbers);
> +
> +protected:
> +    BaseConnectionEmergencyModeInterface();
> +
> +private:
> +    void createAdaptor();
> +
> +    class Adaptee;
> +    friend class Adaptee;
> +    struct Private;
> +    friend struct Private;
> +    Private *mPriv;
> +};
> +
> +
> +class TP_QT_EXPORT ConnectionInterfaceEmergencyModeAdaptor : public Tp::AbstractAdaptor
> +{
> +    Q_OBJECT
> +    Q_CLASSINFO("D-Bus Interface", TP_QT_IFACE_CONNECTION_EMERGENCYMODE)
> +    Q_CLASSINFO("D-Bus Introspection", ""
> +"  <interface name=\"com.canonical.Telephony.EmergencyMode\">\n"
> +"    <method name=\"EmergencyNumbers\">\n"
> +"      <arg direction=\"out\" type=\"as\" name=\"emergencyNumbers\"/>\n"
> +"    </method>\n"
> +"    <signal name=\"EmergencyNumbersChanged\">\n"
> +"      <arg type=\"as\" name=\"numbers\"/>\n"
> +"    </signal>\n"
> +"  </interface>\n"
> +"")
> +
> +public:
> +    ConnectionInterfaceEmergencyModeAdaptor(const QDBusConnection& dbusConnection, QObject* adaptee, QObject* parent);
> +    virtual ~ConnectionInterfaceEmergencyModeAdaptor();
> +
> +    typedef Tp::MethodInvocationContextPtr< QStringList > EmergencyNumbersContextPtr;
> +
> +public Q_SLOTS: // METHODS
> +    QStringList EmergencyNumbers(const QDBusMessage& dbusMessage);
> +
> +Q_SIGNALS: // SIGNALS
> +    void EmergencyNumbersChanged(const QStringList &numbers);
> +};
> +
> +
> +class TP_QT_NO_EXPORT BaseConnectionEmergencyModeInterface::Adaptee : public QObject
> +{
> +    Q_OBJECT
> +
> +public:
> +    Adaptee(BaseConnectionEmergencyModeInterface *interface);
> +    ~Adaptee();
> +
> +private Q_SLOTS:
> +    void emergencyNumbers(const ConnectionInterfaceEmergencyModeAdaptor::EmergencyNumbersContextPtr &context);
> +
> +Q_SIGNALS:
> +    void emergencyNumbersChanged(const QStringList &numbers);
> +
> +public:
> +    BaseConnectionEmergencyModeInterface *mInterface;
> +};
> +
> +#endif
> 
> === modified file 'tests/common/mock/main.cpp'
> --- handler/tests/mock/main.cpp	2014-01-07 19:53:45 +0000
> +++ tests/common/mock/main.cpp	2015-03-27 02:49:31 +0000
> @@ -31,10 +31,17 @@
>      Tp::enableDebug(true);
>      Tp::enableWarnings(true);
>  
> +    // create a standard protocol
>      Tp::BaseProtocolPtr proto = Tp::BaseProtocol::create<Protocol>(
>              QDBusConnection::sessionBus(), QLatin1String("mock"));
> +
> +    // create a phone protocol
> +    Tp::BaseProtocolPtr phoneProto = Tp::BaseProtocol::create<Protocol>(
> +            QDBusConnection::sessionBus(), QLatin1String("ofono"));
> +
>      Tp::BaseConnectionManagerPtr cm = Tp::BaseConnectionManager::create(
>              QDBusConnection::sessionBus(), QLatin1String("mock"));
> +    cm->addProtocol(phoneProto);
>      cm->addProtocol(proto);
>      cm->registerObject();
>  
> 
> === modified file 'tests/common/mock/mockconnectiondbus.cpp'
> --- handler/tests/mock/mockconnectiondbus.cpp	2014-03-20 21:03:26 +0000
> +++ tests/common/mock/mockconnectiondbus.cpp	2015-03-27 02:49:31 +0000
> @@ -28,7 +28,9 @@
>  MockConnectionDBus::MockConnectionDBus(MockConnection *parent) :
>      QObject(parent), mAdaptor(0), mConnection(parent)
>  {
> -
> +    connect(mConnection,
> +            SIGNAL(messageRead(QString)),
> +            SIGNAL(MessageRead(QString)));
>      connect(mConnection,
>              SIGNAL(messageSent(QString,QVariantMap)),
>              SIGNAL(MessageSent(QString,QVariantMap)));
> @@ -50,10 +52,22 @@
>      connect(mConnection,
>              SIGNAL(channelSplitted(QString)),
>              SIGNAL(ChannelSplitted(QString)));
> +    connect(mConnection,
> +            SIGNAL(disconnected()),
> +            SIGNAL(Disconnected()));
> +    connect(mConnection,
> +            SIGNAL(destroyed()),
> +            SIGNAL(Destroyed()));
>      qDBusRegisterMetaType<QList<QVariantMap> >();
> +    mObjectPath = "/com/canonical/MockConnection/" + mConnection->protocolName();
>      connectToBus();
>  }
>  
> +MockConnectionDBus::~MockConnectionDBus()
> +{
> +    QDBusConnection::sessionBus().unregisterObject(mObjectPath, QDBusConnection::UnregisterTree);
> +}
> +
>  bool MockConnectionDBus::connectToBus()
>  {
>      bool ok = QDBusConnection::sessionBus().registerService("com.canonical.MockConnection");
> @@ -65,7 +79,7 @@
>          mAdaptor = new MockConnectionAdaptor(this);
>      }
>  
> -    return QDBusConnection::sessionBus().registerObject("/com/canonical/MockConnection", this);
> +    return QDBusConnection::sessionBus().registerObject(mObjectPath, this);
>  }
>  
>  void MockConnectionDBus::PlaceIncomingMessage(const QString &message, const QVariantMap &properties)
> @@ -87,3 +101,39 @@
>  {
>      mConnection->setCallState(phoneNumber, state);
>  }
> +
> +void MockConnectionDBus::SetOnline(bool online)
> +{
> +    mConnection->setOnline(online);
> +}
> +
> +void MockConnectionDBus::SetPresence(const QString &status, const QString &statusMessage)
> +{
> +    Tp::DBusError error;
> +    mConnection->setPresence(status, statusMessage, &error);
> +}
> +
> +void MockConnectionDBus::SetVoicemailIndicator(bool active)
> +{
> +    mConnection->setVoicemailIndicator(active);
> +}
> +
> +void MockConnectionDBus::SetVoicemailNumber(const QString &number)
> +{
> +    mConnection->setVoicemailNumber(number);
> +}
> +
> +void MockConnectionDBus::SetVoicemailCount(int count)
> +{
> +    mConnection->setVoicemailCount(count);
> +}
> +
> +void MockConnectionDBus::SetEmergencyNumbers(const QStringList &numbers)
> +{
> +    mConnection->setEmergencyNumbers(numbers);
> +}
> +
> +QString MockConnectionDBus::Serial()
> +{
> +    return mConnection->serial();
> +}
> 
> === modified file 'tests/common/mock/mockconnectiondbus.h'
> --- handler/tests/mock/mockconnectiondbus.h	2014-03-20 21:03:26 +0000
> +++ tests/common/mock/mockconnectiondbus.h	2015-03-27 02:49:31 +0000
> @@ -30,15 +30,30 @@
>      Q_OBJECT
>  public:
>      explicit MockConnectionDBus(MockConnection *parent);
> +    ~MockConnectionDBus();
>  
>      bool connectToBus();
>      void PlaceIncomingMessage(const QString &message, const QVariantMap &properties);
>      QString PlaceCall(const QVariantMap &properties);
>      void HangupCall(const QString &callerId);
>      void SetCallState(const QString &phoneNumber, const QString &state);
> +    void SetOnline(bool online);
> +    void SetPresence(const QString &status, const QString &statusMessage);
> +
> +    // voicemail stuff
> +    void SetVoicemailIndicator(bool active);
> +    void SetVoicemailNumber(const QString &number);
> +    void SetVoicemailCount(int count);
> +
> +    // emergency numbers stuff
> +    void SetEmergencyNumbers(const QStringList &numbers);
> +
> +    // USSD stuff
> +    QString Serial();
>  
>  Q_SIGNALS:
>      // signals that will be relayed into the bus
> +    void MessageRead(const QString &messageId);
>      void MessageSent(const QString &mesasge, const QVariantMap &properties);
>      void CallReceived(const QString &callerId);
>      void CallEnded(const QString &callerId);
> @@ -47,9 +62,13 @@
>      void ChannelMerged(const QString &objectPath);
>      void ChannelSplitted(const QString &objectPath);
>  
> +    void Disconnected();
> +    void Destroyed();
> +
>  private:
>      MockConnectionAdaptor *mAdaptor;
>      MockConnection *mConnection;
> +    QString mObjectPath;
>  };
>  
>  #endif // MOCKCONNECTIONDBUS_H
> 
> === modified file 'tests/common/mock/protocol.cpp'
> --- handler/tests/mock/protocol.cpp	2014-01-07 19:53:45 +0000
> +++ tests/common/mock/protocol.cpp	2015-03-27 02:49:31 +0000
> @@ -30,6 +30,19 @@
>                                   Tp::RequestableChannelClassSpec::audioCall());
>  
>      setCreateConnectionCallback(memFun(this, &Protocol::createConnection));
> +
> +    Tp::ProtocolParameterList parameters;
> +    Tp::ProtocolParameter parameter("modem-objpath", "s", 0);
> +    parameters << parameter;
> +    setParameters(parameters);
> +
> +    addressingIface = Tp::BaseProtocolAddressingInterface::create();
> +    if (name == "ofono") {
> +        addressingIface->setAddressableVCardFields(QStringList() << "tel");
> +    } else {
> +        addressingIface->setAddressableVCardFields(QStringList() << "x-mock-im" << "x-sip");
> +    }
> +    plugInterface(addressingIface);
>  }
>  
>  Tp::BaseConnectionPtr Protocol::createConnection(const QVariantMap &parameters, Tp::DBusError *error) {
> 
> === modified file 'tests/common/mock/protocol.h'
> --- handler/tests/mock/protocol.h	2014-01-07 19:53:45 +0000
> +++ tests/common/mock/protocol.h	2015-03-27 02:49:31 +0000
> @@ -31,6 +31,7 @@
>  
>  public:
>      Protocol(const QDBusConnection &dbusConnection, const QString &name);
> +    Tp::BaseProtocolAddressingInterfacePtr addressingIface;
>  
>  private:
>      Tp::BaseConnectionPtr createConnection(const QVariantMap &parameters, Tp::DBusError *error);
> 
> === modified file 'tests/common/mock/speakeriface.h'
> --- handler/tests/mock/speakeriface.h	2014-03-13 17:11:09 +0000
> +++ tests/common/mock/speakeriface.h	2015-03-27 02:49:31 +0000
> @@ -1,19 +1,20 @@
>  /**
> - * Copyright (C) 2013 Canonical, Ltd.
> + * Copyright (C) 2013-2015 Canonical, Ltd.
>   *
>   * This program is free software: you can redistribute it and/or modify it under
> - * the terms of the GNU Lesser General Public License version 3, as published by
> + * the terms of the GNU General Public License version 3, as published by
>   * the Free Software Foundation.
>   *
>   * This program is distributed in the hope that it will be useful, but WITHOUT
>   * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
>   * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> + * General Public License for more details.
>   *
> - * You should have received a copy of the GNU Lesser General Public License
> + * You should have received a copy of the GNU General Public License
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   *
>   * Authors: Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> +            Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
>   */
>  
>  #ifndef OFONOSPEAKERIFACE_H
> 
> === modified file 'tests/common/mock/textchannel.cpp'
> --- handler/tests/mock/textchannel.cpp	2014-01-07 19:53:45 +0000
> +++ tests/common/mock/textchannel.cpp	2015-03-27 02:49:31 +0000
> @@ -36,20 +36,24 @@
>      return argument;
>  }
>  
> -MockTextChannel::MockTextChannel(MockConnection *conn, QString phoneNumber, uint targetHandle, QObject *parent):
> +MockTextChannel::MockTextChannel(MockConnection *conn, QStringList recipients, uint targetHandle, QObject *parent):
>      QObject(parent),
>      mConnection(conn),
> -    mPhoneNumber(phoneNumber),
> +    mRecipients(recipients),
>      mTargetHandle(targetHandle),
>      mMessageCounter(1)
>  {
>      qDBusRegisterMetaType<AttachmentStruct>();
>      qDBusRegisterMetaType<AttachmentList>();
>  
> +    Tp::HandleType type = recipients.count() > 1 ? Tp::HandleTypeNone : Tp::HandleTypeContact;
> +
> +
>      Tp::BaseChannelPtr baseChannel = Tp::BaseChannel::create(mConnection,
>                                                               TP_QT_IFACE_CHANNEL_TYPE_TEXT,
>                                                               targetHandle,
> -                                                             Tp::HandleTypeContact);
> +                                                             type);
> +    mBaseChannel = baseChannel;
>      Tp::BaseChannelTextTypePtr textType = Tp::BaseChannelTextType::create(baseChannel.data());
>      baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(textType));
>  
> @@ -67,9 +71,15 @@
>                                                            deliveryReportingSupport);
>  
>      mMessagesIface->setSendMessageCallback(Tp::memFun(this,&MockTextChannel::sendMessage));
> -
>      baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(mMessagesIface));
> -    mBaseChannel = baseChannel;
> +
> +    // group stuff
> +    mGroupIface = Tp::BaseChannelGroupInterface::create(Tp::ChannelGroupFlagCanAdd, conn->selfHandle());
> +    mGroupIface->setAddMembersCallback(Tp::memFun(this,&MockTextChannel::onAddMembers));
> +    mGroupIface->setRemoveMembersCallback(Tp::memFun(this,&MockTextChannel::onRemoveMembers));
> +    baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(mGroupIface));
> +    addMembers(recipients);
> +
>      mTextChannel = Tp::BaseChannelTextTypePtr::dynamicCast(mBaseChannel->interface(TP_QT_IFACE_CHANNEL_TYPE_TEXT));
>      mTextChannel->setMessageAcknowledgedCallback(Tp::memFun(this,&MockTextChannel::messageAcknowledged));
>      QObject::connect(mBaseChannel.data(), SIGNAL(closed()), this, SLOT(deleteLater()));
> @@ -101,11 +111,20 @@
>      QString messageText = body["content"].variant().toString();
>      QVariantMap properties;
>      properties["SentTime"] = QDateTime::currentDateTime().toString(Qt::ISODate);
> -    properties["Recipients"] = QStringList() << mPhoneNumber;
> +    properties["Recipients"] = mRecipients;
>      properties["Id"] = id;
>  
>      Q_EMIT messageSent(messageText, properties);
>  
> +    QTimer *deliveryReportTimer = new QTimer(this);
> +    deliveryReportTimer->setSingleShot(true);
> +    deliveryReportTimer->setInterval(100);
> +    connect(deliveryReportTimer, &QTimer::timeout, [id, deliveryReportTimer, this] {
> +        this->placeDeliveryReport(id, "sent");
> +        deliveryReportTimer->deleteLater();
> +    });
> +    deliveryReportTimer->start();
> +
>      return id;
>  }
>  
> @@ -125,7 +144,8 @@
>      Tp::MessagePartList partList;
>      Tp::MessagePart header;
>      header["message-sender"] = QDBusVariant(mTargetHandle);
> -    header["message-sender-id"] = QDBusVariant(mPhoneNumber);
> +    // FIXME: fix it
> +    header["message-sender-id"] = QDBusVariant(mRecipients.first());
>      header["message-type"] = QDBusVariant(Tp::ChannelTextMessageTypeDeliveryReport);
>      header["delivery-status"] = QDBusVariant(delivery_status);
>      header["delivery-token"] = QDBusVariant(messageId);
> @@ -145,7 +165,7 @@
>      header["message-token"] = QDBusVariant(info["SentTime"].toString() +"-" + QString::number(mMessageCounter++));
>      header["message-received"] = QDBusVariant(QDateTime::fromString(info["SentTime"].toString(), Qt::ISODate).toTime_t());
>      header["message-sender"] = QDBusVariant(mTargetHandle);
> -    header["message-sender-id"] = QDBusVariant(mPhoneNumber);
> +    header["message-sender-id"] = QDBusVariant(mRecipients.first());
>      header["message-type"] = QDBusVariant(Tp::ChannelTextMessageTypeNormal);
>      partList << header << body;
>  
> @@ -198,3 +218,45 @@
>  
>      mTextChannel->addReceivedMessage(message);
>  }
> +
> +void MockTextChannel::addMembers(QStringList recipients)
> +{
> +    Tp::UIntList handles;
> +    Q_FOREACH(const QString &recipient, recipients) {
> +        uint handle = mConnection->ensureHandle(recipient);
> +        handles << handle;
> +        if (!mRecipients.contains(recipient)) {
> +            mRecipients << recipient;
> +        }
> +        if (!mMembers.contains(handle)) {
> +            mMembers << handle;
> +        }
> +    }
> +    mGroupIface->addMembers(handles, recipients);
> +}
> +
> +QStringList MockTextChannel::recipients() const
> +{
> +    return mRecipients;
> +}
> +
> +Tp::UIntList MockTextChannel::members()
> +{
> +    return mMembers;
> +}
> +
> +void MockTextChannel::onAddMembers(const Tp::UIntList &handles, const QString &message, Tp::DBusError *error)
> +{
> +    addMembers(mConnection->inspectHandles(Tp::HandleTypeContact, handles, error));
> +}
> +
> +void MockTextChannel::onRemoveMembers(const Tp::UIntList &handles, const QString &message, Tp::DBusError *error)
> +{
> +    Q_FOREACH(uint handle, handles) {
> +        Q_FOREACH(const QString &recipient, mConnection->inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error)) {
> +            mRecipients.removeAll(recipient);
> +        }
> +        mMembers.removeAll(handle);
> +    }
> +    mGroupIface->removeMembers(handles);
> +}
> 
> === modified file 'tests/common/mock/textchannel.h'
> --- handler/tests/mock/textchannel.h	2014-01-07 19:53:45 +0000
> +++ tests/common/mock/textchannel.h	2015-03-27 02:49:31 +0000
> @@ -35,13 +35,19 @@
>  {
>      Q_OBJECT
>  public:
> -    MockTextChannel(MockConnection *conn, QString phoneNumber, uint targetHandle, QObject *parent = 0);
> +    MockTextChannel(MockConnection *conn, QStringList recipients, uint targetHandle, QObject *parent = 0);
>      QString sendMessage(const Tp::MessagePartList& message, uint flags, Tp::DBusError* error);
>      void messageReceived(const QString & message, const QVariantMap &info);
>      Tp::BaseChannelPtr baseChannel();
>      void messageAcknowledged(const QString &id);
>      void mmsReceived(const QString &id, const QVariantMap &properties);
>  
> +    void addMembers(QStringList recipients);
> +    QStringList recipients() const;
> +    Tp::UIntList members();
> +    void onAddMembers(const Tp::UIntList& handles, const QString& message, Tp::DBusError* error);
> +    void onRemoveMembers(const Tp::UIntList& handles, const QString& message, Tp::DBusError* error);
> +
>  public Q_SLOTS:
>      void placeDeliveryReport(const QString &messageId, const QString &status);
>  
> @@ -52,12 +58,14 @@
>  private:
>      ~MockTextChannel();
>      Tp::BaseChannelPtr mBaseChannel;
> -    QString mPhoneNumber;
> +    QStringList mRecipients;
>      MockConnection *mConnection;
>      uint mTargetHandle;
>      Tp::BaseChannelMessagesInterfacePtr mMessagesIface;
> +    Tp::BaseChannelGroupInterfacePtr mGroupIface;
>      Tp::BaseChannelTextTypePtr mTextChannel;
>      uint mMessageCounter;
> +    Tp::UIntList mMembers;
>  };
>  
>  #endif // MOCKTEXTCHANNEL_H
> 
> === added file 'tests/common/mock/ussdiface.cpp'
> --- tests/common/mock/ussdiface.cpp	1970-01-01 00:00:00 +0000
> +++ tests/common/mock/ussdiface.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,312 @@
> +/**
> + * Copyright (C) 2013-2015 Canonical, Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors: Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> +            Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> + */
> +
> +#include <QDebug>
> +
> +#include <TelepathyQt/Constants>
> +#include <TelepathyQt/DBusObject>
> +
> +#include "ussdiface.h"
> +
> +// Conn.I.USSD
> +BaseConnectionUSSDInterface::Adaptee::Adaptee(BaseConnectionUSSDInterface *interface)
> +    : QObject(interface),
> +      mInterface(interface)
> +{
> +}
> +
> +
> +struct TP_QT_NO_EXPORT BaseConnectionUSSDInterface::Private {
> +    Private(BaseConnectionUSSDInterface *parent)
> +        : adaptee(new BaseConnectionUSSDInterface::Adaptee(parent)) {
> +    }
> +    QString state;
> +    QString serial;
> +    InitiateCallback initiateCB;
> +    RespondCallback respondCB;
> +    CancelCallback cancelCB;
> +    BaseConnectionUSSDInterface::Adaptee *adaptee;
> +};
> +
> +BaseConnectionUSSDInterface::Adaptee::~Adaptee()
> +{
> +}
> +
> +void BaseConnectionUSSDInterface::Adaptee::initiate(const QString &command, const ConnectionInterfaceUSSDAdaptor::InitiateContextPtr &context)
> +{
> +    if (!mInterface->mPriv->initiateCB.isValid()) {
> +        context->setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"));
> +        return;
> +    }
> +    Tp::DBusError error;
> +    mInterface->mPriv->initiateCB(command, &error);
> +    if (error.isValid()) {
> +        context->setFinishedWithError(error.name(), error.message());
> +        return;
> +    }
> +    context->setFinished();
> +}
> +
> +void BaseConnectionUSSDInterface::Adaptee::respond(const QString &reply, const ConnectionInterfaceUSSDAdaptor::RespondContextPtr &context)
> +{
> +    if (!mInterface->mPriv->respondCB.isValid()) {
> +        context->setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"));
> +        return;
> +    }
> +    Tp::DBusError error;
> +    mInterface->mPriv->respondCB(reply, &error);
> +    if (error.isValid()) {
> +        context->setFinishedWithError(error.name(), error.message());
> +        return;
> +    }
> +    context->setFinished();
> +}
> +
> +void BaseConnectionUSSDInterface::Adaptee::cancel(const ConnectionInterfaceUSSDAdaptor::CancelContextPtr &context)
> +{
> +    if (!mInterface->mPriv->cancelCB.isValid()) {
> +        context->setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"));
> +        return;
> +    }
> +    Tp::DBusError error;
> +    mInterface->mPriv->cancelCB(&error);
> +    if (error.isValid()) {
> +        context->setFinishedWithError(error.name(), error.message());
> +        return;
> +    }
> +    context->setFinished();
> +}
> +
> +BaseConnectionUSSDInterface::BaseConnectionUSSDInterface()
> +    : AbstractConnectionInterface(TP_QT_IFACE_CONNECTION_USSD),
> +      mPriv(new Private(this))
> +{
> +}
> +
> +BaseConnectionUSSDInterface::~BaseConnectionUSSDInterface()
> +{
> +    delete mPriv;
> +}
> +
> +void BaseConnectionUSSDInterface::setInitiateCallback(const InitiateCallback &cb)
> +{
> +    mPriv->initiateCB = cb;
> +}
> +
> +void BaseConnectionUSSDInterface::setRespondCallback(const RespondCallback &cb)
> +{
> +    mPriv->respondCB = cb;
> +}
> +
> +void BaseConnectionUSSDInterface::setCancelCallback(const CancelCallback &cb)
> +{
> +    mPriv->cancelCB = cb;
> +}
> +
> +QString BaseConnectionUSSDInterface::state() const
> +{
> +    return mPriv->state;
> +}
> +
> +void BaseConnectionUSSDInterface::setSerial(const QString &serial) const
> +{
> +    mPriv->serial = serial;
> +}
> +
> +
> +QString BaseConnectionUSSDInterface::serial() const
> +{
> +    return mPriv->serial;
> +}
> +
> +void BaseConnectionUSSDInterface::StateChanged(const QString &state)
> +{
> +    mPriv->state = state;
> +    Q_EMIT mPriv->adaptee->stateChanged(state);
> +}
> +
> +void BaseConnectionUSSDInterface::InitiateUSSDComplete(const QString &ussdResp)
> +{
> +    Q_EMIT mPriv->adaptee->initiateUSSDComplete(ussdResp);
> +}
> +
> +void BaseConnectionUSSDInterface::RespondComplete(bool success, const QString &ussdResp)
> +{
> +    Q_EMIT mPriv->adaptee->respondComplete(success, ussdResp);
> +}
> +
> +void BaseConnectionUSSDInterface::BarringComplete(const QString &ssOp, const QString &cbService, const QVariantMap &cbMap)
> +{
> +    Q_EMIT mPriv->adaptee->barringComplete(ssOp, cbService, cbMap);
> +}
> +
> +void BaseConnectionUSSDInterface::ForwardingComplete(const QString &ssOp, const QString &cfService, const QVariantMap &cfMap)
> +{
> +    Q_EMIT mPriv->adaptee->forwardingComplete(ssOp, cfService, cfMap);
> +}
> +
> +void BaseConnectionUSSDInterface::WaitingComplete(const QString &ssOp, const QVariantMap &cwMap)
> +{
> +    Q_EMIT mPriv->adaptee->waitingComplete(ssOp, cwMap);
> +}
> +
> +void BaseConnectionUSSDInterface::CallingLinePresentationComplete(const QString &ssOp, const QString &status)
> +{
> +    Q_EMIT mPriv->adaptee->callingLinePresentationComplete(ssOp, status);
> +}
> +
> +void BaseConnectionUSSDInterface::ConnectedLinePresentationComplete(const QString &ssOp, const QString &status)
> +{
> +    Q_EMIT mPriv->adaptee->connectedLinePresentationComplete(ssOp, status);
> +}
> +
> +void BaseConnectionUSSDInterface::CallingLineRestrictionComplete(const QString &ssOp, const QString &status)
> +{
> +    Q_EMIT mPriv->adaptee->callingLineRestrictionComplete(ssOp, status);
> +}
> +
> +void BaseConnectionUSSDInterface::ConnectedLineRestrictionComplete(const QString &ssOp, const QString &status)
> +{
> +    Q_EMIT mPriv->adaptee->connectedLineRestrictionComplete(ssOp, status);
> +}
> +
> +void BaseConnectionUSSDInterface::InitiateFailed()
> +{
> +    Q_EMIT mPriv->adaptee->initiateFailed();
> +}
> +
> +void BaseConnectionUSSDInterface::NotificationReceived(const QString &message)
> +{
> +    Q_EMIT mPriv->adaptee->notificationReceived(message);
> +}
> +
> +void BaseConnectionUSSDInterface::RequestReceived(const QString &message)
> +{
> +    Q_EMIT mPriv->adaptee->requestReceived(message);
> +}
> +
> +
> +QVariantMap BaseConnectionUSSDInterface::immutableProperties() const
> +{
> +    QVariantMap map;
> +    return map;
> +}
> +
> +void BaseConnectionUSSDInterface::createAdaptor()
> +{
> +    (void) new ConnectionInterfaceUSSDAdaptor(dbusObject()->dbusConnection(),
> +            mPriv->adaptee, dbusObject());
> +}
> +
> +
> +ConnectionInterfaceUSSDAdaptor::ConnectionInterfaceUSSDAdaptor(const QDBusConnection& bus, QObject* adaptee, QObject* parent)
> +    : Tp::AbstractAdaptor(bus, adaptee, parent)
> +{
> +    connect(adaptee, SIGNAL(notificationReceived(const QString &)), SIGNAL(NotificationReceived(const QString &)));
> +    connect(adaptee, SIGNAL(requestReceived(const QString &)), SIGNAL(RequestReceived(const QString &)));
> +
> +    connect(adaptee, SIGNAL(initiateUSSDComplete(const QString &)), SIGNAL(InitiateUSSDComplete(const QString &)));
> +
> +    connect(adaptee, SIGNAL(barringComplete(const QString &, const QString &, const QVariantMap &)), 
> +        SIGNAL(BarringComplete(const QString &, const QString &, const QVariantMap &)));
> +
> +    connect(adaptee, SIGNAL(forwardingComplete(const QString &, const QString &, const QVariantMap &)), 
> +        SIGNAL(ForwardingComplete(const QString &, const QString &, const QVariantMap &)));
> +
> +    connect(adaptee, SIGNAL(waitingComplete(const QString &, const QVariantMap &)), 
> +        SIGNAL(WaitingComplete(const QString &, const QVariantMap &)));
> +
> +    connect(adaptee, SIGNAL(callingLinePresentationComplete(const QString &, const QString &)), 
> +        SIGNAL(CallingLinePresentationComplete(const QString &, const QString &)));
> +
> +    connect(adaptee, SIGNAL(connectedLinePresentationComplete(const QString &, const QString &)), 
> +        SIGNAL(ConnectedLinePresentationComplete(const QString &, const QString &)));
> +
> +    connect(adaptee, SIGNAL(callingLineRestrictionComplete(const QString &, const QString &)), 
> +        SIGNAL(CallingLineRestrictionComplete(const QString &, const QString &)));
> +
> +    connect(adaptee, SIGNAL(connectedLineRestrictionComplete(const QString &, const QString &)), 
> +        SIGNAL(ConnectedLineRestrictionComplete(const QString &, const QString &)));
> +
> +    connect(adaptee, SIGNAL(initiateFailed()), SIGNAL(InitiateFailed()));
> +
> +    connect(adaptee, SIGNAL(stateChanged(const QString&)), SIGNAL(StateChanged(const QString&)));
> +
> +    connect(adaptee, SIGNAL(respondComplete(bool, const QString &)), SIGNAL(RespondComplete(bool, const QString &)));
> +}
> +
> +ConnectionInterfaceUSSDAdaptor::~ConnectionInterfaceUSSDAdaptor()
> +{
> +}
> +
> +void ConnectionInterfaceUSSDAdaptor::Initiate(const QString &command, const QDBusMessage& dbusMessage)
> +{
> +    if (!adaptee()->metaObject()->indexOfMethod("initiate(const QString &,ConnectionInterfaceUSSDAdaptor::InitiateContextPtr)") == -1) {
> +        dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented")));
> +        return;
> +    }
> +
> +    InitiateContextPtr ctx = InitiateContextPtr(
> +            new Tp::MethodInvocationContext< >(dbusConnection(), dbusMessage));
> +    QMetaObject::invokeMethod(adaptee(), "initiate",
> +        Q_ARG(QString, command),
> +        Q_ARG(ConnectionInterfaceUSSDAdaptor::InitiateContextPtr, ctx));
> +    return;
> +}
> +
> +void ConnectionInterfaceUSSDAdaptor::Respond(const QString &reply, const QDBusMessage& dbusMessage)
> +{
> +    if (!adaptee()->metaObject()->indexOfMethod("respond(QConnectionInterfaceUSSDAdaptor::RespondContextPtr)") == -1) {
> +        dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented")));
> +        return;
> +    }
> +
> +    RespondContextPtr ctx = RespondContextPtr(
> +            new Tp::MethodInvocationContext< >(dbusConnection(), dbusMessage));
> +    QMetaObject::invokeMethod(adaptee(), "respond",
> +        Q_ARG(QString, reply),
> +        Q_ARG(ConnectionInterfaceUSSDAdaptor::RespondContextPtr, ctx));
> +    return;
> +}
> +
> +void ConnectionInterfaceUSSDAdaptor::Cancel(const QDBusMessage& dbusMessage)
> +{
> +    if (!adaptee()->metaObject()->indexOfMethod("cancel(ConnectionInterfaceUSSDAdaptor::CancelContextPtr)") == -1) {
> +        dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented")));
> +        return;
> +    }
> +
> +    CancelContextPtr ctx = CancelContextPtr(
> +            new Tp::MethodInvocationContext< >(dbusConnection(), dbusMessage));
> +    QMetaObject::invokeMethod(adaptee(), "cancel",
> +        Q_ARG(ConnectionInterfaceUSSDAdaptor::CancelContextPtr, ctx));
> +    return;
> +}
> +
> +QString ConnectionInterfaceUSSDAdaptor::Serial() const
> +{
> +    return qvariant_cast< QString >(adaptee()->property("serial"));
> +}
> +
> +
> +QString ConnectionInterfaceUSSDAdaptor::State() const
> +{
> +    return qvariant_cast< QString >(adaptee()->property("state"));
> +}
> +
> 
> === added file 'tests/common/mock/ussdiface.h'
> --- tests/common/mock/ussdiface.h	1970-01-01 00:00:00 +0000
> +++ tests/common/mock/ussdiface.h	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,244 @@
> +/**
> + * Copyright (C) 2013-2015 Canonical, Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors: Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> +            Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> + */
> +
> +#ifndef OFONOUSSDIFACE_H
> +#define OFONOUSSDIFACE_H
> +
> +// telepathy-qt
> +#include <TelepathyQt/Constants>
> +#include <TelepathyQt/BaseConnection>
> +#include <TelepathyQt/AbstractAdaptor>
> +#include <TelepathyQt/DBusError>
> +#include <TelepathyQt/Callbacks>
> +
> +class BaseConnectionUSSDInterface;
> +
> +typedef Tp::SharedPtr<BaseConnectionUSSDInterface> BaseConnectionUSSDInterfacePtr;
> +
> +#define TP_QT_IFACE_CONNECTION_USSD "com.canonical.Telephony.USSD"
> +
> +class TP_QT_EXPORT BaseConnectionUSSDInterface : public Tp::AbstractConnectionInterface
> +{
> +    Q_OBJECT
> +    Q_DISABLE_COPY(BaseConnectionUSSDInterface)
> +
> +public:
> +    static BaseConnectionUSSDInterfacePtr create() {
> +        return BaseConnectionUSSDInterfacePtr(new BaseConnectionUSSDInterface());
> +    }
> +    template<typename BaseConnectionUSSDInterfaceSubclass>
> +    static Tp::SharedPtr<BaseConnectionUSSDInterfaceSubclass> create() {
> +        return Tp::SharedPtr<BaseConnectionUSSDInterfaceSubclass>(
> +                   new BaseConnectionUSSDInterfaceSubclass());
> +    }
> +    QVariantMap immutableProperties() const;
> +    virtual ~BaseConnectionUSSDInterface();
> +
> +    typedef Tp::Callback2<void, const QString&, Tp::DBusError*> InitiateCallback;
> +    void setInitiateCallback(const InitiateCallback &cb);
> +
> +    typedef Tp::Callback2<void, const QString&, Tp::DBusError*> RespondCallback;
> +    void setRespondCallback(const RespondCallback &cb);
> +
> +    typedef Tp::Callback1<void, Tp::DBusError*> CancelCallback;
> +    void setCancelCallback(const CancelCallback &cb);
> +
> +
> +    QString state() const;
> +    QString serial() const;
> +
> +public Q_SLOTS:
> +    void NotificationReceived(const QString &message);
> +    void RequestReceived(const QString &message);
> +
> +    void InitiateUSSDComplete(const QString &ussdResp);
> +    void RespondComplete(bool success, const QString &ussdResp);
> +    void BarringComplete(const QString &ssOp, const QString &cbService, const QVariantMap &cbMap);
> +    void ForwardingComplete(const QString &ssOp, const QString &cfService, const QVariantMap &cfMap);
> +    void WaitingComplete(const QString &ssOp, const QVariantMap &cwMap);
> +    void CallingLinePresentationComplete(const QString &ssOp, const QString &status);
> +    void ConnectedLinePresentationComplete(const QString &ssOp, const QString &status);
> +    void CallingLineRestrictionComplete(const QString &ssOp, const QString &status);
> +    void ConnectedLineRestrictionComplete(const QString &ssOp, const QString &status);
> +    void InitiateFailed();
> +    void StateChanged(const QString &state);
> +
> +    void setSerial(const QString& serial) const;
> +protected:
> +    BaseConnectionUSSDInterface();
> +
> +private:
> +    void createAdaptor();
> +
> +    class Adaptee;
> +    friend class Adaptee;
> +    struct Private;
> +    friend struct Private;
> +    Private *mPriv;
> +};
> +
> +
> +class TP_QT_EXPORT ConnectionInterfaceUSSDAdaptor : public Tp::AbstractAdaptor
> +{
> +    Q_OBJECT
> +    Q_CLASSINFO("D-Bus Interface", TP_QT_IFACE_CONNECTION_USSD)
> +    Q_CLASSINFO("D-Bus Introspection", ""
> +"  <interface name=\"com.canonical.Telephony.USSD\">\n"
> +"    <property access=\"read\" type=\"s\" name=\"State\"/>\n"
> +"    <property access=\"read\" type=\"s\" name=\"Serial\"/>\n"
> +"    <method name=\"Initiate\">\n"
> +"      <arg direction=\"in\" type=\"s\" name=\"command\"/>\n"
> +"    </method>\n"
> +"    <method name=\"Respond\">\n"
> +"      <arg direction=\"in\" type=\"s\" name=\"reply\"/>\n"
> +"    </method>\n"
> +"    <method name=\"Cancel\" />\n"
> +"    <signal name=\"NotificationReceived\">\n"
> +"      <arg type=\"s\" name=\"message\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"RequestReceived\">\n"
> +"      <arg type=\"s\" name=\"message\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"InitiateUSSDComplete\">\n"
> +"      <arg type=\"s\" name=\"response\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"RespondComplete\">\n"
> +"      <arg type=\"b\" name=\"success\"/>\n"
> +"      <arg type=\"s\" name=\"response\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"BarringComplete\">\n"
> +"      <arg type=\"s\" name=\"ssOp\"/>\n"
> +"      <arg type=\"s\" name=\"cbService\"/>\n"
> +"      <arg type=\"a{sv}\" name=\"cbMap\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"ForwardingComplete\">\n"
> +"      <arg type=\"s\" name=\"ssOp\"/>\n"
> +"      <arg type=\"s\" name=\"cfService\"/>\n"
> +"      <arg type=\"a{sv}\" name=\"cfMap\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"WaitingComplete\">\n"
> +"      <arg type=\"s\" name=\"ssOp\"/>\n"
> +"      <arg type=\"a{sv}\" name=\"cwMap\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"CallingLinePresentationComplete\">\n"
> +"      <arg type=\"s\" name=\"ssOp\"/>\n"
> +"      <arg type=\"s\" name=\"status\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"ConnectedLinePresentationComplete\">\n"
> +"      <arg type=\"s\" name=\"ssOp\"/>\n"
> +"      <arg type=\"s\" name=\"status\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"CallingLineRestrictionComplete\">\n"
> +"      <arg type=\"s\" name=\"ssOp\"/>\n"
> +"      <arg type=\"s\" name=\"status\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"ConnectedLineRestrictionComplete\">\n"
> +"      <arg type=\"s\" name=\"ssOp\"/>\n"
> +"      <arg type=\"s\" name=\"status\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"InitiateFailed\" />\n"
> +"    <signal name=\"StateChanged\">\n"
> +"      <arg type=\"s\" name=\"state\"/>\n"
> +"    </signal>\n"
> +"  </interface>\n"
> +"")
> +    Q_PROPERTY(QString State READ State)
> +    Q_PROPERTY(QString Serial READ Serial)
> +
> +public:
> +    ConnectionInterfaceUSSDAdaptor(const QDBusConnection& dbusConnection, QObject* adaptee, QObject* parent);
> +    virtual ~ConnectionInterfaceUSSDAdaptor();
> +
> +    typedef Tp::MethodInvocationContextPtr< > InitiateContextPtr;
> +    typedef Tp::MethodInvocationContextPtr< > RespondContextPtr;
> +    typedef Tp::MethodInvocationContextPtr< > CancelContextPtr;
> +
> +public Q_SLOTS: // METHODS
> +    void Initiate(const QString &command, const QDBusMessage& dbusMessage);
> +    void Respond(const QString &reply, const QDBusMessage& dbusMessage);
> +    void Cancel(const QDBusMessage& dbusMessage);
> +
> +    QString State() const;
> +    QString Serial() const;
> +
> +Q_SIGNALS: // SIGNALS
> +    void NotificationReceived(const QString &message);
> +    void RequestReceived(const QString &message);
> +
> +    void InitiateUSSDComplete(const QString &ussdResp);
> +    void RespondComplete(bool success, const QString &ussdResp);
> +    void BarringComplete(const QString &ssOp, const QString &cbService, const QVariantMap &cbMap);
> +    void ForwardingComplete(const QString &ssOp, const QString &cfService, const QVariantMap &cfMap);
> +    void WaitingComplete(const QString &ssOp, const QVariantMap &cwMap);
> +    void CallingLinePresentationComplete(const QString &ssOp, const QString &status);
> +    void ConnectedLinePresentationComplete(const QString &ssOp, const QString &status);
> +    void CallingLineRestrictionComplete(const QString &ssOp, const QString &status);
> +    void ConnectedLineRestrictionComplete(const QString &ssOp, const QString &status);
> +    void InitiateFailed();
> +
> +    void StateChanged(const QString &state);
> +};
> +
> +
> +class TP_QT_NO_EXPORT BaseConnectionUSSDInterface::Adaptee : public QObject
> +{
> +    Q_OBJECT
> +    Q_PROPERTY(QString state READ state)
> +    Q_PROPERTY(QString serial READ serial)
> +
> +public:
> +    Adaptee(BaseConnectionUSSDInterface *interface);
> +    ~Adaptee();
> +    QString state() const
> +    {
> +        return mInterface->state();
> +    }
> +    QString serial() const
> +    {
> +        return mInterface->serial();
> +    }
> +
> +
> +private Q_SLOTS:
> +    void initiate(const QString &command, const ConnectionInterfaceUSSDAdaptor::InitiateContextPtr &context);
> +    void respond(const QString &reply, const ConnectionInterfaceUSSDAdaptor::RespondContextPtr &context);
> +    void cancel(const ConnectionInterfaceUSSDAdaptor::CancelContextPtr &context);
> +
> +Q_SIGNALS:
> +    void notificationReceived(const QString &message);
> +    void requestReceived(const QString &message);
> +
> +    void initiateUSSDComplete(const QString &ussdResp);
> +    void barringComplete(const QString &ssOp, const QString &cbService, const QVariantMap &cbMap);
> +    void forwardingComplete(const QString &ssOp, const QString &cfService, const QVariantMap &cfMap);
> +    void waitingComplete(const QString &ssOp, const QVariantMap &cwMap);
> +    void callingLinePresentationComplete(const QString &ssOp, const QString &status);
> +    void connectedLinePresentationComplete(const QString &ssOp, const QString &status);
> +    void callingLineRestrictionComplete(const QString &ssOp, const QString &status);
> +    void connectedLineRestrictionComplete(const QString &ssOp, const QString &status);
> +    void initiateFailed();
> +    void respondComplete(bool success, const QString &response);
> +
> +    void stateChanged(const QString &state);
> +
> +public:
> +    BaseConnectionUSSDInterface *mInterface;
> +};
> +
> +#endif
> 
> === added file 'tests/common/mock/voicemailiface.cpp'
> --- tests/common/mock/voicemailiface.cpp	1970-01-01 00:00:00 +0000
> +++ tests/common/mock/voicemailiface.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,202 @@
> +/**
> + * Copyright (C) 2013-2015 Canonical, Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors: Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> +            Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> + */
> +
> +#include <QDebug>
> +
> +#include <TelepathyQt/Constants>
> +#include <TelepathyQt/DBusObject>
> +
> +#include "voicemailiface.h"
> +
> +// Conn.I.Voicemail
> +BaseConnectionVoicemailInterface::Adaptee::Adaptee(BaseConnectionVoicemailInterface *interface)
> +    : QObject(interface),
> +      mInterface(interface)
> +{
> +}
> +
> +
> +struct TP_QT_NO_EXPORT BaseConnectionVoicemailInterface::Private {
> +    Private(BaseConnectionVoicemailInterface *parent)
> +        : adaptee(new BaseConnectionVoicemailInterface::Adaptee(parent)) {
> +    }
> +    VoicemailCountCallback voicemailCountCB;
> +    VoicemailNumberCallback voicemailNumberCB;
> +    VoicemailIndicatorCallback voicemailIndicatorCB;
> +    BaseConnectionVoicemailInterface::Adaptee *adaptee;
> +};
> +
> +BaseConnectionVoicemailInterface::Adaptee::~Adaptee()
> +{
> +}
> +
> +void BaseConnectionVoicemailInterface::Adaptee::voicemailIndicator(const ConnectionInterfaceVoicemailAdaptor::VoicemailIndicatorContextPtr &context)
> +{
> +    if (!mInterface->mPriv->voicemailIndicatorCB.isValid()) {
> +        context->setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"));
> +        return;
> +    }
> +    Tp::DBusError error;
> +    bool active = mInterface->mPriv->voicemailIndicatorCB(&error);
> +    if (error.isValid()) {
> +        context->setFinishedWithError(error.name(), error.message());
> +        return;
> +    }
> +    context->setFinished(active);
> +}
> +
> +void BaseConnectionVoicemailInterface::Adaptee::voicemailNumber(const ConnectionInterfaceVoicemailAdaptor::VoicemailNumberContextPtr &context)
> +{
> +    if (!mInterface->mPriv->voicemailNumberCB.isValid()) {
> +        context->setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"));
> +        return;
> +    }
> +    Tp::DBusError error;
> +    QString number = mInterface->mPriv->voicemailNumberCB(&error);
> +    if (error.isValid()) {
> +        context->setFinishedWithError(error.name(), error.message());
> +        return;
> +    }
> +    context->setFinished(number);
> +}
> +
> +void BaseConnectionVoicemailInterface::Adaptee::voicemailCount(const ConnectionInterfaceVoicemailAdaptor::VoicemailCountContextPtr &context)
> +{
> +    if (!mInterface->mPriv->voicemailCountCB.isValid()) {
> +        context->setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"));
> +        return;
> +    }
> +    Tp::DBusError error;
> +    uint count = mInterface->mPriv->voicemailCountCB(&error);
> +    if (error.isValid()) {
> +        context->setFinishedWithError(error.name(), error.message());
> +        return;
> +    }
> +    context->setFinished(count);
> +}
> +
> +
> +BaseConnectionVoicemailInterface::BaseConnectionVoicemailInterface()
> +    : AbstractConnectionInterface(TP_QT_IFACE_CONNECTION_VOICEMAIL),
> +      mPriv(new Private(this))
> +{
> +}
> +
> +BaseConnectionVoicemailInterface::~BaseConnectionVoicemailInterface()
> +{
> +    delete mPriv;
> +}
> +
> +void BaseConnectionVoicemailInterface::setVoicemailIndicatorCallback(const VoicemailIndicatorCallback &cb)
> +{
> +    mPriv->voicemailIndicatorCB = cb;
> +}
> +
> +void BaseConnectionVoicemailInterface::setVoicemailNumberCallback(const VoicemailNumberCallback &cb)
> +{
> +    mPriv->voicemailNumberCB = cb;
> +}
> +
> +void BaseConnectionVoicemailInterface::setVoicemailCountCallback(const VoicemailCountCallback &cb)
> +{
> +    mPriv->voicemailCountCB = cb;
> +}
> +
> +void BaseConnectionVoicemailInterface::setVoicemailCount(int count)
> +{
> +    Q_EMIT mPriv->adaptee->voicemailCountChanged(uint(count));
> +}
> +
> +void BaseConnectionVoicemailInterface::setVoicemailNumber(const QString &voicemailNumber)
> +{
> +    Q_EMIT mPriv->adaptee->voicemailNumberChanged(voicemailNumber);
> +}
> +
> +void BaseConnectionVoicemailInterface::setVoicemailIndicator(bool active)
> +{
> +    Q_EMIT mPriv->adaptee->voicemailIndicatorChanged(active);
> +}
> +
> +QVariantMap BaseConnectionVoicemailInterface::immutableProperties() const
> +{
> +    QVariantMap map;
> +    return map;
> +}
> +
> +void BaseConnectionVoicemailInterface::createAdaptor()
> +{
> +    (void) new ConnectionInterfaceVoicemailAdaptor(dbusObject()->dbusConnection(),
> +            mPriv->adaptee, dbusObject());
> +}
> +
> +
> +ConnectionInterfaceVoicemailAdaptor::ConnectionInterfaceVoicemailAdaptor(const QDBusConnection& bus, QObject* adaptee, QObject* parent)
> +    : Tp::AbstractAdaptor(bus, adaptee, parent)
> +{
> +    connect(adaptee, SIGNAL(voicemailCountChanged(uint)), SIGNAL(VoicemailCountChanged(uint)));
> +    connect(adaptee, SIGNAL(voicemailIndicatorChanged(bool)), SIGNAL(VoicemailIndicatorChanged(bool)));
> +    connect(adaptee, SIGNAL(voicemailNumberChanged(QString)), SIGNAL(VoicemailNumberChanged(QString)));
> +}
> +
> +ConnectionInterfaceVoicemailAdaptor::~ConnectionInterfaceVoicemailAdaptor()
> +{
> +}
> +
> +bool ConnectionInterfaceVoicemailAdaptor::VoicemailIndicator(const QDBusMessage& dbusMessage)
> +{
> +    if (!adaptee()->metaObject()->indexOfMethod("voicemailIndicator(ConnectionInterfaceVoicemailAdaptor::VoicemailIndicatorContextPtr)") == -1) {
> +        dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented")));
> +        return bool();
> +    }
> +
> +    VoicemailIndicatorContextPtr ctx = VoicemailIndicatorContextPtr(
> +            new Tp::MethodInvocationContext< bool >(dbusConnection(), dbusMessage));
> +    QMetaObject::invokeMethod(adaptee(), "voicemailIndicator",
> +        Q_ARG(ConnectionInterfaceVoicemailAdaptor::VoicemailIndicatorContextPtr, ctx));
> +    return bool();
> +}
> +
> +QString ConnectionInterfaceVoicemailAdaptor::VoicemailNumber(const QDBusMessage& dbusMessage)
> +{
> +    if (!adaptee()->metaObject()->indexOfMethod("voicemailNumber(ConnectionInterfaceVoicemailAdaptor::VoicemailNumberContextPtr)") == -1) {
> +        dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented")));
> +        return QString();
> +    }
> +
> +    VoicemailNumberContextPtr ctx = VoicemailNumberContextPtr(
> +            new Tp::MethodInvocationContext< QString >(dbusConnection(), dbusMessage));
> +    QMetaObject::invokeMethod(adaptee(), "voicemailNumber",
> +        Q_ARG(ConnectionInterfaceVoicemailAdaptor::VoicemailNumberContextPtr, ctx));
> +    return QString();
> +}
> +
> +uint ConnectionInterfaceVoicemailAdaptor::VoicemailCount(const QDBusMessage& dbusMessage)
> +{
> +    if (!adaptee()->metaObject()->indexOfMethod("voicemailCount(ConnectionInterfaceVoicemailAdaptor::VoicemailCountContextPtr)") == -1) {
> +        dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented")));
> +        return uint();
> +    }
> +
> +    VoicemailCountContextPtr ctx = VoicemailCountContextPtr(
> +            new Tp::MethodInvocationContext< uint >(dbusConnection(), dbusMessage));
> +    QMetaObject::invokeMethod(adaptee(), "voicemailCount",
> +        Q_ARG(ConnectionInterfaceVoicemailAdaptor::VoicemailCountContextPtr, ctx));
> +    return uint();
> +}
> +
> 
> === added file 'tests/common/mock/voicemailiface.h'
> --- tests/common/mock/voicemailiface.h	1970-01-01 00:00:00 +0000
> +++ tests/common/mock/voicemailiface.h	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,150 @@
> +/**
> + * Copyright (C) 2013-2015 Canonical, Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 3, as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
> + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authors: Tiago Salem Herrmann <tiago.herrmann at canonical.com>
> +            Gustavo Pichorim Boiko <gustavo.boiko at canonical.com>
> + */
> +
> +#ifndef OFONOVOICEMAILIFACE_H
> +#define OFONOVOICEMAILIFACE_H
> +
> +// telepathy-qt
> +#include <TelepathyQt/Constants>
> +#include <TelepathyQt/BaseConnection>
> +#include <TelepathyQt/AbstractAdaptor>
> +#include <TelepathyQt/DBusError>
> +#include <TelepathyQt/Callbacks>
> +
> +class BaseConnectionVoicemailInterface;
> +
> +typedef Tp::SharedPtr<BaseConnectionVoicemailInterface> BaseConnectionVoicemailInterfacePtr;
> +
> +#define TP_QT_IFACE_CONNECTION_VOICEMAIL "com.canonical.Telephony.Voicemail"
> +
> +class TP_QT_EXPORT BaseConnectionVoicemailInterface : public Tp::AbstractConnectionInterface
> +{
> +    Q_OBJECT
> +    Q_DISABLE_COPY(BaseConnectionVoicemailInterface)
> +
> +public:
> +    static BaseConnectionVoicemailInterfacePtr create() {
> +        return BaseConnectionVoicemailInterfacePtr(new BaseConnectionVoicemailInterface());
> +    }
> +    template<typename BaseConnectionVoicemailInterfaceSubclass>
> +    static Tp::SharedPtr<BaseConnectionVoicemailInterfaceSubclass> create() {
> +        return Tp::SharedPtr<BaseConnectionVoicemailInterfaceSubclass>(
> +                   new BaseConnectionVoicemailInterfaceSubclass());
> +    }
> +    QVariantMap immutableProperties() const;
> +    virtual ~BaseConnectionVoicemailInterface();
> +
> +    typedef Tp::Callback1<uint, Tp::DBusError*> VoicemailCountCallback;
> +    void setVoicemailCountCallback(const VoicemailCountCallback &cb);
> +
> +    typedef Tp::Callback1<bool, Tp::DBusError*> VoicemailIndicatorCallback;
> +    void setVoicemailIndicatorCallback(const VoicemailIndicatorCallback &cb);
> +
> +    typedef Tp::Callback1<QString, Tp::DBusError*> VoicemailNumberCallback;
> +    void setVoicemailNumberCallback(const VoicemailNumberCallback &cb);
> +
> +public Q_SLOTS:
> +    void setVoicemailCount(int count);
> +    void setVoicemailIndicator(bool active);
> +    void setVoicemailNumber(const QString &voicemailNumber);
> +
> +protected:
> +    BaseConnectionVoicemailInterface();
> +
> +private:
> +    void createAdaptor();
> +
> +    class Adaptee;
> +    friend class Adaptee;
> +    struct Private;
> +    friend struct Private;
> +    Private *mPriv;
> +};
> +
> +
> +class TP_QT_EXPORT ConnectionInterfaceVoicemailAdaptor : public Tp::AbstractAdaptor
> +{
> +    Q_OBJECT
> +    Q_CLASSINFO("D-Bus Interface", TP_QT_IFACE_CONNECTION_VOICEMAIL)
> +    Q_CLASSINFO("D-Bus Introspection", ""
> +"  <interface name=\"com.canonical.Telephony.Voicemail\">\n"
> +"    <method name=\"VoicemailIndicator\">\n"
> +"      <arg direction=\"out\" type=\"b\" name=\"voicemailIndicator\"/>\n"
> +"    </method>\n"
> +"    <method name=\"VoicemailNumber\">\n"
> +"      <arg direction=\"out\" type=\"s\" name=\"voicemailNumber\"/>\n"
> +"    </method>\n"
> +"    <method name=\"VoicemailCount\">\n"
> +"      <arg direction=\"out\" type=\"u\" name=\"voicemailCount\"/>\n"
> +"    </method>\n"
> +"    <signal name=\"VoicemailCountChanged\">\n"
> +"      <arg type=\"u\" name=\"count\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"VoicemailIndicatorChanged\">\n"
> +"      <arg type=\"b\" name=\"active\"/>\n"
> +"    </signal>\n"
> +"    <signal name=\"VoicemailNumberChanged\">\n"
> +"      <arg type=\"s\" name=\"voicemailNumber\"/>\n"
> +"    </signal>\n"
> +"  </interface>\n"
> +"")
> +
> +public:
> +    ConnectionInterfaceVoicemailAdaptor(const QDBusConnection& dbusConnection, QObject* adaptee, QObject* parent);
> +    virtual ~ConnectionInterfaceVoicemailAdaptor();
> +
> +    typedef Tp::MethodInvocationContextPtr< bool > VoicemailIndicatorContextPtr;
> +    typedef Tp::MethodInvocationContextPtr< QString > VoicemailNumberContextPtr;
> +    typedef Tp::MethodInvocationContextPtr< uint > VoicemailCountContextPtr;
> +
> +public Q_SLOTS: // METHODS
> +    bool VoicemailIndicator(const QDBusMessage& dbusMessage);
> +    QString VoicemailNumber(const QDBusMessage& dbusMessage);
> +    uint VoicemailCount(const QDBusMessage& dbusMessage);
> +
> +Q_SIGNALS: // SIGNALS
> +    void VoicemailCountChanged(uint count);
> +    void VoicemailIndicatorChanged(bool active);
> +    void VoicemailNumberChanged(const QString &voicemailNumber);
> +};
> +
> +
> +class TP_QT_NO_EXPORT BaseConnectionVoicemailInterface::Adaptee : public QObject
> +{
> +    Q_OBJECT
> +
> +public:
> +    Adaptee(BaseConnectionVoicemailInterface *interface);
> +    ~Adaptee();
> +
> +private Q_SLOTS:
> +    void voicemailIndicator(const ConnectionInterfaceVoicemailAdaptor::VoicemailIndicatorContextPtr &context);
> +    void voicemailNumber(const ConnectionInterfaceVoicemailAdaptor::VoicemailNumberContextPtr &context);
> +    void voicemailCount(const ConnectionInterfaceVoicemailAdaptor::VoicemailCountContextPtr &context);
> +
> +Q_SIGNALS:
> +    void voicemailCountChanged(uint count);
> +    void voicemailIndicatorChanged(bool active);
> +    void voicemailNumberChanged(const QString &voicemailNumber);
> +
> +public:
> +    BaseConnectionVoicemailInterface *mInterface;
> +};
> +
> +#endif
> 
> === renamed file 'handler/tests/mockcontroller.cpp' => 'tests/common/mockcontroller.cpp'
> --- handler/tests/mockcontroller.cpp	2014-03-20 21:03:26 +0000
> +++ tests/common/mockcontroller.cpp	2015-03-27 02:49:31 +0000
> @@ -21,27 +21,34 @@
>  #include "mockcontroller.h"
>  #include <QDBusReply>
>  
> -#define MOCK_SERVICE "com.canonical.MockConnection"
> -#define MOCK_OBJECT "/com/canonical/MockConnection"
> -#define MOCK_INTERFACE "com.canonical.MockConnection"
> -
> -MockController::MockController(QObject *parent) :
> -    QObject(parent),
> -    mMockInterface(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE)
> -{
> -    QDBusConnection::sessionBus().connect(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE, "MessageSent", this, SIGNAL(messageSent(QString, QVariantMap)));
> -    QDBusConnection::sessionBus().connect(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE, "CallReceived", this, SIGNAL(callReceived(QString)));
> -    QDBusConnection::sessionBus().connect(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE, "CallEnded", this, SIGNAL(callEnded(QString)));
> -    QDBusConnection::sessionBus().connect(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE, "CallStateChanged", this, SIGNAL(callStateChanged(QString,QString,QString)));
> -    QDBusConnection::sessionBus().connect(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE, "ConferenceCreated", this, SIGNAL(conferenceCreated(QString)));
> -    QDBusConnection::sessionBus().connect(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE, "ChannelMerged", this, SIGNAL(channelMerged(QString)));
> -    QDBusConnection::sessionBus().connect(MOCK_SERVICE, MOCK_OBJECT, MOCK_INTERFACE, "ChannelSplitted", this, SIGNAL(channelSplitted(QString)));
> -}
> -
> -MockController *MockController::instance()
> -{
> -    static MockController *self = new MockController();
> -    return self;
> +static const QString mockService("com.canonical.MockConnection");
> +static const QString mockObject("/com/canonical/MockConnection/%1");
> +static const QString mockInterface("com.canonical.MockConnection");
> +
> +MockController::MockController(const QString &protocol, QObject *parent) :
> +    QObject(parent), mProtocol(protocol), mMockObject(mockObject.arg(protocol)),
> +    mMockInterface(mockService, mockObject.arg(protocol), mockInterface)
> +{
> +    connect(&mMockInterface, SIGNAL(MessageRead(QString)),
> +            this, SIGNAL(messageRead(QString)));
> +    connect(&mMockInterface, SIGNAL(MessageSent(QString, QVariantMap)),
> +            this, SIGNAL(messageSent(QString, QVariantMap)));
> +    connect(&mMockInterface, SIGNAL(CallReceived(QString)),
> +            this, SIGNAL(callReceived(QString)));
> +    connect(&mMockInterface, SIGNAL(CallEnded(QString)),
> +            this, SIGNAL(callEnded(QString)));
> +    connect(&mMockInterface, SIGNAL(CallStateChanged(QString, QString, QString)),
> +            this, SIGNAL(callStateChanged(QString,QString,QString)));
> +    connect(&mMockInterface, SIGNAL(ConferenceCreated(QString)),
> +            this, SIGNAL(conferenceCreated(QString)));
> +    connect(&mMockInterface, SIGNAL(ChannelMerged(QString)),
> +            this, SIGNAL(channelMerged(QString)));
> +    connect(&mMockInterface, SIGNAL(ChannelSplitted(QString)),
> +            this, SIGNAL(channelSplitted(QString)));
> +    connect(&mMockInterface, SIGNAL(Disconnected()),
> +            this, SIGNAL(disconnected()));
> +    connect(&mMockInterface, SIGNAL(Destroyed()),
> +            this, SIGNAL(connectionDestroyed()));
>  }
>  
>  void MockController::placeIncomingMessage(const QString &message, const QVariantMap &properties)
> @@ -64,3 +71,43 @@
>  {
>      mMockInterface.call("SetCallState", phoneNumber, state);
>  }
> +
> +void MockController::setOnline(bool online)
> +{
> +    mMockInterface.call("SetOnline", online);
> +}
> +
> +void MockController::setPresence(const QString &status, const QString &statusMessage)
> +{
> +    mMockInterface.call("SetPresence", status, statusMessage);
> +}
> +
> +void MockController::setVoicemailNumber(const QString &number)
> +{
> +    mMockInterface.call("SetVoicemailNumber", number);
> +}
> +
> +void MockController::setVoicemailIndicator(bool active)
> +{
> +    mMockInterface.call("SetVoicemailIndicator", active);
> +}
> +
> +void MockController::setVoicemailCount(int count)
> +{
> +    mMockInterface.call("SetVoicemailCount", count);
> +}
> +
> +void MockController::setEmergencyNumbers(const QStringList &numbers)
> +{
> +    mMockInterface.call("SetEmergencyNumbers", numbers);
> +}
> +
> +QString MockController::serial()
> +{
> +    QDBusReply<QString> reply = mMockInterface.call("Serial");
> +    if (!reply.isValid()) {
> +        return QString::null;
> +    }
> +
> +    return reply.value();
> +}
> 
> === renamed file 'handler/tests/mockcontroller.h' => 'tests/common/mockcontroller.h'
> --- handler/tests/mockcontroller.h	2014-03-20 21:03:26 +0000
> +++ tests/common/mockcontroller.h	2015-03-27 02:49:31 +0000
> @@ -28,9 +28,10 @@
>  {
>      Q_OBJECT
>  public:
> -    static MockController *instance();
> +    explicit MockController(const QString &protocol, QObject *parent = 0);
>  
>  Q_SIGNALS:
> +    void messageRead(const QString &messageId);
>      void messageSent(const QString &message, const QVariantMap &properties);
>      void callReceived(const QString &callerId);
>      void callEnded(const QString &callerId);
> @@ -38,16 +39,32 @@
>      void conferenceCreated(const QString &objectPath);
>      void channelMerged(const QString &objectPath);
>      void channelSplitted(const QString &objectPath);
> +    void disconnected();
> +    void connectionDestroyed();
>  
>  public Q_SLOTS:
>      void placeIncomingMessage(const QString &message, const QVariantMap &properties);
>      QString placeCall(const QVariantMap &properties);
>      void hangupCall(const QString &callerId);
>      void setCallState(const QString &phoneNumber, const QString &state);
> +    void setOnline(bool online);
> +    void setPresence(const QString &status, const QString &statusMessage);
> +
> +    // voicemail stuff
> +    void setVoicemailNumber(const QString &number);
> +    void setVoicemailIndicator(bool active);
> +    void setVoicemailCount(int count);
> +
> +    // emergency numbers stuff
> +    void setEmergencyNumbers(const QStringList &numbers);
> +
> +    // USSD stuff
> +    QString serial();
>  
>  private:
> -    explicit MockController(QObject *parent = 0);
>      QDBusInterface mMockInterface;
> +    QString mProtocol;
> +    QString mMockObject;
>  };
>  
>  #endif // MOCKCONTROLLER_H
> 
> === added file 'tests/common/telepathytest.cpp'
> --- tests/common/telepathytest.cpp	1970-01-01 00:00:00 +0000
> +++ tests/common/telepathytest.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,140 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.
> + *
> + * This file is part of telephony-service.
> + *
> + * telephony-service is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * telephony-service is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <QtCore/QObject>
> +#include <QtTest/QtTest>
> +#include <TelepathyQt/PendingAccount>
> +#include <TelepathyQt/PendingOperation>
> +#include <TelepathyQt/Account>
> +#include "telepathytest.h"
> +#include "telepathyhelper.h"
> +#include "accountentry.h"
> +
> +void TelepathyTest::initialize()
> +{
> +    Tp::registerTypes();
> +
> +    QSignalSpy spy(TelepathyHelper::instance(), SIGNAL(setupReady()));
> +    QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, DEFAULT_TIMEOUT);
> +
> +    // just in case, remove any existing account that might be a leftover from
> +    // previous test runs
> +    Q_FOREACH(const AccountEntry *account, TelepathyHelper::instance()->accounts()) {
> +        QVERIFY(removeAccount(account->account()));
> +    }
> +
> +    // create an account manager instance to help testing
> +    Tp::Features accountFeatures;
> +    accountFeatures << Tp::Account::FeatureCore
> +                    << Tp::Account::FeatureProtocolInfo;
> +    Tp::Features contactFeatures;
> +    contactFeatures << Tp::Contact::FeatureAlias
> +                    << Tp::Contact::FeatureAvatarData
> +                    << Tp::Contact::FeatureAvatarToken
> +                    << Tp::Contact::FeatureCapabilities
> +                    << Tp::Contact::FeatureSimplePresence;
> +    Tp::Features connectionFeatures;
> +    connectionFeatures << Tp::Connection::FeatureCore
> +                       << Tp::Connection::FeatureSelfContact
> +                       << Tp::Connection::FeatureSimplePresence;
> +
> +    Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus());
> +    channelFactory->addCommonFeatures(Tp::Channel::FeatureCore);
> +
> +    mAccountManager = Tp::AccountManager::create(
> +            Tp::AccountFactory::create(QDBusConnection::sessionBus(), accountFeatures),
> +            Tp::ConnectionFactory::create(QDBusConnection::sessionBus(), connectionFeatures),
> +            channelFactory,
> +            Tp::ContactFactory::create(contactFeatures));
> +
> +    mReady = false;
> +    connect(mAccountManager->becomeReady(Tp::AccountManager::FeatureCore),
> +            &Tp::PendingOperation::finished, [=]{
> +        mReady = true;
> +    });
> +
> +    QTRY_VERIFY(mReady);
> +
> +    // give some time for telepathy stuff to settle
> +    QTest::qWait(1000);
> +}
> +
> +void TelepathyTest::doCleanup()
> +{
> +    // remove all accounts on every test to prevent garbage to go from one test to another
> +    Q_FOREACH(const Tp::AccountPtr &account, mAccounts) {
> +        QVERIFY(removeAccount(account));
> +    }
> +    QVERIFY(mAccounts.isEmpty());
> +}
> +
> +
> +Tp::AccountPtr TelepathyTest::addAccount(const QString &manager, const QString &protocol, const QString &displayName, const QVariantMap &parameters)
> +{
> +    bool finished = false;
> +    Tp::AccountPtr account;
> +    connect(mAccountManager->createAccount(manager, protocol, displayName, parameters), &Tp::PendingOperation::finished,
> +            [&](Tp::PendingOperation *op) {
> +        Tp::PendingAccount *pa = qobject_cast<Tp::PendingAccount*>(op);
> +        if (op->isError() || !pa) {
> +            qCritical() << "Failed to create account:" << op->errorName() << op->errorMessage();
> +            finished = true;
> +            return;
> +        }
> +
> +        account = pa->account();
> +        finished = true;
> +    });
> +
> +    while (!finished) {
> +        QTest::qWait(100);
> +    }
> +    mAccounts << account;
> +    return account;
> +}
> +
> +bool TelepathyTest::removeAccount(const Tp::AccountPtr &account)
> +{
> +    bool success = false;
> +    bool finished = false;
> +
> +    connect(account->remove(), &Tp::PendingOperation::finished,
> +            [&](Tp::PendingOperation *op) {
> +        success = !op->isError();
> +        finished = true;
> +    });
> +
> +    while (!finished) {
> +        QTest::qWait(100);
> +    }
> +    if (success) {
> +        mAccounts.removeAll(account);
> +    }
> +    return success;
> +}
> +
> +
> +QList<Tp::AccountPtr> TelepathyTest::accounts() const
> +{
> +    return mAccounts;
> +}
> +
> +void TelepathyTest::cleanup()
> +{
> +    doCleanup();
> +}
> 
> === added file 'tests/common/telepathytest.h'
> --- tests/common/telepathytest.h	1970-01-01 00:00:00 +0000
> +++ tests/common/telepathytest.h	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,54 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.
> + *
> + * This file is part of telephony-service.
> + *
> + * telephony-service is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * telephony-service is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef TELEPATHYTEST_H
> +#define TELEPATHYTEST_H
> +
> +#include <QtCore/QObject>
> +#include <TelepathyQt/Account>
> +#include "telepathyhelper.h"
> +
> +#define DEFAULT_TIMEOUT 15

I believe the DEFAULT_TIMEOUT needs to be in miliseconds. Also, there are some calls to QTRY_COMPARE_WITH_TIMEOUT() on TelepathyHelperTest that need to be updated as well.

> +
> +class TelepathyTest : public QObject
> +{
> +    Q_OBJECT
> +
> +protected:
> +    void initialize();
> +    void doCleanup();
> +
> +    // helper slots
> +    void onAccountManagerReady(Tp::PendingOperation *op);
> +    Tp::AccountPtr addAccount(const QString &manager,
> +                              const QString &protocol,
> +                              const QString &displayName,
> +                              const QVariantMap &parameters = QVariantMap());
> +    bool removeAccount(const Tp::AccountPtr &account);
> +    QList<Tp::AccountPtr> accounts() const;
> +
> +private Q_SLOTS:
> +    void cleanup();
> +
> +private:
> +    Tp::AccountManagerPtr mAccountManager;
> +    bool mReady;
> +    QList<Tp::AccountPtr> mAccounts;
> +};
> +
> +#endif //TELEPATHYTEST_H
> 
> === renamed directory 'handler/tests' => 'tests/handler'
> === modified file 'tests/handler/CMakeLists.txt'
> --- handler/tests/CMakeLists.txt	2014-01-22 12:33:43 +0000
> +++ tests/handler/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -1,43 +1,9 @@
>  include_directories(
>      ${CMAKE_CURRENT_BINARY_DIR}
> +    ${CMAKE_CURRENT_SOURCE_DIR}/../common
>      ${CMAKE_SOURCE_DIR}
> +    ${CMAKE_SOURCE_DIR}/libtelephonyservice
> +    ${TP_QT5_INCLUDE_DIRS}
>      )
>  
> -macro(generate_test TESTNAME USE_DBUS)
> -    add_executable(${TESTNAME} ${ARGN} ${TESTNAME}.cpp)
> -    qt5_use_modules(${TESTNAME} Core DBus Test)
> -    set(TEST_COMMAND )
> -    if (${USE_DBUS})
> -        set(TEST_COMMAND -p ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME} -p -xunitxml -p -o -p ${CMAKE_BINARY_DIR}/test_${TESTNAME}.xml)
> -        add_test(${TESTNAME} ${DBUS_RUNNER} --keep-env
> -                                            --task ${CMAKE_CURRENT_BINARY_DIR}/dbus-test-wrapper.sh ${TEST_COMMAND})
> -    else (${USE_DBUS})
> -        add_test(${TESTNAME} ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME} -xunitxml -o ${CMAKE_BINARY_DIR}/test_${TESTNAME}.xml)
> -    endif(${USE_DBUS})
> -    # force telepathy not to use system approvers when available,
> -    # also force usage of memory backend in history-service
> -    set(TMPDIR "/tmp/telephony_service_test_home")
> -    set(TEST_ENVIRONMENT "HOME=${TMPDIR};"
> -                         "HISTORY_SQLITE_DBPATH=:memory:;"
> -                         "XDG_CONFIG_HOME=${TMPDIR};
> -                          XDG_DATA_HOME=${TMPDIR};
> -                          XDG_CACHE_DIR=${TMPDIR};
> -                          XDG_CACHE_HOME=${TMPDIR};
> -                          XDG_DATA_DIRS=${TMPDIR};
> -                          MC_ACCOUNT_DIR=${TMPDIR};
> -                          MC_MANAGER_DIR=${TMPDIR}")
> -    set_tests_properties(${TESTNAME} PROPERTIES
> -                          ENVIRONMENT "${TEST_ENVIRONMENT}"
> -                          TIMEOUT 30)
> -    target_link_libraries(${TESTNAME}
> -                          ${TP_QT5_LIBRARIES}
> -                         )
> -endmacro(generate_test)
> -
> -configure_file(dbus-test-wrapper.sh.in ${CMAKE_CURRENT_BINARY_DIR}/dbus-test-wrapper.sh)
> -
> -if (DBUS_RUNNER)
> -    generate_test(HandlerTest True telepathyhelper.cpp handlercontroller.cpp mockcontroller.cpp approver.cpp)
> -endif(DBUS_RUNNER)
> -
> -add_subdirectory(mock)
> +generate_telepathy_test(HandlerTest SOURCES HandlerTest.cpp handlercontroller.cpp approver.cpp)
> 
> === modified file 'tests/handler/HandlerTest.cpp'
> --- handler/tests/HandlerTest.cpp	2014-08-18 17:37:19 +0000
> +++ tests/handler/HandlerTest.cpp	2015-03-27 02:49:31 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2013 Canonical, Ltd.
> + * Copyright (C) 2013-2015 Canonical, Ltd.
>   *
>   * This file is part of telephony-service.
>   *
> @@ -18,19 +18,22 @@
>  
>  #include <QtCore/QObject>
>  #include <QtTest/QtTest>
> +#include "telepathytest.h"
>  #include "handlercontroller.h"
>  #include "mockcontroller.h"
>  #include "approver.h"
> +#include "accountentry.h"
> +#include "accountentryfactory.h"
>  #include "telepathyhelper.h"
>  
> -#define DEFAULT_TIMEOUT 15000
> -
> -class HandlerTest : public QObject
> +class HandlerTest : public TelepathyTest
>  {
>      Q_OBJECT
>  
>  private Q_SLOTS:
>      void initTestCase();
> +    void init();
> +    void cleanup();
>      void testMakingCalls();
>      void testHangUpCall();
>      void testCallHold();
> @@ -42,34 +45,51 @@
>  private:
>      void waitForCallActive(const QString &callerId);
>      Approver *mApprover;
> +    MockController *mMockController;
> +    Tp::AccountPtr mTpAccount;
>  };
>  
>  void HandlerTest::initTestCase()
>  {
> -    QSignalSpy spy(TelepathyHelper::instance(), SIGNAL(accountReady()));
> -    QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, DEFAULT_TIMEOUT);
> -    QTRY_VERIFY_WITH_TIMEOUT(TelepathyHelper::instance()->connected(), DEFAULT_TIMEOUT);
> +    initialize();
>  
>      // register the approver
>      mApprover = new Approver(this);
>      TelepathyHelper::instance()->registerClient(mApprover, "TelephonyTestApprover");
>      // Tp-qt does not set registered status to approvers
>      QTRY_VERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(TELEPHONY_SERVICE_APPROVER));
> -
> -    // we need to wait in order to give telepathy time to notify about the approver
> -    QTest::qWait(3000);
> +}
> +
> +void HandlerTest::init()
> +{
> +    mTpAccount = addAccount("mock", "mock", "the account");
> +    QVERIFY(!mTpAccount.isNull());
> +    QTRY_VERIFY(mTpAccount->isReady(Tp::Account::FeatureCore));
> +
> +    // make sure the connection is available
> +    QTRY_VERIFY(!mTpAccount->connection().isNull());
> +    QTRY_COMPARE(mTpAccount->connection()->selfContact()->presence().type(), Tp::ConnectionPresenceTypeAvailable);
> +
> +    // and create the mock controller
> +    mMockController = new MockController("mock", this);
> +}
> +
> +void HandlerTest::cleanup()
> +{
> +    doCleanup();
> +    mMockController->deleteLater();
>  }
>  
>  void HandlerTest::testMakingCalls()
>  {
>      QString callerId("1234567");
> -    QSignalSpy callReceivedSpy(MockController::instance(), SIGNAL(callReceived(QString)));
> +    QSignalSpy callReceivedSpy(mMockController, SIGNAL(callReceived(QString)));
>      // FIXME: add support for multiple accounts
> -    HandlerController::instance()->startCall(callerId, TelepathyHelper::instance()->accountId());
> +    HandlerController::instance()->startCall(callerId, mTpAccount->uniqueIdentifier());
>      QTRY_COMPARE(callReceivedSpy.count(), 1);
>      QCOMPARE(callReceivedSpy.first().first().toString(), callerId);
>  
> -    MockController::instance()->hangupCall(callerId);
> +    mMockController->hangupCall(callerId);
>  }
>  
>  void HandlerTest::testHangUpCall()
> @@ -81,7 +101,7 @@
>      properties["State"] = "incoming";
>  
>      QSignalSpy approverCallSpy(mApprover, SIGNAL(newCall()));
> -    QString objectPath = MockController::instance()->placeCall(properties);
> +    QString objectPath = mMockController->placeCall(properties);
>      QVERIFY(!objectPath.isEmpty());
>  
>      // wait for the channel to hit the approver
> @@ -91,7 +111,7 @@
>      waitForCallActive(callerId);
>  
>      // and finally request the hangup
> -    QSignalSpy callEndedSpy(MockController::instance(), SIGNAL(callEnded(QString)));
> +    QSignalSpy callEndedSpy(mMockController, SIGNAL(callEnded(QString)));
>      HandlerController::instance()->hangUpCall(objectPath);
>      QTRY_COMPARE(callEndedSpy.count(), 1);
>  }
> @@ -105,7 +125,7 @@
>      properties["State"] = "incoming";
>  
>      QSignalSpy approverCallSpy(mApprover, SIGNAL(newCall()));
> -    QString objectPath = MockController::instance()->placeCall(properties);
> +    QString objectPath = mMockController->placeCall(properties);
>      QVERIFY(!objectPath.isEmpty());
>  
>      // wait for the channel to hit the approver
> @@ -114,7 +134,7 @@
>  
>      waitForCallActive(callerId);
>  
> -    QSignalSpy callStateSpy(MockController::instance(), SIGNAL(callStateChanged(QString,QString,QString)));
> +    QSignalSpy callStateSpy(mMockController, SIGNAL(callStateChanged(QString,QString,QString)));
>  
>      // set the call on hold
>      HandlerController::instance()->setHold(objectPath, true);
> @@ -127,7 +147,7 @@
>      QTRY_COMPARE(callStateSpy.count(), 1);
>      QCOMPARE(callStateSpy.first()[2].toString(), QString("active"));
>  
> -    MockController::instance()->hangupCall(callerId);
> +    mMockController->hangupCall(callerId);
>  }
>  
>  void HandlerTest::testCallProperties()
> @@ -140,7 +160,7 @@
>  
>      QSignalSpy approverCallSpy(mApprover, SIGNAL(newCall()));
>      QSignalSpy handlerCallPropertiesSpy(HandlerController::instance(), SIGNAL(callPropertiesChanged(QString,QVariantMap)));
> -    MockController::instance()->placeCall(properties);
> +    mMockController->placeCall(properties);
>  
>      // wait for the channel to hit the approver
>      QTRY_COMPARE(approverCallSpy.count(), 1);
> @@ -183,6 +203,7 @@
>      QCOMPARE(dtmfStringFromMethod, dtmfString);
>  
>      HandlerController::instance()->hangUpCall(objectPath);
> +    QTest::qWait(500);
>  }
>  
>  void HandlerTest::testConferenceCall()
> @@ -196,7 +217,7 @@
>      properties["State"] = "incoming";
>  
>      QSignalSpy approverCallSpy(mApprover, SIGNAL(newCall()));
> -    QString call1 = MockController::instance()->placeCall(properties);
> +    QString call1 = mMockController->placeCall(properties);
>  
>      // wait for the channel to hit the approver
>      QTRY_COMPARE(approverCallSpy.count(), 1);
> @@ -206,7 +227,7 @@
>  
>      // make a second call
>      properties["Caller"] = callerId2;
> -    QString call2 = MockController::instance()->placeCall(properties);
> +    QString call2 = mMockController->placeCall(properties);
>      // wait for the channel to hit the approver
>      QTRY_COMPARE(approverCallSpy.count(), 1);
>      mApprover->acceptCall();
> @@ -214,27 +235,27 @@
>      waitForCallActive(callerId2);
>  
>      // now create the conf call
> -    QSignalSpy conferenceCreatedSpy(MockController::instance(), SIGNAL(conferenceCreated(QString)));
> +    QSignalSpy conferenceCreatedSpy(mMockController, SIGNAL(conferenceCreated(QString)));
>      HandlerController::instance()->createConferenceCall(QStringList() << call1 << call2);
>      QTRY_COMPARE(conferenceCreatedSpy.count(), 1);
>      QString conferenceObjectPath = conferenceCreatedSpy.first().first().toString();
>  
>      // now place a third call and try to merge it
>      properties["Caller"] = callerId3;
> -    QString call3 = MockController::instance()->placeCall(properties);
> +    QString call3 = mMockController->placeCall(properties);
>      QTRY_COMPARE(approverCallSpy.count(), 1);
>      mApprover->acceptCall();
>      approverCallSpy.clear();
>      waitForCallActive(callerId3);
>  
>      // merge that call on the conference
> -    QSignalSpy channelMergedSpy(MockController::instance(), SIGNAL(channelMerged(QString)));
> +    QSignalSpy channelMergedSpy(mMockController, SIGNAL(channelMerged(QString)));
>      HandlerController::instance()->mergeCall(conferenceObjectPath, call3);
>      QTRY_COMPARE(channelMergedSpy.count(), 1);
>      QCOMPARE(channelMergedSpy.first().first().toString(), call3);
>  
>      // now try to split one of the channels
> -    QSignalSpy channelSplittedSpy(MockController::instance(), SIGNAL(channelSplitted(QString)));
> +    QSignalSpy channelSplittedSpy(mMockController, SIGNAL(channelSplitted(QString)));
>      HandlerController::instance()->splitCall(call2);
>      QTRY_COMPARE(channelSplittedSpy.count(), 1);
>      QCOMPARE(channelSplittedSpy.first().first().toString(), call2);
> @@ -244,15 +265,18 @@
>      HandlerController::instance()->hangUpCall(call1);
>      HandlerController::instance()->hangUpCall(call2);
>      HandlerController::instance()->hangUpCall(call3);
> +
> +    // just to make sure it is all done before removing the accounts
> +    QTest::qWait(500);
>  }
>  
>  void HandlerTest::testSendMessage()
>  {
>      QString recipient("22222222");
>      QString message("Hello, world!");
> -    QSignalSpy messageSentSpy(MockController::instance(), SIGNAL(messageSent(QString,QVariantMap)));
> +    QSignalSpy messageSentSpy(mMockController, SIGNAL(messageSent(QString,QVariantMap)));
>      // FIXME: add support for multiple accounts
> -    HandlerController::instance()->sendMessage(recipient, message, TelepathyHelper::instance()->accountId());
> +    HandlerController::instance()->sendMessage(recipient, message, mTpAccount->uniqueIdentifier());
>      QTRY_COMPARE(messageSentSpy.count(), 1);
>      QString sentMessage = messageSentSpy.first().first().toString();
>      QVariantMap messageProperties = messageSentSpy.first().last().value<QVariantMap>();
> @@ -284,7 +308,7 @@
>  void HandlerTest::waitForCallActive(const QString &callerId)
>  {
>      // wait until the call state is "accepted"
> -    QSignalSpy callStateSpy(MockController::instance(), SIGNAL(callStateChanged(QString,QString,QString)));
> +    QSignalSpy callStateSpy(mMockController, SIGNAL(callStateChanged(QString,QString,QString)));
>      QString state;
>      QString objectPath;
>      QString caller;
> 
> === modified file 'tests/handler/approver.cpp'
> --- handler/tests/approver.cpp	2014-01-07 19:53:45 +0000
> +++ tests/handler/approver.cpp	2015-03-27 02:49:31 +0000
> @@ -115,6 +115,7 @@
>              if (dispatchOperation->possibleHandlers().contains(TELEPHONY_SERVICE_HANDLER)) {
>                  dispatchOperation->handleWith(TELEPHONY_SERVICE_HANDLER);
>                  mDispatchOps.removeAll(dispatchOperation);
> +                break;
>              }
>          }
>      }
> 
> === renamed directory 'libtelephonyservice/tests' => 'tests/libtelephonyservice'
> === added file 'tests/libtelephonyservice/AccountEntryFactoryTest.cpp'
> --- tests/libtelephonyservice/AccountEntryFactoryTest.cpp	1970-01-01 00:00:00 +0000
> +++ tests/libtelephonyservice/AccountEntryFactoryTest.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,67 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.
> + *
> + * This file is part of telephony-service.
> + *
> + * telephony-service is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * telephony-service is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <QtCore/QObject>
> +#include <QtTest/QtTest>
> +#include "telepathytest.h"
> +#include "accountentry.h"
> +#include "accountentryfactory.h"
> +#include "ofonoaccountentry.h"
> +#include "telepathyhelper.h"
> +
> +class AccountEntryFactoryTest : public TelepathyTest
> +{
> +    Q_OBJECT
> +
> +private Q_SLOTS:
> +    void initTestCase();
> +    void testCorrectInstancesCreated();
> +    void testNullAccount();
> +};
> +
> +void AccountEntryFactoryTest::initTestCase()
> +{
> +    initialize();
> +}
> +
> +void AccountEntryFactoryTest::testCorrectInstancesCreated()
> +{
> +    Tp::AccountPtr genericTpAccount = addAccount("mock", "mock", "generic");
> +    QVERIFY(!genericTpAccount.isNull());
> +    AccountEntry *genericAccount = AccountEntryFactory::createEntry(genericTpAccount, this);
> +    QVERIFY(genericAccount);
> +    QCOMPARE(genericAccount->type(), AccountEntry::GenericAccount);
> +    QVERIFY(!qobject_cast<OfonoAccountEntry*>(genericAccount));
> +
> +    Tp::AccountPtr ofonoTpAccount = addAccount("mock", "ofono", "phone account");
> +    AccountEntry *ofonoAccount = AccountEntryFactory::createEntry(ofonoTpAccount, this);
> +    QVERIFY(ofonoAccount);
> +    QCOMPARE(ofonoAccount->type(), AccountEntry::PhoneAccount);
> +    QVERIFY(qobject_cast<OfonoAccountEntry*>(ofonoAccount));
> +}
> +
> +void AccountEntryFactoryTest::testNullAccount()
> +{
> +    AccountEntry *nullAccount = AccountEntryFactory::createEntry(Tp::AccountPtr(), this);
> +    QVERIFY(nullAccount);
> +    QVERIFY(nullAccount->accountId().isNull());
> +}
> +
> +
> +QTEST_MAIN(AccountEntryFactoryTest)
> +#include "AccountEntryFactoryTest.moc"
> 
> === added file 'tests/libtelephonyservice/AccountEntryTest.cpp'
> --- tests/libtelephonyservice/AccountEntryTest.cpp	1970-01-01 00:00:00 +0000
> +++ tests/libtelephonyservice/AccountEntryTest.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,228 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.
> + *
> + * This file is part of telephony-service.
> + *
> + * telephony-service is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * telephony-service is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <QtCore/QObject>
> +#include <QtTest/QtTest>
> +#include "telepathytest.h"
> +#include "accountentry.h"
> +#include "accountentryfactory.h"
> +#include "telepathyhelper.h"
> +#include "mockcontroller.h"
> +
> +class AccountEntryTest : public TelepathyTest
> +{
> +    Q_OBJECT
> +
> +private Q_SLOTS:
> +    void initTestCase();
> +    void init();
> +    void cleanup();
> +    void testAccountId();
> +    void testActive();
> +    void testDisplayName();
> +    void testStatus();
> +    void testStatusMessage();
> +    void testConnected();
> +    void testCompareIds_data();
> +    void testCompareIds();
> +    void testAddressableVCardFields();
> +
> +private:
> +    AccountEntry *mAccount;
> +    Tp::AccountPtr mTpAccount;
> +    AccountEntry *mNullAccount;
> +    MockController *mMockController;
> +};
> +
> +void AccountEntryTest::initTestCase()
> +{
> +    initialize();
> +
> +    // create a null account
> +    mNullAccount = AccountEntryFactory::createEntry(Tp::AccountPtr(), this);
> +}
> +
> +void AccountEntryTest::init()
> +{
> +    mTpAccount = addAccount("mock", "mock", "the account");
> +    QVERIFY(!mTpAccount.isNull());
> +    QTRY_VERIFY(mTpAccount->isReady(Tp::Account::FeatureCore));
> +
> +    mAccount = AccountEntryFactory::createEntry(mTpAccount, this);
> +    QVERIFY(mAccount);
> +
> +    // make sure the connection is available
> +    QTRY_VERIFY(!mTpAccount->connection().isNull());
> +    QTRY_COMPARE(mTpAccount->connection()->selfContact()->presence().type(), Tp::ConnectionPresenceTypeAvailable);
> +    QTRY_VERIFY(mAccount->connected());
> +
> +    // and create the mock controller
> +    mMockController = new MockController("mock", this);
> +
> +    // just in case, wait some time
> +    QTest::qWait(500);
> +}
> +
> +void AccountEntryTest::cleanup()
> +{
> +    doCleanup();
> +
> +    mAccount->deleteLater();
> +    mMockController->deleteLater();
> +}
> +
> +void AccountEntryTest::testAccountId()
> +{
> +    QCOMPARE(mAccount->accountId(), mTpAccount->uniqueIdentifier());
> +    QVERIFY(mNullAccount->accountId().isNull());
> +}
> +
> +void AccountEntryTest::testActive()
> +{
> +    QSignalSpy activeChangedSpy(mAccount, SIGNAL(activeChanged()));
> +
> +    // the mock account is enabled/connected by default, so make sure it is like that
> +    QVERIFY(mAccount->active());
> +
> +    // now set the account offline and see if the active flag changes correctly
> +    mMockController->setOnline(false);
> +    QTRY_VERIFY(!mAccount->active());
> +    QCOMPARE(activeChangedSpy.count(), 1);
> +
> +    // now re-enable the account and check that the entry is updated
> +    activeChangedSpy.clear();
> +    mMockController->setOnline(true);
> +    QTRY_VERIFY(mAccount->active());
> +    QCOMPARE(activeChangedSpy.count(), 1);
> +
> +    // check that for a null account active is false
> +    QVERIFY(!mNullAccount->active());
> +}
> +
> +void AccountEntryTest::testDisplayName()
> +{
> +    QSignalSpy displayNameChangedSpy(mAccount, SIGNAL(displayNameChanged()));
> +
> +    // check that the value is correct already
> +    QCOMPARE(mAccount->displayName(), mTpAccount->displayName());
> +
> +    // now try to set the display in the telepathy account directly and see that the entry gets updated
> +    QString newDisplayName = "some other display name";
> +    mTpAccount->setDisplayName(newDisplayName);
> +    QTRY_COMPARE(mAccount->displayName(), newDisplayName);
> +    QCOMPARE(displayNameChangedSpy.count(), 1);
> +
> +    // and try setting the display name in the entry itself
> +    displayNameChangedSpy.clear();
> +    newDisplayName = "changing again";
> +    mAccount->setDisplayName(newDisplayName);
> +    QTRY_COMPARE(mAccount->displayName(), newDisplayName);
> +    QCOMPARE(displayNameChangedSpy.count(), 1);
> +    QCOMPARE(mTpAccount->displayName(), newDisplayName);
> +
> +    // check that for a null account the displayName is null
> +    QVERIFY(mNullAccount->displayName().isNull());
> +}
> +
> +void AccountEntryTest::testStatus()
> +{
> +    QSignalSpy statusChangedSpy(mAccount, SIGNAL(statusChanged()));
> +
> +    // check that the value is correct already
> +    QCOMPARE(mAccount->status(), mTpAccount->connection()->selfContact()->presence().status());
> +
> +    // and now set a new value
> +    Tp::Presence presence(Tp::ConnectionPresenceTypeAway, "away", "away");
> +    mTpAccount->setRequestedPresence(presence);
> +
> +    QTRY_COMPARE(mAccount->status(), QString("away"));
> +    QCOMPARE(statusChangedSpy.count(), 1);
> +
> +    // check that for a null account the status is null
> +    QVERIFY(mNullAccount->status().isNull());
> +}
> +
> +void AccountEntryTest::testStatusMessage()
> +{
> +    QSignalSpy statusMessageChangedSpy(mAccount, SIGNAL(statusMessageChanged()));
> +
> +    // check that the value is correct already
> +    QTRY_COMPARE(mAccount->statusMessage(), mTpAccount->connection()->selfContact()->presence().statusMessage());
> +
> +    // and now set a new value
> +    QString statusMessage("I am online");
> +    Tp::Presence presence(Tp::ConnectionPresenceTypeAvailable, "available", statusMessage);
> +    mTpAccount->setRequestedPresence(presence);
> +
> +    QTRY_COMPARE(mAccount->statusMessage(), statusMessage);
> +    QCOMPARE(statusMessageChangedSpy.count(), 1);
> +
> +    // check that for a null account the displayName is null
> +    QVERIFY(mNullAccount->statusMessage().isNull());
> +}
> +
> +void AccountEntryTest::testConnected()
> +{
> +    QSignalSpy connectedChangedSpy(mAccount, SIGNAL(connectedChanged()));
> +
> +    // the mock account is enabled/connected by default, so make sure it is like that
> +    QVERIFY(mAccount->connected());
> +
> +    // now set the account offline and see if the active flag changes correctly
> +    mMockController->setOnline(false);
> +    QTRY_VERIFY(!mAccount->connected());
> +    QTRY_COMPARE(connectedChangedSpy.count(), 1);
> +
> +    // now re-enable the account and check that the entry is updated
> +    connectedChangedSpy.clear();
> +    mMockController->setOnline(true);
> +    QTRY_VERIFY(mAccount->connected());
> +    QTRY_COMPARE(connectedChangedSpy.count(), 1);
> +
> +    // check that for a null account the displayName is null
> +    QVERIFY(!mNullAccount->connected());
> +}
> +
> +void AccountEntryTest::testCompareIds_data()
> +{
> +    QTest::addColumn<QString>("first");
> +    QTest::addColumn<QString>("second");
> +    QTest::addColumn<bool>("expectedResult");
> +
> +    QTest::newRow("identical values") << "1234567" << "1234567" << true;
> +    QTest::newRow("case difference") << "TestId" << "testid" << false;
> +    QTest::newRow("phone prefix") << "1234567" << "1231234567" << false;
> +}
> +
> +void AccountEntryTest::testCompareIds()
> +{
> +    QFETCH(QString, first);
> +    QFETCH(QString, second);
> +    QFETCH(bool, expectedResult);
> +
> +    QCOMPARE(mAccount->compareIds(first, second), expectedResult);
> +}
> +
> +void AccountEntryTest::testAddressableVCardFields()
> +{
> +    QVERIFY(!mAccount->addressableVCardFields().isEmpty());
> +    QCOMPARE(mAccount->addressableVCardFields(), mTpAccount->protocolInfo().addressableVCardFields());
> +}
> +
> +QTEST_MAIN(AccountEntryTest)
> +#include "AccountEntryTest.moc"
> 
> === modified file 'tests/libtelephonyservice/CMakeLists.txt'
> --- libtelephonyservice/tests/CMakeLists.txt	2014-07-01 16:05:21 +0000
> +++ tests/libtelephonyservice/CMakeLists.txt	2015-03-27 02:49:31 +0000
> @@ -1,44 +1,28 @@
> +set(LIBTELEPHONYSERVICE_DIR ${CMAKE_SOURCE_DIR}/libtelephonyservice)
>  include_directories(
>      ${CMAKE_CURRENT_BINARY_DIR}
> -    ${CMAKE_SOURCE_DIR}/libtelephonyservice
> +    ${LIBTELEPHONYSERVICE_DIR}
> +    ${TP_QT5_INCLUDE_DIRS}
> +    ${CMAKE_SOURCE_DIR}/tests/common
>      )
>  
>  add_executable(GreeterContactsTestServerExe GreeterContactsTestServer.cpp)
>  qt5_use_modules(GreeterContactsTestServerExe Core DBus)
>  
> -add_executable(GreeterContactsTestExe GreeterContactsTest.cpp ../greetercontacts.cpp)
> -set_target_properties(GreeterContactsTestExe PROPERTIES COMPILE_DEFINITIONS "AS_BUSNAME=sessionBus;CMAKE_SOURCE_DIR=\"${CMAKE_SOURCE_DIR}\"")
> -qt5_use_modules(GreeterContactsTestExe Contacts Core DBus Test)
> -
> -add_test(NAME GreeterContactsTest
> -    COMMAND env
> -        -u LD_PRELOAD  # fakeroot's preload doesn't play well with dbus-test-runner
> -        -u LD_LIBRARY_PATH  # fakeroot fills this too
> -        XDG_SESSION_CLASS=greeter
> -        XDG_GREETER_DATA_DIR=${CMAKE_BINARY_DIR}/Testing/Temporary
> -        dbus-test-runner
> -        --task ${CMAKE_CURRENT_BINARY_DIR}/GreeterContactsTestServerExe
> -        --task-name server
> -        --ignore-return
> -        --task ${CMAKE_CURRENT_BINARY_DIR}/GreeterContactsTestExe
> -        --task-name test
> -        --wait-for org.freedesktop.Accounts
> -        -p -xunitxml -p -o -p ${CMAKE_BINARY_DIR}/test_GreeterContactsTest.xml
> -    DEPENDENCIES GreeterContactsTestServerExe GreeterContactsTestExe
> -    )
> -
> -macro(generate_tests)
> -    foreach(test ${ARGN})
> -        add_executable(${test} ${test}.cpp)
> -        qt5_use_modules(${test} Contacts Core DBus Qml Test)
> -        target_link_libraries(${test}
> -            telephonyservice
> -            )
> -        add_test(${test} ${CMAKE_CURRENT_BINARY_DIR}/${test} -platform offscreen -xunitxml -o ${CMAKE_BINARY_DIR}/test_${test}.xml)
> -    endforeach(test)
> -endmacro(generate_tests)
> -
> -generate_tests(
> -    ContactUtilsTest
> -    PhoneUtilsTest
> -    )
> +generate_test(GreeterContactsTest USE_DBUS
> +              SOURCES GreeterContactsTest.cpp ${LIBTELEPHONYSERVICE_DIR}/greetercontacts.cpp
> +              QT5_MODULES Contacts Core DBus Test
> +              ENVIRONMENT XDG_SESSION_CLASS=greeter XDG_GREETER_DATA_DIR=${CMAKE_BINARY_DIR}/Testing/Temporary
> +              TASKS --task env --ignore-return --task ${CMAKE_CURRENT_BINARY_DIR}/GreeterContactsTestServerExe --task-name server --ignore-return
> +              WAIT_FOR org.freedesktop.Accounts)
> +set_target_properties(GreeterContactsTest PROPERTIES COMPILE_DEFINITIONS "AS_BUSNAME=sessionBus;CMAKE_SOURCE_DIR=\"${CMAKE_SOURCE_DIR}\"")
> +add_dependencies(GreeterContactsTest GreeterContactsTestServerExe)
> +
> +generate_test(ContactUtilsTest SOURCES ContactUtilsTest.cpp QT5_MODULES Contacts Core Test LIBRARIES telephonyservice USE_UI)
> +generate_test(PhoneUtilsTest SOURCES PhoneUtilsTest.cpp LIBRARIES telephonyservice USE_UI)
> +
> +generate_telepathy_test(AccountEntryFactoryTest SOURCES AccountEntryFactoryTest.cpp)
> +generate_telepathy_test(AccountEntryTest SOURCES AccountEntryTest.cpp)
> +generate_telepathy_test(ChatManagerTest SOURCES ChatManagerTest.cpp)
> +generate_telepathy_test(OfonoAccountEntryTest SOURCES OfonoAccountEntryTest.cpp)
> +generate_telepathy_test(TelepathyHelperTest SOURCES TelepathyHelperTest.cpp)
> 
> === added file 'tests/libtelephonyservice/ChatManagerTest.cpp'
> --- tests/libtelephonyservice/ChatManagerTest.cpp	1970-01-01 00:00:00 +0000
> +++ tests/libtelephonyservice/ChatManagerTest.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,177 @@
> +/*
> + * Copyright (C) 2013-2015 Canonical, Ltd.
> + *
> + * This file is part of telephony-service.
> + *
> + * telephony-service is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * telephony-service is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <QtCore/QObject>
> +#include <QtTest/QtTest>
> +#include "telepathytest.h"
> +#include "accountentry.h"
> +#include "chatmanager.h"
> +#include "telepathyhelper.h"
> +#include "mockcontroller.h"
> +
> +class ChatManagerTest : public TelepathyTest
> +{
> +    Q_OBJECT
> +
> +private Q_SLOTS:
> +    void initTestCase();
> +    void init();
> +    void cleanup();
> +    void testSendMessage_data();
> +    void testSendMessage();
> +    void testMessageReceived();
> +    void testAcknowledgeMessages();
> +
> +private:
> +    Tp::AccountPtr mGenericTpAccount;
> +    Tp::AccountPtr mPhoneTpAccount;
> +    MockController *mGenericMockController;
> +    MockController *mPhoneMockController;
> +};
> +
> +void ChatManagerTest::initTestCase()
> +{
> +    initialize();
> +
> +    TelepathyHelper::instance()->registerChannelObserver();
> +
> +    // just give telepathy some time to register the observer
> +    QTest::qWait(1000);
> +}
> +
> +void ChatManagerTest::init()
> +{
> +    // add two accounts
> +    mGenericTpAccount = addAccount("mock", "mock", "the generic account");
> +    QTRY_VERIFY(!mGenericTpAccount->connection().isNull());
> +
> +    mPhoneTpAccount = addAccount("mock", "ofono", "the phone account");
> +    QTRY_VERIFY(!mPhoneTpAccount->connection().isNull());
> +
> +    // and create the mock controller
> +    mGenericMockController = new MockController("mock", this);
> +    mPhoneMockController = new MockController("ofono", this);
> +}
> +
> +void ChatManagerTest::cleanup()
> +{
> +    // the accounts are removed in the parent class.
> +    doCleanup();
> +
> +    mGenericMockController->deleteLater();
> +    mPhoneMockController->deleteLater();
> +}
> +
> +void ChatManagerTest::testSendMessage_data()
> +{
> +    QTest::addColumn<QStringList>("recipients");
> +    QTest::addColumn<QString>("message");
> +    QTest::addColumn<QString>("accountId");
> +
> +    QTest::newRow("message via the generic account") << (QStringList() << "recipient1") << QString("Hello world") << QString("mock/mock/account0");
> +    QTest::newRow("message via the phone account") << (QStringList() << "recipient2") << QString("Hello Phone World") << QString("mock/ofono/account0");
> +    QTest::newRow("multiple recipients") << (QStringList() << "123" << "456" << "789") << QString("Hi friends!") << QString("mock/mock/account0");
> +}
> +
> +void ChatManagerTest::testSendMessage()
> +{
> +    QFETCH(QStringList, recipients);
> +    QFETCH(QString, message);
> +    QFETCH(QString, accountId);
> +
> +    // just to make it easier, sort the recipients
> +    qSort(recipients);
> +
> +    MockController *controller = accountId.startsWith("mock/mock") ? mGenericMockController : mPhoneMockController;
> +    QSignalSpy controllerMessageSentSpy(controller, SIGNAL(messageSent(QString,QVariantMap)));
> +    QSignalSpy messageSentSpy(ChatManager::instance(), SIGNAL(messageSent(QStringList,QString)));
> +
> +    ChatManager::instance()->sendMessage(recipients, message, accountId);
> +
> +    QTRY_COMPARE(controllerMessageSentSpy.count(), 1);
> +    QString messageText = controllerMessageSentSpy.first()[0].toString();
> +    QVariantMap messageProperties = controllerMessageSentSpy.first()[1].toMap();
> +    QStringList messageRecipients = messageProperties["Recipients"].toStringList();
> +    qSort(messageRecipients);
> +    QCOMPARE(messageText, message);
> +    QCOMPARE(messageRecipients, recipients);
> +
> +    QTRY_COMPARE(messageSentSpy.count(), 1);
> +    messageRecipients = messageSentSpy.first()[0].toStringList();
> +    qSort(messageRecipients);
> +    messageText = messageSentSpy.first()[1].toString();
> +    QCOMPARE(messageText, message);
> +    QCOMPARE(messageRecipients, recipients);
> +}
> +
> +void ChatManagerTest::testMessageReceived()
> +{
> +    QSignalSpy messageReceivedSpy(ChatManager::instance(), SIGNAL(messageReceived(QString,QString,QDateTime,QString,bool)));
> +
> +    QVariantMap properties;
> +    properties["Sender"] = "12345";
> +    properties["Recipients"] = (QStringList() << "12345");
> +    QString message("Hi there");
> +    mGenericMockController->placeIncomingMessage(message, properties);
> +
> +    QTRY_COMPARE(messageReceivedSpy.count(), 1);
> +    QString sender = messageReceivedSpy.first()[0].toString();
> +    QString receivedMessage = messageReceivedSpy.first()[1].toString();
> +    QCOMPARE(sender, properties["Sender"].toString());
> +    QCOMPARE(receivedMessage, message);
> +}
> +
> +void ChatManagerTest::testAcknowledgeMessages()
> +{
> +    QSignalSpy messageReceivedSpy(ChatManager::instance(), SIGNAL(messageReceived(QString,QString,QDateTime,QString,bool)));
> +
> +    QVariantMap properties;
> +    properties["Sender"] = "12345";
> +    properties["Recipients"] = (QStringList() << "12345");
> +    QStringList messages;
> +    messages << "Hi there" << "How are you" << "Always look on the bright side of life";
> +    Q_FOREACH(const QString &message, messages) {
> +        mGenericMockController->placeIncomingMessage(message, properties);
> +        QTest::qWait(100);

why exactly do we need to wait 100ms here? to grant the order messages will be received? Looks like you sort the ids before comparing them anyway.

> +    }
> +    QTRY_COMPARE(messageReceivedSpy.count(), messages.count());
> +
> +    QStringList messageIds;
> +    for (int i = 0; i < messages.count(); ++i) {
> +        QString messageId = messageReceivedSpy[i][3].toString();
> +        messageIds << messageId;
> +    }
> +
> +    QSignalSpy messageReadSpy(mGenericMockController, SIGNAL(messageRead(QString)));
> +    Q_FOREACH(const QString &messageId, messageIds) {
> +        ChatManager::instance()->acknowledgeMessage(properties["Recipients"].toStringList(), messageId, "mock/mock/account0");
> +    }
> +
> +    QTRY_COMPARE(messageReadSpy.count(), messageIds.count());
> +    QStringList receivedIds;
> +    for (int i = 0; i < messageReadSpy.count(); ++i) {
> +        receivedIds << messageReadSpy[i][0].toString();
> +    }
> +
> +    qSort(receivedIds);
> +    qSort(messageIds);
> +    QCOMPARE(receivedIds, messageIds);
> +}
> +
> +QTEST_MAIN(ChatManagerTest)
> +#include "ChatManagerTest.moc"
> 
> === modified file 'tests/libtelephonyservice/ContactUtilsTest.cpp'
> --- libtelephonyservice/tests/ContactUtilsTest.cpp	2013-08-13 22:25:18 +0000
> +++ tests/libtelephonyservice/ContactUtilsTest.cpp	2015-03-27 02:49:31 +0000
> @@ -34,8 +34,6 @@
>      void testSharedManagerCreation();
>  };
>  
> -
> -
>  void ContactUtilsTest::testFormatContactName_data()
>  {
>      QTest::addColumn<QString>("firstName");
> 
> === modified file 'tests/libtelephonyservice/GreeterContactsTest.cpp'
> --- libtelephonyservice/tests/GreeterContactsTest.cpp	2014-07-01 16:10:33 +0000
> +++ tests/libtelephonyservice/GreeterContactsTest.cpp	2015-03-27 02:49:31 +0000
> @@ -281,8 +281,7 @@
>                           "com.canonical.TelephonyServiceApprover",
>                           QDBusConnection::sessionBus());
>      QSignalSpy spy(&iface, SIGNAL(InitialQueriesDone()));
> -    QVERIFY(spy.wait());
> -    QCOMPARE(spy.count(), 1);
> +    QTRY_COMPARE(spy.count(), 1);
>  }
>  
>  void GreeterContactsTest::makeGreeterContacts()
> @@ -293,8 +292,7 @@
>  
>  void GreeterContactsTest::waitForUpdatedSignal(bool convertedPath)
>  {
> -    QVERIFY(mSpy->wait());
> -    QCOMPARE(mSpy->count(), 1);
> +    QTRY_COMPARE(mSpy->count(), 1);
>  
>      QList<QVariant> arguments = mSpy->takeFirst();
>      QContact expectedContact = makeTestContact(convertedPath);
> 
> === modified file 'tests/libtelephonyservice/GreeterContactsTestServer.cpp'
> --- libtelephonyservice/tests/GreeterContactsTestServer.cpp	2014-07-01 16:05:21 +0000
> +++ tests/libtelephonyservice/GreeterContactsTestServer.cpp	2015-03-27 02:49:31 +0000
> @@ -24,7 +24,6 @@
>  #include <QStringList>
>  #include <unistd.h>
>  
> -
>  #include <QDebug>
>  bool listGetCalled = false;
>  bool userGetCalled = false;
> 
> === added file 'tests/libtelephonyservice/OfonoAccountEntryTest.cpp'
> --- tests/libtelephonyservice/OfonoAccountEntryTest.cpp	1970-01-01 00:00:00 +0000
> +++ tests/libtelephonyservice/OfonoAccountEntryTest.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,273 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.
> + *
> + * This file is part of telephony-service.
> + *
> + * telephony-service is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * telephony-service is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <QtCore/QObject>
> +#include <QtTest/QtTest>
> +#include "telepathytest.h"
> +#include "ofonoaccountentry.h"
> +#include "accountentryfactory.h"
> +#include "mockcontroller.h"
> +
> +class OfonoAccountEntryTest : public TelepathyTest
> +{
> +    Q_OBJECT
> +
> +private Q_SLOTS:
> +    void initTestCase();
> +    void init();
> +    void cleanup();
> +    void testAccountType();
> +    void testConnected();
> +    void testCompareIds_data();
> +    void testCompareIds();
> +    void testEmergencyNumbers();
> +    void testSerial();
> +    void testVoicemailIndicator();
> +    void testVoicemailNumber();
> +    void testVoicemailCount();
> +    void testSimLocked();
> +    void testEmergencyCallsAvailable_data();
> +    void testEmergencyCallsAvailable();
> +    void testNetworkName();
> +    void testAddressableVCardFields();
> +
> +private:
> +    OfonoAccountEntry *mAccount;
> +    Tp::AccountPtr mTpAccount;
> +    MockController *mMockController;
> +};
> +
> +void OfonoAccountEntryTest::initTestCase()
> +{
> +    initialize();
> +}
> +
> +void OfonoAccountEntryTest::init()
> +{
> +    mTpAccount = addAccount("mock", "ofono", "phone account");
> +    QVERIFY(!mTpAccount.isNull());
> +    QTRY_VERIFY(mTpAccount->isReady(Tp::Account::FeatureCore));
> +
> +    mAccount = qobject_cast<OfonoAccountEntry*>(AccountEntryFactory::createEntry(mTpAccount, this));
> +    QVERIFY(mAccount);
> +
> +    // make sure the connection is available
> +    QTRY_VERIFY(!mTpAccount->connection().isNull());
> +    QTRY_COMPARE(mTpAccount->connection()->selfContact()->presence().type(), Tp::ConnectionPresenceTypeAvailable);
> +    QTRY_VERIFY(mAccount->connected());
> +
> +    // create the mock controller
> +    mMockController = new MockController("ofono", this);
> +
> +    // just in case, wait some time
> +    QTest::qWait(500);
> +}
> +
> +void OfonoAccountEntryTest::cleanup()
> +{
> +    doCleanup();
> +    mAccount->deleteLater();
> +    mMockController->deleteLater();
> +}
> +
> +void OfonoAccountEntryTest::testAccountType()
> +{
> +    QCOMPARE(mAccount->type(), AccountEntry::PhoneAccount);
> +}
> +
> +void OfonoAccountEntryTest::testConnected()
> +{
> +    // the mock account is enabled/connected by default, so make sure it is like that
> +    QTRY_VERIFY(mAccount->connected());
> +
> +    // right now the ofono account connection status behave exactly like the generic class,
> +    // but as the code path is different, test it again
> +    QSignalSpy connectedChangedSpy(mAccount, SIGNAL(connectedChanged()));
> +
> +    // now set the account offline and see if the active flag changes correctly
> +    mMockController->setOnline(false);
> +    QTRY_VERIFY(!mAccount->connected());
> +    QCOMPARE(connectedChangedSpy.count(), 1);
> +
> +    // now re-enable the account and check that the entry is updated
> +    connectedChangedSpy.clear();
> +    mMockController->setOnline(true);
> +    QTRY_VERIFY(mAccount->connected());
> +    QCOMPARE(connectedChangedSpy.count(), 1);
> +}
> +
> +void OfonoAccountEntryTest::testCompareIds_data()
> +{
> +    QTest::addColumn<QString>("first");
> +    QTest::addColumn<QString>("second");
> +    QTest::addColumn<bool>("expectedResult");
> +
> +    QTest::newRow("identical values") << "1234567" << "1234567" << true;
> +    QTest::newRow("case difference") << "TestId" << "testid" << false;
> +    QTest::newRow("phone prefix") << "1234567" << "1231234567" << true;
> +}
> +
> +void OfonoAccountEntryTest::testCompareIds()
> +{
> +    QFETCH(QString, first);
> +    QFETCH(QString, second);
> +    QFETCH(bool, expectedResult);
> +
> +    QCOMPARE(mAccount->compareIds(first, second), expectedResult);
> +}
> +
> +void OfonoAccountEntryTest::testEmergencyNumbers()
> +{
> +    QSignalSpy emergencyNumbersChangedSpy(mAccount, SIGNAL(emergencyNumbersChanged()));
> +
> +    // check that the list is not empty at startup
> +    QVERIFY(!mAccount->emergencyNumbers().isEmpty());
> +
> +    QStringList numbers;
> +    numbers << "111" << "190" << "911";
> +    qSort(numbers);
> +    mMockController->setEmergencyNumbers(numbers);
> +    QTRY_COMPARE(emergencyNumbersChangedSpy.count(), 1);
> +
> +    QStringList emergencyNumbers = mAccount->emergencyNumbers();
> +    qSort(emergencyNumbers);
> +
> +    QCOMPARE(emergencyNumbers, numbers);
> +}
> +
> +void OfonoAccountEntryTest::testSerial()
> +{
> +    QCOMPARE(mAccount->serial(), mMockController->serial());
> +}
> +
> +void OfonoAccountEntryTest::testVoicemailIndicator()
> +{
> +    // voicemail indicator is off by default on the mock CM
> +    QVERIFY(!mAccount->voicemailIndicator());
> +
> +    QSignalSpy voiceMailIndicatorSpy(mAccount, SIGNAL(voicemailIndicatorChanged()));
> +
> +    // set to true
> +    mMockController->setVoicemailIndicator(true);
> +    QTRY_COMPARE(voiceMailIndicatorSpy.count(), 1);
> +    QVERIFY(mAccount->voicemailIndicator());
> +
> +    // and set back to false
> +    voiceMailIndicatorSpy.clear();
> +    mMockController->setVoicemailIndicator(false);
> +    QTRY_COMPARE(voiceMailIndicatorSpy.count(), 1);
> +    QVERIFY(!mAccount->voicemailIndicator());
> +}
> +
> +void OfonoAccountEntryTest::testVoicemailNumber()
> +{
> +    QSignalSpy voicemailNumberSpy(mAccount, SIGNAL(voicemailNumberChanged()));
> +
> +    // check that the number is not empty at startup
> +    QVERIFY(!mAccount->voicemailNumber().isEmpty());
> +
> +    // try changing the number
> +    QString number("12345");
> +    mMockController->setVoicemailNumber(number);
> +    QTRY_COMPARE(voicemailNumberSpy.count(), 1);
> +    QCOMPARE(mAccount->voicemailNumber(), number);
> +}
> +
> +void OfonoAccountEntryTest::testVoicemailCount()
> +{
> +    QSignalSpy voicemailCountSpy(mAccount, SIGNAL(voicemailCountChanged()));
> +
> +    // check that the count is zero at startup
> +    QCOMPARE((int)mAccount->voicemailCount(), 0);
> +
> +    // set it to a bigger value
> +    int count = 10;
> +    mMockController->setVoicemailCount(count);
> +    QTRY_COMPARE(voicemailCountSpy.count(), 1);
> +    QCOMPARE((int)mAccount->voicemailCount(), count);
> +
> +    // and back to zero
> +    voicemailCountSpy.clear();
> +    mMockController->setVoicemailCount(0);
> +    QTRY_COMPARE(voicemailCountSpy.count(), 1);
> +    QCOMPARE((int)mAccount->voicemailCount(), 0);
> +}
> +
> +void OfonoAccountEntryTest::testSimLocked()
> +{
> +    QSignalSpy simLockedSpy(mAccount, SIGNAL(simLockedChanged()));
> +
> +    // check that it is not locked by default
> +    QVERIFY(!mAccount->simLocked());
> +
> +    // now try to set the status to simlocked
> +    mMockController->setPresence("simlocked", "simlocked");
> +    QTRY_COMPARE(simLockedSpy.count(), 1);
> +    QVERIFY(mAccount->simLocked());
> +}
> +
> +void OfonoAccountEntryTest::testEmergencyCallsAvailable_data()
> +{
> +    QTest::addColumn<QString>("status");
> +    QTest::addColumn<bool>("available");
> +
> +    QTest::newRow("available") << "available" << true;
> +    QTest::newRow("away") << "away" << true;
> +    QTest::newRow("simlocked") << "simlocked" << true;
> +    QTest::newRow("flightmode") << "flightmode" << false;
> +    QTest::newRow("nosim") << "nosim" << true;
> +    QTest::newRow("nomodem") << "nomodem" << false;
> +    QTest::newRow("registered") << "registered" << true;
> +    QTest::newRow("roaming") << "roaming" << true;
> +    QTest::newRow("unregistered") << "unregistered" << true;
> +    QTest::newRow("denied") << "denied" << true;
> +    QTest::newRow("unknown") << "unknown" << true;
> +    QTest::newRow("searching") << "searching" << true;
> +}
> +
> +void OfonoAccountEntryTest::testEmergencyCallsAvailable()
> +{
> +    QFETCH(QString, status);
> +    QFETCH(bool, available);
> +
> +    mMockController->setPresence(status, "");
> +    QTRY_COMPARE(mAccount->status(), status);
> +    QCOMPARE(mAccount->emergencyCallsAvailable(), available);
> +}
> +
> +void OfonoAccountEntryTest::testNetworkName()
> +{
> +    QSignalSpy networkNameChangedSpy(mAccount, SIGNAL(statusMessageChanged()));
> +
> +    // set the value
> +    QString statusMessage("SomeNetwork");
> +    Tp::Presence presence(Tp::ConnectionPresenceTypeAvailable, "available", statusMessage);
> +    mTpAccount->setRequestedPresence(presence);
> +
> +    QTRY_COMPARE(mAccount->networkName(), statusMessage);
> +    QCOMPARE(networkNameChangedSpy.count(), 1);
> +}
> +
> +void OfonoAccountEntryTest::testAddressableVCardFields()
> +{
> +    QVERIFY(!mAccount->addressableVCardFields().isEmpty());
> +    QCOMPARE(mAccount->addressableVCardFields(), mTpAccount->protocolInfo().addressableVCardFields());
> +}
> +
> +QTEST_MAIN(OfonoAccountEntryTest)
> +#include "OfonoAccountEntryTest.moc"
> 
> === added file 'tests/libtelephonyservice/TelepathyHelperTest.cpp'
> --- tests/libtelephonyservice/TelepathyHelperTest.cpp	1970-01-01 00:00:00 +0000
> +++ tests/libtelephonyservice/TelepathyHelperTest.cpp	2015-03-27 02:49:31 +0000
> @@ -0,0 +1,286 @@
> +/*
> + * Copyright (C) 2015 Canonical, Ltd.
> + *
> + * This file is part of telephony-service.
> + *
> + * telephony-service is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * telephony-service is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <QtCore/QObject>
> +#include <QtTest/QtTest>
> +#include <TelepathyQt/PendingAccount>
> +#include <TelepathyQt/PendingOperation>
> +#include <TelepathyQt/Account>
> +#include "telepathytest.h"
> +#include "accountentry.h"
> +#include "accountentryfactory.h"
> +#include "telepathyhelper.h"
> +#include "mockcontroller.h"
> +
> +class TelepathyHelperTest : public TelepathyTest
> +{
> +    Q_OBJECT
> +
> +private Q_SLOTS:
> +    void initTestCase();
> +    void init();
> +    void cleanup();
> +    void testConnected();
> +    void testAccounts();
> +    void testAccountSorting();
> +    void testAccountIds();
> +    void testActiveAccounts();
> +    void testAccountForId();
> +    void testAccountForConnection();
> +    void testEmergencyCallsAvailable();
> +
> +private:
> +    Tp::AccountPtr mGenericTpAccount;
> +    Tp::AccountPtr mPhoneTpAccount;
> +    MockController *mGenericController;
> +    MockController *mPhoneController;
> +};
> +
> +void TelepathyHelperTest::initTestCase()
> +{
> +    initialize();
> +}
> +
> +void TelepathyHelperTest::init()
> +{
> +    // add two accounts
> +    mGenericTpAccount = addAccount("mock", "mock", "the generic account");
> +    QTRY_VERIFY(!mGenericTpAccount->connection().isNull());
> +
> +    mPhoneTpAccount = addAccount("mock", "ofono", "the phone account");
> +    QTRY_VERIFY(!mPhoneTpAccount->connection().isNull());
> +
> +    // and create the mock controller
> +    mGenericController = new MockController("mock", this);
> +    mPhoneController = new MockController("ofono", this);
> +}
> +
> +void TelepathyHelperTest::cleanup()
> +{
> +    // the accounts are removed in the parent class.
> +    doCleanup();
> +
> +    mGenericController->deleteLater();
> +    mPhoneController->deleteLater();
> +}
> +
> +void TelepathyHelperTest::testConnected()
> +{
> +    QSignalSpy connectedChangedSpy(TelepathyHelper::instance(), SIGNAL(connectedChanged()));
> +
> +    // check that the default status is connected (always true for mock accounts)
> +    QVERIFY(TelepathyHelper::instance()->connected());
> +
> +    // set one of the accounts offline and check that the connected status stays true
> +    mGenericController->setOnline(false);
> +    QTest::qWait(1000);
> +    QCOMPARE(connectedChangedSpy.count(), 0);
> +    QVERIFY(TelepathyHelper::instance()->connected());
> +
> +    // and set the other account as offline too. This time connected needs to change to false
> +    mPhoneController->setOnline(false);
> +    QTRY_COMPARE(connectedChangedSpy.count(), 1);
> +    QVERIFY(!TelepathyHelper::instance()->connected());
> +
> +    // now set one of the accounts back online
> +    connectedChangedSpy.clear();
> +    mPhoneController->setOnline(true);
> +    QTRY_COMPARE(connectedChangedSpy.count(), 1);
> +    QVERIFY(TelepathyHelper::instance()->connected());
> +
> +    // and the other one just in case
> +    connectedChangedSpy.clear();
> +    mGenericController->setOnline(true);
> +    QTest::qWait(1000);
> +    QCOMPARE(connectedChangedSpy.count(), 0);
> +    QVERIFY(TelepathyHelper::instance()->connected());
> +}
> +
> +void TelepathyHelperTest::testAccounts()
> +{
> +    QCOMPARE(TelepathyHelper::instance()->accounts().count(), 2);
> +    AccountEntry *first = TelepathyHelper::instance()->accounts()[0];
> +    AccountEntry *second = TelepathyHelper::instance()->accounts()[1];
> +    QVERIFY(first->accountId() != second->accountId());
> +
> +    // now check that new accounts are captured
> +    QSignalSpy accountsChangedSpy(TelepathyHelper::instance(), SIGNAL(accountsChanged()));
> +    Tp::AccountPtr newAccount = addAccount("mock", "mock", "extra");
> +    QVERIFY(!newAccount.isNull());
> +
> +    QTRY_COMPARE(accountsChangedSpy.count(), 1);
> +    QCOMPARE(TelepathyHelper::instance()->accounts().count(), 3);
> +
> +    bool accountFound = false;
> +    Q_FOREACH(AccountEntry *entry, TelepathyHelper::instance()->accounts()) {
> +        if (entry->accountId() == newAccount->uniqueIdentifier()) {
> +            accountFound = true;
> +            break;
> +        }
> +    }
> +    QVERIFY(accountFound);
> +
> +    // now remove the extra account and make sure it is properly removed
> +    accountsChangedSpy.clear();
> +    QVERIFY(removeAccount(newAccount));
> +    QTRY_COMPARE(accountsChangedSpy.count(), 1);
> +    QCOMPARE(TelepathyHelper::instance()->accounts().count(), 2);
> +    QCOMPARE(TelepathyHelper::instance()->accounts()[0]->accountId(), first->accountId());
> +    QCOMPARE(TelepathyHelper::instance()->accounts()[1]->accountId(), second->accountId());
> +}
> +
> +void TelepathyHelperTest::testAccountSorting()
> +{
> +    // create two accounts with modem-objpath parameters and make sure they are listed first
> +    QVariantMap parameters;
> +    parameters["modem-objpath"] = "/phonesim1";
> +    Tp::AccountPtr firstAccount = addAccount("mock", "ofono", "firstPhoneAccount", parameters);
> +    QVERIFY(!firstAccount.isNull());
> +
> +    parameters["modem-objpath"] = "/phonesim2";
> +    Tp::AccountPtr secondAccount = addAccount("mock", "ofono", "secondPhoneAccount", parameters);
> +    QVERIFY(!secondAccount.isNull());
> +
> +    // wait for the accounts to appear;
> +    QTRY_COMPARE(TelepathyHelper::instance()->accounts().count(), 4);
> +
> +    // and check the order
> +    QCOMPARE(TelepathyHelper::instance()->accounts()[0]->accountId(), firstAccount->uniqueIdentifier());
> +    QCOMPARE(TelepathyHelper::instance()->accounts()[1]->accountId(), secondAccount->uniqueIdentifier());
> +
> +    // now add a third account that should go before the two others
> +    parameters["modem-objpath"] = "/phonesim0";
> +    Tp::AccountPtr thirdAccount = addAccount("mock", "ofono", "thirdPhoneAccount", parameters);
> +    QVERIFY(!thirdAccount.isNull());
> +
> +    // wait for the accounts to appear;
> +    QTRY_COMPARE(TelepathyHelper::instance()->accounts().count(), 5);
> +    QCOMPARE(TelepathyHelper::instance()->accounts()[0]->accountId(), thirdAccount->uniqueIdentifier());
> +
> +    // and remove the created accounts
> +    QVERIFY(removeAccount(firstAccount));
> +    QVERIFY(removeAccount(secondAccount));
> +    QVERIFY(removeAccount(thirdAccount));
> +}
> +
> +void TelepathyHelperTest::testAccountIds()
> +{
> +    QCOMPARE(TelepathyHelper::instance()->accountIds().count(), 2);
> +
> +    // now check that new accounts are captured
> +    QSignalSpy accountIdsChangedSpy(TelepathyHelper::instance(), SIGNAL(accountIdsChanged()));
> +    Tp::AccountPtr newAccount = addAccount("mock", "mock", "extra");
> +    QVERIFY(!newAccount.isNull());
> +
> +    QTRY_COMPARE(accountIdsChangedSpy.count(), 1);
> +    QCOMPARE(TelepathyHelper::instance()->accountIds().count(), 3);
> +
> +    // just to make sure check that each account id matches one account
> +    for (int i = 0; i < 3; ++i) {
> +        QCOMPARE(TelepathyHelper::instance()->accountIds()[i], TelepathyHelper::instance()->accounts()[i]->accountId());
> +    }
> +
> +    // now remove the extra account and make sure it is properly removed
> +    accountIdsChangedSpy.clear();
> +    QVERIFY(removeAccount(newAccount));
> +    QTRY_COMPARE(accountIdsChangedSpy.count(), 1);
> +    QCOMPARE(TelepathyHelper::instance()->accountIds().count(), 2);
> +    QCOMPARE(TelepathyHelper::instance()->accountIds()[0], TelepathyHelper::instance()->accounts()[0]->accountId());
> +    QCOMPARE(TelepathyHelper::instance()->accountIds()[1], TelepathyHelper::instance()->accounts()[1]->accountId());
> +}
> +
> +void TelepathyHelperTest::testActiveAccounts()
> +{
> +    QSignalSpy activeAccountsSpy(TelepathyHelper::instance(), SIGNAL(activeAccountsChanged()));
> +
> +    // at startup, all accounts are active, so make sure we got two active accounts
> +    QCOMPARE(TelepathyHelper::instance()->activeAccounts().count(), 2);
> +
> +    // now set one of the accounts as offline and make sure it is captured
> +    mGenericController->setOnline(false);
> +    QTRY_COMPARE_WITH_TIMEOUT(activeAccountsSpy.count(), 1, 10);
> +    QCOMPARE(TelepathyHelper::instance()->activeAccounts().count(), 1);
> +    QCOMPARE(TelepathyHelper::instance()->activeAccounts()[0]->accountId(), mPhoneTpAccount->uniqueIdentifier());
> +
> +    // set the other account offline to make sure
> +    activeAccountsSpy.clear();
> +    mPhoneController->setOnline(false);
> +    QTRY_COMPARE_WITH_TIMEOUT(activeAccountsSpy.count(), 1, 10);
> +    QVERIFY(TelepathyHelper::instance()->activeAccounts().isEmpty());
> +
> +    // and set both accounts online again
> +    activeAccountsSpy.clear();
> +    mGenericController->setOnline(true);
> +    mPhoneController->setOnline(true);
> +    QTRY_COMPARE_WITH_TIMEOUT(activeAccountsSpy.count(), 2, 10);
> +    QCOMPARE(TelepathyHelper::instance()->activeAccounts().count(), 2);
> +}
> +
> +void TelepathyHelperTest::testAccountForId()
> +{
> +    AccountEntry *genericAccount = TelepathyHelper::instance()->accountForId(mGenericTpAccount->uniqueIdentifier());
> +    QVERIFY(genericAccount);
> +    QCOMPARE(genericAccount->accountId(), mGenericTpAccount->uniqueIdentifier());
> +
> +    AccountEntry *phoneAccount = TelepathyHelper::instance()->accountForId(mPhoneTpAccount->uniqueIdentifier());
> +    QVERIFY(phoneAccount);
> +    QCOMPARE(phoneAccount->accountId(), mPhoneTpAccount->uniqueIdentifier());
> +}
> +
> +void TelepathyHelperTest::testAccountForConnection()
> +{
> +    Q_FOREACH(AccountEntry *account, TelepathyHelper::instance()->accounts()) {
> +        AccountEntry *entry = TelepathyHelper::instance()->accountForConnection(account->account()->connection());
> +        QVERIFY(entry);
> +        QCOMPARE(entry, account);
> +    }
> +}
> +
> +void TelepathyHelperTest::testEmergencyCallsAvailable()
> +{
> +    QSignalSpy emergencyCallsSpy(TelepathyHelper::instance(), SIGNAL(emergencyCallsAvailableChanged()));
> +
> +    // check that calls are available by default
> +    QVERIFY(TelepathyHelper::instance()->emergencyCallsAvailable());
> +
> +    // set the generic account as "flightmode" and make sure it doesn't affect the emergencyCallsAvailable
> +    mGenericController->setPresence("flightmode", "");
> +    QTest::qWait(500);
> +    QCOMPARE(emergencyCallsSpy.count(), 0);
> +    QVERIFY(TelepathyHelper::instance()->emergencyCallsAvailable());
> +
> +    // now set the phone account as "flightmode", and see if the emergencyCallsAvailable value
> +    mPhoneController->setPresence("flightmode", "");
> +    QTRY_COMPARE(emergencyCallsSpy.count(), 1);
> +    QVERIFY(!TelepathyHelper::instance()->emergencyCallsAvailable());
> +
> +    // set the generic account online and check if it affects the value
> +    emergencyCallsSpy.clear();
> +    mGenericController->setOnline(true);
> +    QTest::qWait(500);
> +    QCOMPARE(emergencyCallsSpy.count(), 0);
> +    QVERIFY(!TelepathyHelper::instance()->emergencyCallsAvailable());
> +
> +    // and finally set the phone account back online
> +    mPhoneController->setOnline(true);
> +    QTRY_COMPARE(emergencyCallsSpy.count(), 1);
> +    QVERIFY(TelepathyHelper::instance()->emergencyCallsAvailable());
> +}
> +
> +QTEST_MAIN(TelepathyHelperTest)
> +#include "TelepathyHelperTest.moc"
> 


-- 
https://code.launchpad.net/~boiko/telephony-service/non_phone_accounts_tests/+merge/252522
Your team Ubuntu Phablet Team is subscribed to branch lp:telephony-service.



More information about the Ubuntu-reviews mailing list