From 58f10c864fd301fbe509c232488cab7b5c99a6b8 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Mon, 7 Sep 2015 15:11:19 +0200 Subject: test version for gmenuharness --- tests/CMakeLists.txt | 197 +++++++-------- tests/dbus-types/CMakeLists.txt | 48 ++++ .../com.ubuntu.AccountsService.Sound.xml | 9 + tests/dbus-types/dbus-types.h | 40 ++++ .../org.PulseAudio.Ext.StreamRestore1.xml | 7 + tests/dbus-types/org.freedesktop.Accounts.xml | 8 + .../dbus-types/org.freedesktop.DBus.Properties.xml | 21 ++ tests/dbus-types/org.gtk.Menus.xml | 6 + tests/dbus-types/pulseaudio-volume.cpp | 156 ++++++++++++ tests/dbus-types/pulseaudio-volume.h | 71 ++++++ tests/integration/CMakeLists.txt | 128 ++++++++++ tests/integration/Copy of test-sound.wav | Bin 0 -> 191989 bytes tests/integration/indicator-sound-test-base.cpp | 263 +++++++++++++++++++++ tests/integration/indicator-sound-test-base.h | 83 +++++++ tests/integration/main.cpp | 58 +++++ tests/integration/test-indicator.cpp | 182 ++++++++++++++ tests/integration/test-sound.wav | Bin 0 -> 7665640 bytes tests/integration/touch-stream-restore.table | 4 + tests/integration/utils/dbus-pulse-volume.cpp | 252 ++++++++++++++++++++ tests/integration/utils/dbus-pulse-volume.h | 57 +++++ tests/integration/utils/get-volume.cpp | 33 +++ tests/integration/utils/set-volume.cpp | 36 +++ 22 files changed, 1562 insertions(+), 97 deletions(-) create mode 100644 tests/dbus-types/CMakeLists.txt create mode 100644 tests/dbus-types/com.ubuntu.AccountsService.Sound.xml create mode 100644 tests/dbus-types/dbus-types.h create mode 100644 tests/dbus-types/org.PulseAudio.Ext.StreamRestore1.xml create mode 100644 tests/dbus-types/org.freedesktop.Accounts.xml create mode 100644 tests/dbus-types/org.freedesktop.DBus.Properties.xml create mode 100644 tests/dbus-types/org.gtk.Menus.xml create mode 100644 tests/dbus-types/pulseaudio-volume.cpp create mode 100644 tests/dbus-types/pulseaudio-volume.h create mode 100644 tests/integration/CMakeLists.txt create mode 100644 tests/integration/Copy of test-sound.wav create mode 100644 tests/integration/indicator-sound-test-base.cpp create mode 100644 tests/integration/indicator-sound-test-base.h create mode 100644 tests/integration/main.cpp create mode 100644 tests/integration/test-indicator.cpp create mode 100644 tests/integration/test-sound.wav create mode 100755 tests/integration/touch-stream-restore.table create mode 100644 tests/integration/utils/dbus-pulse-volume.cpp create mode 100644 tests/integration/utils/dbus-pulse-volume.h create mode 100644 tests/integration/utils/get-volume.cpp create mode 100644 tests/integration/utils/set-volume.cpp (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2bbd8c5..4c28cdf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,10 +5,10 @@ include_directories(${GTEST_INCLUDE_DIR}) -add_library (gtest STATIC +add_library (gtest-static STATIC ${GTEST_SOURCE_DIR}/gtest-all.cc ${GTEST_SOURCE_DIR}/gtest_main.cc) -target_link_libraries(gtest ${GTEST_LIBS}) +target_link_libraries(gtest-static ${GTEST_LIBS}) ########################### # GSettings Schema @@ -41,74 +41,74 @@ set(VALA_MOCKS_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/vala-mocks.h") set(VALA_MOCKS_SYMBOLS_PATH "${CMAKE_CURRENT_BINARY_DIR}/vala-mocks.def") vala_init(vala-mocks - DEPENDS - indicator-sound-service-lib - PACKAGES - config - gio-2.0 - gio-unix-2.0 - libxml-2.0 - libpulse - libpulse-mainloop-glib - libnotify - accounts-service - indicator-sound-service - OPTIONS - --ccode - --thread - --vapidir=${CMAKE_BINARY_DIR}/src/ - --vapidir=${CMAKE_SOURCE_DIR}/vapi/ - --vapidir=. + DEPENDS + indicator-sound-service-lib + PACKAGES + config + gio-2.0 + gio-unix-2.0 + libxml-2.0 + libpulse + libpulse-mainloop-glib + libnotify + accounts-service + indicator-sound-service + OPTIONS + --ccode + --thread + --vapidir=${CMAKE_BINARY_DIR}/src/ + --vapidir=${CMAKE_SOURCE_DIR}/vapi/ + --vapidir=. ) vala_add(vala-mocks - media-player-mock.vala + media-player-mock.vala ) vala_add(vala-mocks - media-player-list-mock.vala + media-player-list-mock.vala ) vala_add(vala-mocks - volume-control-mock.vala + volume-control-mock.vala ) vala_finish(vala-mocks - SOURCES - vala_mocks_VALA_SOURCES - OUTPUTS - vala_mocks_VALA_C - GENERATE_HEADER - ${VALA_MOCKS_HEADER_PATH} - GENERATE_SYMBOLS - ${VALA_MOCKS_SYMBOLS_PATH} + SOURCES + vala_mocks_VALA_SOURCES + OUTPUTS + vala_mocks_VALA_C + GENERATE_HEADER + ${VALA_MOCKS_HEADER_PATH} + GENERATE_SYMBOLS + ${VALA_MOCKS_SYMBOLS_PATH} ) set_source_files_properties( - ${vala_mocks_VALA_SOURCES} - PROPERTIES - HEADER_FILE_ONLY TRUE + ${vala_mocks_VALA_SOURCES} + PROPERTIES + HEADER_FILE_ONLY TRUE ) set( - VALA_MOCKS_SOURCES - ${vala_mocks_VALA_SOURCES} - ${vala_mocks_VALA_C} - ${VALA_MOCKS_SYMBOLS_PATH} + VALA_MOCKS_SOURCES + ${vala_mocks_VALA_SOURCES} + ${vala_mocks_VALA_C} + ${VALA_MOCKS_SYMBOLS_PATH} ) add_definitions( - -Wno-unused-but-set-variable + -Wno-unused-but-set-variable ) add_library( - vala-mocks-lib STATIC - ${VALA_MOCKS_SOURCES} + vala-mocks-lib STATIC + ${VALA_MOCKS_SOURCES} ) target_link_libraries( - vala-mocks-lib - indicator-sound-service-lib + vala-mocks-lib + indicator-sound-service-lib ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) @@ -118,9 +118,9 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) ########################### add_library( - pulse-mock - SHARED - pa-mock.cpp + pulse-mock + SHARED + pa-mock.cpp ) target_link_libraries (pulse-mock ${PULSEAUDIO_LIBRARIES}) @@ -131,7 +131,7 @@ target_link_libraries (pulse-mock ${PULSEAUDIO_LIBRARIES}) include_directories(${CMAKE_SOURCE_DIR}/src) add_executable (name-watch-test name-watch-test.cc ${CMAKE_SOURCE_DIR}/src/bus-watch-namespace.c) -target_link_libraries (name-watch-test gtest ${SOUNDSERVICE_LIBRARIES}) +target_link_libraries (name-watch-test gtest-static ${SOUNDSERVICE_LIBRARIES}) add_test(name-watch-test name-watch-test) ########################### @@ -141,21 +141,21 @@ add_test(name-watch-test name-watch-test) include_directories(${CMAKE_SOURCE_DIR}/src) add_executable (accounts-service-user-test accounts-service-user.cc) target_link_libraries ( - accounts-service-user-test - indicator-sound-service-lib - vala-mocks-lib - gtest - ${SOUNDSERVICE_LIBRARIES} - ${TEST_LIBRARIES} + accounts-service-user-test + indicator-sound-service-lib + vala-mocks-lib + gtest-static + ${SOUNDSERVICE_LIBRARIES} + ${TEST_LIBRARIES} ) # Split tests to work around libaccountservice sucking add_test(accounts-service-user-test-basic - accounts-service-user-test --gtest_filter=AccountsServiceUserTest.BasicObject + accounts-service-user-test --gtest_filter=AccountsServiceUserTest.BasicObject ) add_test(accounts-service-user-test-player - accounts-service-user-test --gtest_filter=AccountsServiceUserTest.SetMediaPlayer + accounts-service-user-test --gtest_filter=AccountsServiceUserTest.SetMediaPlayer ) ########################### @@ -165,11 +165,11 @@ add_test(accounts-service-user-test-player include_directories(${CMAKE_SOURCE_DIR}/src) add_executable (volume-control-test volume-control-test.cc gschemas.compiled) target_link_libraries ( - volume-control-test - indicator-sound-service-lib - pulse-mock - gtest - ${TEST_LIBRARIES} + volume-control-test + indicator-sound-service-lib + pulse-mock + gtest-static + ${TEST_LIBRARIES} ) add_test(volume-control-test volume-control-test) @@ -181,12 +181,12 @@ add_test(volume-control-test volume-control-test) include_directories(${CMAKE_SOURCE_DIR}/src) add_executable (sound-menu-test sound-menu.cc) target_link_libraries ( - sound-menu-test - indicator-sound-service-lib - vala-mocks-lib - gtest - ${SOUNDSERVICE_LIBRARIES} - ${TEST_LIBRARIES} + sound-menu-test + indicator-sound-service-lib + vala-mocks-lib + gtest-static + ${SOUNDSERVICE_LIBRARIES} + ${TEST_LIBRARIES} ) add_test(sound-menu-test sound-menu-test) @@ -198,13 +198,13 @@ add_test(sound-menu-test sound-menu-test) include_directories(${CMAKE_SOURCE_DIR}/src) add_executable (notifications-test notifications-test.cc) target_link_libraries ( - notifications-test - indicator-sound-service-lib - vala-mocks-lib - pulse-mock - gtest - ${SOUNDSERVICE_LIBRARIES} - ${TEST_LIBRARIES} + notifications-test + indicator-sound-service-lib + vala-mocks-lib + pulse-mock + gtest-static + ${SOUNDSERVICE_LIBRARIES} + ${TEST_LIBRARIES} ) add_test(notifications-test notifications-test) @@ -216,23 +216,23 @@ add_test(notifications-test notifications-test) include_directories(${CMAKE_SOURCE_DIR}/src) add_executable (media-player-user-test media-player-user.cc) target_link_libraries ( - media-player-user-test - indicator-sound-service-lib - vala-mocks-lib - gtest - ${SOUNDSERVICE_LIBRARIES} - ${TEST_LIBRARIES} + media-player-user-test + indicator-sound-service-lib + vala-mocks-lib + gtest-static + ${SOUNDSERVICE_LIBRARIES} + ${TEST_LIBRARIES} ) # Split tests to work around libaccountservice sucking add_test(media-player-user-test-basic - media-player-user-test --gtest_filter=MediaPlayerUserTest.BasicObject + media-player-user-test --gtest_filter=MediaPlayerUserTest.BasicObject ) add_test(media-player-user-test-dataset - media-player-user-test --gtest_filter=MediaPlayerUserTest.DataSet + media-player-user-test --gtest_filter=MediaPlayerUserTest.DataSet ) add_test(media-player-user-test-timeout - media-player-user-test --gtest_filter=MediaPlayerUserTest.TimeoutTest + media-player-user-test --gtest_filter=MediaPlayerUserTest.TimeoutTest ) ########################### @@ -242,20 +242,20 @@ add_test(media-player-user-test-timeout include_directories(${CMAKE_SOURCE_DIR}/src) add_executable (greeter-list-test greeter-list.cc) target_link_libraries ( - greeter-list-test - indicator-sound-service-lib - vala-mocks-lib - gtest - ${SOUNDSERVICE_LIBRARIES} - ${TEST_LIBRARIES} + greeter-list-test + indicator-sound-service-lib + vala-mocks-lib + gtest-static + ${SOUNDSERVICE_LIBRARIES} + ${TEST_LIBRARIES} ) # Split tests to work around libaccountservice sucking add_test(greeter-list-test-basic - greeter-list-test --gtest_filter=GreeterListTest.BasicObject + greeter-list-test --gtest_filter=GreeterListTest.BasicObject ) add_test(greeter-list-test-iterator - greeter-list-test --gtest_filter=GreeterListTest.BasicIterator + greeter-list-test --gtest_filter=GreeterListTest.BasicIterator ) ########################### @@ -263,18 +263,21 @@ add_test(greeter-list-test-iterator ########################### add_definitions( - -DINDICATOR_SOUND_SERVICE_BINARY="${CMAKE_BINARY_DIR}/src/indicator-sound-service" - -DPA_MOCK_LIB="${CMAKE_CURRENT_BINARY_DIR}/libpulse-mock.so" + -DINDICATOR_SOUND_SERVICE_BINARY="${CMAKE_BINARY_DIR}/src/indicator-sound-service" + -DPA_MOCK_LIB="${CMAKE_CURRENT_BINARY_DIR}/libpulse-mock.so" ) add_executable (indicator-test indicator-test.cc gschemas.compiled) target_link_libraries ( - indicator-test - gtest - ${SOUNDSERVICE_LIBRARIES} - ${TEST_LIBRARIES} + indicator-test + gtest-static + ${SOUNDSERVICE_LIBRARIES} + ${TEST_LIBRARIES} ) # Split tests to work around libaccountservice sucking add_test(indcator-test - indicator-test + indicator-test ) + +add_subdirectory(integration) +add_subdirectory(dbus-types) \ No newline at end of file diff --git a/tests/dbus-types/CMakeLists.txt b/tests/dbus-types/CMakeLists.txt new file mode 100644 index 0000000..6346e25 --- /dev/null +++ b/tests/dbus-types/CMakeLists.txt @@ -0,0 +1,48 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +find_package(Qt5DBus REQUIRED) +include_directories(${Qt5DBus_INCLUDE_DIRS}) + +add_definitions(-DQT_NO_KEYWORDS=1) + +set(dbusinterface_streamrestore_xml "org.PulseAudio.Ext.StreamRestore1.xml") +set_source_files_properties(${dbusinterface_streamrestore_xml} PROPERTIES + CLASSNAME StreamRestoreInterface) + +set(dbusinterface_accounts_xml "org.freedesktop.Accounts.xml") +set_source_files_properties(${dbusinterface_accounts_xml} PROPERTIES + CLASSNAME AccountsInterface) + +set(dbusinterface_accountssound_xml "com.ubuntu.AccountsService.Sound.xml") +set_source_files_properties(${dbusinterface_accountssound_xml} PROPERTIES + CLASSNAME AccountsSoundInterface) + +set(dbusinterface_properties_xml "org.freedesktop.DBus.Properties.xml") +set_source_files_properties(${dbusinterface_properties_xml} PROPERTIES + CLASSNAME DBusPropertiesInterface + NO_NAMESPACE YES + INCLUDE "dbus-types.h") + +set(dbusinterface_menus_xml "org.gtk.Menus.xml") +set_source_files_properties(${dbusinterface_menus_xml} PROPERTIES + CLASSNAME MenusInterface) + +qt5_add_dbus_interface(interface_files ${dbusinterface_streamrestore_xml} stream_restore_interface) +qt5_add_dbus_interface(interface_files ${dbusinterface_properties_xml} dbus_properties_interface) +qt5_add_dbus_interface(interface_files ${dbusinterface_accounts_xml} dbus_accounts_interface) +qt5_add_dbus_interface(interface_files ${dbusinterface_accountssound_xml} dbus_accountssound_interface) +qt5_add_dbus_interface(interface_files ${dbusinterface_menus_xml} dbus_menus_interface) + +add_library( + sound-indicator-dbus-interfaces + STATIC + ${interface_files} + pulseaudio-volume.cpp +) + +qt5_use_modules( + sound-indicator-dbus-interfaces + Core + DBus +) diff --git a/tests/dbus-types/com.ubuntu.AccountsService.Sound.xml b/tests/dbus-types/com.ubuntu.AccountsService.Sound.xml new file mode 100644 index 0000000..27c915a --- /dev/null +++ b/tests/dbus-types/com.ubuntu.AccountsService.Sound.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/dbus-types/dbus-types.h b/tests/dbus-types/dbus-types.h new file mode 100644 index 0000000..f747458 --- /dev/null +++ b/tests/dbus-types/dbus-types.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include +#include "pulseaudio-volume.h" + +namespace DBusTypes +{ + inline void registerMetaTypes() + { + PulseaudioVolume::registerMetaType(); + PulseaudioVolumeArray::registerMetaType(); + } + + static constexpr char const* DBUS_NAME = "com.canonical.indicator.sound"; + + static constexpr char const* DBUS_PULSE = "org.PulseAudio1"; + + static constexpr char const* STREAM_RESTORE_NAME = "org.PulseAudio.Ext.StreamRestore1"; + + static constexpr char const* STREAM_RESTORE_PATH = "/org/pulseaudio/stream_restore1"; + + static constexpr char const* STREAM_RESTORE_ENTRY_NAME = "org.PulseAudio.Ext.StreamRestore1.RestoreEntry"; +} diff --git a/tests/dbus-types/org.PulseAudio.Ext.StreamRestore1.xml b/tests/dbus-types/org.PulseAudio.Ext.StreamRestore1.xml new file mode 100644 index 0000000..bf9af76 --- /dev/null +++ b/tests/dbus-types/org.PulseAudio.Ext.StreamRestore1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tests/dbus-types/org.freedesktop.Accounts.xml b/tests/dbus-types/org.freedesktop.Accounts.xml new file mode 100644 index 0000000..d9c6b2a --- /dev/null +++ b/tests/dbus-types/org.freedesktop.Accounts.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/dbus-types/org.freedesktop.DBus.Properties.xml b/tests/dbus-types/org.freedesktop.DBus.Properties.xml new file mode 100644 index 0000000..19a1b90 --- /dev/null +++ b/tests/dbus-types/org.freedesktop.DBus.Properties.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/dbus-types/org.gtk.Menus.xml b/tests/dbus-types/org.gtk.Menus.xml new file mode 100644 index 0000000..a0d6a83 --- /dev/null +++ b/tests/dbus-types/org.gtk.Menus.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/dbus-types/pulseaudio-volume.cpp b/tests/dbus-types/pulseaudio-volume.cpp new file mode 100644 index 0000000..8ee305f --- /dev/null +++ b/tests/dbus-types/pulseaudio-volume.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include "dbus-types.h" + +PulseaudioVolume::PulseaudioVolume() : + type_(0), + volume_(10) +{ +} + +PulseaudioVolume::PulseaudioVolume(unsigned int type, unsigned int volume) : + type_(type) + , volume_(volume) +{ +} + +PulseaudioVolume::PulseaudioVolume(const PulseaudioVolume &other) : + type_(other.type_), + volume_(other.volume_) +{ +} + +PulseaudioVolume& PulseaudioVolume::operator=(const PulseaudioVolume &other) +{ + type_ = other.type_; + volume_ = other.volume_; + + return *this; +} + +PulseaudioVolume::~PulseaudioVolume() +{ +} + +unsigned int PulseaudioVolume::getType() const +{ + return type_; +} + +unsigned int PulseaudioVolume::getVolume() const +{ + return volume_; +} + +void PulseaudioVolume::registerMetaType() +{ + qRegisterMetaType("PulseaudioVolume"); + + qDBusRegisterMetaType(); +} + +QDBusArgument &operator<<(QDBusArgument &argument, const PulseaudioVolume& volume) +{ + argument.beginStructure(); + argument << volume.type_; + argument << volume.volume_; + argument.endStructure(); + + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, PulseaudioVolume &volume) +{ + argument.beginStructure(); + argument >> volume.type_; + argument >> volume.volume_; + argument.endStructure(); + + return argument; +} + +PulseaudioVolumeArray::PulseaudioVolumeArray() +{ +} + +PulseaudioVolumeArray::PulseaudioVolumeArray(const PulseaudioVolumeArray &other) : + volume_array_(other.volume_array_) +{ +} + +PulseaudioVolumeArray& PulseaudioVolumeArray::operator=(const PulseaudioVolumeArray &other) +{ + volume_array_ = other.volume_array_; + + return *this; +} + +PulseaudioVolumeArray::~PulseaudioVolumeArray() +{ +} + +int PulseaudioVolumeArray::getNumItems() const +{ + return volume_array_.size(); +} + +PulseaudioVolume PulseaudioVolumeArray::getItem(int i) const +{ + if (i < volume_array_.size()) + { + return volume_array_[i]; + } + return PulseaudioVolume(); +} + +void PulseaudioVolumeArray::addItem(PulseaudioVolume const &item) +{ + volume_array_.push_back(item); +} + +void PulseaudioVolumeArray::registerMetaType() +{ + qRegisterMetaType("PulseaudioVolumeArray"); + + qDBusRegisterMetaType(); +} + +QDBusArgument &operator<<(QDBusArgument &argument, const PulseaudioVolumeArray& volume) +{ + argument.beginArray( qMetaTypeId() ); + for (int i = 0; i < volume.volume_array_.size(); ++ i) + { + PulseaudioVolume item = volume.getItem(i); + argument << item; + } + argument.endArray(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, PulseaudioVolumeArray &volume) +{ + argument.beginArray(); + while ( !argument.atEnd() ) { + PulseaudioVolume item; + argument >> item; + volume.volume_array_.push_back(item); + } + argument.endArray(); + + return argument; +} diff --git a/tests/dbus-types/pulseaudio-volume.h b/tests/dbus-types/pulseaudio-volume.h new file mode 100644 index 0000000..e9fe73d --- /dev/null +++ b/tests/dbus-types/pulseaudio-volume.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include + +class PulseaudioVolume +{ +public: + PulseaudioVolume(); + PulseaudioVolume(unsigned int type, unsigned int volume); + PulseaudioVolume(const PulseaudioVolume &other); + PulseaudioVolume& operator=(const PulseaudioVolume &other); + ~PulseaudioVolume(); + + friend QDBusArgument &operator<<(QDBusArgument &argument, PulseaudioVolume const & volume); + friend const QDBusArgument &operator>>(QDBusArgument const & argument, PulseaudioVolume &volume); + + unsigned int getType() const; + unsigned int getVolume() const; + + //register Message with the Qt type system + static void registerMetaType(); + +private: + unsigned int type_; + unsigned int volume_; +}; + +Q_DECLARE_METATYPE(PulseaudioVolume) + + +class PulseaudioVolumeArray +{ +public: + PulseaudioVolumeArray(); + PulseaudioVolumeArray(QString const &interface, QString const &property, QDBusVariant const& value); + PulseaudioVolumeArray(const PulseaudioVolumeArray &other); + PulseaudioVolumeArray& operator=(const PulseaudioVolumeArray &other); + ~PulseaudioVolumeArray(); + + friend QDBusArgument &operator<<(QDBusArgument &argument, PulseaudioVolumeArray const & volume); + friend const QDBusArgument &operator>>(QDBusArgument const & argument, PulseaudioVolumeArray &volume); + + int getNumItems() const; + PulseaudioVolume getItem(int i) const; + void addItem(PulseaudioVolume const &item); + + //register Message with the Qt type system + static void registerMetaType(); + +private: + QVector volume_array_; +}; + +Q_DECLARE_METATYPE(PulseaudioVolumeArray) diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt new file mode 100644 index 0000000..2e4004a --- /dev/null +++ b/tests/integration/CMakeLists.txt @@ -0,0 +1,128 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +include(FindGMock) + +#pkg_check_modules(GMENUHARNESS REQUIRED libgmenuharness REQUIRED) +#include_directories(${GMENUHARNESS_INCLUDE_DIRS}) +include_directories("${CMAKE_SOURCE_DIR}/include") + +pkg_check_modules(QTDBUSTEST REQUIRED libqtdbustest-1 REQUIRED) +include_directories(${QTDBUSTEST_INCLUDE_DIRS}) + +pkg_check_modules(QTDBUSMOCK REQUIRED libqtdbusmock-1 REQUIRED) +include_directories(${QTDBUSMOCK_INCLUDE_DIRS}) + +find_package(Qt5Test REQUIRED) +include_directories(${Qt5Test_INCLUDE_DIRS}) + +find_package(Qt5DBus REQUIRED) +include_directories(${Qt5DBus_INCLUDE_DIRS}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${GMOCK_INCLUDE_DIRS}) +include_directories(${GTEST_INCLUDE_DIRS}) + +include_directories("${CMAKE_SOURCE_DIR}/tests/dbus-types") +include_directories("${CMAKE_BINARY_DIR}/tests/dbus-types") + +add_definitions(-DSOUND_SERVICE_BIN="${CMAKE_BINARY_DIR}/src/indicator-sound-service" + -DSTREAM_RESTORE_TABLE="${CMAKE_SOURCE_DIR}/tests/integration/touch-stream-restore.table" + -DVOLUME_SET_BIN="${CMAKE_BINARY_DIR}/tests/integration/set-volume" + -DTEST_SOUND="${CMAKE_SOURCE_DIR}/tests/integration/test-sound.wav" + -DQT_NO_KEYWORDS=1 +) + +set(GLIB_REQUIRED_VERSION 2.26) + +pkg_check_modules( + GLIB REQUIRED + glib-2.0>=${GLIB_REQUIRED_VERSION} + gio-2.0>=${GLIB_REQUIRED_VERSION} +) +include_directories(${GLIB_INCLUDE_DIRS}) + +set( + INTEGRATION_TESTS_SRC + indicator-sound-test-base.cpp + test-indicator.cpp + utils/dbus-pulse-volume.cpp + main.cpp +) + +add_executable( + integration-tests + ${INTEGRATION_TESTS_SRC} +) + +qt5_use_modules( + integration-tests + Core + DBus + Test +) + +target_link_libraries( + integration-tests + sound-indicator-dbus-interfaces + ${QTDBUSMOCK_LDFLAGS} + ${QTDBUSTEST_LDFLAGS} + ${GTEST_LIBRARIES} + ${GMOCK_LIBRARIES} +# ${GMENUHARNESS_LDFLAGS} + ${GLIB_LDFLAGS} + gmenuharness-shared +) + +add_test( + integration-tests + integration-tests +) + +set( + SET-VOLUME-SRC + utils/dbus-pulse-volume.cpp + utils/set-volume.cpp +) + +set( + GET-VOLUME-SRC + utils/dbus-pulse-volume.cpp + utils/get-volume.cpp +) + +add_executable( + set-volume + ${SET-VOLUME-SRC} +) + +add_executable( + get-volume + ${GET-VOLUME-SRC} +) + +qt5_use_modules( + set-volume + Core + DBus + Test +) + +qt5_use_modules( + get-volume + Core + DBus + Test +) + +target_link_libraries( + get-volume + sound-indicator-dbus-interfaces +) + +target_link_libraries( + set-volume + sound-indicator-dbus-interfaces +) + +#add_subdirectory(utils) \ No newline at end of file diff --git a/tests/integration/Copy of test-sound.wav b/tests/integration/Copy of test-sound.wav new file mode 100644 index 0000000..709c6eb Binary files /dev/null and b/tests/integration/Copy of test-sound.wav differ diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp new file mode 100644 index 0000000..6e05efe --- /dev/null +++ b/tests/integration/indicator-sound-test-base.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#include "indicator-sound-test-base.h" + +#include "dbus_menus_interface.h" +#include "dbus_properties_interface.h" +#include "dbus_accounts_interface.h" +#include "dbus_accountssound_interface.h" +#include "dbus-types.h" + +#include + +#include +#include "utils/dbus-pulse-volume.h" + +using namespace QtDBusTest; +using namespace QtDBusMock; +using namespace std; +using namespace testing; +namespace mh = unity::gmenuharness; + +IndicatorSoundTestBase::IndicatorSoundTestBase() : + dbusMock(dbusTestRunner) +{ +} + +IndicatorSoundTestBase::~IndicatorSoundTestBase() +{ + +} + +bool IndicatorSoundTestBase::setVolume(QString const &role, double volume) +{ + QProcess setVolume; + setVolume.start(VOLUME_SET_BIN, QStringList() + << role + << QString("%1").arg(volume)); + if (!setVolume.waitForStarted()) + return false; + + if (!setVolume.waitForFinished()) + return false; + + return setVolume.exitCode() == 0; +} + +bool IndicatorSoundTestBase::startTestSound(QString const &role) +{ + testSoundProcess.terminate(); + testSoundProcess.start("paplay", QStringList() + << "-s" + << "127.0.0.1" + << TEST_SOUND + << QString("--property=media.role=%1").arg(role)); + + if (!testSoundProcess.waitForStarted()) + return false; + +// sleep(1); + return true; +} + +void IndicatorSoundTestBase::stopTestSound() +{ + testSoundProcess.terminate(); +} + +void IndicatorSoundTestBase::startPulse() +{ + try + { + pulseaudio.reset( + new QProcessDBusService(DBusTypes::DBUS_PULSE, + QDBusConnection::SessionBus, + "pulseaudio", + QStringList() << "--start" + << "-vvvv" + << "--disable-shm=true" + << "--daemonize=false" + << "--use-pid-file=false" + << "--system=false" + << "--exit-idle-time=-1" + << "-n" + << "--load=module-null-sink" + << "--log-target=file:/tmp/pulse-daemon.log" + << QString("--load=module-stream-restore restore_device=false restore_muted=false fallback_table=%1").arg(STREAM_RESTORE_TABLE) + << "--load=module-dbus-protocol" + << "--load=module-native-protocol-tcp auth-ip-acl=127.0.0.1" + )); + pulseaudio->start(dbusTestRunner.sessionConnection()); + } + catch (exception const& e) + { + cout << "pulseaudio(): " << e.what() << endl; + throw; + } +} + +void IndicatorSoundTestBase::startIndicator() +{ + try + { + setenv("PULSE_SERVER", "127.0.0.1", true); + setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true); + indicator.reset( + new QProcessDBusService(DBusTypes::DBUS_NAME, + QDBusConnection::SessionBus, + SOUND_SERVICE_BIN, + QStringList())); + indicator->start(dbusTestRunner.sessionConnection()); + } + catch (exception const& e) + { + cout << "startIndicator(): " << e.what() << endl; + throw; + } +} + +// /usr/bin/pulseaudio --start -vvvv --disable-shm=true --daemonize=false --use-pid-file=false --system=false --exit-idle-time=-1 -n "--load=module-null-sink sink_name=multimedia" --load=module-stream-restore + +mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters() +{ + return mh::MenuMatcher::Parameters( + "com.canonical.indicator.sound", + { { "indicator", "/com/canonical/indicator/sound" } }, + "/com/canonical/indicator/sound/desktop"); +} + +void IndicatorSoundTestBase::SetUp() +{ + initializeAccountsInterface(); +} + +void IndicatorSoundTestBase::TearDown() +{ + unsetenv("PULSE_SERVER"); +} + +void gvariant_deleter(GVariant* varptr) +{ + if (varptr != nullptr) + { + g_variant_unref(varptr); + } +} + +std::shared_ptr IndicatorSoundTestBase::volume_variant(double volume) +{ + GVariantBuilder builder; + + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&builder, + "{sv}", + "title", + g_variant_new_string("_Sound")); + + g_variant_builder_add(&builder, + "{sv}", + "accessible-desc", + g_variant_new_string("_Sound")); + + auto icon = g_themed_icon_new("icon"); + g_variant_builder_add(&builder, + "{sv}", + "icon", + g_icon_serialize(icon)); + + g_variant_builder_add(&builder, + "{sv}", + "visible", + g_variant_new_boolean(true)); + return shared_ptr(g_variant_builder_end(&builder), &gvariant_deleter); +} + +unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::volumeSlider(double volume) +{ + return mh::MenuItemMatcher().radio() + .label("Volume") + .round_doubles(0.1) + .pass_through_double_attribute("action", volume); +} + +bool IndicatorSoundTestBase::waitMenuChange() +{ + if (!menu_interface_) + { + menu_interface_.reset(new MenusInterface("com.canonical.indicator.sound", + "/com/canonical/indicator/sound/desktop", + QDBusConnection::sessionBus(), 0)); + } + if (menu_interface_) + { + qDebug() << "Waiting for signal"; + QSignalSpy spy(menu_interface_.get(), &MenusInterface::Changed); + qDebug() << "Signal count " << spy.count(); + return spy.wait(); + } + return false; +} + +bool IndicatorSoundTestBase::waitVolumeChangedInIndicator() +{ + qDebug() << "IndicatorSoundTestBase::waitVolumeChangedInIndicator() signal " << (void *)signal_spy_volume_changed_.get(); + if (signal_spy_volume_changed_) + { + return signal_spy_volume_changed_->wait(); + } + return false; +} + +void IndicatorSoundTestBase::initializeAccountsInterface() +{ + auto username = qgetenv("USER"); + if (username != "") + { + qDebug() << "Setting Accounts interface for user: " << username; + std::unique_ptr setInterface(new AccountsInterface("org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + QDBusConnection::systemBus(), 0)); + qDebug() << "Interface: " << setInterface.get(); + + QDBusReply userResp = setInterface->call(QLatin1String("FindUserByName"), + QLatin1String(username)); + + if (!userResp.isValid()) + { + qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << userResp.error().message(); + } + auto userPath = userResp.value().path(); + if (userPath != "") + { + std::unique_ptr soundInterface(new AccountsSoundInterface("org.freedesktop.Accounts", + userPath, + QDBusConnection::systemBus(), 0)); + + accounts_interface_.reset(new DBusPropertiesInterface("org.freedesktop.Accounts", + userPath, + soundInterface->connection(), 0)); + qDebug() << "Interface for setting volume: " << accounts_interface_.get(); + if (!accounts_interface_->isValid()) + { + qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << accounts_interface_->lastError().message(); + } + signal_spy_volume_changed_.reset(new QSignalSpy(accounts_interface_.get(),&DBusPropertiesInterface::PropertiesChanged)); + } + } +} diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h new file mode 100644 index 0000000..81d8204 --- /dev/null +++ b/tests/integration/indicator-sound-test-base.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include +#include + +class MenusInterface; +class DBusPulseVolume; +class DBusPropertiesInterface; +class QSignalSpy; + +class IndicatorSoundTestBase: public testing::Test +{ +public: + IndicatorSoundTestBase(); + + ~IndicatorSoundTestBase(); + +protected: + void SetUp() override; + void TearDown() override; + + void startIndicator(); + void startPulse(); + + bool setVolume(QString const &role, double volume); + + bool startTestSound(QString const &role); + + void stopTestSound(); + + static std::shared_ptr volume_variant(double volume); + + static unity::gmenuharness::MenuMatcher::Parameters desktopParameters(); + + static unity::gmenuharness::MenuItemMatcher volumeSlider(double volume); + + bool waitMenuChange(); + + bool waitVolumeChangedInIndicator(); + + void initializeAccountsInterface(); + + QtDBusTest::DBusTestRunner dbusTestRunner; + + QtDBusMock::DBusMock dbusMock; + + QtDBusTest::DBusServicePtr indicator; + + QtDBusTest::DBusServicePtr pulseaudio; + + QProcess testSoundProcess; + + std::unique_ptr menu_interface_; + + std::unique_ptr accounts_interface_; + + std::unique_ptr signal_spy_volume_changed_; +}; diff --git a/tests/integration/main.cpp b/tests/integration/main.cpp new file mode 100644 index 0000000..a29b3b6 --- /dev/null +++ b/tests/integration/main.cpp @@ -0,0 +1,58 @@ +/* + * Copyright © 2014 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 Free Software Foundation. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authors: + * Pete Woods + */ + +//#include + +#include +#include +#include + +#include + +#include "dbus-types.h" + +using namespace QtDBusMock; + +class Runner: public QObject +{ + Q_OBJECT +public Q_SLOTS: + void run() + { + QCoreApplication::exit(RUN_ALL_TESTS()); + } +}; + +int main(int argc, char **argv) +{ + qputenv("LANG", "C.UTF-8"); + unsetenv("LC_ALL"); + + QCoreApplication application(argc, argv); + DBusMock::registerMetaTypes(); + DBusTypes::registerMetaTypes(); + ::testing::InitGoogleTest(&argc, argv); + + Runner runner; + QTimer::singleShot(0, &runner, SLOT(run())); + + return application.exec(); +} + +#include "main.moc" diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp new file mode 100644 index 0000000..8803f91 --- /dev/null +++ b/tests/integration/test-indicator.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#include + +#include +#include +#include + +using namespace std; +using namespace testing; +namespace mh = unity::gmenuharness; +namespace +{ + +class TestIndicator: public IndicatorSoundTestBase +{ +}; + +TEST_F(TestIndicator, ChangeRoleVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startPulse()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setVolume("mutimedia", INITIAL_VOLUME)); + EXPECT_TRUE(setVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // Generate a random volume + QTime now = QTime::currentTime(); + qsrand(now.msec()); + int randInt = qrand() % 100; + double randomVolume = randInt / 100.0; + + // set an initial volume to the alert role + setVolume("alert", 1.0); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + // play a test sound, it should change the role in the indicator + EXPECT_TRUE(startTestSound("multimedia")); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + // set the random volume to the multimedia role + EXPECT_TRUE(setVolume("multimedia", randomVolume)); + if (randomVolume != INITIAL_VOLUME) + { + EXPECT_TRUE(waitVolumeChangedInIndicator()); + } + + // check the indicator + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(randomVolume)) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); + + // stop the test sound, the role should change again to alert + stopTestSound(); + if (randomVolume != 1.0) + { + // we only wait if the volume in the alert and the + // one set in the multimedia roles differ + EXPECT_TRUE(waitVolumeChangedInIndicator()); + } + + // check the initial volume for the alert role + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(1.0)) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); +} + +TEST_F(TestIndicator, BasicInitialVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startPulse()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // check the initial volume for the alert role + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME)) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); +} + +} // namespace diff --git a/tests/integration/test-sound.wav b/tests/integration/test-sound.wav new file mode 100644 index 0000000..f696657 Binary files /dev/null and b/tests/integration/test-sound.wav differ diff --git a/tests/integration/touch-stream-restore.table b/tests/integration/touch-stream-restore.table new file mode 100755 index 0000000..146b02e --- /dev/null +++ b/tests/integration/touch-stream-restore.table @@ -0,0 +1,4 @@ +sink-input-by-media-role:multimedia -8 +sink-input-by-media-role:alert -8 +sink-input-by-media-role:alarm -8 +sink-input-by-media-role:phone -15 diff --git a/tests/integration/utils/dbus-pulse-volume.cpp b/tests/integration/utils/dbus-pulse-volume.cpp new file mode 100644 index 0000000..6989754 --- /dev/null +++ b/tests/integration/utils/dbus-pulse-volume.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#include "dbus_properties_interface.h" +#include "dbus_accounts_interface.h" +#include "dbus_accountssound_interface.h" +#include "stream_restore_interface.h" + +#include +#include "dbus-pulse-volume.h" + +#include + +unsigned int volumeDoubleToUint(double volume) +{ + double tmp = (double)(PA_VOLUME_NORM - PA_VOLUME_MUTED) * volume; + return (unsigned int)tmp + PA_VOLUME_MUTED; +} + +double volumeUIntToDoulbe(uint volume) +{ + double tmp = (double)(volume - PA_VOLUME_MUTED); + return tmp / (double)(PA_VOLUME_NORM - PA_VOLUME_MUTED); +} + +DBusPulseVolume::DBusPulseVolume() : + QObject() +{ + std::unique_ptr basicConnectionInterface(new DBusPropertiesInterface("org.PulseAudio1", + "/org/pulseaudio/server_lookup1", + QDBusConnection::sessionBus(), 0)); + + QDBusReply connection_string = basicConnectionInterface->call(QLatin1String("Get"), + QLatin1String("org.PulseAudio.ServerLookup1"), + QLatin1String("Address")); + + if (!connection_string.isValid()) + { + qWarning() << "DBusPulseVolume::DBusPulseVolume(): D-Bus error: " << connection_string.error().message(); + } + + qDebug() << "********************************Connetion: " << connection_string.value().toString(); + +// connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer(connection_string.value().toString(), "set-volume"))); + + connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer("unix:path=/run/user/1000/pulse/dbus-socket", "set-volume"))); + qDebug() << "Is connected " << connection_->isConnected(); + + if (connection_->isConnected()) + { + interface_paths_.reset(new StreamRestoreInterface("org.PulseAudio.Ext.StreamRestore1", + "/org/pulseaudio/stream_restore1", + *(connection_.get()), 0)); + qDebug() << "Interface " << (void *)interface_paths_.get(); + + if (interface_paths_) + { + // get the role paths + fillRolePath("multimedia"); + fillRolePath("alert"); + fillRolePath("alarm"); + fillRolePath("phone"); + } + + initializeAccountsInterface(); + } + else + { + qWarning() << "DBusPulseVolume::DBusPulseVolume(): Error connecting: " << connection_->lastError().message(); + } +} + +DBusPulseVolume::~DBusPulseVolume() +{ + connection_->disconnectFromPeer("unix:path=/run/user/1000/pulse/dbus-socket"); +} + +QString DBusPulseVolume::fillRolePath(QString const &role) +{ + QString role_complete_name = QString("sink-input-by-media-role:") + role; + // get the role paths + QDBusReply objectPath = interface_paths_->call(QLatin1String("GetEntryByName"), role_complete_name); + if (!objectPath.isValid()) + { + qWarning() << "SetVolume::fillRolePath(): D-Bus error: " << objectPath.error().message(); + return ""; + } + qDebug() << "XGM: path for role " << role << "=" << objectPath.value().path(); + auto role_info = std::make_shared(); + role_info->interface_.reset(new DBusPropertiesInterface("org.PulseAudio.Ext.StreamRestore1.RestoreEntry", + objectPath.value().path(), + *(connection_.get()), 0)); + if (!role_info->interface_) + { + qWarning() << "SetVolume::fillRolePath() - Error obtaining properties interface"; + return ""; + } + role_info->path_ = objectPath.value().path(); + roles_map_[role] = role_info; + return role_info->path_; +} + +bool DBusPulseVolume::setVolume(QString const & role, double volume) +{ + if (!interface_paths_) + { + qWarning() << "SetVolume::setVolume(): error: Volume interfaces are not initialized"; + return false; + } + RolesMap::const_iterator iter = roles_map_.find(role); + if (iter != roles_map_.end()) + { + QDBusReply prev_vol = (*iter).second->interface_->call(QLatin1String("Get"), + QLatin1String("org.PulseAudio.Ext.StreamRestore1.RestoreEntry"), + QLatin1String("Volume")); + + if (!prev_vol.isValid()) + { + qWarning() << "SetVolume::setVolume(): D-Bus error: " << prev_vol.error().message(); + return false; + } + QDBusArgument arg = prev_vol.value().value(); + PulseaudioVolumeArray element; + arg >> element; + + PulseaudioVolume signal_vol(0, 4000); + PulseaudioVolumeArray vol_array; + vol_array.addItem(signal_vol); + + QVariant var; + PulseaudioVolumeArray t; + PulseaudioVolume vv(0, volumeDoubleToUint(volume)); + t.addItem(vv); + var.setValue(t); + QDBusVariant dbusVar(var); + QDBusReply set_vol = (*iter).second->interface_->call(QLatin1String("Set"), + QVariant::fromValue(QString("org.PulseAudio.Ext.StreamRestore1.RestoreEntry")), + QVariant::fromValue(QString("Volume")), + QVariant::fromValue(dbusVar)); + + if (!set_vol.isValid()) + { + qWarning() << "SetVolume::setVolume(): D-Bus error: " << set_vol.error().message(); + return false; + } + + if (accounts_interface_) + { + QDBusVariant dbusVar(QVariant::fromValue(volume)); + QDBusReply set_vol = accounts_interface_->call(QLatin1String("Set"), + QVariant::fromValue(QString("com.ubuntu.AccountsService.Sound")), + QVariant::fromValue(QString("Volume")), + QVariant::fromValue(dbusVar)); + if (!set_vol.isValid()) + { + qWarning() << "SetVolume::setVolume(): D-Bus error: " << set_vol.error().message(); + return false; + } + } + } + return true; +} + +double DBusPulseVolume::getVolume(QString const & role) +{ + if (interface_paths_) + { + RolesMap::const_iterator iter = roles_map_.find(role); + if (iter != roles_map_.end()) + { + QDBusReply prev_vol = (*iter).second->interface_->call(QLatin1String("Get"), + QLatin1String("org.PulseAudio.Ext.StreamRestore1.RestoreEntry"), + QLatin1String("Volume")); + + if (!prev_vol.isValid()) + { + qWarning() << "SetVolume::setVolume(): D-Bus error: " << prev_vol.error().message(); + } + QDBusArgument arg = prev_vol.value().value(); + PulseaudioVolumeArray element; + arg >> element; + return volumeUIntToDoulbe(element.getItem(0).getVolume()); + } + } + return -1.0; +} + +void DBusPulseVolume::initializeAccountsInterface() +{ + auto username = qgetenv("USER"); + if (username != "") + { + qDebug() << "Setting Accounts interface for user: " << username; + std::unique_ptr setInterface(new AccountsInterface("org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + QDBusConnection::systemBus(), 0)); + qDebug() << "Interface: " << setInterface.get(); + + QDBusReply userResp = setInterface->call(QLatin1String("FindUserByName"), + QLatin1String(username)); + + if (!userResp.isValid()) + { + qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << userResp.error().message(); + } + auto userPath = userResp.value().path(); + if (userPath != "") + { + std::unique_ptr soundInterface(new AccountsSoundInterface("org.freedesktop.Accounts", + userPath, + QDBusConnection::systemBus(), 0)); + + accounts_interface_.reset(new DBusPropertiesInterface("org.freedesktop.Accounts", + userPath, + soundInterface->connection(), 0)); + qDebug() << "Interface for setting volume: " << accounts_interface_.get(); + if (!accounts_interface_->isValid()) + { + qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << accounts_interface_->lastError().message(); + } + signal_spy_volume_changed_.reset(new QSignalSpy(accounts_interface_.get(),&DBusPropertiesInterface::PropertiesChanged)); + } + } +} + +bool DBusPulseVolume::waitForVolumeChangedInAccountsService() +{ + if (signal_spy_volume_changed_) + { + return signal_spy_volume_changed_->wait(); + } + else + { + qWarning() << "DBusPulseVolume::waitForVolumeChangedInAccountsService(): signal was not instantiated"; + } + return false; +} diff --git a/tests/integration/utils/dbus-pulse-volume.h b/tests/integration/utils/dbus-pulse-volume.h new file mode 100644 index 0000000..2d55e89 --- /dev/null +++ b/tests/integration/utils/dbus-pulse-volume.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include +#include + +#include +#include + +class StreamRestoreInterface; +class DBusPropertiesInterface; +class AccountsInterface; +class AccountsSoundInterface; +class QSignalSpy; + +struct RoleInformation +{ + std::unique_ptr interface_; + QString path_; +}; + +class DBusPulseVolume : public QObject +{ +public: + DBusPulseVolume(); + ~DBusPulseVolume(); + + bool setVolume(QString const & role, double volume); + double getVolume(QString const & role); + bool waitForVolumeChangedInAccountsService(); + +protected: + QString fillRolePath(QString const &role); + void initializeAccountsInterface(); + std::unique_ptr connection_; + std::unique_ptr interface_paths_; + typedef std::map> RolesMap; + RolesMap roles_map_; + std::unique_ptr accounts_interface_; + std::unique_ptr signal_spy_volume_changed_; +}; diff --git a/tests/integration/utils/get-volume.cpp b/tests/integration/utils/get-volume.cpp new file mode 100644 index 0000000..309da36 --- /dev/null +++ b/tests/integration/utils/get-volume.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#include "dbus-types.h" + +#include +#include "dbus-pulse-volume.h" + +int main(int argc, char **argv) +{ + DBusTypes::registerMetaTypes(); + if (argc == 2) + { + DBusPulseVolume volume; + volume.getVolume(argv[1]); + } + return 0; +} diff --git a/tests/integration/utils/set-volume.cpp b/tests/integration/utils/set-volume.cpp new file mode 100644 index 0000000..d29e5ef --- /dev/null +++ b/tests/integration/utils/set-volume.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#include "dbus-types.h" + +#include +#include "dbus-pulse-volume.h" + +int main(int argc, char **argv) +{ + DBusTypes::registerMetaTypes(); + if (argc == 3) + { + DBusPulseVolume volume; + if(!volume.setVolume(argv[1], std::stod(argv[2]))) + { + return 1; + } + } + return 0; +} -- cgit v1.2.3 From a3b4aa7d5959ed275dd501ae2264e81b00b184b3 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Tue, 15 Sep 2015 14:16:10 +0200 Subject: Added changed to reflect the state of the player control buttons --- tests/media-player-mock.vala | 6 + tests/sound-menu.cc | 324 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 273 insertions(+), 57 deletions(-) (limited to 'tests') diff --git a/tests/media-player-mock.vala b/tests/media-player-mock.vala index 14028f5..0c4ae80 100644 --- a/tests/media-player-mock.vala +++ b/tests/media-player-mock.vala @@ -28,6 +28,9 @@ public class MediaPlayerMock: MediaPlayer { public override bool is_running { get { return mock_is_running; } } public override bool can_raise { get { return mock_can_raise; } } + public override bool can_do_next { get { return mock_can_do_next; } } + public override bool can_do_prev { get { return mock_can_do_prev; } } + public override bool can_do_play { get { return mock_can_do_play; } } public override MediaPlayer.Track? current_track { get { return mock_current_track; } set { this.mock_current_track = value; } } @@ -40,6 +43,9 @@ public class MediaPlayerMock: MediaPlayer { public bool mock_is_running { get; set; } public bool mock_can_raise { get; set; } + public bool mock_can_do_next { get; set; } + public bool mock_can_do_prev { get; set; } + public bool mock_can_do_play { get; set; } public MediaPlayer.Track? mock_current_track { get; set; } diff --git a/tests/sound-menu.cc b/tests/sound-menu.cc index 10c0cb9..6fe2c90 100644 --- a/tests/sound-menu.cc +++ b/tests/sound-menu.cc @@ -27,87 +27,297 @@ extern "C" { class SoundMenuTest : public ::testing::Test { - protected: - GTestDBus * bus = nullptr; + protected: + GTestDBus * bus = nullptr; - virtual void SetUp() { - bus = g_test_dbus_new(G_TEST_DBUS_NONE); - g_test_dbus_up(bus); - } + virtual void SetUp() { + bus = g_test_dbus_new(G_TEST_DBUS_NONE); + g_test_dbus_up(bus); + } - virtual void TearDown() { - g_test_dbus_down(bus); - g_clear_object(&bus); - } + virtual void TearDown() { + g_test_dbus_down(bus); + g_clear_object(&bus); + } - void verify_item_attribute (GMenuModel * mm, guint index, const gchar * name, GVariant * value) { - g_variant_ref_sink(value); + void verify_item_attribute (GMenuModel * mm, guint index, const gchar * name, GVariant * value) { + g_variant_ref_sink(value); - gchar * variantstr = g_variant_print(value, TRUE); - g_debug("Expecting item %d to have a '%s' attribute: %s", index, name, variantstr); + gchar * variantstr = g_variant_print(value, TRUE); + g_debug("Expecting item %d to have a '%s' attribute: %s", index, name, variantstr); - const GVariantType * type = g_variant_get_type(value); - GVariant * itemval = g_menu_model_get_item_attribute_value(mm, index, name, type); + const GVariantType * type = g_variant_get_type(value); + GVariant * itemval = g_menu_model_get_item_attribute_value(mm, index, name, type); - ASSERT_NE(nullptr, itemval); - EXPECT_TRUE(g_variant_equal(itemval, value)); + ASSERT_NE(nullptr, itemval); + EXPECT_TRUE(g_variant_equal(itemval, value)); - g_variant_unref(value); - } + g_variant_unref(value); + } + + void verify_item_attribute_is_not_set(GMenuModel * mm, guint index, const gchar * name, const GVariantType * type) { + GVariant * itemval = g_menu_model_get_item_attribute_value(mm, index, name, type); + EXPECT_EQ(itemval, nullptr); + } }; TEST_F(SoundMenuTest, BasicObject) { - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); - ASSERT_NE(nullptr, menu); + ASSERT_NE(nullptr, menu); - g_clear_object(&menu); - return; + g_clear_object(&menu); + return; } TEST_F(SoundMenuTest, AddRemovePlayer) { - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + + MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); + + MediaPlayerMock * media = MEDIA_PLAYER_MOCK( + g_object_new(TYPE_MEDIA_PLAYER_MOCK, + "mock-id", "player-id", + "mock-name", "Test Player", + "mock-state", "Playing", + "mock-is-running", TRUE, + "mock-can-raise", FALSE, + "mock-current-track", track, + "mock-can-do-play", TRUE, + "mock-can-do-next", TRUE, + "mock-can-do-prev", TRUE, + NULL) + ); + g_clear_object(&track); + + sound_menu_add_player(menu, MEDIA_PLAYER(media)); + + ASSERT_NE(nullptr, menu->menu); + EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); + ASSERT_NE(nullptr, section); + EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ + + /* Player display */ + verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); + verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); + + /* Player control */ + verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); + verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); + verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); + + g_clear_object(§ion); + + sound_menu_remove_player(menu, MEDIA_PLAYER(media)); + + EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + g_clear_object(&media); + g_clear_object(&menu); + return; +} + +TEST_F(SoundMenuTest, AddRemovePlayerNoPlayNextPrev) { + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + + MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); + + MediaPlayerMock * media = MEDIA_PLAYER_MOCK( + g_object_new(TYPE_MEDIA_PLAYER_MOCK, + "mock-id", "player-id", + "mock-name", "Test Player", + "mock-state", "Playing", + "mock-is-running", TRUE, + "mock-can-raise", FALSE, + "mock-current-track", track, + "mock-can-do-play", FALSE, + "mock-can-do-next", FALSE, + "mock-can-do-prev", FALSE, + NULL) + ); + g_clear_object(&track); + + sound_menu_add_player(menu, MEDIA_PLAYER(media)); + + ASSERT_NE(nullptr, menu->menu); + EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); + ASSERT_NE(nullptr, section); + EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ + + /* Player display */ + verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); + verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); + + /* Player control */ + verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); + verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id.disabled")); + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id.disabled")); + verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id.disabled")); + + g_clear_object(§ion); + + sound_menu_remove_player(menu, MEDIA_PLAYER(media)); + + EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + g_clear_object(&media); + g_clear_object(&menu); + return; +} + +TEST_F(SoundMenuTest, AddRemovePlayerNoNext) { + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); - MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); + MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); - MediaPlayerMock * media = MEDIA_PLAYER_MOCK( - g_object_new(TYPE_MEDIA_PLAYER_MOCK, - "mock-id", "player-id", - "mock-name", "Test Player", - "mock-state", "Playing", - "mock-is-running", TRUE, - "mock-can-raise", FALSE, - "mock-current-track", track, - NULL) - ); - g_clear_object(&track); + MediaPlayerMock * media = MEDIA_PLAYER_MOCK( + g_object_new(TYPE_MEDIA_PLAYER_MOCK, + "mock-id", "player-id", + "mock-name", "Test Player", + "mock-state", "Playing", + "mock-is-running", TRUE, + "mock-can-raise", FALSE, + "mock-current-track", track, + "mock-can-do-play", TRUE, + "mock-can-do-next", FALSE, + "mock-can-do-prev", TRUE, + NULL) + ); + g_clear_object(&track); - sound_menu_add_player(menu, MEDIA_PLAYER(media)); + sound_menu_add_player(menu, MEDIA_PLAYER(media)); - ASSERT_NE(nullptr, menu->menu); - EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + ASSERT_NE(nullptr, menu->menu); + EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); - ASSERT_NE(nullptr, section); - EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ + GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); + ASSERT_NE(nullptr, section); + EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ - /* Player display */ - verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); - verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); + /* Player display */ + verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); + verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); - /* Player control */ - verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); - verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); - verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); - verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); + /* Player control */ + verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); + verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id.disabled")); + verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); - g_clear_object(§ion); + g_clear_object(§ion); - sound_menu_remove_player(menu, MEDIA_PLAYER(media)); + sound_menu_remove_player(menu, MEDIA_PLAYER(media)); - EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - g_clear_object(&media); - g_clear_object(&menu); - return; + g_clear_object(&media); + g_clear_object(&menu); + return; } + +TEST_F(SoundMenuTest, AddRemovePlayerNoPrev) { + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + + MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); + + MediaPlayerMock * media = MEDIA_PLAYER_MOCK( + g_object_new(TYPE_MEDIA_PLAYER_MOCK, + "mock-id", "player-id", + "mock-name", "Test Player", + "mock-state", "Playing", + "mock-is-running", TRUE, + "mock-can-raise", FALSE, + "mock-current-track", track, + "mock-can-do-play", TRUE, + "mock-can-do-next", TRUE, + "mock-can-do-prev", FALSE, + NULL) + ); + g_clear_object(&track); + + sound_menu_add_player(menu, MEDIA_PLAYER(media)); + + ASSERT_NE(nullptr, menu->menu); + EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); + ASSERT_NE(nullptr, section); + EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ + + /* Player display */ + verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); + verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); + + /* Player control */ + verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); + verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); + verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id.disabled")); + + g_clear_object(§ion); + + sound_menu_remove_player(menu, MEDIA_PLAYER(media)); + + EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + g_clear_object(&media); + g_clear_object(&menu); + return; +} + +TEST_F(SoundMenuTest, AddRemovePlayerNoPlay) { + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + + MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); + + MediaPlayerMock * media = MEDIA_PLAYER_MOCK( + g_object_new(TYPE_MEDIA_PLAYER_MOCK, + "mock-id", "player-id", + "mock-name", "Test Player", + "mock-state", "Playing", + "mock-is-running", TRUE, + "mock-can-raise", FALSE, + "mock-current-track", track, + "mock-can-do-play", FALSE, + "mock-can-do-next", TRUE, + "mock-can-do-prev", TRUE, + NULL) + ); + g_clear_object(&track); + + sound_menu_add_player(menu, MEDIA_PLAYER(media)); + + ASSERT_NE(nullptr, menu->menu); + EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); + ASSERT_NE(nullptr, section); + EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ + + /* Player display */ + verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); + verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); + + /* Player control */ + verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); + verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id.disabled")); + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); + verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); + + g_clear_object(§ion); + + sound_menu_remove_player(menu, MEDIA_PLAYER(media)); + + EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + + g_clear_object(&media); + g_clear_object(&menu); + return; +} + +// -- cgit v1.2.3 From 619162fa3519848d135b4502f782cb4f118b5fac Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Wed, 16 Sep 2015 18:18:46 +0200 Subject: Unit tests refactored --- tests/sound-menu.cc | 240 ++++++++++++---------------------------------------- 1 file changed, 53 insertions(+), 187 deletions(-) (limited to 'tests') diff --git a/tests/sound-menu.cc b/tests/sound-menu.cc index 6fe2c90..75a661b 100644 --- a/tests/sound-menu.cc +++ b/tests/sound-menu.cc @@ -59,118 +59,68 @@ class SoundMenuTest : public ::testing::Test GVariant * itemval = g_menu_model_get_item_attribute_value(mm, index, name, type); EXPECT_EQ(itemval, nullptr); } -}; -TEST_F(SoundMenuTest, BasicObject) { - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + void check_player_control_buttons(bool canPlay, bool canNext, bool canPrev) + { + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); - ASSERT_NE(nullptr, menu); + MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); - g_clear_object(&menu); - return; -} + MediaPlayerMock * media = MEDIA_PLAYER_MOCK( + g_object_new(TYPE_MEDIA_PLAYER_MOCK, + "mock-id", "player-id", + "mock-name", "Test Player", + "mock-state", "Playing", + "mock-is-running", TRUE, + "mock-can-raise", FALSE, + "mock-current-track", track, + "mock-can-do-play", canPlay, + "mock-can-do-next", canNext, + "mock-can-do-prev", canPrev, + NULL) + ); + g_clear_object(&track); -TEST_F(SoundMenuTest, AddRemovePlayer) { - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); + sound_menu_add_player(menu, MEDIA_PLAYER(media)); - MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); + ASSERT_NE(nullptr, menu->menu); + EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - MediaPlayerMock * media = MEDIA_PLAYER_MOCK( - g_object_new(TYPE_MEDIA_PLAYER_MOCK, - "mock-id", "player-id", - "mock-name", "Test Player", - "mock-state", "Playing", - "mock-is-running", TRUE, - "mock-can-raise", FALSE, - "mock-current-track", track, - "mock-can-do-play", TRUE, - "mock-can-do-next", TRUE, - "mock-can-do-prev", TRUE, - NULL) - ); - g_clear_object(&track); + GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); + ASSERT_NE(nullptr, section); + EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ - sound_menu_add_player(menu, MEDIA_PLAYER(media)); + /* Player display */ + verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); + verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); - ASSERT_NE(nullptr, menu->menu); - EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + /* Player control */ + verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); + verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string(canPlay ? "indicator.play.player-id" : "indicator.play.player-id.disabled")); + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string(canNext ? "indicator.next.player-id" : "indicator.next.player-id.disabled")); + verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string(canPrev ? "indicator.previous.player-id" : "indicator.previous.player-id.disabled")); - GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); - ASSERT_NE(nullptr, section); - EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ + g_clear_object(§ion); - /* Player display */ - verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); - verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); + sound_menu_remove_player(menu, MEDIA_PLAYER(media)); - /* Player control */ - verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); - verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); - verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); - verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); - - g_clear_object(§ion); - - sound_menu_remove_player(menu, MEDIA_PLAYER(media)); + EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - - g_clear_object(&media); - g_clear_object(&menu); - return; -} + g_clear_object(&media); + g_clear_object(&menu); + } +}; -TEST_F(SoundMenuTest, AddRemovePlayerNoPlayNextPrev) { +TEST_F(SoundMenuTest, BasicObject) { SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); - MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); - - MediaPlayerMock * media = MEDIA_PLAYER_MOCK( - g_object_new(TYPE_MEDIA_PLAYER_MOCK, - "mock-id", "player-id", - "mock-name", "Test Player", - "mock-state", "Playing", - "mock-is-running", TRUE, - "mock-can-raise", FALSE, - "mock-current-track", track, - "mock-can-do-play", FALSE, - "mock-can-do-next", FALSE, - "mock-can-do-prev", FALSE, - NULL) - ); - g_clear_object(&track); - - sound_menu_add_player(menu, MEDIA_PLAYER(media)); - - ASSERT_NE(nullptr, menu->menu); - EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - - GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); - ASSERT_NE(nullptr, section); - EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ - - /* Player display */ - verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); - verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); - - /* Player control */ - verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); - verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id.disabled")); - verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id.disabled")); - verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id.disabled")); - - g_clear_object(§ion); - - sound_menu_remove_player(menu, MEDIA_PLAYER(media)); - - EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); + ASSERT_NE(nullptr, menu); - g_clear_object(&media); g_clear_object(&menu); return; } -TEST_F(SoundMenuTest, AddRemovePlayerNoNext) { +TEST_F(SoundMenuTest, AddRemovePlayer) { SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); @@ -184,7 +134,7 @@ TEST_F(SoundMenuTest, AddRemovePlayerNoNext) { "mock-can-raise", FALSE, "mock-current-track", track, "mock-can-do-play", TRUE, - "mock-can-do-next", FALSE, + "mock-can-do-next", TRUE, "mock-can-do-prev", TRUE, NULL) ); @@ -206,7 +156,7 @@ TEST_F(SoundMenuTest, AddRemovePlayerNoNext) { /* Player control */ verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); - verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id.disabled")); + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); g_clear_object(§ion); @@ -220,104 +170,20 @@ TEST_F(SoundMenuTest, AddRemovePlayerNoNext) { return; } -TEST_F(SoundMenuTest, AddRemovePlayerNoPrev) { - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); - - MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); - - MediaPlayerMock * media = MEDIA_PLAYER_MOCK( - g_object_new(TYPE_MEDIA_PLAYER_MOCK, - "mock-id", "player-id", - "mock-name", "Test Player", - "mock-state", "Playing", - "mock-is-running", TRUE, - "mock-can-raise", FALSE, - "mock-current-track", track, - "mock-can-do-play", TRUE, - "mock-can-do-next", TRUE, - "mock-can-do-prev", FALSE, - NULL) - ); - g_clear_object(&track); - - sound_menu_add_player(menu, MEDIA_PLAYER(media)); - - ASSERT_NE(nullptr, menu->menu); - EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - - GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); - ASSERT_NE(nullptr, section); - EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ - - /* Player display */ - verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); - verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); - - /* Player control */ - verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); - verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); - verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); - verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id.disabled")); - - g_clear_object(§ion); - - sound_menu_remove_player(menu, MEDIA_PLAYER(media)); +TEST_F(SoundMenuTest, AddRemovePlayerNoPlayNextPrev) { + check_player_control_buttons(false, false, false); +} - EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); +TEST_F(SoundMenuTest, AddRemovePlayerNoNext) { + check_player_control_buttons(true, false, true); +} - g_clear_object(&media); - g_clear_object(&menu); - return; +TEST_F(SoundMenuTest, AddRemovePlayerNoPrev) { + check_player_control_buttons(true, true, false); } TEST_F(SoundMenuTest, AddRemovePlayerNoPlay) { - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); - - MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); - - MediaPlayerMock * media = MEDIA_PLAYER_MOCK( - g_object_new(TYPE_MEDIA_PLAYER_MOCK, - "mock-id", "player-id", - "mock-name", "Test Player", - "mock-state", "Playing", - "mock-is-running", TRUE, - "mock-can-raise", FALSE, - "mock-current-track", track, - "mock-can-do-play", FALSE, - "mock-can-do-next", TRUE, - "mock-can-do-prev", TRUE, - NULL) - ); - g_clear_object(&track); - - sound_menu_add_player(menu, MEDIA_PLAYER(media)); - - ASSERT_NE(nullptr, menu->menu); - EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - - GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION); - ASSERT_NE(nullptr, section); - EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */ - - /* Player display */ - verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id")); - verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player")); - - /* Player control */ - verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); - verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id.disabled")); - verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); - verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); - - g_clear_object(§ion); - - sound_menu_remove_player(menu, MEDIA_PLAYER(media)); - - EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu))); - - g_clear_object(&media); - g_clear_object(&menu); - return; + check_player_control_buttons(false, true, true); } // -- cgit v1.2.3 From 09fc613f1ce55910698aca6b8b5d909ac3ae77a0 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Fri, 18 Sep 2015 15:15:59 +0200 Subject: Added AccountsService Mock to the integration tests --- tests/CMakeLists.txt | 3 +- tests/accounts-mock/AccountsDefs.h | 26 ++++++++++ tests/accounts-mock/AccountsMock.cpp | 38 ++++++++++++++ tests/accounts-mock/AccountsMock.h | 35 +++++++++++++ tests/accounts-mock/AccountsServiceSoundMock.cpp | 60 ++++++++++++++++++++++ tests/accounts-mock/AccountsServiceSoundMock.h | 44 ++++++++++++++++ tests/accounts-mock/CMakeLists.txt | 40 +++++++++++++++ .../com.ubuntu.AccountsService.Sound.Mock.xml | 6 +++ tests/accounts-mock/main.cpp | 58 +++++++++++++++++++++ .../org.freedesktop.Accounts.Mock.xml | 13 +++++ tests/dbus-types/dbus-types.h | 2 + tests/integration/CMakeLists.txt | 1 + tests/integration/indicator-sound-test-base.cpp | 27 +++++++--- tests/integration/indicator-sound-test-base.h | 3 ++ tests/integration/test-indicator.cpp | 2 + 15 files changed, 351 insertions(+), 7 deletions(-) create mode 100644 tests/accounts-mock/AccountsDefs.h create mode 100644 tests/accounts-mock/AccountsMock.cpp create mode 100644 tests/accounts-mock/AccountsMock.h create mode 100644 tests/accounts-mock/AccountsServiceSoundMock.cpp create mode 100644 tests/accounts-mock/AccountsServiceSoundMock.h create mode 100644 tests/accounts-mock/CMakeLists.txt create mode 100644 tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml create mode 100644 tests/accounts-mock/main.cpp create mode 100644 tests/accounts-mock/org.freedesktop.Accounts.Mock.xml (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4c28cdf..d818a2d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -280,4 +280,5 @@ add_test(indcator-test ) add_subdirectory(integration) -add_subdirectory(dbus-types) \ No newline at end of file +add_subdirectory(dbus-types) +add_subdirectory(accounts-mock) \ No newline at end of file diff --git a/tests/accounts-mock/AccountsDefs.h b/tests/accounts-mock/AccountsDefs.h new file mode 100644 index 0000000..e2b24ab --- /dev/null +++ b/tests/accounts-mock/AccountsDefs.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +namespace +{ + constexpr const char ACCOUNTS_SERVICE[] = "org.freedesktop.Accounts"; + constexpr const char USER_PATH[] = "/org/freedesktop/Accounts/UserTest"; + constexpr const char ACCOUNTS_PATH[] = "/org/freedesktop/Accounts"; + constexpr const char ACCOUNTS_SOUND_INTERFACE[] = "com.ubuntu.AccountsService.Sound"; +} diff --git a/tests/accounts-mock/AccountsMock.cpp b/tests/accounts-mock/AccountsMock.cpp new file mode 100644 index 0000000..72f86a6 --- /dev/null +++ b/tests/accounts-mock/AccountsMock.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include + +#include "AccountsMock.h" +#include "AccountsDefs.h" + +AccountsMock::AccountsMock(QObject* parent) + : QObject(parent) +{ +} + +AccountsMock::~AccountsMock() = default; + +QDBusObjectPath AccountsMock::FindUserByName(QString const & username) const +{ + return QDBusObjectPath(USER_PATH); +} + +QDBusObjectPath AccountsMock::FindUserById(int64_t uid) const +{ + return QDBusObjectPath(USER_PATH); +} diff --git a/tests/accounts-mock/AccountsMock.h b/tests/accounts-mock/AccountsMock.h new file mode 100644 index 0000000..759443c --- /dev/null +++ b/tests/accounts-mock/AccountsMock.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include +#include +#include + +class AccountsMock : public QObject, protected QDBusContext +{ + Q_OBJECT + +public Q_SLOTS: + QDBusObjectPath FindUserByName(QString const & username) const; + QDBusObjectPath FindUserById(int64_t uid) const; + +public: + AccountsMock(QObject* parent = 0); + virtual ~AccountsMock(); +}; diff --git a/tests/accounts-mock/AccountsServiceSoundMock.cpp b/tests/accounts-mock/AccountsServiceSoundMock.cpp new file mode 100644 index 0000000..10f4f8d --- /dev/null +++ b/tests/accounts-mock/AccountsServiceSoundMock.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include +#include +#include + +#include "AccountsServiceSoundMock.h" +#include "AccountsDefs.h" + +AccountsServiceSoundMock::AccountsServiceSoundMock(QObject* parent) + : QObject(parent) + , volume_(0.0) +{ +} + +AccountsServiceSoundMock::~AccountsServiceSoundMock() = default; + +double AccountsServiceSoundMock::volume() const +{ + return volume_; +} + +void AccountsServiceSoundMock::setVolume(double volume) +{ + volume_ = volume; + notifyPropertyChanged(ACCOUNTS_SOUND_INTERFACE, + USER_PATH, + "Volume"); +} + +void AccountsServiceSoundMock::notifyPropertyChanged(QString const & interface, + QString const & path, + QString const & propertyName) +{ + QDBusMessage signal = QDBusMessage::createSignal( + path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged"); + signal << interface; + QVariantMap changedProps; + changedProps.insert(propertyName, property(propertyName.toStdString().c_str())); + signal << changedProps; + signal << QStringList(); + QDBusConnection::systemBus().send(signal); +} diff --git a/tests/accounts-mock/AccountsServiceSoundMock.h b/tests/accounts-mock/AccountsServiceSoundMock.h new file mode 100644 index 0000000..2be996f --- /dev/null +++ b/tests/accounts-mock/AccountsServiceSoundMock.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include +#include + +class AccountsServiceSoundMock : public QObject, protected QDBusContext +{ + Q_OBJECT +// Q_CLASSINFO("D-Bus Interface", "test.com.ubuntu.AccountsService.Sound") + Q_PROPERTY(double Volume READ volume WRITE setVolume) + +public Q_SLOTS: + double volume() const; + void setVolume(double volume); + +public: + AccountsServiceSoundMock(QObject* parent = 0); + virtual ~AccountsServiceSoundMock(); + +protected: + void notifyPropertyChanged(QString const & interface, + QString const & path, + QString const & propertyName); + +private: + double volume_; +}; diff --git a/tests/accounts-mock/CMakeLists.txt b/tests/accounts-mock/CMakeLists.txt new file mode 100644 index 0000000..fcfab2d --- /dev/null +++ b/tests/accounts-mock/CMakeLists.txt @@ -0,0 +1,40 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +find_package(Qt5DBus REQUIRED) +include_directories(${Qt5DBus_INCLUDE_DIRS}) + +add_definitions(-DQT_NO_KEYWORDS=1) + +set(dbusinterface_sound_xml "com.ubuntu.AccountsService.Sound.Mock.xml") +set_source_files_properties(${dbusinterface_sound_xml} PROPERTIES + CLASSNAME AccountsServiceSoundMockInterface) + +qt5_add_dbus_interface(interface_files ${dbusinterface_sound_xml} accountsservice_sound_interface) + +qt5_add_dbus_adaptor(adaptor_files + com.ubuntu.AccountsService.Sound.Mock.xml + AccountsServiceSoundMock.h + AccountsServiceSoundMock + AccountsServiceSoundMockAdaptor) + +qt5_add_dbus_adaptor(adaptor_files + org.freedesktop.Accounts.Mock.xml + AccountsMock.h + AccountsMock + AccountsMockAdaptor) + +add_executable( + accounts-service-sound + ${interface_files} + ${adaptor_files} + AccountsServiceSoundMock.cpp + AccountsMock.cpp + main.cpp +) + +qt5_use_modules( + accounts-service-sound + Core + DBus +) diff --git a/tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml b/tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml new file mode 100644 index 0000000..859cd46 --- /dev/null +++ b/tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tests/accounts-mock/main.cpp b/tests/accounts-mock/main.cpp new file mode 100644 index 0000000..ca1a426 --- /dev/null +++ b/tests/accounts-mock/main.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include +#include + +#include + +#include "AccountsDefs.h" +#include "AccountsServiceSoundMock.h" +#include "AccountsServiceSoundMockAdaptor.h" +#include "AccountsMock.h" +#include "AccountsMockAdaptor.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QDBusConnection connection = QDBusConnection::systemBus(); + if (!connection.interface()->isServiceRegistered(ACCOUNTS_SERVICE)) + { + auto service = new AccountsServiceSoundMock(&app); + new SoundAdaptor(service); + + auto accounts_service = new AccountsMock(&app); + new AccountsAdaptor(accounts_service); + + if (!connection.registerService(ACCOUNTS_SERVICE)) + { + qFatal("Could not register AccountsService Volume service."); + } + + if (!connection.registerObject(USER_PATH, service)) + { + qFatal("Could not register AccountsService Volume object."); + } + + if (!connection.registerObject(ACCOUNTS_PATH, accounts_service)) + { + qFatal("Could not register Accounts object."); + } + } + qDebug() << "Service is already registered!."; + return app.exec(); +} diff --git a/tests/accounts-mock/org.freedesktop.Accounts.Mock.xml b/tests/accounts-mock/org.freedesktop.Accounts.Mock.xml new file mode 100644 index 0000000..f284d54 --- /dev/null +++ b/tests/accounts-mock/org.freedesktop.Accounts.Mock.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/dbus-types/dbus-types.h b/tests/dbus-types/dbus-types.h index f747458..8c7f253 100644 --- a/tests/dbus-types/dbus-types.h +++ b/tests/dbus-types/dbus-types.h @@ -32,6 +32,8 @@ namespace DBusTypes static constexpr char const* DBUS_PULSE = "org.PulseAudio1"; + static constexpr char const* ACCOUNTS_SERVICE = "org.freedesktop.Accounts"; + static constexpr char const* STREAM_RESTORE_NAME = "org.PulseAudio.Ext.StreamRestore1"; static constexpr char const* STREAM_RESTORE_PATH = "/org/pulseaudio/stream_restore1"; diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index 2e4004a..ace155a 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -29,6 +29,7 @@ include_directories("${CMAKE_BINARY_DIR}/tests/dbus-types") add_definitions(-DSOUND_SERVICE_BIN="${CMAKE_BINARY_DIR}/src/indicator-sound-service" -DSTREAM_RESTORE_TABLE="${CMAKE_SOURCE_DIR}/tests/integration/touch-stream-restore.table" -DVOLUME_SET_BIN="${CMAKE_BINARY_DIR}/tests/integration/set-volume" + -DACCOUNTS_SERVICE_BIN="${CMAKE_BINARY_DIR}/tests/accounts-mock/accounts-service-sound" -DTEST_SOUND="${CMAKE_SOURCE_DIR}/tests/integration/test-sound.wav" -DQT_NO_KEYWORDS=1 ) diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index 6e05efe..10717c7 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -112,12 +112,31 @@ void IndicatorSoundTestBase::startPulse() } } +void IndicatorSoundTestBase::startAccountsService() +{ + try + { + accountsService.reset( + new QProcessDBusService(DBusTypes::ACCOUNTS_SERVICE, + QDBusConnection::SystemBus, + ACCOUNTS_SERVICE_BIN, + QStringList() )); + accountsService->start(dbusTestRunner.systemConnection()); + + initializeAccountsInterface(); + } + catch (exception const& e) + { + cout << "accountsService(): " << e.what() << endl; + throw; + } +} + void IndicatorSoundTestBase::startIndicator() { try { setenv("PULSE_SERVER", "127.0.0.1", true); - setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true); indicator.reset( new QProcessDBusService(DBusTypes::DBUS_NAME, QDBusConnection::SessionBus, @@ -144,7 +163,7 @@ mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters() void IndicatorSoundTestBase::SetUp() { - initializeAccountsInterface(); + setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true); } void IndicatorSoundTestBase::TearDown() @@ -216,7 +235,6 @@ bool IndicatorSoundTestBase::waitMenuChange() bool IndicatorSoundTestBase::waitVolumeChangedInIndicator() { - qDebug() << "IndicatorSoundTestBase::waitVolumeChangedInIndicator() signal " << (void *)signal_spy_volume_changed_.get(); if (signal_spy_volume_changed_) { return signal_spy_volume_changed_->wait(); @@ -229,11 +247,9 @@ void IndicatorSoundTestBase::initializeAccountsInterface() auto username = qgetenv("USER"); if (username != "") { - qDebug() << "Setting Accounts interface for user: " << username; std::unique_ptr setInterface(new AccountsInterface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", QDBusConnection::systemBus(), 0)); - qDebug() << "Interface: " << setInterface.get(); QDBusReply userResp = setInterface->call(QLatin1String("FindUserByName"), QLatin1String(username)); @@ -252,7 +268,6 @@ void IndicatorSoundTestBase::initializeAccountsInterface() accounts_interface_.reset(new DBusPropertiesInterface("org.freedesktop.Accounts", userPath, soundInterface->connection(), 0)); - qDebug() << "Interface for setting volume: " << accounts_interface_.get(); if (!accounts_interface_->isValid()) { qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << accounts_interface_->lastError().message(); diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h index 81d8204..04a579f 100644 --- a/tests/integration/indicator-sound-test-base.h +++ b/tests/integration/indicator-sound-test-base.h @@ -46,6 +46,7 @@ protected: void startIndicator(); void startPulse(); + void startAccountsService(); bool setVolume(QString const &role, double volume); @@ -73,6 +74,8 @@ protected: QtDBusTest::DBusServicePtr pulseaudio; + QtDBusTest::DBusServicePtr accountsService; + QProcess testSoundProcess; std::unique_ptr menu_interface_; diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp index 8803f91..bb5adec 100644 --- a/tests/integration/test-indicator.cpp +++ b/tests/integration/test-indicator.cpp @@ -36,6 +36,7 @@ TEST_F(TestIndicator, ChangeRoleVolume) { double INITIAL_VOLUME = 0.0; + ASSERT_NO_THROW(startAccountsService()); ASSERT_NO_THROW(startPulse()); // initialize volumes in pulseaudio @@ -140,6 +141,7 @@ TEST_F(TestIndicator, BasicInitialVolume) { double INITIAL_VOLUME = 0.0; + ASSERT_NO_THROW(startAccountsService()); ASSERT_NO_THROW(startPulse()); // initialize volumes in pulseaudio -- cgit v1.2.3 From 83e68a4d2b9e40d7d4f047a2e58c70c484cbd916 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Fri, 18 Sep 2015 16:29:32 +0200 Subject: Updated schema dir for integration tests --- tests/accounts-mock/main.cpp | 5 ++++- tests/integration/CMakeLists.txt | 1 + tests/integration/indicator-sound-test-base.cpp | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/accounts-mock/main.cpp b/tests/accounts-mock/main.cpp index ca1a426..04ec530 100644 --- a/tests/accounts-mock/main.cpp +++ b/tests/accounts-mock/main.cpp @@ -53,6 +53,9 @@ int main(int argc, char *argv[]) qFatal("Could not register Accounts object."); } } - qDebug() << "Service is already registered!."; + else + { + qDebug() << "Service is already registered!."; + } return app.exec(); } diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index ace155a..52c4e70 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -32,6 +32,7 @@ add_definitions(-DSOUND_SERVICE_BIN="${CMAKE_BINARY_DIR}/src/indicator-sound-ser -DACCOUNTS_SERVICE_BIN="${CMAKE_BINARY_DIR}/tests/accounts-mock/accounts-service-sound" -DTEST_SOUND="${CMAKE_SOURCE_DIR}/tests/integration/test-sound.wav" -DQT_NO_KEYWORDS=1 + -DSCHEMA_DIR="${SCHEMA_DIR}" ) set(GLIB_REQUIRED_VERSION 2.26) diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index 10717c7..49e2ec5 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -163,11 +163,15 @@ mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters() void IndicatorSoundTestBase::SetUp() { + setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, true); + setenv("GSETTINGS_BACKEND", "memory", true); setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true); } void IndicatorSoundTestBase::TearDown() { + unsetenv("GSETTINGS_SCHEMA_DIR"); + unsetenv("GSETTINGS_BACKEND"); unsetenv("PULSE_SERVER"); } -- cgit v1.2.3 From 913282e093a723b7e3a7bb899a77a068edafcd01 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Sun, 20 Sep 2015 20:16:27 +0200 Subject: Updated set-volume utility --- tests/integration/utils/dbus-pulse-volume.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/integration/utils/dbus-pulse-volume.cpp b/tests/integration/utils/dbus-pulse-volume.cpp index 6989754..b42ea15 100644 --- a/tests/integration/utils/dbus-pulse-volume.cpp +++ b/tests/integration/utils/dbus-pulse-volume.cpp @@ -56,9 +56,9 @@ DBusPulseVolume::DBusPulseVolume() : qDebug() << "********************************Connetion: " << connection_string.value().toString(); -// connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer(connection_string.value().toString(), "set-volume"))); + connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer(connection_string.value().toString(), "set-volume"))); - connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer("unix:path=/run/user/1000/pulse/dbus-socket", "set-volume"))); +// connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer("unix:path=/run/user/1000/pulse/dbus-socket", "set-volume"))); qDebug() << "Is connected " << connection_->isConnected(); if (connection_->isConnected()) -- cgit v1.2.3 From ae0602ca11090c6c70cdf289ce3871766d36519c Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Mon, 21 Sep 2015 11:53:31 +0200 Subject: code cleanup --- tests/accounts-mock/AccountsDefs.h | 15 ++++++++-- tests/accounts-mock/AccountsMock.cpp | 2 ++ tests/accounts-mock/AccountsMock.h | 15 ++++++++++ tests/accounts-mock/AccountsServiceSoundMock.cpp | 26 +++++------------ tests/accounts-mock/AccountsServiceSoundMock.h | 26 +++++++++++++---- tests/accounts-mock/CMakeLists.txt | 5 ++-- tests/accounts-mock/main.cpp | 2 ++ tests/dbus-types/dbus-types.h | 4 ++- .../dbus-types/org.freedesktop.DBus.Properties.xml | 1 + tests/dbus-types/pulseaudio-volume.h | 4 +-- tests/integration/utils/dbus-pulse-volume.cpp | 33 +++------------------- 11 files changed, 71 insertions(+), 62 deletions(-) (limited to 'tests') diff --git a/tests/accounts-mock/AccountsDefs.h b/tests/accounts-mock/AccountsDefs.h index e2b24ab..0e4f270 100644 --- a/tests/accounts-mock/AccountsDefs.h +++ b/tests/accounts-mock/AccountsDefs.h @@ -17,10 +17,21 @@ */ #pragma once -namespace +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing { constexpr const char ACCOUNTS_SERVICE[] = "org.freedesktop.Accounts"; constexpr const char USER_PATH[] = "/org/freedesktop/Accounts/UserTest"; constexpr const char ACCOUNTS_PATH[] = "/org/freedesktop/Accounts"; constexpr const char ACCOUNTS_SOUND_INTERFACE[] = "com.ubuntu.AccountsService.Sound"; -} +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu + diff --git a/tests/accounts-mock/AccountsMock.cpp b/tests/accounts-mock/AccountsMock.cpp index 72f86a6..5c92dc5 100644 --- a/tests/accounts-mock/AccountsMock.cpp +++ b/tests/accounts-mock/AccountsMock.cpp @@ -20,6 +20,8 @@ #include "AccountsMock.h" #include "AccountsDefs.h" +using namespace ubuntu::indicators::testing; + AccountsMock::AccountsMock(QObject* parent) : QObject(parent) { diff --git a/tests/accounts-mock/AccountsMock.h b/tests/accounts-mock/AccountsMock.h index 759443c..72372e0 100644 --- a/tests/accounts-mock/AccountsMock.h +++ b/tests/accounts-mock/AccountsMock.h @@ -21,6 +21,15 @@ #include #include +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + class AccountsMock : public QObject, protected QDBusContext { Q_OBJECT @@ -33,3 +42,9 @@ public: AccountsMock(QObject* parent = 0); virtual ~AccountsMock(); }; + +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu diff --git a/tests/accounts-mock/AccountsServiceSoundMock.cpp b/tests/accounts-mock/AccountsServiceSoundMock.cpp index 10f4f8d..37de377 100644 --- a/tests/accounts-mock/AccountsServiceSoundMock.cpp +++ b/tests/accounts-mock/AccountsServiceSoundMock.cpp @@ -22,6 +22,8 @@ #include "AccountsServiceSoundMock.h" #include "AccountsDefs.h" +using namespace ubuntu::indicators::testing; + AccountsServiceSoundMock::AccountsServiceSoundMock(QObject* parent) : QObject(parent) , volume_(0.0) @@ -38,23 +40,9 @@ double AccountsServiceSoundMock::volume() const void AccountsServiceSoundMock::setVolume(double volume) { volume_ = volume; - notifyPropertyChanged(ACCOUNTS_SOUND_INTERFACE, - USER_PATH, - "Volume"); -} - -void AccountsServiceSoundMock::notifyPropertyChanged(QString const & interface, - QString const & path, - QString const & propertyName) -{ - QDBusMessage signal = QDBusMessage::createSignal( - path, - "org.freedesktop.DBus.Properties", - "PropertiesChanged"); - signal << interface; - QVariantMap changedProps; - changedProps.insert(propertyName, property(propertyName.toStdString().c_str())); - signal << changedProps; - signal << QStringList(); - QDBusConnection::systemBus().send(signal); + notifier_.notifyPropertyChanged(QDBusConnection::systemBus(), + ACCOUNTS_SOUND_INTERFACE, + USER_PATH, + "Volume", + property("Volume")); } diff --git a/tests/accounts-mock/AccountsServiceSoundMock.h b/tests/accounts-mock/AccountsServiceSoundMock.h index 2be996f..bb3dbe8 100644 --- a/tests/accounts-mock/AccountsServiceSoundMock.h +++ b/tests/accounts-mock/AccountsServiceSoundMock.h @@ -20,10 +20,22 @@ #include #include +#include "DBusPropertiesNotifier.h" + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + +class DBusPropertiesNotifier; + class AccountsServiceSoundMock : public QObject, protected QDBusContext { Q_OBJECT -// Q_CLASSINFO("D-Bus Interface", "test.com.ubuntu.AccountsService.Sound") Q_PROPERTY(double Volume READ volume WRITE setVolume) public Q_SLOTS: @@ -34,11 +46,13 @@ public: AccountsServiceSoundMock(QObject* parent = 0); virtual ~AccountsServiceSoundMock(); -protected: - void notifyPropertyChanged(QString const & interface, - QString const & path, - QString const & propertyName); - private: double volume_; + DBusPropertiesNotifier notifier_; }; + +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu diff --git a/tests/accounts-mock/CMakeLists.txt b/tests/accounts-mock/CMakeLists.txt index fcfab2d..aab7940 100644 --- a/tests/accounts-mock/CMakeLists.txt +++ b/tests/accounts-mock/CMakeLists.txt @@ -15,13 +15,13 @@ qt5_add_dbus_interface(interface_files ${dbusinterface_sound_xml} accountsservic qt5_add_dbus_adaptor(adaptor_files com.ubuntu.AccountsService.Sound.Mock.xml AccountsServiceSoundMock.h - AccountsServiceSoundMock + ubuntu::indicators::testing::AccountsServiceSoundMock AccountsServiceSoundMockAdaptor) qt5_add_dbus_adaptor(adaptor_files org.freedesktop.Accounts.Mock.xml AccountsMock.h - AccountsMock + ubuntu::indicators::testing::AccountsMock AccountsMockAdaptor) add_executable( @@ -30,6 +30,7 @@ add_executable( ${adaptor_files} AccountsServiceSoundMock.cpp AccountsMock.cpp + DBusPropertiesNotifier.cpp main.cpp ) diff --git a/tests/accounts-mock/main.cpp b/tests/accounts-mock/main.cpp index 04ec530..d6cd1d3 100644 --- a/tests/accounts-mock/main.cpp +++ b/tests/accounts-mock/main.cpp @@ -26,6 +26,8 @@ #include "AccountsMock.h" #include "AccountsMockAdaptor.h" +using namespace ubuntu::indicators::testing; + int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); diff --git a/tests/dbus-types/dbus-types.h b/tests/dbus-types/dbus-types.h index 8c7f253..4abe9ff 100644 --- a/tests/dbus-types/dbus-types.h +++ b/tests/dbus-types/dbus-types.h @@ -39,4 +39,6 @@ namespace DBusTypes static constexpr char const* STREAM_RESTORE_PATH = "/org/pulseaudio/stream_restore1"; static constexpr char const* STREAM_RESTORE_ENTRY_NAME = "org.PulseAudio.Ext.StreamRestore1.RestoreEntry"; -} + +} // namespace DBusTypes + diff --git a/tests/dbus-types/org.freedesktop.DBus.Properties.xml b/tests/dbus-types/org.freedesktop.DBus.Properties.xml index 19a1b90..bdf6cad 100644 --- a/tests/dbus-types/org.freedesktop.DBus.Properties.xml +++ b/tests/dbus-types/org.freedesktop.DBus.Properties.xml @@ -5,6 +5,7 @@ + diff --git a/tests/dbus-types/pulseaudio-volume.h b/tests/dbus-types/pulseaudio-volume.h index e9fe73d..6d5a222 100644 --- a/tests/dbus-types/pulseaudio-volume.h +++ b/tests/dbus-types/pulseaudio-volume.h @@ -42,9 +42,6 @@ private: unsigned int volume_; }; -Q_DECLARE_METATYPE(PulseaudioVolume) - - class PulseaudioVolumeArray { public: @@ -68,4 +65,5 @@ private: QVector volume_array_; }; +Q_DECLARE_METATYPE(PulseaudioVolume) Q_DECLARE_METATYPE(PulseaudioVolumeArray) diff --git a/tests/integration/utils/dbus-pulse-volume.cpp b/tests/integration/utils/dbus-pulse-volume.cpp index b42ea15..a282f77 100644 --- a/tests/integration/utils/dbus-pulse-volume.cpp +++ b/tests/integration/utils/dbus-pulse-volume.cpp @@ -16,13 +16,14 @@ * Author: Xavi Garcia */ +#include "dbus-pulse-volume.h" + #include "dbus_properties_interface.h" #include "dbus_accounts_interface.h" #include "dbus_accountssound_interface.h" #include "stream_restore_interface.h" #include -#include "dbus-pulse-volume.h" #include @@ -54,20 +55,13 @@ DBusPulseVolume::DBusPulseVolume() : qWarning() << "DBusPulseVolume::DBusPulseVolume(): D-Bus error: " << connection_string.error().message(); } - qDebug() << "********************************Connetion: " << connection_string.value().toString(); - connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer(connection_string.value().toString(), "set-volume"))); -// connection_.reset(new QDBusConnection(QDBusConnection::connectToPeer("unix:path=/run/user/1000/pulse/dbus-socket", "set-volume"))); - qDebug() << "Is connected " << connection_->isConnected(); - if (connection_->isConnected()) { interface_paths_.reset(new StreamRestoreInterface("org.PulseAudio.Ext.StreamRestore1", "/org/pulseaudio/stream_restore1", *(connection_.get()), 0)); - qDebug() << "Interface " << (void *)interface_paths_.get(); - if (interface_paths_) { // get the role paths @@ -87,7 +81,6 @@ DBusPulseVolume::DBusPulseVolume() : DBusPulseVolume::~DBusPulseVolume() { - connection_->disconnectFromPeer("unix:path=/run/user/1000/pulse/dbus-socket"); } QString DBusPulseVolume::fillRolePath(QString const &role) @@ -100,7 +93,7 @@ QString DBusPulseVolume::fillRolePath(QString const &role) qWarning() << "SetVolume::fillRolePath(): D-Bus error: " << objectPath.error().message(); return ""; } - qDebug() << "XGM: path for role " << role << "=" << objectPath.value().path(); + auto role_info = std::make_shared(); role_info->interface_.reset(new DBusPropertiesInterface("org.PulseAudio.Ext.StreamRestore1.RestoreEntry", objectPath.value().path(), @@ -122,26 +115,10 @@ bool DBusPulseVolume::setVolume(QString const & role, double volume) qWarning() << "SetVolume::setVolume(): error: Volume interfaces are not initialized"; return false; } + RolesMap::const_iterator iter = roles_map_.find(role); if (iter != roles_map_.end()) { - QDBusReply prev_vol = (*iter).second->interface_->call(QLatin1String("Get"), - QLatin1String("org.PulseAudio.Ext.StreamRestore1.RestoreEntry"), - QLatin1String("Volume")); - - if (!prev_vol.isValid()) - { - qWarning() << "SetVolume::setVolume(): D-Bus error: " << prev_vol.error().message(); - return false; - } - QDBusArgument arg = prev_vol.value().value(); - PulseaudioVolumeArray element; - arg >> element; - - PulseaudioVolume signal_vol(0, 4000); - PulseaudioVolumeArray vol_array; - vol_array.addItem(signal_vol); - QVariant var; PulseaudioVolumeArray t; PulseaudioVolume vv(0, volumeDoubleToUint(volume)); @@ -209,7 +186,6 @@ void DBusPulseVolume::initializeAccountsInterface() std::unique_ptr setInterface(new AccountsInterface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", QDBusConnection::systemBus(), 0)); - qDebug() << "Interface: " << setInterface.get(); QDBusReply userResp = setInterface->call(QLatin1String("FindUserByName"), QLatin1String(username)); @@ -228,7 +204,6 @@ void DBusPulseVolume::initializeAccountsInterface() accounts_interface_.reset(new DBusPropertiesInterface("org.freedesktop.Accounts", userPath, soundInterface->connection(), 0)); - qDebug() << "Interface for setting volume: " << accounts_interface_.get(); if (!accounts_interface_->isValid()) { qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << accounts_interface_->lastError().message(); -- cgit v1.2.3 From 42d7df585cf61eb64cdb7fc7e171969ce35f6173 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Mon, 21 Sep 2015 11:54:04 +0200 Subject: added DBusPropertiesNotifier --- tests/accounts-mock/DBusPropertiesNotifier.cpp | 41 ++++++++++++++++++++++ tests/accounts-mock/DBusPropertiesNotifier.h | 48 ++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 tests/accounts-mock/DBusPropertiesNotifier.cpp create mode 100644 tests/accounts-mock/DBusPropertiesNotifier.h (limited to 'tests') diff --git a/tests/accounts-mock/DBusPropertiesNotifier.cpp b/tests/accounts-mock/DBusPropertiesNotifier.cpp new file mode 100644 index 0000000..686e4e9 --- /dev/null +++ b/tests/accounts-mock/DBusPropertiesNotifier.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#include "DBusPropertiesNotifier.h" + +#include + +using namespace ubuntu::indicators::testing; + +void DBusPropertiesNotifier::notifyPropertyChanged(QDBusConnection const & connection, + QString const & interface, + QString const & path, + QString const & propertyName, + QVariant const & propertyValue) +{ + QDBusMessage signal = QDBusMessage::createSignal( + path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged"); + signal << interface; + QVariantMap changedProps; + changedProps.insert(propertyName, propertyValue); + signal << changedProps; + signal << QStringList(); + connection.send(signal); +} diff --git a/tests/accounts-mock/DBusPropertiesNotifier.h b/tests/accounts-mock/DBusPropertiesNotifier.h new file mode 100644 index 0000000..9fa013b --- /dev/null +++ b/tests/accounts-mock/DBusPropertiesNotifier.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + +class DBusPropertiesNotifier +{ +public: + DBusPropertiesNotifier() = default; + ~DBusPropertiesNotifier() = default; + + void notifyPropertyChanged(QDBusConnection const & connection, + QString const & interface, + QString const & path, + QString const & propertyName, + QVariant const & propertyValue); +}; + +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu -- cgit v1.2.3 From 22de41f3cc382adbf06be8642af5cfa7ec664c8e Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Mon, 21 Sep 2015 16:01:33 +0200 Subject: Added separated integration tests for desktop and phone, with different instances of pulseaudio --- tests/integration/indicator-sound-test-base.cpp | 76 +++++++++- tests/integration/indicator-sound-test-base.h | 11 +- tests/integration/test-indicator.cpp | 186 +++++++++++++++++++++--- tests/integration/utils/dbus-pulse-volume.cpp | 5 + 4 files changed, 255 insertions(+), 23 deletions(-) (limited to 'tests') diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index 49e2ec5..a839fbc 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -45,7 +45,7 @@ IndicatorSoundTestBase::~IndicatorSoundTestBase() } -bool IndicatorSoundTestBase::setVolume(QString const &role, double volume) +bool IndicatorSoundTestBase::setStreamRestoreVolume(QString const &role, double volume) { QProcess setVolume; setVolume.start(VOLUME_SET_BIN, QStringList() @@ -60,6 +60,25 @@ bool IndicatorSoundTestBase::setVolume(QString const &role, double volume) return setVolume.exitCode() == 0; } +bool IndicatorSoundTestBase::setSinkVolume(double volume) +{ + QString volume_percentage = QString("%1\%").arg(volume*100); + QProcess setVolume; + setVolume.start("pactl", QStringList() + << "-s" + << "127.0.0.1" + << "set-sink-volume" + << "0" + << volume_percentage); + if (!setVolume.waitForStarted()) + return false; + + if (!setVolume.waitForFinished()) + return false; + + return setVolume.exitCode() == 0; +} + bool IndicatorSoundTestBase::startTestSound(QString const &role) { testSoundProcess.terminate(); @@ -81,7 +100,37 @@ void IndicatorSoundTestBase::stopTestSound() testSoundProcess.terminate(); } -void IndicatorSoundTestBase::startPulse() +void IndicatorSoundTestBase::startPulseDesktop() +{ + try + { + pulseaudio.reset( + new QProcessDBusService(DBusTypes::DBUS_PULSE, + QDBusConnection::SessionBus, + "pulseaudio", + QStringList() << "--start" + << "-vvvv" + << "--disable-shm=true" + << "--daemonize=false" + << "--use-pid-file=false" + << "--system=false" + << "--exit-idle-time=-1" + << "-n" + << "--load=module-null-sink" + << "--log-target=file:/tmp/pulse-daemon.log" + << "--load=module-dbus-protocol" + << "--load=module-native-protocol-tcp auth-ip-acl=127.0.0.1" + )); + pulseaudio->start(dbusTestRunner.sessionConnection()); + } + catch (exception const& e) + { + cout << "pulseaudio(): " << e.what() << endl; + throw; + } +} + +void IndicatorSoundTestBase::startPulsePhone() { try { @@ -151,8 +200,6 @@ void IndicatorSoundTestBase::startIndicator() } } -// /usr/bin/pulseaudio --start -vvvv --disable-shm=true --daemonize=false --use-pid-file=false --system=false --exit-idle-time=-1 -n "--load=module-null-sink sink_name=multimedia" --load=module-stream-restore - mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters() { return mh::MenuMatcher::Parameters( @@ -161,6 +208,14 @@ mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters() "/com/canonical/indicator/sound/desktop"); } +mh::MenuMatcher::Parameters IndicatorSoundTestBase::phoneParameters() +{ + return mh::MenuMatcher::Parameters( + "com.canonical.indicator.sound", + { { "indicator", "/com/canonical/indicator/sound" } }, + "/com/canonical/indicator/sound/phone"); +} + void IndicatorSoundTestBase::SetUp() { setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, true); @@ -216,9 +271,22 @@ unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::volumeSlider(double return mh::MenuItemMatcher().radio() .label("Volume") .round_doubles(0.1) + .int32_attribute("target", 0) + .double_attribute("min-value", 0.0) + .double_attribute("max-value", 1.0) + .double_attribute("step", 0.01) + .string_attribute("x-canonical-type", "com.canonical.unity.slider") .pass_through_double_attribute("action", volume); } +unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::silentModeSwitch(bool toggled) +{ + return mh::MenuItemMatcher::checkbox() + .label("Silent Mode") + .action("indicator.silent-mode") + .toggled(toggled); +} + bool IndicatorSoundTestBase::waitMenuChange() { if (!menu_interface_) diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h index 04a579f..019efc9 100644 --- a/tests/integration/indicator-sound-test-base.h +++ b/tests/integration/indicator-sound-test-base.h @@ -45,10 +45,13 @@ protected: void TearDown() override; void startIndicator(); - void startPulse(); + void startPulseDesktop(); + void startPulsePhone(); void startAccountsService(); - bool setVolume(QString const &role, double volume); + bool setStreamRestoreVolume(QString const &role, double volume); + + bool setSinkVolume(double volume); bool startTestSound(QString const &role); @@ -58,8 +61,12 @@ protected: static unity::gmenuharness::MenuMatcher::Parameters desktopParameters(); + static unity::gmenuharness::MenuMatcher::Parameters phoneParameters(); + static unity::gmenuharness::MenuItemMatcher volumeSlider(double volume); + static unity::gmenuharness::MenuItemMatcher silentModeSwitch(bool toggled); + bool waitMenuChange(); bool waitVolumeChangedInIndicator(); diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp index bb5adec..a248658 100644 --- a/tests/integration/test-indicator.cpp +++ b/tests/integration/test-indicator.cpp @@ -32,16 +32,15 @@ class TestIndicator: public IndicatorSoundTestBase { }; -TEST_F(TestIndicator, ChangeRoleVolume) +TEST_F(TestIndicator, PhoneChangeRoleVolume) { double INITIAL_VOLUME = 0.0; ASSERT_NO_THROW(startAccountsService()); - ASSERT_NO_THROW(startPulse()); + ASSERT_NO_THROW(startPulsePhone()); // initialize volumes in pulseaudio - EXPECT_TRUE(setVolume("mutimedia", INITIAL_VOLUME)); - EXPECT_TRUE(setVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); // start now the indicator, so it picks the new volumes ASSERT_NO_THROW(startIndicator()); @@ -53,7 +52,7 @@ TEST_F(TestIndicator, ChangeRoleVolume) double randomVolume = randInt / 100.0; // set an initial volume to the alert role - setVolume("alert", 1.0); + setStreamRestoreVolume("alert", 1.0); EXPECT_TRUE(waitVolumeChangedInIndicator()); // play a test sound, it should change the role in the indicator @@ -61,31 +60,31 @@ TEST_F(TestIndicator, ChangeRoleVolume) EXPECT_TRUE(waitVolumeChangedInIndicator()); // set the random volume to the multimedia role - EXPECT_TRUE(setVolume("multimedia", randomVolume)); + EXPECT_TRUE(setStreamRestoreVolume("multimedia", randomVolume)); if (randomVolume != INITIAL_VOLUME) { EXPECT_TRUE(waitVolumeChangedInIndicator()); } // check the indicator - EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) .item(mh::MenuItemMatcher() .action("indicator.root") .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") .mode(mh::MenuItemMatcher::Mode::starts_with) .submenu() .item(mh::MenuItemMatcher() .section() - .item(mh::MenuItemMatcher().checkbox() - .label("Mute") - ) + .item(silentModeSwitch(false)) .item(volumeSlider(randomVolume)) ) ).match()); // check that the last item is Sound Settings - EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) .item(mh::MenuItemMatcher() .action("indicator.root") .string_attribute("x-canonical-type", "com.canonical.indicator.root") @@ -94,6 +93,7 @@ TEST_F(TestIndicator, ChangeRoleVolume) .submenu() .item(mh::MenuItemMatcher() .label("Sound Settings…") + .action("indicator.phone-settings") ) ).match()); @@ -106,6 +106,97 @@ TEST_F(TestIndicator, ChangeRoleVolume) EXPECT_TRUE(waitVolumeChangedInIndicator()); } + // check the initial volume for the alert role + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(1.0)) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); +} + +TEST_F(TestIndicator, PhoneBasicInitialVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // check the initial volume for the alert role + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME)) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); +} + +TEST_F(TestIndicator, DesktopBasicInitialVolume) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulseDesktop()); + + // initialize volumes in pulseaudio + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + // check the initial volume for the alert role EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) .item(mh::MenuItemMatcher() @@ -119,7 +210,7 @@ TEST_F(TestIndicator, ChangeRoleVolume) .item(mh::MenuItemMatcher().checkbox() .label("Mute") ) - .item(volumeSlider(1.0)) + .item(volumeSlider(INITIAL_VOLUME)) ) ).match()); @@ -137,20 +228,42 @@ TEST_F(TestIndicator, ChangeRoleVolume) ).match()); } -TEST_F(TestIndicator, BasicInitialVolume) +TEST_F(TestIndicator, DesktopChangeRoleVolume) { double INITIAL_VOLUME = 0.0; ASSERT_NO_THROW(startAccountsService()); - ASSERT_NO_THROW(startPulse()); + ASSERT_NO_THROW(startPulseDesktop()); // initialize volumes in pulseaudio - EXPECT_TRUE(setVolume("alert", INITIAL_VOLUME)); + // expect false for stream restore, because the module + // is not loaded in the desktop pulseaudio instance + EXPECT_FALSE(setStreamRestoreVolume("mutimedia", INITIAL_VOLUME)); + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); // start now the indicator, so it picks the new volumes ASSERT_NO_THROW(startIndicator()); - // check the initial volume for the alert role + // Generate a random volume + QTime now = QTime::currentTime(); + qsrand(now.msec()); + int randInt = qrand() % 100; + double randomVolume = randInt / 100.0; + +// // play a test sound, it should NOT change the role in the indicator + EXPECT_TRUE(startTestSound("multimedia")); + EXPECT_FALSE(waitVolumeChangedInIndicator()); + + // set the random volume + EXPECT_TRUE(setSinkVolume(randomVolume)); + if (randomVolume != INITIAL_VOLUME) + { + EXPECT_FALSE(waitVolumeChangedInIndicator()); + } + + // check the indicator EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) .item(mh::MenuItemMatcher() .action("indicator.root") @@ -163,7 +276,7 @@ TEST_F(TestIndicator, BasicInitialVolume) .item(mh::MenuItemMatcher().checkbox() .label("Mute") ) - .item(volumeSlider(INITIAL_VOLUME)) + .item(volumeSlider(randomVolume)) ) ).match()); @@ -179,6 +292,45 @@ TEST_F(TestIndicator, BasicInitialVolume) .label("Sound Settings…") ) ).match()); + + // stop the test sound, the role should change again to alert + stopTestSound(); + + // although we were playing something in the multimedia role + // the server does not have the streamrestore module, so + // the volume does not change (the role does not change) + EXPECT_FALSE(waitVolumeChangedInIndicator()); + + // check the initial volume for the alert role + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(randomVolume)) + ) + ).match()); + + // check that the last item is Sound Settings + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::ends_with) + .submenu() + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); } } // namespace diff --git a/tests/integration/utils/dbus-pulse-volume.cpp b/tests/integration/utils/dbus-pulse-volume.cpp index a282f77..c8b6ae6 100644 --- a/tests/integration/utils/dbus-pulse-volume.cpp +++ b/tests/integration/utils/dbus-pulse-volume.cpp @@ -150,6 +150,11 @@ bool DBusPulseVolume::setVolume(QString const & role, double volume) } } } + else + { + qWarning() << "SetVolume::setVolume(): role " << role << " was not found."; + return false; + } return true; } -- cgit v1.2.3 From b9ef4f6abdefb7b1d31d34f35b742016f1b5b87f Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Tue, 22 Sep 2015 11:52:43 +0200 Subject: Added themed_icon to integration tests --- tests/integration/indicator-sound-test-base.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests') diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index a839fbc..bbede82 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -276,6 +276,8 @@ unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::volumeSlider(double .double_attribute("max-value", 1.0) .double_attribute("step", 0.01) .string_attribute("x-canonical-type", "com.canonical.unity.slider") + .themed_icon("max-icon", {"audio-volume-high-panel", "audio-volume-high", "audio-volume", "audio"}) + .themed_icon("min-icon", {"audio-volume-low-zero-panel", "audio-volume-low-zero", "audio-volume-low", "audio-volume", "audio"}) .pass_through_double_attribute("action", volume); } -- cgit v1.2.3 From eb22c54e4587e5941378b066ec8220a56d26db4b Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Wed, 23 Sep 2015 16:10:54 +0200 Subject: Added test MPRIS player integration test --- tests/CMakeLists.txt | 6 +- tests/accounts-mock/AccountsDefs.h | 37 -------- tests/accounts-mock/AccountsMock.cpp | 40 -------- tests/accounts-mock/AccountsMock.h | 50 ---------- tests/accounts-mock/AccountsServiceSoundMock.cpp | 48 ---------- tests/accounts-mock/AccountsServiceSoundMock.h | 58 ------------ tests/accounts-mock/CMakeLists.txt | 41 -------- tests/accounts-mock/DBusPropertiesNotifier.cpp | 41 -------- tests/accounts-mock/DBusPropertiesNotifier.h | 48 ---------- .../com.ubuntu.AccountsService.Sound.Mock.xml | 6 -- tests/accounts-mock/main.cpp | 63 ------------- .../org.freedesktop.Accounts.Mock.xml | 13 --- tests/integration/CMakeLists.txt | 5 +- tests/integration/indicator-sound-test-base.cpp | 36 ++++++- tests/integration/indicator-sound-test-base.h | 6 ++ tests/integration/test-indicator.cpp | 74 +++++++++++---- tests/service-mocks/CMakeLists.txt | 2 + tests/service-mocks/DBusPropertiesNotifier.cpp | 41 ++++++++ tests/service-mocks/DBusPropertiesNotifier.h | 48 ++++++++++ tests/service-mocks/accounts-mock/AccountsDefs.h | 37 ++++++++ tests/service-mocks/accounts-mock/AccountsMock.cpp | 40 ++++++++ tests/service-mocks/accounts-mock/AccountsMock.h | 50 ++++++++++ .../accounts-mock/AccountsServiceSoundMock.cpp | 48 ++++++++++ .../accounts-mock/AccountsServiceSoundMock.h | 58 ++++++++++++ tests/service-mocks/accounts-mock/CMakeLists.txt | 42 +++++++++ .../com.ubuntu.AccountsService.Sound.Mock.xml | 6 ++ tests/service-mocks/accounts-mock/main.cpp | 63 +++++++++++++ .../org.freedesktop.Accounts.Mock.xml | 13 +++ .../media-player-mpris-mock/CMakeLists.txt | 63 +++++++++++++ .../media-player-mpris-mock/MediaPlayerMprisDefs.h | 37 ++++++++ .../MediaPlayerMprisMock.cpp | 103 +++++++++++++++++++++ .../media-player-mpris-mock/MediaPlayerMprisMock.h | 77 +++++++++++++++ .../applications/testplayer1.desktop | 21 +++++ .../service-mocks/media-player-mpris-mock/main.cpp | 64 +++++++++++++ .../org.mpris.MediaPlayer2.Player.xml | 24 +++++ .../org.mpris.MediaPlayer2.xml | 6 ++ .../media-player-mpris-mock/player-update.cpp | 93 +++++++++++++++++++ 37 files changed, 1037 insertions(+), 471 deletions(-) delete mode 100644 tests/accounts-mock/AccountsDefs.h delete mode 100644 tests/accounts-mock/AccountsMock.cpp delete mode 100644 tests/accounts-mock/AccountsMock.h delete mode 100644 tests/accounts-mock/AccountsServiceSoundMock.cpp delete mode 100644 tests/accounts-mock/AccountsServiceSoundMock.h delete mode 100644 tests/accounts-mock/CMakeLists.txt delete mode 100644 tests/accounts-mock/DBusPropertiesNotifier.cpp delete mode 100644 tests/accounts-mock/DBusPropertiesNotifier.h delete mode 100644 tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml delete mode 100644 tests/accounts-mock/main.cpp delete mode 100644 tests/accounts-mock/org.freedesktop.Accounts.Mock.xml create mode 100644 tests/service-mocks/CMakeLists.txt create mode 100644 tests/service-mocks/DBusPropertiesNotifier.cpp create mode 100644 tests/service-mocks/DBusPropertiesNotifier.h create mode 100644 tests/service-mocks/accounts-mock/AccountsDefs.h create mode 100644 tests/service-mocks/accounts-mock/AccountsMock.cpp create mode 100644 tests/service-mocks/accounts-mock/AccountsMock.h create mode 100644 tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp create mode 100644 tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h create mode 100644 tests/service-mocks/accounts-mock/CMakeLists.txt create mode 100644 tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml create mode 100644 tests/service-mocks/accounts-mock/main.cpp create mode 100644 tests/service-mocks/accounts-mock/org.freedesktop.Accounts.Mock.xml create mode 100644 tests/service-mocks/media-player-mpris-mock/CMakeLists.txt create mode 100644 tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisDefs.h create mode 100644 tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.cpp create mode 100644 tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.h create mode 100644 tests/service-mocks/media-player-mpris-mock/applications/testplayer1.desktop create mode 100644 tests/service-mocks/media-player-mpris-mock/main.cpp create mode 100644 tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.Player.xml create mode 100644 tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.xml create mode 100644 tests/service-mocks/media-player-mpris-mock/player-update.cpp (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d818a2d..adc08de 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -22,7 +22,8 @@ set_source_files_properties (gschemas.compiled GENERATED) # GSettings: # compile the indicator-sound schema into a gschemas.compiled file in this directory, # and help the tests to find that file by setting -DSCHEMA_DIR -set (SCHEMA_DIR "${CMAKE_CURRENT_BINARY_DIR}/gsettings-schemas") +set (XDG_DATA_DIRS "${CMAKE_CURRENT_BINARY_DIR}/gsettings-schemas") +set (SCHEMA_DIR "${XDG_DATA_DIRS}/glib-2.0/schemas") add_definitions(-DSCHEMA_DIR="${SCHEMA_DIR}") execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} gio-2.0 --variable glib_compile_schemas OUTPUT_VARIABLE COMPILE_SCHEMA_EXECUTABLE @@ -31,6 +32,7 @@ add_custom_command (OUTPUT gschemas.compiled DEPENDS ${CMAKE_SOURCE_DIR}/data/com.canonical.indicator.sound.gschema.xml COMMAND mkdir -p ${SCHEMA_DIR} COMMAND cp -f ${CMAKE_SOURCE_DIR}/data/*gschema.xml ${SCHEMA_DIR} + COMMAND cp -f /usr/share/glib-2.0/schemas/com.ubuntu.sound.gschema.xml ${SCHEMA_DIR} COMMAND ${COMPILE_SCHEMA_EXECUTABLE} ${SCHEMA_DIR}) ########################### @@ -281,4 +283,4 @@ add_test(indcator-test add_subdirectory(integration) add_subdirectory(dbus-types) -add_subdirectory(accounts-mock) \ No newline at end of file +add_subdirectory(service-mocks) \ No newline at end of file diff --git a/tests/accounts-mock/AccountsDefs.h b/tests/accounts-mock/AccountsDefs.h deleted file mode 100644 index 0e4f270..0000000 --- a/tests/accounts-mock/AccountsDefs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ -#pragma once - -namespace ubuntu -{ - -namespace indicators -{ - -namespace testing -{ - constexpr const char ACCOUNTS_SERVICE[] = "org.freedesktop.Accounts"; - constexpr const char USER_PATH[] = "/org/freedesktop/Accounts/UserTest"; - constexpr const char ACCOUNTS_PATH[] = "/org/freedesktop/Accounts"; - constexpr const char ACCOUNTS_SOUND_INTERFACE[] = "com.ubuntu.AccountsService.Sound"; -} // namespace testing - -} // namespace indicators - -} // namespace ubuntu - diff --git a/tests/accounts-mock/AccountsMock.cpp b/tests/accounts-mock/AccountsMock.cpp deleted file mode 100644 index 5c92dc5..0000000 --- a/tests/accounts-mock/AccountsMock.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ -#include - -#include "AccountsMock.h" -#include "AccountsDefs.h" - -using namespace ubuntu::indicators::testing; - -AccountsMock::AccountsMock(QObject* parent) - : QObject(parent) -{ -} - -AccountsMock::~AccountsMock() = default; - -QDBusObjectPath AccountsMock::FindUserByName(QString const & username) const -{ - return QDBusObjectPath(USER_PATH); -} - -QDBusObjectPath AccountsMock::FindUserById(int64_t uid) const -{ - return QDBusObjectPath(USER_PATH); -} diff --git a/tests/accounts-mock/AccountsMock.h b/tests/accounts-mock/AccountsMock.h deleted file mode 100644 index 72372e0..0000000 --- a/tests/accounts-mock/AccountsMock.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ -#pragma once - -#include -#include -#include - -namespace ubuntu -{ - -namespace indicators -{ - -namespace testing -{ - -class AccountsMock : public QObject, protected QDBusContext -{ - Q_OBJECT - -public Q_SLOTS: - QDBusObjectPath FindUserByName(QString const & username) const; - QDBusObjectPath FindUserById(int64_t uid) const; - -public: - AccountsMock(QObject* parent = 0); - virtual ~AccountsMock(); -}; - -} // namespace testing - -} // namespace indicators - -} // namespace ubuntu diff --git a/tests/accounts-mock/AccountsServiceSoundMock.cpp b/tests/accounts-mock/AccountsServiceSoundMock.cpp deleted file mode 100644 index 37de377..0000000 --- a/tests/accounts-mock/AccountsServiceSoundMock.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ -#include -#include -#include - -#include "AccountsServiceSoundMock.h" -#include "AccountsDefs.h" - -using namespace ubuntu::indicators::testing; - -AccountsServiceSoundMock::AccountsServiceSoundMock(QObject* parent) - : QObject(parent) - , volume_(0.0) -{ -} - -AccountsServiceSoundMock::~AccountsServiceSoundMock() = default; - -double AccountsServiceSoundMock::volume() const -{ - return volume_; -} - -void AccountsServiceSoundMock::setVolume(double volume) -{ - volume_ = volume; - notifier_.notifyPropertyChanged(QDBusConnection::systemBus(), - ACCOUNTS_SOUND_INTERFACE, - USER_PATH, - "Volume", - property("Volume")); -} diff --git a/tests/accounts-mock/AccountsServiceSoundMock.h b/tests/accounts-mock/AccountsServiceSoundMock.h deleted file mode 100644 index bb3dbe8..0000000 --- a/tests/accounts-mock/AccountsServiceSoundMock.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ -#pragma once - -#include -#include - -#include "DBusPropertiesNotifier.h" - -namespace ubuntu -{ - -namespace indicators -{ - -namespace testing -{ - -class DBusPropertiesNotifier; - -class AccountsServiceSoundMock : public QObject, protected QDBusContext -{ - Q_OBJECT - Q_PROPERTY(double Volume READ volume WRITE setVolume) - -public Q_SLOTS: - double volume() const; - void setVolume(double volume); - -public: - AccountsServiceSoundMock(QObject* parent = 0); - virtual ~AccountsServiceSoundMock(); - -private: - double volume_; - DBusPropertiesNotifier notifier_; -}; - -} // namespace testing - -} // namespace indicators - -} // namespace ubuntu diff --git a/tests/accounts-mock/CMakeLists.txt b/tests/accounts-mock/CMakeLists.txt deleted file mode 100644 index aab7940..0000000 --- a/tests/accounts-mock/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -set(CMAKE_AUTOMOC ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -find_package(Qt5DBus REQUIRED) -include_directories(${Qt5DBus_INCLUDE_DIRS}) - -add_definitions(-DQT_NO_KEYWORDS=1) - -set(dbusinterface_sound_xml "com.ubuntu.AccountsService.Sound.Mock.xml") -set_source_files_properties(${dbusinterface_sound_xml} PROPERTIES - CLASSNAME AccountsServiceSoundMockInterface) - -qt5_add_dbus_interface(interface_files ${dbusinterface_sound_xml} accountsservice_sound_interface) - -qt5_add_dbus_adaptor(adaptor_files - com.ubuntu.AccountsService.Sound.Mock.xml - AccountsServiceSoundMock.h - ubuntu::indicators::testing::AccountsServiceSoundMock - AccountsServiceSoundMockAdaptor) - -qt5_add_dbus_adaptor(adaptor_files - org.freedesktop.Accounts.Mock.xml - AccountsMock.h - ubuntu::indicators::testing::AccountsMock - AccountsMockAdaptor) - -add_executable( - accounts-service-sound - ${interface_files} - ${adaptor_files} - AccountsServiceSoundMock.cpp - AccountsMock.cpp - DBusPropertiesNotifier.cpp - main.cpp -) - -qt5_use_modules( - accounts-service-sound - Core - DBus -) diff --git a/tests/accounts-mock/DBusPropertiesNotifier.cpp b/tests/accounts-mock/DBusPropertiesNotifier.cpp deleted file mode 100644 index 686e4e9..0000000 --- a/tests/accounts-mock/DBusPropertiesNotifier.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ - -#include "DBusPropertiesNotifier.h" - -#include - -using namespace ubuntu::indicators::testing; - -void DBusPropertiesNotifier::notifyPropertyChanged(QDBusConnection const & connection, - QString const & interface, - QString const & path, - QString const & propertyName, - QVariant const & propertyValue) -{ - QDBusMessage signal = QDBusMessage::createSignal( - path, - "org.freedesktop.DBus.Properties", - "PropertiesChanged"); - signal << interface; - QVariantMap changedProps; - changedProps.insert(propertyName, propertyValue); - signal << changedProps; - signal << QStringList(); - connection.send(signal); -} diff --git a/tests/accounts-mock/DBusPropertiesNotifier.h b/tests/accounts-mock/DBusPropertiesNotifier.h deleted file mode 100644 index 9fa013b..0000000 --- a/tests/accounts-mock/DBusPropertiesNotifier.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ -#pragma once - -#include - -namespace ubuntu -{ - -namespace indicators -{ - -namespace testing -{ - -class DBusPropertiesNotifier -{ -public: - DBusPropertiesNotifier() = default; - ~DBusPropertiesNotifier() = default; - - void notifyPropertyChanged(QDBusConnection const & connection, - QString const & interface, - QString const & path, - QString const & propertyName, - QVariant const & propertyValue); -}; - -} // namespace testing - -} // namespace indicators - -} // namespace ubuntu diff --git a/tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml b/tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml deleted file mode 100644 index 859cd46..0000000 --- a/tests/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/tests/accounts-mock/main.cpp b/tests/accounts-mock/main.cpp deleted file mode 100644 index d6cd1d3..0000000 --- a/tests/accounts-mock/main.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 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 . - * - * Author: Xavi Garcia - */ -#include -#include - -#include - -#include "AccountsDefs.h" -#include "AccountsServiceSoundMock.h" -#include "AccountsServiceSoundMockAdaptor.h" -#include "AccountsMock.h" -#include "AccountsMockAdaptor.h" - -using namespace ubuntu::indicators::testing; - -int main(int argc, char *argv[]) -{ - QCoreApplication app(argc, argv); - QDBusConnection connection = QDBusConnection::systemBus(); - if (!connection.interface()->isServiceRegistered(ACCOUNTS_SERVICE)) - { - auto service = new AccountsServiceSoundMock(&app); - new SoundAdaptor(service); - - auto accounts_service = new AccountsMock(&app); - new AccountsAdaptor(accounts_service); - - if (!connection.registerService(ACCOUNTS_SERVICE)) - { - qFatal("Could not register AccountsService Volume service."); - } - - if (!connection.registerObject(USER_PATH, service)) - { - qFatal("Could not register AccountsService Volume object."); - } - - if (!connection.registerObject(ACCOUNTS_PATH, accounts_service)) - { - qFatal("Could not register Accounts object."); - } - } - else - { - qDebug() << "Service is already registered!."; - } - return app.exec(); -} diff --git a/tests/accounts-mock/org.freedesktop.Accounts.Mock.xml b/tests/accounts-mock/org.freedesktop.Accounts.Mock.xml deleted file mode 100644 index f284d54..0000000 --- a/tests/accounts-mock/org.freedesktop.Accounts.Mock.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index 52c4e70..5798f14 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -29,10 +29,11 @@ include_directories("${CMAKE_BINARY_DIR}/tests/dbus-types") add_definitions(-DSOUND_SERVICE_BIN="${CMAKE_BINARY_DIR}/src/indicator-sound-service" -DSTREAM_RESTORE_TABLE="${CMAKE_SOURCE_DIR}/tests/integration/touch-stream-restore.table" -DVOLUME_SET_BIN="${CMAKE_BINARY_DIR}/tests/integration/set-volume" - -DACCOUNTS_SERVICE_BIN="${CMAKE_BINARY_DIR}/tests/accounts-mock/accounts-service-sound" + -DACCOUNTS_SERVICE_BIN="${CMAKE_BINARY_DIR}/tests/service-mocks/accounts-mock/accounts-service-sound" + -DMEDIA_PLAYER_MPRIS_BIN="${CMAKE_BINARY_DIR}/tests/service-mocks/media-player-mpris-mock/media-player-mpris-mock" -DTEST_SOUND="${CMAKE_SOURCE_DIR}/tests/integration/test-sound.wav" -DQT_NO_KEYWORDS=1 - -DSCHEMA_DIR="${SCHEMA_DIR}" + -DXDG_DATA_DIRS="${XDG_DATA_DIRS}" ) set(GLIB_REQUIRED_VERSION 2.26) diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index bbede82..2b6b3d7 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -79,6 +79,36 @@ bool IndicatorSoundTestBase::setSinkVolume(double volume) return setVolume.exitCode() == 0; } +bool IndicatorSoundTestBase::clearGSettingsPlayers() +{ + QProcess clearPlayers; + + clearPlayers.start("gsettings", QStringList() + << "set" + << "com.canonical.indicator.sound" + << "interested-media-players" + << "[]"); + if (!clearPlayers.waitForStarted()) + return false; + + if (!clearPlayers.waitForFinished()) + return false; + + return clearPlayers.exitCode() == 0; +} + +bool IndicatorSoundTestBase::startTestMprisPlayer(QString const& playerName) +{ + testPlayer1.terminate(); + testPlayer1.start(MEDIA_PLAYER_MPRIS_BIN, QStringList() + << playerName); + if (!testPlayer1.waitForStarted()) + return false; + + + return true; +} + bool IndicatorSoundTestBase::startTestSound(QString const &role) { testSoundProcess.terminate(); @@ -218,15 +248,13 @@ mh::MenuMatcher::Parameters IndicatorSoundTestBase::phoneParameters() void IndicatorSoundTestBase::SetUp() { - setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, true); - setenv("GSETTINGS_BACKEND", "memory", true); + setenv("XDG_DATA_DIRS", XDG_DATA_DIRS, true); setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true); } void IndicatorSoundTestBase::TearDown() { - unsetenv("GSETTINGS_SCHEMA_DIR"); - unsetenv("GSETTINGS_BACKEND"); + unsetenv("XDG_DATA_DIRS"); unsetenv("PULSE_SERVER"); } diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h index 019efc9..741580b 100644 --- a/tests/integration/indicator-sound-test-base.h +++ b/tests/integration/indicator-sound-test-base.h @@ -49,6 +49,10 @@ protected: void startPulsePhone(); void startAccountsService(); + bool clearGSettingsPlayers(); + + bool startTestMprisPlayer(QString const& playerName); + bool setStreamRestoreVolume(QString const &role, double volume); bool setSinkVolume(double volume); @@ -85,6 +89,8 @@ protected: QProcess testSoundProcess; + QProcess testPlayer1; + std::unique_ptr menu_interface_; std::unique_ptr accounts_interface_; diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp index a248658..ca3d298 100644 --- a/tests/integration/test-indicator.cpp +++ b/tests/integration/test-indicator.cpp @@ -143,6 +143,7 @@ TEST_F(TestIndicator, PhoneBasicInitialVolume) double INITIAL_VOLUME = 0.0; ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); ASSERT_NO_THROW(startPulsePhone()); // initialize volumes in pulseaudio @@ -151,7 +152,6 @@ TEST_F(TestIndicator, PhoneBasicInitialVolume) // start now the indicator, so it picks the new volumes ASSERT_NO_THROW(startIndicator()); - // check the initial volume for the alert role EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) .item(mh::MenuItemMatcher() .action("indicator.root") @@ -159,23 +159,17 @@ TEST_F(TestIndicator, PhoneBasicInitialVolume) .string_attribute("x-canonical-scroll-action", "indicator.scroll") .string_attribute("x-canonical-secondary-action", "indicator.mute") .string_attribute("submenu-action", "indicator.indicator-shown") - .mode(mh::MenuItemMatcher::Mode::starts_with) + .mode(mh::MenuItemMatcher::Mode::all) .submenu() .item(mh::MenuItemMatcher() .section() .item(silentModeSwitch(false)) .item(volumeSlider(INITIAL_VOLUME)) ) - ).match()); - - // check that the last item is Sound Settings - EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) - .item(mh::MenuItemMatcher() - .action("indicator.root") - .string_attribute("x-canonical-type", "com.canonical.indicator.root") - .string_attribute("x-canonical-secondary-action", "indicator.mute") - .mode(mh::MenuItemMatcher::Mode::ends_with) - .submenu() +// .item(mh::MenuItemMatcher() +// .section() +// .action("indicator.testplayer1.desktop") +// ) .item(mh::MenuItemMatcher() .label("Sound Settings…") .action("indicator.phone-settings") @@ -188,6 +182,7 @@ TEST_F(TestIndicator, DesktopBasicInitialVolume) double INITIAL_VOLUME = 0.0; ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); ASSERT_NO_THROW(startPulseDesktop()); // initialize volumes in pulseaudio @@ -197,13 +192,12 @@ TEST_F(TestIndicator, DesktopBasicInitialVolume) // start now the indicator, so it picks the new volumes ASSERT_NO_THROW(startIndicator()); - // check the initial volume for the alert role EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) .item(mh::MenuItemMatcher() .action("indicator.root") .string_attribute("x-canonical-type", "com.canonical.indicator.root") .string_attribute("x-canonical-secondary-action", "indicator.mute") - .mode(mh::MenuItemMatcher::Mode::starts_with) + .mode(mh::MenuItemMatcher::Mode::all) .submenu() .item(mh::MenuItemMatcher() .section() @@ -212,19 +206,63 @@ TEST_F(TestIndicator, DesktopBasicInitialVolume) ) .item(volumeSlider(INITIAL_VOLUME)) ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) ).match()); +} - // check that the last item is Sound Settings +TEST_F(TestIndicator, DesktopAddPlayer) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulseDesktop()); + + // initialize volumes in pulseaudio + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // check that the player is added EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) .item(mh::MenuItemMatcher() .action("indicator.root") .string_attribute("x-canonical-type", "com.canonical.indicator.root") .string_attribute("x-canonical-secondary-action", "indicator.mute") - .mode(mh::MenuItemMatcher::Mode::ends_with) + .mode(mh::MenuItemMatcher::Mode::all) .submenu() .item(mh::MenuItemMatcher() - .label("Sound Settings…") + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME)) ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) ).match()); } @@ -252,7 +290,7 @@ TEST_F(TestIndicator, DesktopChangeRoleVolume) int randInt = qrand() % 100; double randomVolume = randInt / 100.0; -// // play a test sound, it should NOT change the role in the indicator + // play a test sound, it should NOT change the role in the indicator EXPECT_TRUE(startTestSound("multimedia")); EXPECT_FALSE(waitVolumeChangedInIndicator()); diff --git a/tests/service-mocks/CMakeLists.txt b/tests/service-mocks/CMakeLists.txt new file mode 100644 index 0000000..9cd8acb --- /dev/null +++ b/tests/service-mocks/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(accounts-mock) +add_subdirectory(media-player-mpris-mock) diff --git a/tests/service-mocks/DBusPropertiesNotifier.cpp b/tests/service-mocks/DBusPropertiesNotifier.cpp new file mode 100644 index 0000000..686e4e9 --- /dev/null +++ b/tests/service-mocks/DBusPropertiesNotifier.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ + +#include "DBusPropertiesNotifier.h" + +#include + +using namespace ubuntu::indicators::testing; + +void DBusPropertiesNotifier::notifyPropertyChanged(QDBusConnection const & connection, + QString const & interface, + QString const & path, + QString const & propertyName, + QVariant const & propertyValue) +{ + QDBusMessage signal = QDBusMessage::createSignal( + path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged"); + signal << interface; + QVariantMap changedProps; + changedProps.insert(propertyName, propertyValue); + signal << changedProps; + signal << QStringList(); + connection.send(signal); +} diff --git a/tests/service-mocks/DBusPropertiesNotifier.h b/tests/service-mocks/DBusPropertiesNotifier.h new file mode 100644 index 0000000..9fa013b --- /dev/null +++ b/tests/service-mocks/DBusPropertiesNotifier.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + +class DBusPropertiesNotifier +{ +public: + DBusPropertiesNotifier() = default; + ~DBusPropertiesNotifier() = default; + + void notifyPropertyChanged(QDBusConnection const & connection, + QString const & interface, + QString const & path, + QString const & propertyName, + QVariant const & propertyValue); +}; + +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu diff --git a/tests/service-mocks/accounts-mock/AccountsDefs.h b/tests/service-mocks/accounts-mock/AccountsDefs.h new file mode 100644 index 0000000..0e4f270 --- /dev/null +++ b/tests/service-mocks/accounts-mock/AccountsDefs.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + constexpr const char ACCOUNTS_SERVICE[] = "org.freedesktop.Accounts"; + constexpr const char USER_PATH[] = "/org/freedesktop/Accounts/UserTest"; + constexpr const char ACCOUNTS_PATH[] = "/org/freedesktop/Accounts"; + constexpr const char ACCOUNTS_SOUND_INTERFACE[] = "com.ubuntu.AccountsService.Sound"; +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu + diff --git a/tests/service-mocks/accounts-mock/AccountsMock.cpp b/tests/service-mocks/accounts-mock/AccountsMock.cpp new file mode 100644 index 0000000..5c92dc5 --- /dev/null +++ b/tests/service-mocks/accounts-mock/AccountsMock.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include + +#include "AccountsMock.h" +#include "AccountsDefs.h" + +using namespace ubuntu::indicators::testing; + +AccountsMock::AccountsMock(QObject* parent) + : QObject(parent) +{ +} + +AccountsMock::~AccountsMock() = default; + +QDBusObjectPath AccountsMock::FindUserByName(QString const & username) const +{ + return QDBusObjectPath(USER_PATH); +} + +QDBusObjectPath AccountsMock::FindUserById(int64_t uid) const +{ + return QDBusObjectPath(USER_PATH); +} diff --git a/tests/service-mocks/accounts-mock/AccountsMock.h b/tests/service-mocks/accounts-mock/AccountsMock.h new file mode 100644 index 0000000..72372e0 --- /dev/null +++ b/tests/service-mocks/accounts-mock/AccountsMock.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include +#include +#include + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + +class AccountsMock : public QObject, protected QDBusContext +{ + Q_OBJECT + +public Q_SLOTS: + QDBusObjectPath FindUserByName(QString const & username) const; + QDBusObjectPath FindUserById(int64_t uid) const; + +public: + AccountsMock(QObject* parent = 0); + virtual ~AccountsMock(); +}; + +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu diff --git a/tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp b/tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp new file mode 100644 index 0000000..37de377 --- /dev/null +++ b/tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include +#include +#include + +#include "AccountsServiceSoundMock.h" +#include "AccountsDefs.h" + +using namespace ubuntu::indicators::testing; + +AccountsServiceSoundMock::AccountsServiceSoundMock(QObject* parent) + : QObject(parent) + , volume_(0.0) +{ +} + +AccountsServiceSoundMock::~AccountsServiceSoundMock() = default; + +double AccountsServiceSoundMock::volume() const +{ + return volume_; +} + +void AccountsServiceSoundMock::setVolume(double volume) +{ + volume_ = volume; + notifier_.notifyPropertyChanged(QDBusConnection::systemBus(), + ACCOUNTS_SOUND_INTERFACE, + USER_PATH, + "Volume", + property("Volume")); +} diff --git a/tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h b/tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h new file mode 100644 index 0000000..bb3dbe8 --- /dev/null +++ b/tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include +#include + +#include "DBusPropertiesNotifier.h" + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + +class DBusPropertiesNotifier; + +class AccountsServiceSoundMock : public QObject, protected QDBusContext +{ + Q_OBJECT + Q_PROPERTY(double Volume READ volume WRITE setVolume) + +public Q_SLOTS: + double volume() const; + void setVolume(double volume); + +public: + AccountsServiceSoundMock(QObject* parent = 0); + virtual ~AccountsServiceSoundMock(); + +private: + double volume_; + DBusPropertiesNotifier notifier_; +}; + +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu diff --git a/tests/service-mocks/accounts-mock/CMakeLists.txt b/tests/service-mocks/accounts-mock/CMakeLists.txt new file mode 100644 index 0000000..bc71a8b --- /dev/null +++ b/tests/service-mocks/accounts-mock/CMakeLists.txt @@ -0,0 +1,42 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +find_package(Qt5DBus REQUIRED) +include_directories(${Qt5DBus_INCLUDE_DIRS} + "${CMAKE_SOURCE_DIR}/tests/service-mocks") + +add_definitions(-DQT_NO_KEYWORDS=1) + +set(dbusinterface_sound_xml "com.ubuntu.AccountsService.Sound.Mock.xml") +set_source_files_properties(${dbusinterface_sound_xml} PROPERTIES + CLASSNAME AccountsServiceSoundMockInterface) + +qt5_add_dbus_interface(interface_files ${dbusinterface_sound_xml} accountsservice_sound_interface) + +qt5_add_dbus_adaptor(adaptor_files + com.ubuntu.AccountsService.Sound.Mock.xml + AccountsServiceSoundMock.h + ubuntu::indicators::testing::AccountsServiceSoundMock + AccountsServiceSoundMockAdaptor) + +qt5_add_dbus_adaptor(adaptor_files + org.freedesktop.Accounts.Mock.xml + AccountsMock.h + ubuntu::indicators::testing::AccountsMock + AccountsMockAdaptor) + +add_executable( + accounts-service-sound + ${interface_files} + ${adaptor_files} + AccountsServiceSoundMock.cpp + AccountsMock.cpp + ${CMAKE_SOURCE_DIR}/tests/service-mocks/DBusPropertiesNotifier.cpp + main.cpp +) + +qt5_use_modules( + accounts-service-sound + Core + DBus +) diff --git a/tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml b/tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml new file mode 100644 index 0000000..859cd46 --- /dev/null +++ b/tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tests/service-mocks/accounts-mock/main.cpp b/tests/service-mocks/accounts-mock/main.cpp new file mode 100644 index 0000000..d6cd1d3 --- /dev/null +++ b/tests/service-mocks/accounts-mock/main.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include +#include + +#include + +#include "AccountsDefs.h" +#include "AccountsServiceSoundMock.h" +#include "AccountsServiceSoundMockAdaptor.h" +#include "AccountsMock.h" +#include "AccountsMockAdaptor.h" + +using namespace ubuntu::indicators::testing; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QDBusConnection connection = QDBusConnection::systemBus(); + if (!connection.interface()->isServiceRegistered(ACCOUNTS_SERVICE)) + { + auto service = new AccountsServiceSoundMock(&app); + new SoundAdaptor(service); + + auto accounts_service = new AccountsMock(&app); + new AccountsAdaptor(accounts_service); + + if (!connection.registerService(ACCOUNTS_SERVICE)) + { + qFatal("Could not register AccountsService Volume service."); + } + + if (!connection.registerObject(USER_PATH, service)) + { + qFatal("Could not register AccountsService Volume object."); + } + + if (!connection.registerObject(ACCOUNTS_PATH, accounts_service)) + { + qFatal("Could not register Accounts object."); + } + } + else + { + qDebug() << "Service is already registered!."; + } + return app.exec(); +} diff --git a/tests/service-mocks/accounts-mock/org.freedesktop.Accounts.Mock.xml b/tests/service-mocks/accounts-mock/org.freedesktop.Accounts.Mock.xml new file mode 100644 index 0000000..f284d54 --- /dev/null +++ b/tests/service-mocks/accounts-mock/org.freedesktop.Accounts.Mock.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/service-mocks/media-player-mpris-mock/CMakeLists.txt b/tests/service-mocks/media-player-mpris-mock/CMakeLists.txt new file mode 100644 index 0000000..a1f9e83 --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/CMakeLists.txt @@ -0,0 +1,63 @@ +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fPIC -pthread") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fno-strict-aliasing -Wextra -fPIC -pthread") + +find_package(Qt5DBus REQUIRED) +include_directories(${Qt5DBus_INCLUDE_DIRS} + "${CMAKE_SOURCE_DIR}/tests/service-mocks") + +add_definitions(-DQT_NO_KEYWORDS=1) + +set(dbusinterface_mediaplayermpris_xml "org.mpris.MediaPlayer2.Player.xml") +set_source_files_properties(${dbusinterface_mediaplayermpris_xml} PROPERTIES + CLASSNAME MediaPlayerMprisMockInterface) + +qt5_add_dbus_interface(interface_files ${dbusinterface_mediaplayermpris_xml} MediaPlayerMprisMockInterface) + +qt5_add_dbus_adaptor(adaptor_files + org.mpris.MediaPlayer2.Player.xml + MediaPlayerMprisMock.h + ubuntu::indicators::testing::MediaPlayerMprisMock + MediaPlayerMprisMockAdaptor) + +qt5_add_dbus_adaptor(adaptor_files + org.mpris.MediaPlayer2.xml + MediaPlayerMprisMock.h + ubuntu::indicators::testing::MediaPlayerMprisMock + MediaPlayer2MockAdaptor) + +add_executable( + media-player-mpris-mock + ${adaptor_files} + MediaPlayerMprisMock.cpp + ${CMAKE_SOURCE_DIR}/tests/service-mocks/DBusPropertiesNotifier.cpp + main.cpp + testplayers +) + +add_executable( + media-player-mpris-mock-update + ${interface_files} + player-update.cpp + testplayers +) + +qt5_use_modules( + media-player-mpris-mock + Core + DBus +) + +qt5_use_modules( + media-player-mpris-mock-update + Core + DBus +) + +# test players desktop files +add_custom_command (OUTPUT testplayers + DEPENDS ${CMAKE_SOURCE_DIR}/tests/service-mocks/media-player-mpris-mock/applications + COMMAND mkdir -p ${SCHEMA_DIR} + COMMAND cp -r ${CMAKE_SOURCE_DIR}/tests/service-mocks/media-player-mpris-mock/applications ${SCHEMA_DIR}) diff --git a/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisDefs.h b/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisDefs.h new file mode 100644 index 0000000..4d28b38 --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisDefs.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + constexpr const char MEDIA_PLAYER_MPRIS_SERVICE[] = "org.freedesktop.Accounts"; + constexpr const char USER_PATH[] = "/org/freedesktop/Accounts/UserTest"; + constexpr const char ACCOUNTS_PATH[] = "/org/freedesktop/Accounts"; + constexpr const char ACCOUNTS_SOUND_INTERFACE[] = "com.ubuntu.AccountsService.Sound"; +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu + diff --git a/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.cpp b/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.cpp new file mode 100644 index 0000000..25fe0b7 --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include + +#include "MediaPlayerMprisMock.h" + +using namespace ubuntu::indicators::testing; + +MediaPlayerMprisMock::MediaPlayerMprisMock(QString const &playerName, QObject* parent) + : QObject(parent) + , can_play_(true) + , can_pause_(true) + , can_gonext_(true) + , can_goprevious_(true) + , player_name_(playerName) +{ +} + +MediaPlayerMprisMock::~MediaPlayerMprisMock() = default; + +bool MediaPlayerMprisMock::canPlay() const +{ + return can_play_; +} + +void MediaPlayerMprisMock::setCanPlay(bool canPlay) +{ + can_play_ = canPlay; + notifier_.notifyPropertyChanged(QDBusConnection::sessionBus(), + "org.mpris.MediaPlayer2.Player", + "/org/mpris/MediaPlayer2", + "CanPlay", + property("CanPlay")); +} + +bool MediaPlayerMprisMock::canPause() const +{ + return can_pause_; +} + +void MediaPlayerMprisMock::setCanPause(bool canPause) +{ + can_pause_ = canPause; + notifier_.notifyPropertyChanged(QDBusConnection::sessionBus(), + "org.mpris.MediaPlayer2.Player", + "/org/mpris/MediaPlayer2", + "CanPause", + property("CanPause")); +} + +bool MediaPlayerMprisMock::canGoNext() const +{ + return can_gonext_; +} + +void MediaPlayerMprisMock::setCanGoNext(bool canGoNext) +{ + can_gonext_ = canGoNext; + notifier_.notifyPropertyChanged(QDBusConnection::sessionBus(), + "org.mpris.MediaPlayer2.Player", + "/org/mpris/MediaPlayer2", + "CanGoNext", + property("CanGoNext")); +} + +bool MediaPlayerMprisMock::canGoPrevious() const +{ + return can_goprevious_; +} + +void MediaPlayerMprisMock::setCanGoPrevious(bool canGoPrevious) +{ + can_goprevious_ = canGoPrevious; + notifier_.notifyPropertyChanged(QDBusConnection::sessionBus(), + "org.mpris.MediaPlayer2.Player", + "/org/mpris/MediaPlayer2", + "CanGoPrevious", + property("CanGoPrevious")); +} + +QString MediaPlayerMprisMock::desktopEntry() const +{ + return player_name_; +} + +void MediaPlayerMprisMock::setDesktopEntry(QString const &) +{ +} diff --git a/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.h b/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.h new file mode 100644 index 0000000..58dce8d --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/MediaPlayerMprisMock.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#pragma once + +#include +#include +#include + +#include "DBusPropertiesNotifier.h" + +namespace ubuntu +{ + +namespace indicators +{ + +namespace testing +{ + +class MediaPlayerMprisMock : public QObject, protected QDBusContext +{ + Q_OBJECT + Q_PROPERTY(bool CanPlay READ canPlay WRITE setCanPlay) + Q_PROPERTY(bool CanPause READ canPause WRITE setCanPause) + Q_PROPERTY(bool CanGoNext READ canGoNext WRITE setCanGoNext) + Q_PROPERTY(bool CanGoPrevious READ canGoPrevious WRITE setCanGoPrevious) + Q_PROPERTY(QString DesktopEntry READ desktopEntry WRITE setDesktopEntry) + +public Q_SLOTS: + bool canPlay() const; + void setCanPlay(bool canPlay); + + bool canPause() const; + void setCanPause(bool canPause); + + bool canGoNext() const; + void setCanGoNext(bool canGoNext); + + bool canGoPrevious() const; + void setCanGoPrevious(bool canGoPrevious); + + QString desktopEntry() const; + void setDesktopEntry(QString const &destopEntry); + +public: + MediaPlayerMprisMock(QString const &playerName, QObject* parent = 0); + virtual ~MediaPlayerMprisMock(); + +private: + bool can_play_; + bool can_pause_; + bool can_gonext_; + bool can_goprevious_; + DBusPropertiesNotifier notifier_; + QString player_name_; +}; + +} // namespace testing + +} // namespace indicators + +} // namespace ubuntu diff --git a/tests/service-mocks/media-player-mpris-mock/applications/testplayer1.desktop b/tests/service-mocks/media-player-mpris-mock/applications/testplayer1.desktop new file mode 100644 index 0000000..2ed5008 --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/applications/testplayer1.desktop @@ -0,0 +1,21 @@ +[Desktop Entry] +Name=TestPlayer1 +GenericName=Test Player 1 +X-GNOME-FullName=Test Player 1 +Comment=Play and organize your music collection +Keywords=Audio;Song;MP3;CD;Podcast;MTP;iPod;Playlist;Last.fm;UPnP;DLNA;Radio; +Exec=echo %U +Terminal=false +Type=Application +Icon=testplayer +X-GNOME-DocPath=testplayer/testplayer.xml +Categories=GNOME;GTK;AudioVideo;Audio;Player; +MimeType=application/x-ogg;application/ogg;audio/x-vorbis+ogg;audio/x-scpls;audio/x-mp3;audio/x-mpeg;audio/mpeg;audio/x-mpegurl;audio/x-flac;audio/mp4;x-scheme-handler/itms;x-scheme-handler/itmss; +StartupNotify=true +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=testplayer +X-GNOME-Bugzilla-Component=general +X-GNOME-Bugzilla-OtherBinaries=rhythmbox-client;rhythmbox-metadata; +X-GNOME-Bugzilla-Version=3.1 +X-GNOME-UsesNotifications=true + diff --git a/tests/service-mocks/media-player-mpris-mock/main.cpp b/tests/service-mocks/media-player-mpris-mock/main.cpp new file mode 100644 index 0000000..8945673 --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/main.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include +#include + +#include + +#include "MediaPlayerMprisDefs.h" +#include "MediaPlayerMprisMock.h" +#include "MediaPlayerMprisMockAdaptor.h" +#include "MediaPlayer2MockAdaptor.h" + +using namespace ubuntu::indicators::testing; + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + qWarning() << "usage: " << argv[0] << "TEST_PLAYER_NAME"; + return 1; + } + QString playerName = QString(argv[1]); + + QCoreApplication app(argc, argv); + QString playerService = QString("org.mpris.MediaPlayer2.") + playerName; + QDBusConnection connection = QDBusConnection::sessionBus(); + if (!connection.interface()->isServiceRegistered(playerService)) + { + auto service = new MediaPlayerMprisMock(playerName, &app); + new PlayerAdaptor(service); + new MediaPlayer2Adaptor(service); + + if (!connection.registerService(playerService)) + { + qDebug() << connection.lastError(); + qFatal("Could not register MediaPlayerMprisMock service."); + } + + if (!connection.registerObject("/org/mpris/MediaPlayer2", service)) + { + qFatal("Could not register MediaPlayerMprisMock object."); + } + } + else + { + qDebug() << "Service is already registered!."; + } + return app.exec(); +} diff --git a/tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.Player.xml b/tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.Player.xml new file mode 100644 index 0000000..3efd002 --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.Player.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.xml b/tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.xml new file mode 100644 index 0000000..489c68a --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/org.mpris.MediaPlayer2.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/service-mocks/media-player-mpris-mock/player-update.cpp b/tests/service-mocks/media-player-mpris-mock/player-update.cpp new file mode 100644 index 0000000..5768372 --- /dev/null +++ b/tests/service-mocks/media-player-mpris-mock/player-update.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 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 . + * + * Author: Xavi Garcia + */ +#include "MediaPlayerMprisMockInterface.h" + +#include + +QMap getPropertiesMap() +{ + QMap retMap; + + retMap["CANPLAY"] = "setCanPlay"; + retMap["CANPAUSE"] = "setCanPause"; + retMap["CANGONEXT"] = "setCanGoNext"; + retMap["CANGOPREVIOUS"] = "setCanGoPrevious"; + + return retMap; +} + +bool getBoolValue(QString const & str) +{ + if (str == "TRUE") + { + return true; + } + return false; +} + +QTextStream& qStdErr() +{ + static QTextStream ts( stderr ); + return ts; +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + if (argc != 4) + { + qStdErr() << "usage: " << argv[0] << "TEST_PLAYER_NAME PropertyName true|false\n"; + return 1; + } + + QString state = QString(argv[3]).toUpper(); + QString property = QString(argv[2]).toUpper(); + QString playerName = QString(argv[1]); + + auto propertiesMap = getPropertiesMap(); + + std::shared_ptr iface( + new MediaPlayerMprisMockInterface("org.mpris.MediaPlayer2." + playerName, + "/org/mpris/MediaPlayer2", + QDBusConnection::sessionBus())); + if (!iface) + { + qWarning() << argv[0] << ": error creating interface"; + return 1; + } + + QMap::iterator iter = propertiesMap.find(property); + if (iter == propertiesMap.end()) + { + qWarning() << argv[0] << ": property " << property << " was not found."; + return 1; + } + + QDBusReply set_prop = iface->call(QLatin1String((*iter).toStdString().c_str()), + QVariant::fromValue(getBoolValue(state))); + + if (!set_prop.isValid()) + { + qWarning() << argv[0] << ": D-Bus error: " << set_prop.error().message(); + return 1; + } + + return 0; +} + -- cgit v1.2.3 From 53b1246ced87efdaaf4600cdbe606a6be7cae680 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Thu, 24 Sep 2015 10:35:46 +0200 Subject: fixed path for players desktop files --- tests/service-mocks/media-player-mpris-mock/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/service-mocks/media-player-mpris-mock/CMakeLists.txt b/tests/service-mocks/media-player-mpris-mock/CMakeLists.txt index a1f9e83..b5f5861 100644 --- a/tests/service-mocks/media-player-mpris-mock/CMakeLists.txt +++ b/tests/service-mocks/media-player-mpris-mock/CMakeLists.txt @@ -59,5 +59,5 @@ qt5_use_modules( # test players desktop files add_custom_command (OUTPUT testplayers DEPENDS ${CMAKE_SOURCE_DIR}/tests/service-mocks/media-player-mpris-mock/applications - COMMAND mkdir -p ${SCHEMA_DIR} - COMMAND cp -r ${CMAKE_SOURCE_DIR}/tests/service-mocks/media-player-mpris-mock/applications ${SCHEMA_DIR}) + COMMAND mkdir -p ${XDG_DATA_DIRS} + COMMAND cp -r ${CMAKE_SOURCE_DIR}/tests/service-mocks/media-player-mpris-mock/applications ${XDG_DATA_DIRS}) -- cgit v1.2.3 From 5d88ce9836c1d32abfd369e650354ed855ec4654 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Fri, 25 Sep 2015 10:31:24 +0200 Subject: Added attribute_not_set to gmenuharness, added tests for player control buttons --- tests/integration/CMakeLists.txt | 1 + tests/integration/indicator-sound-test-base.cpp | 19 ++ tests/integration/indicator-sound-test-base.h | 2 + tests/integration/test-indicator.cpp | 228 +++++++++++++++++++++++- 4 files changed, 245 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index 5798f14..939e329 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -31,6 +31,7 @@ add_definitions(-DSOUND_SERVICE_BIN="${CMAKE_BINARY_DIR}/src/indicator-sound-ser -DVOLUME_SET_BIN="${CMAKE_BINARY_DIR}/tests/integration/set-volume" -DACCOUNTS_SERVICE_BIN="${CMAKE_BINARY_DIR}/tests/service-mocks/accounts-mock/accounts-service-sound" -DMEDIA_PLAYER_MPRIS_BIN="${CMAKE_BINARY_DIR}/tests/service-mocks/media-player-mpris-mock/media-player-mpris-mock" + -DMEDIA_PLAYER_MPRIS_UPDATE_BIN="${CMAKE_BINARY_DIR}/tests/service-mocks/media-player-mpris-mock/media-player-mpris-mock-update" -DTEST_SOUND="${CMAKE_SOURCE_DIR}/tests/integration/test-sound.wav" -DQT_NO_KEYWORDS=1 -DXDG_DATA_DIRS="${XDG_DATA_DIRS}" diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index 2b6b3d7..16f0bd6 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -109,6 +109,25 @@ bool IndicatorSoundTestBase::startTestMprisPlayer(QString const& playerName) return true; } +bool IndicatorSoundTestBase::setTestMprisPlayerProperty(QString const &testPlayer, QString const &property, bool value) +{ + QProcess setProperty; + QString strValue; + strValue = value ? "true" : "false"; + + setProperty.start(MEDIA_PLAYER_MPRIS_UPDATE_BIN, QStringList() + << testPlayer + << property + << strValue); + if (!setProperty.waitForStarted()) + return false; + + if (!setProperty.waitForFinished()) + return false; + + return setProperty.exitCode() == 0; +} + bool IndicatorSoundTestBase::startTestSound(QString const &role) { testSoundProcess.terminate(); diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h index 741580b..00ccf1a 100644 --- a/tests/integration/indicator-sound-test-base.h +++ b/tests/integration/indicator-sound-test-base.h @@ -53,6 +53,8 @@ protected: bool startTestMprisPlayer(QString const& playerName); + bool setTestMprisPlayerProperty(QString const &testPlayer, QString const &property, bool value); + bool setStreamRestoreVolume(QString const &role, double volume); bool setSinkVolume(double volume); diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp index ca3d298..82f06a4 100644 --- a/tests/integration/test-indicator.cpp +++ b/tests/integration/test-indicator.cpp @@ -166,10 +166,41 @@ TEST_F(TestIndicator, PhoneBasicInitialVolume) .item(silentModeSwitch(false)) .item(volumeSlider(INITIAL_VOLUME)) ) -// .item(mh::MenuItemMatcher() -// .section() -// .action("indicator.testplayer1.desktop") -// ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); +} + +TEST_F(TestIndicator, PhoneAddMprisPlayer) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME)) + ) .item(mh::MenuItemMatcher() .label("Sound Settings…") .action("indicator.phone-settings") @@ -189,9 +220,66 @@ TEST_F(TestIndicator, DesktopBasicInitialVolume) EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME)) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); +} + +TEST_F(TestIndicator, DesktopAddMprisPlayer) +{ + double INITIAL_VOLUME = 0.0; + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulseDesktop()); + + // initialize volumes in pulseaudio + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); + + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + // start now the indicator, so it picks the new volumes ASSERT_NO_THROW(startIndicator()); + // check that the player is added EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) .item(mh::MenuItemMatcher() .action("indicator.root") @@ -206,13 +294,28 @@ TEST_F(TestIndicator, DesktopBasicInitialVolume) ) .item(volumeSlider(INITIAL_VOLUME)) ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) .item(mh::MenuItemMatcher() .label("Sound Settings…") ) ).match()); } -TEST_F(TestIndicator, DesktopAddPlayer) +TEST_F(TestIndicator, DesktopMprisPlayerButtonsState) { double INITIAL_VOLUME = 0.0; @@ -264,6 +367,121 @@ TEST_F(TestIndicator, DesktopAddPlayer) .label("Sound Settings…") ) ).match()); + + // change the state of CanGoNext + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoNext", false)); + + // verify that the action changes + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME)) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .attribute_not_set("x-canonical-next-action") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); + + + // change the state of CanGoPrevious + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoPrevious", false)); + + // verify that the action changes + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME)) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .attribute_not_set("x-canonical-previous-action") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .attribute_not_set("x-canonical-next-action") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); + + // set back both to true + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoNext", true)); + EXPECT_TRUE(setTestMprisPlayerProperty("testplayer1", "CanGoPrevious", true)); + + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher().checkbox() + .label("Mute") + ) + .item(volumeSlider(INITIAL_VOLUME)) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + ) + ).match()); } TEST_F(TestIndicator, DesktopChangeRoleVolume) -- cgit v1.2.3 From 2dba91ca24ce98f866498333c7a39e20d68813f7 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Thu, 1 Oct 2015 15:15:16 +0200 Subject: added mechanism to wait for the gmenu to change. Added player test for the phone profile --- tests/dbus-types/CMakeLists.txt | 6 ++-- tests/dbus-types/org.gtk.Actions.xml | 13 +++++++ tests/dbus-types/org.gtk.Menus.xml | 6 ---- tests/integration/indicator-sound-test-base.cpp | 38 +++++++++++++------- tests/integration/indicator-sound-test-base.h | 4 +++ tests/integration/test-indicator.cpp | 47 ++++++++++++++++++++++++- 6 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 tests/dbus-types/org.gtk.Actions.xml delete mode 100644 tests/dbus-types/org.gtk.Menus.xml (limited to 'tests') diff --git a/tests/dbus-types/CMakeLists.txt b/tests/dbus-types/CMakeLists.txt index 6346e25..30dff60 100644 --- a/tests/dbus-types/CMakeLists.txt +++ b/tests/dbus-types/CMakeLists.txt @@ -24,15 +24,15 @@ set_source_files_properties(${dbusinterface_properties_xml} PROPERTIES NO_NAMESPACE YES INCLUDE "dbus-types.h") -set(dbusinterface_menus_xml "org.gtk.Menus.xml") -set_source_files_properties(${dbusinterface_menus_xml} PROPERTIES +set(dbusinterface_actions_xml "org.gtk.Actions.xml") +set_source_files_properties(${dbusinterface_actions_xml} PROPERTIES CLASSNAME MenusInterface) qt5_add_dbus_interface(interface_files ${dbusinterface_streamrestore_xml} stream_restore_interface) qt5_add_dbus_interface(interface_files ${dbusinterface_properties_xml} dbus_properties_interface) qt5_add_dbus_interface(interface_files ${dbusinterface_accounts_xml} dbus_accounts_interface) qt5_add_dbus_interface(interface_files ${dbusinterface_accountssound_xml} dbus_accountssound_interface) -qt5_add_dbus_interface(interface_files ${dbusinterface_menus_xml} dbus_menus_interface) +qt5_add_dbus_interface(interface_files ${dbusinterface_actions_xml} dbus_menus_interface) add_library( sound-indicator-dbus-interfaces diff --git a/tests/dbus-types/org.gtk.Actions.xml b/tests/dbus-types/org.gtk.Actions.xml new file mode 100644 index 0000000..b691f1f --- /dev/null +++ b/tests/dbus-types/org.gtk.Actions.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tests/dbus-types/org.gtk.Menus.xml b/tests/dbus-types/org.gtk.Menus.xml deleted file mode 100644 index a0d6a83..0000000 --- a/tests/dbus-types/org.gtk.Menus.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index 16f0bd6..a8d41a0 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -140,7 +140,6 @@ bool IndicatorSoundTestBase::startTestSound(QString const &role) if (!testSoundProcess.waitForStarted()) return false; -// sleep(1); return true; } @@ -218,7 +217,7 @@ void IndicatorSoundTestBase::startAccountsService() new QProcessDBusService(DBusTypes::ACCOUNTS_SERVICE, QDBusConnection::SystemBus, ACCOUNTS_SERVICE_BIN, - QStringList() )); + QStringList())); accountsService->start(dbusTestRunner.systemConnection()); initializeAccountsInterface(); @@ -275,6 +274,7 @@ void IndicatorSoundTestBase::TearDown() { unsetenv("XDG_DATA_DIRS"); unsetenv("PULSE_SERVER"); + unsetenv("DBUS_SYSTEM_BUS_ADDRESS"); } void gvariant_deleter(GVariant* varptr) @@ -337,21 +337,32 @@ unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::silentModeSwitch(bo } bool IndicatorSoundTestBase::waitMenuChange() +{ + if (signal_spy_menu_changed_) + { + return signal_spy_menu_changed_->wait(); + } + return false; +} + +bool IndicatorSoundTestBase::initializeMenuChangedSignal() { if (!menu_interface_) { menu_interface_.reset(new MenusInterface("com.canonical.indicator.sound", - "/com/canonical/indicator/sound/desktop", - QDBusConnection::sessionBus(), 0)); + "/com/canonical/indicator/sound", + dbusTestRunner.sessionConnection(), 0)); } if (menu_interface_) { qDebug() << "Waiting for signal"; - QSignalSpy spy(menu_interface_.get(), &MenusInterface::Changed); - qDebug() << "Signal count " << spy.count(); - return spy.wait(); + signal_spy_menu_changed_.reset(new QSignalSpy(menu_interface_.get(), &MenusInterface::Changed)); } - return false; + if (!menu_interface_ || !signal_spy_menu_changed_) + { + return false; + } + return true; } bool IndicatorSoundTestBase::waitVolumeChangedInIndicator() @@ -368,27 +379,28 @@ void IndicatorSoundTestBase::initializeAccountsInterface() auto username = qgetenv("USER"); if (username != "") { - std::unique_ptr setInterface(new AccountsInterface("org.freedesktop.Accounts", + std::unique_ptr accountsInterface(new AccountsInterface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", - QDBusConnection::systemBus(), 0)); + dbusTestRunner.systemConnection(), 0)); - QDBusReply userResp = setInterface->call(QLatin1String("FindUserByName"), + QDBusReply userResp = accountsInterface->call(QLatin1String("FindUserByName"), QLatin1String(username)); if (!userResp.isValid()) { qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << userResp.error().message(); } + auto userPath = userResp.value().path(); if (userPath != "") { std::unique_ptr soundInterface(new AccountsSoundInterface("org.freedesktop.Accounts", userPath, - QDBusConnection::systemBus(), 0)); + dbusTestRunner.systemConnection(), 0)); accounts_interface_.reset(new DBusPropertiesInterface("org.freedesktop.Accounts", userPath, - soundInterface->connection(), 0)); + dbusTestRunner.systemConnection(), 0)); if (!accounts_interface_->isValid()) { qWarning() << "SetVolume::initializeAccountsInterface(): D-Bus error: " << accounts_interface_->lastError().message(); diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h index 00ccf1a..0dc0052 100644 --- a/tests/integration/indicator-sound-test-base.h +++ b/tests/integration/indicator-sound-test-base.h @@ -75,6 +75,8 @@ protected: bool waitMenuChange(); + bool initializeMenuChangedSignal(); + bool waitVolumeChangedInIndicator(); void initializeAccountsInterface(); @@ -98,4 +100,6 @@ protected: std::unique_ptr accounts_interface_; std::unique_ptr signal_spy_volume_changed_; + + std::unique_ptr signal_spy_menu_changed_; }; diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp index 82f06a4..22c0041 100644 --- a/tests/integration/test-indicator.cpp +++ b/tests/integration/test-indicator.cpp @@ -206,6 +206,51 @@ TEST_F(TestIndicator, PhoneAddMprisPlayer) .action("indicator.phone-settings") ) ).match()); + + // initialize the signal spy + EXPECT_TRUE(initializeMenuChangedSignal()); + + // start the test player + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); + + // wait fot the menu change + EXPECT_TRUE(waitMenuChange()); + + // finally verify that the player is added + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME)) + ) + .item(mh::MenuItemMatcher() + .section() + .item(mh::MenuItemMatcher() + .action("indicator.testplayer1.desktop") + .label("TestPlayer1") + .themed_icon("icon", {"testplayer"}) + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") + ) + .item(mh::MenuItemMatcher() + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") + ) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); } TEST_F(TestIndicator, DesktopBasicInitialVolume) @@ -516,7 +561,7 @@ TEST_F(TestIndicator, DesktopChangeRoleVolume) EXPECT_TRUE(setSinkVolume(randomVolume)); if (randomVolume != INITIAL_VOLUME) { - EXPECT_FALSE(waitVolumeChangedInIndicator()); + EXPECT_TRUE(waitVolumeChangedInIndicator()); } // check the indicator -- cgit v1.2.3 From 8402eadfcbd96b753f7cf2402956c100812de54e Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Thu, 1 Oct 2015 15:45:30 +0200 Subject: fixed typo in comment --- tests/integration/test-indicator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp index 22c0041..5a4b4ee 100644 --- a/tests/integration/test-indicator.cpp +++ b/tests/integration/test-indicator.cpp @@ -213,7 +213,7 @@ TEST_F(TestIndicator, PhoneAddMprisPlayer) // start the test player EXPECT_TRUE(startTestMprisPlayer("testplayer1")); - // wait fot the menu change + // wait for the menu change EXPECT_TRUE(waitMenuChange()); // finally verify that the player is added -- cgit v1.2.3 From 828fae630464f2eae96145cffcf97e5791497264 Mon Sep 17 00:00:00 2001 From: Xavi Garcia Mena Date: Tue, 13 Oct 2015 09:49:55 +0200 Subject: Added notifications tests integrated with the test instance of pulseAudio and gmenuharness --- tests/dbus-types/CMakeLists.txt | 5 + tests/dbus-types/dbus-types.h | 4 + tests/dbus-types/org.freedesktop.Notifications.xml | 47 +++ tests/integration/indicator-sound-test-base.cpp | 319 +++++++++++++++++---- tests/integration/indicator-sound-test-base.h | 29 ++ tests/integration/test-indicator.cpp | 288 +++++++++++++++++++ 6 files changed, 641 insertions(+), 51 deletions(-) create mode 100644 tests/dbus-types/org.freedesktop.Notifications.xml (limited to 'tests') diff --git a/tests/dbus-types/CMakeLists.txt b/tests/dbus-types/CMakeLists.txt index 30dff60..cb7f512 100644 --- a/tests/dbus-types/CMakeLists.txt +++ b/tests/dbus-types/CMakeLists.txt @@ -28,11 +28,16 @@ set(dbusinterface_actions_xml "org.gtk.Actions.xml") set_source_files_properties(${dbusinterface_actions_xml} PROPERTIES CLASSNAME MenusInterface) +set(dbusinterface_notifications_xml "org.freedesktop.Notifications.xml") +set_source_files_properties(${dbusinterface_notifications_xml} PROPERTIES + CLASSNAME NotificationsInterface) + qt5_add_dbus_interface(interface_files ${dbusinterface_streamrestore_xml} stream_restore_interface) qt5_add_dbus_interface(interface_files ${dbusinterface_properties_xml} dbus_properties_interface) qt5_add_dbus_interface(interface_files ${dbusinterface_accounts_xml} dbus_accounts_interface) qt5_add_dbus_interface(interface_files ${dbusinterface_accountssound_xml} dbus_accountssound_interface) qt5_add_dbus_interface(interface_files ${dbusinterface_actions_xml} dbus_menus_interface) +qt5_add_dbus_interface(interface_files ${dbusinterface_notifications_xml} dbus_notifications_interface) add_library( sound-indicator-dbus-interfaces diff --git a/tests/dbus-types/dbus-types.h b/tests/dbus-types/dbus-types.h index 4abe9ff..b75acf0 100644 --- a/tests/dbus-types/dbus-types.h +++ b/tests/dbus-types/dbus-types.h @@ -40,5 +40,9 @@ namespace DBusTypes static constexpr char const* STREAM_RESTORE_ENTRY_NAME = "org.PulseAudio.Ext.StreamRestore1.RestoreEntry"; + static constexpr char const* MAIN_SERVICE_PATH = "/com/canonical/indicator/sound"; + + static constexpr char const* ACTIONS_INTERFACE = "org.gtk.Actions"; + } // namespace DBusTypes diff --git a/tests/dbus-types/org.freedesktop.Notifications.xml b/tests/dbus-types/org.freedesktop.Notifications.xml new file mode 100644 index 0000000..f7d923e --- /dev/null +++ b/tests/dbus-types/org.freedesktop.Notifications.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp index a8d41a0..f9db365 100644 --- a/tests/integration/indicator-sound-test-base.cpp +++ b/tests/integration/indicator-sound-test-base.cpp @@ -22,6 +22,7 @@ #include "dbus_properties_interface.h" #include "dbus_accounts_interface.h" #include "dbus_accountssound_interface.h" +#include "dbus_notifications_interface.h" #include "dbus-types.h" #include @@ -42,7 +43,67 @@ IndicatorSoundTestBase::IndicatorSoundTestBase() : IndicatorSoundTestBase::~IndicatorSoundTestBase() { +} + +void IndicatorSoundTestBase::SetUp() +{ + setenv("XDG_DATA_DIRS", XDG_DATA_DIRS, true); + setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true); + setenv("DBUS_SESSION_BUS_ADDRESS", dbusTestRunner.sessionBus().toStdString().c_str(), true); + dbusMock.registerNotificationDaemon(); + + dbusTestRunner.startServices(); + + auto& notifications = notificationsMockInterface(); + notifications.AddMethod("org.freedesktop.Notifications", + "GetCapabilities", + "", + "as", + "ret = ['actions', 'body', 'body-markup', 'icon-static', 'image/svg+xml', 'x-canonical-private-synchronous', 'x-canonical-append', 'x-canonical-private-icon-only', 'x-canonical-truncation', 'private-synchronous', 'append', 'private-icon-only', 'truncation']" + ).waitForFinished(); +} + +void IndicatorSoundTestBase::TearDown() +{ + unsetenv("XDG_DATA_DIRS"); + unsetenv("PULSE_SERVER"); + unsetenv("DBUS_SYSTEM_BUS_ADDRESS"); +} + +void gvariant_deleter(GVariant* varptr) +{ + if (varptr != nullptr) + { + g_variant_unref(varptr); + } +} +std::shared_ptr IndicatorSoundTestBase::volume_variant(double volume) +{ + GVariantBuilder builder; + + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&builder, + "{sv}", + "title", + g_variant_new_string("_Sound")); + + g_variant_builder_add(&builder, + "{sv}", + "accessible-desc", + g_variant_new_string("_Sound")); + + auto icon = g_themed_icon_new("icon"); + g_variant_builder_add(&builder, + "{sv}", + "icon", + g_icon_serialize(icon)); + + g_variant_builder_add(&builder, + "{sv}", + "visible", + g_variant_new_boolean(true)); + return shared_ptr(g_variant_builder_end(&builder), &gvariant_deleter); } bool IndicatorSoundTestBase::setStreamRestoreVolume(QString const &role, double volume) @@ -164,7 +225,8 @@ void IndicatorSoundTestBase::startPulseDesktop() << "--system=false" << "--exit-idle-time=-1" << "-n" - << "--load=module-null-sink" + << QString("--load=module-null-sink sink_name=indicator_sound_test_speaker") + << QString("--load=module-null-sink sink_name=indicator_sound_test_headphones") << "--log-target=file:/tmp/pulse-daemon.log" << "--load=module-dbus-protocol" << "--load=module-native-protocol-tcp auth-ip-acl=127.0.0.1" @@ -194,7 +256,8 @@ void IndicatorSoundTestBase::startPulsePhone() << "--system=false" << "--exit-idle-time=-1" << "-n" - << "--load=module-null-sink" + << QString("--load=module-null-sink sink_name=indicator_sound_test_speaker") + << QString("--load=module-null-sink sink_name=indicator_sound_test_headphones") << "--log-target=file:/tmp/pulse-daemon.log" << QString("--load=module-stream-restore restore_device=false restore_muted=false fallback_table=%1").arg(STREAM_RESTORE_TABLE) << "--load=module-dbus-protocol" @@ -264,55 +327,6 @@ mh::MenuMatcher::Parameters IndicatorSoundTestBase::phoneParameters() "/com/canonical/indicator/sound/phone"); } -void IndicatorSoundTestBase::SetUp() -{ - setenv("XDG_DATA_DIRS", XDG_DATA_DIRS, true); - setenv("DBUS_SYSTEM_BUS_ADDRESS", dbusTestRunner.systemBus().toStdString().c_str(), true); -} - -void IndicatorSoundTestBase::TearDown() -{ - unsetenv("XDG_DATA_DIRS"); - unsetenv("PULSE_SERVER"); - unsetenv("DBUS_SYSTEM_BUS_ADDRESS"); -} - -void gvariant_deleter(GVariant* varptr) -{ - if (varptr != nullptr) - { - g_variant_unref(varptr); - } -} - -std::shared_ptr IndicatorSoundTestBase::volume_variant(double volume) -{ - GVariantBuilder builder; - - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add(&builder, - "{sv}", - "title", - g_variant_new_string("_Sound")); - - g_variant_builder_add(&builder, - "{sv}", - "accessible-desc", - g_variant_new_string("_Sound")); - - auto icon = g_themed_icon_new("icon"); - g_variant_builder_add(&builder, - "{sv}", - "icon", - g_icon_serialize(icon)); - - g_variant_builder_add(&builder, - "{sv}", - "visible", - g_variant_new_boolean(true)); - return shared_ptr(g_variant_builder_end(&builder), &gvariant_deleter); -} - unity::gmenuharness::MenuItemMatcher IndicatorSoundTestBase::volumeSlider(double volume) { return mh::MenuItemMatcher().radio() @@ -409,3 +423,206 @@ void IndicatorSoundTestBase::initializeAccountsInterface() } } } + +OrgFreedesktopDBusMockInterface& IndicatorSoundTestBase::notificationsMockInterface() +{ + return dbusMock.mockInterface("org.freedesktop.Notifications", + "/org/freedesktop/Notifications", + "org.freedesktop.Notifications", + QDBusConnection::SessionBus); +} + +bool IndicatorSoundTestBase::setActionValue(const QString & action, QVariant value) +{ + QDBusInterface actionsInterface(DBusTypes::DBUS_NAME, + DBusTypes::MAIN_SERVICE_PATH, + DBusTypes::ACTIONS_INTERFACE, + dbusTestRunner.sessionConnection()); + + QDBusVariant dbusVar(value); + auto resp = actionsInterface.call("SetState", + action, + QVariant::fromValue(dbusVar), + QVariant::fromValue(QVariantMap())); + + if (resp.type() == QDBusMessage::ErrorMessage) + { + qCritical() << "IndicatorSoundTestBase::setActionValue(): Failed to set value for action " + << action + << " " + << resp.errorMessage(); + return false; + } + else + { + return true; + } +} + +bool IndicatorSoundTestBase::pressNotificationButton(int id, const QString & button) +{ + OrgFreedesktopDBusMockInterface actionsInterface("org.freedesktop.Notifications", + "/org/freedesktop/Notifications", + dbusTestRunner.sessionConnection()); + + actionsInterface.EmitSignal( + "org.freedesktop.Notifications", + "ActionInvoked", "us", QVariantList() << id << button); + + return true; +} + +bool IndicatorSoundTestBase::qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) +{ + if (variant.canConvert()) + { + QDBusArgument value(variant.value()); + if (value.currentType() == QDBusArgument::MapType) + { + value >> map; + return true; + } + } + return false; +} + +void IndicatorSoundTestBase::checkVolumeNotification(double volume, QString const& label, bool isLoud, QVariantList call) +{ + QString icon; + if (volume <= 0.0) + { + icon = "audio-volume-muted"; + } + else if (volume <= 0.3) + { + icon = "audio-volume-low"; + } + else if (volume <= 0.7) + { + icon = "audio-volume-medium"; + } + else + { + icon = "audio-volume-high"; + } + + ASSERT_NE(call.size(), 0); + EXPECT_EQ("Notify", call.at(0)); + + QVariantList const& args(call.at(1).toList()); + ASSERT_EQ(8, args.size()); + EXPECT_EQ("indicator-sound", args.at(0)); + EXPECT_EQ(icon, args.at(2)); + EXPECT_EQ("Volume", args.at(3)); + EXPECT_EQ(label, args.at(4)); + EXPECT_EQ(QStringList(), args.at(5)); + + QVariantMap hints; + ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints)); + ASSERT_TRUE(hints.contains("value")); + ASSERT_TRUE(hints.contains("x-canonical-non-shaped-icon")); + ASSERT_TRUE(hints.contains("x-canonical-value-bar-tint")); + ASSERT_TRUE(hints.contains("x-canonical-private-synchronous")); + + EXPECT_EQ(volume*100, hints["value"]); + EXPECT_EQ(true, hints["x-canonical-non-shaped-icon"]); + EXPECT_EQ(isLoud, hints["x-canonical-value-bar-tint"]); + EXPECT_EQ(true, hints["x-canonical-private-synchronous"]); +} + +void IndicatorSoundTestBase::checkHighVolumeNotification(QVariantList call) +{ + ASSERT_NE(call.size(), 0); + EXPECT_EQ("Notify", call.at(0)); + + QVariantList const& args(call.at(1).toList()); + ASSERT_EQ(8, args.size()); + EXPECT_EQ("indicator-sound", args.at(0)); + EXPECT_EQ("Volume", args.at(3)); +} + +void IndicatorSoundTestBase::checkCloseNotification(int id, QVariantList call) +{ + EXPECT_EQ("CloseNotification", call.at(0)); + QVariantList const& args(call.at(1).toList()); + ASSERT_EQ(1, args.size()); +} + +void IndicatorSoundTestBase::checkNotificationWithNoArgs(QString const& method, QVariantList call) +{ + EXPECT_EQ(method, call.at(0)); + QVariantList const& args(call.at(1).toList()); + ASSERT_EQ(0, args.size()); +} + +int IndicatorSoundTestBase::getNotificationID(QVariantList call) +{ + if (call.size() == 0) + { + return -1; + } + QVariantList const& args(call.at(1).toList()); + if (args.size() != 8) + { + return -1; + } + if (args.at(0) != "indicator-sound") + { + return -1; + } + + bool isInt; + int id = args.at(1).toInt(&isInt); + if (!isInt) + { + return -1; + } + return id; +} + +bool IndicatorSoundTestBase::activateHeadphones(bool headphonesActive) +{ + QProcess pacltProcess; + + QString defaultSinkName = "indicator_sound_test_speaker"; + QString suspendedSinkName = "indicator_sound_test_headphones"; + if (headphonesActive) + { + defaultSinkName = "indicator_sound_test_headphones"; + suspendedSinkName = "indicator_sound_test_speaker"; + } + + pacltProcess.start("pactl", QStringList() << "-s" + << "127.0.0.1" + << "set-default-sink" + << defaultSinkName); + if (!pacltProcess.waitForStarted()) + return false; + + if (!pacltProcess.waitForFinished()) + return false; + + pacltProcess.start("pactl", QStringList() << "-s" + << "127.0.0.1" + << "suspend-sink" + << defaultSinkName + << "0"); + if (!pacltProcess.waitForStarted()) + return false; + + if (!pacltProcess.waitForFinished()) + return false; + + pacltProcess.start("pactl", QStringList() << "-s" + << "127.0.0.1" + << "suspend-sink" + << suspendedSinkName + << "1"); + if (!pacltProcess.waitForStarted()) + return false; + + if (!pacltProcess.waitForFinished()) + return false; + + return pacltProcess.exitCode() == 0; +} diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h index 0dc0052..20e44fc 100644 --- a/tests/integration/indicator-sound-test-base.h +++ b/tests/integration/indicator-sound-test-base.h @@ -33,6 +33,15 @@ class DBusPulseVolume; class DBusPropertiesInterface; class QSignalSpy; +#define WAIT_FOR_SIGNALS(signalSpy, signalsExpected)\ +{\ + while (signalSpy.size() < signalsExpected)\ + {\ + ASSERT_TRUE(signalSpy.wait());\ + }\ + ASSERT_EQ(signalsExpected, signalSpy.size());\ +} + class IndicatorSoundTestBase: public testing::Test { public: @@ -81,6 +90,26 @@ protected: void initializeAccountsInterface(); + OrgFreedesktopDBusMockInterface& notificationsMockInterface(); + + bool setActionValue(const QString & action, QVariant value); + + bool pressNotificationButton(int id, const QString & button); + + bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map); + + void checkVolumeNotification(double volume, QString const& label, bool isLoud, QVariantList call); + + void checkHighVolumeNotification(QVariantList call); + + void checkCloseNotification(int id, QVariantList call); + + void checkNotificationWithNoArgs(QString const& method, QVariantList call); + + int getNotificationID(QVariantList call); + + bool activateHeadphones(bool headphonesActive); + QtDBusTest::DBusTestRunner dbusTestRunner; QtDBusMock::DBusMock dbusMock; diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp index 5a4b4ee..1607367 100644 --- a/tests/integration/test-indicator.cpp +++ b/tests/integration/test-indicator.cpp @@ -634,4 +634,292 @@ TEST_F(TestIndicator, DesktopChangeRoleVolume) ).match()); } +TEST_F(TestIndicator, PhoneNotificationVolume) +{ + double INITIAL_VOLUME = 0.0; + + QSignalSpy notificationsSpy(¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &))); + + ASSERT_NO_THROW(startAccountsService()); + EXPECT_TRUE(clearGSettingsPlayers()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // check the initial state + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::all) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(INITIAL_VOLUME)) + ) + .item(mh::MenuItemMatcher() + .label("Sound Settings…") + .action("indicator.phone-settings") + ) + ).match()); + + // change volume to 1.0 + setActionValue("volume", QVariant::fromValue(1.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 3); + + // the first time we also have the calls to + // GetServerInformation and GetCapabilities + checkNotificationWithNoArgs("GetServerInformation", notificationsSpy.at(0)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(1)); + checkVolumeNotification(1.0, "", false, notificationsSpy.at(2)); + + notificationsSpy.clear(); + setActionValue("volume", QVariant::fromValue(0.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 1) + + checkVolumeNotification(0.0, "", false, notificationsSpy.at(0)); + + notificationsSpy.clear(); + setActionValue("volume", QVariant::fromValue(0.5)); + + WAIT_FOR_SIGNALS(notificationsSpy, 1) + + checkVolumeNotification(0.5, "", false, notificationsSpy.at(0)); +} + +TEST_F(TestIndicator, PhoneNotificationWarningVolume) +{ + double INITIAL_VOLUME = 0.0; + + QSignalSpy notificationsSpy(¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &))); + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setStreamRestoreVolume("multimedia", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // activate the headphones + EXPECT_TRUE(activateHeadphones(true)); + + // set an initial volume to the alert role + setStreamRestoreVolume("alert", 1.0); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + // play a test sound, it should change the role in the indicator + EXPECT_TRUE(startTestSound("multimedia")); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + // change volume to 0.0... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 3); + + // the first time we also have the calls to + // GetServerInformation and GetCapabilities + checkNotificationWithNoArgs("GetServerInformation", notificationsSpy.at(0)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(1)); + checkVolumeNotification(0.0, "", false, notificationsSpy.at(2)); + notificationsSpy.clear(); + + // change volume to 0.5... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.5)); + + WAIT_FOR_SIGNALS(notificationsSpy, 1); + + checkVolumeNotification(0.5, "", false, notificationsSpy.at(0)); + notificationsSpy.clear(); + + // change volume to 1.0... warning should be emitted + setActionValue("volume", QVariant::fromValue(1.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 4); + + // the notification is sent twice (TODO check why) + checkCloseNotification(1, notificationsSpy.at(0)); + checkHighVolumeNotification(notificationsSpy.at(1)); + checkCloseNotification(1, notificationsSpy.at(2)); + checkHighVolumeNotification(notificationsSpy.at(3)); + + // get the last notification ID + int idNotification = getNotificationID(notificationsSpy.at(3)); + ASSERT_NE(-1, idNotification); + + qWarning() << "XGM: id Notification: " << idNotification; + + // cancel the dialog + pressNotificationButton(idNotification, "cancel"); + + // check that the volume was clamped + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(0.74)) + ) + ).match()); + + // try again... + notificationsSpy.clear(); + // change volume to 1.0... warning should be emitted + setActionValue("volume", QVariant::fromValue(1.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 4); + + checkCloseNotification(1, notificationsSpy.at(0)); + checkHighVolumeNotification(notificationsSpy.at(1)); + checkCloseNotification(1, notificationsSpy.at(2)); + checkHighVolumeNotification(notificationsSpy.at(3)); + + // get the last notification ID + idNotification = getNotificationID(notificationsSpy.at(3)); + ASSERT_NE(-1, idNotification); + + qWarning() << "XGM: id Notification: " << idNotification; + + // this time we approve + pressNotificationButton(idNotification, "ok"); + + // check that the volume was applied + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(1.0)) + .item(mh::MenuItemMatcher() + .action("indicator.high-volume-warning-item") + .label("High volume can damage your hearing.") + ) + ) + ).match()); + + // after the warning was approved we should be able to modify the volume + // and don't get the warning + notificationsSpy.clear(); + + // change volume to 0.5... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.5)); + + WAIT_FOR_SIGNALS(notificationsSpy, 2); + + // check the notification TODO check why the sound indicator sends it twice + checkVolumeNotification(0.5, "", false, notificationsSpy.at(0)); + checkVolumeNotification(0.5, "", false, notificationsSpy.at(1)); + + // check that the volume was applied + // and that we don't have the warning item + EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters()) + .item(mh::MenuItemMatcher() + .action("indicator.root") + .string_attribute("x-canonical-type", "com.canonical.indicator.root") + .string_attribute("x-canonical-scroll-action", "indicator.scroll") + .string_attribute("x-canonical-secondary-action", "indicator.mute") + .string_attribute("submenu-action", "indicator.indicator-shown") + .mode(mh::MenuItemMatcher::Mode::starts_with) + .submenu() + .item(mh::MenuItemMatcher() + .section() + .item(silentModeSwitch(false)) + .item(volumeSlider(0.5)) + ) + ).match()); + + // now set high volume again, we should not get the warning dialog + // as we already approved it + notificationsSpy.clear(); + + setActionValue("volume", QVariant::fromValue(1.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 2); + + // check the notification TODO check why the sound indicator sends it twice + checkVolumeNotification(1.0, "High volume can damage your hearing.", true, notificationsSpy.at(0)); + checkVolumeNotification(1.0, "High volume can damage your hearing.", true, notificationsSpy.at(1)); +} + +TEST_F(TestIndicator, PhoneNotificationWarningVolumeAlertMode) +{ + double INITIAL_VOLUME = 0.0; + + QSignalSpy notificationsSpy(¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &))); + + ASSERT_NO_THROW(startAccountsService()); + ASSERT_NO_THROW(startPulsePhone()); + + // initialize volumes in pulseaudio + EXPECT_TRUE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); + EXPECT_TRUE(setStreamRestoreVolume("multimedia", INITIAL_VOLUME)); + + // start now the indicator, so it picks the new volumes + ASSERT_NO_THROW(startIndicator()); + + // activate the headphones + EXPECT_TRUE(activateHeadphones(true)); + + // set an initial volume to the alert role + setStreamRestoreVolume("alert", 1.0); + EXPECT_TRUE(waitVolumeChangedInIndicator()); + + // change volume to 0.0... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 3); + + // the first time we also have the calls to + // GetServerInformation and GetCapabilities + checkNotificationWithNoArgs("GetServerInformation", notificationsSpy.at(0)); + checkNotificationWithNoArgs("GetCapabilities", notificationsSpy.at(1)); + checkVolumeNotification(0.0, "", false, notificationsSpy.at(2)); + notificationsSpy.clear(); + + // change volume to 0.5... no warning should be emitted + setActionValue("volume", QVariant::fromValue(0.5)); + + WAIT_FOR_SIGNALS(notificationsSpy, 1); + + checkVolumeNotification(0.5, "", false, notificationsSpy.at(0)); + notificationsSpy.clear(); + + // change volume to 1.0... no warning should be emitted, we are in alert mode + setActionValue("volume", QVariant::fromValue(1.0)); + + WAIT_FOR_SIGNALS(notificationsSpy, 1); + + checkVolumeNotification(1.0, "", false, notificationsSpy.at(0)); + notificationsSpy.clear(); +} + } // namespace -- cgit v1.2.3