aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorXavi Garcia Mena <xavi.garcia.mena@canonical.com>2015-09-07 15:11:19 +0200
committerXavi Garcia Mena <xavi.garcia.mena@canonical.com>2015-09-07 15:11:19 +0200
commit58f10c864fd301fbe509c232488cab7b5c99a6b8 (patch)
tree63372aa6fc5a8e337489a1df7cd5a1d70f1b1742 /tests
parentf76bbdf9eefaffd594078efe534ad1090f5aa41f (diff)
downloadayatana-indicator-sound-58f10c864fd301fbe509c232488cab7b5c99a6b8.tar.gz
ayatana-indicator-sound-58f10c864fd301fbe509c232488cab7b5c99a6b8.tar.bz2
ayatana-indicator-sound-58f10c864fd301fbe509c232488cab7b5c99a6b8.zip
test version for gmenuharness
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt197
-rw-r--r--tests/dbus-types/CMakeLists.txt48
-rw-r--r--tests/dbus-types/com.ubuntu.AccountsService.Sound.xml9
-rw-r--r--tests/dbus-types/dbus-types.h40
-rw-r--r--tests/dbus-types/org.PulseAudio.Ext.StreamRestore1.xml7
-rw-r--r--tests/dbus-types/org.freedesktop.Accounts.xml8
-rw-r--r--tests/dbus-types/org.freedesktop.DBus.Properties.xml21
-rw-r--r--tests/dbus-types/org.gtk.Menus.xml6
-rw-r--r--tests/dbus-types/pulseaudio-volume.cpp156
-rw-r--r--tests/dbus-types/pulseaudio-volume.h71
-rw-r--r--tests/integration/CMakeLists.txt128
-rw-r--r--tests/integration/Copy of test-sound.wavbin0 -> 191989 bytes
-rw-r--r--tests/integration/indicator-sound-test-base.cpp263
-rw-r--r--tests/integration/indicator-sound-test-base.h83
-rw-r--r--tests/integration/main.cpp58
-rw-r--r--tests/integration/test-indicator.cpp182
-rw-r--r--tests/integration/test-sound.wavbin0 -> 7665640 bytes
-rwxr-xr-xtests/integration/touch-stream-restore.table4
-rw-r--r--tests/integration/utils/dbus-pulse-volume.cpp252
-rw-r--r--tests/integration/utils/dbus-pulse-volume.h57
-rw-r--r--tests/integration/utils/get-volume.cpp33
-rw-r--r--tests/integration/utils/set-volume.cpp36
22 files changed, 1562 insertions, 97 deletions
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 @@
+<node>
+ <interface name="com.ubuntu.AccountsService.Sound">
+ <method name="Set">
+ <arg direction="in" type="s" name="interface" />
+ <arg direction="in" type="s" name="property" />
+ <arg direction="out" type="o" name="path" />
+ </method>
+ </interface>
+</node>
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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+#pragma once
+
+#include <QDBusMetaType>
+#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 @@
+<node>
+ <interface name="org.PulseAudio.Ext.StreamRestore1">
+ <method name="GetEntryByName">
+ <arg direction="in" type="s" name="entry" />
+ <arg direction="out" type="o" name="value" />
+ </interface>
+</node>
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 @@
+<node>
+ <interface name="org.freedesktop.Accounts">
+ <method name="FindUserByName">
+ <arg direction="in" type="s" name="user" />
+ <arg direction="out" type="o" name="path" />
+ </method>
+ </interface>
+</node>
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 @@
+<node>
+ <interface name="org.freedesktop.DBus.Properties">
+ <method name="Set">
+ <arg direction="in" type="s" name="entry" />
+ <arg direction="in" type="s" name="property" />
+ <arg direction="in" type="v" name="value" />
+ </method>
+ <method name="Get">
+ <arg direction="in" type="s" name="entry" />
+ <arg direction="in" type="s" name="property" />
+ <arg direction="out" type="v" name="value" />
+ </method>
+
+ <signal name="PropertiesChanged">
+ <arg type="s" name="interface_name"/>
+ <arg type="a{sv}" name="changed_properties"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+ <arg type="as" name="invalidated_properties"/>
+ </signal>
+ </interface>
+</node>
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 @@
+<node>
+ <interface name="org.gtk.Menus">
+ <signal name="Changed">
+ </signal>
+ </interface>
+</node>
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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+#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>("PulseaudioVolume");
+
+ qDBusRegisterMetaType<PulseaudioVolume>();
+}
+
+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>("PulseaudioVolumeArray");
+
+ qDBusRegisterMetaType<PulseaudioVolumeArray>();
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const PulseaudioVolumeArray& volume)
+{
+ argument.beginArray( qMetaTypeId<PulseaudioVolume>() );
+ 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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+#pragma once
+
+#include <QtDBus>
+
+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<PulseaudioVolume> 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
--- /dev/null
+++ b/tests/integration/Copy of test-sound.wav
Binary files 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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+
+#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 <gio/gio.h>
+
+#include <QSignalSpy>
+#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<GVariant> 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<GVariant>(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<AccountsInterface> setInterface(new AccountsInterface("org.freedesktop.Accounts",
+ "/org/freedesktop/Accounts",
+ QDBusConnection::systemBus(), 0));
+ qDebug() << "Interface: " << setInterface.get();
+
+ QDBusReply<QDBusObjectPath> 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<AccountsSoundInterface> 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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+
+#pragma once
+
+#include <libqtdbustest/DBusTestRunner.h>
+#include <libqtdbustest/QProcessDBusService.h>
+#include <libqtdbusmock/DBusMock.h>
+
+#include <unity/gmenuharness/MatchUtils.h>
+#include <unity/gmenuharness/MenuMatcher.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+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<GVariant> 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<MenusInterface> menu_interface_;
+
+ std::unique_ptr<DBusPropertiesInterface> accounts_interface_;
+
+ std::unique_ptr<QSignalSpy> 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Pete Woods <pete.woods@canonical.com>
+ */
+
+//#include <config.h>
+
+#include <QCoreApplication>
+#include <QTimer>
+#include <gtest/gtest.h>
+
+#include <libqtdbusmock/DBusMock.h>
+
+#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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+
+#include <indicator-sound-test-base.h>
+
+#include <QDebug>
+#include <QTestEventLoop>
+#include <QSignalSpy>
+
+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
--- /dev/null
+++ b/tests/integration/test-sound.wav
Binary files 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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+
+#include "dbus_properties_interface.h"
+#include "dbus_accounts_interface.h"
+#include "dbus_accountssound_interface.h"
+#include "stream_restore_interface.h"
+
+#include <pulse/volume.h>
+#include "dbus-pulse-volume.h"
+
+#include <QSignalSpy>
+
+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<DBusPropertiesInterface> basicConnectionInterface(new DBusPropertiesInterface("org.PulseAudio1",
+ "/org/pulseaudio/server_lookup1",
+ QDBusConnection::sessionBus(), 0));
+
+ QDBusReply<QVariant> 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<QDBusObjectPath> 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<RoleInformation>();
+ 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<QVariant> 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<QDBusArgument>();
+ 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<void> 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<void> 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<QVariant> 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<QDBusArgument>();
+ 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<AccountsInterface> setInterface(new AccountsInterface("org.freedesktop.Accounts",
+ "/org/freedesktop/Accounts",
+ QDBusConnection::systemBus(), 0));
+ qDebug() << "Interface: " << setInterface.get();
+
+ QDBusReply<QDBusObjectPath> 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<AccountsSoundInterface> 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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+#pragma once
+
+#include <QObject>
+#include <QDBusConnection>
+
+#include <map>
+#include <memory>
+
+class StreamRestoreInterface;
+class DBusPropertiesInterface;
+class AccountsInterface;
+class AccountsSoundInterface;
+class QSignalSpy;
+
+struct RoleInformation
+{
+ std::unique_ptr<DBusPropertiesInterface> 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<QDBusConnection> connection_;
+ std::unique_ptr<StreamRestoreInterface> interface_paths_;
+ typedef std::map<QString, std::shared_ptr<RoleInformation>> RolesMap;
+ RolesMap roles_map_;
+ std::unique_ptr<DBusPropertiesInterface> accounts_interface_;
+ std::unique_ptr<QSignalSpy> 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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+
+#include "dbus-types.h"
+
+#include <string>
+#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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Xavi Garcia <xavi.garcia.mena@canonical.com>
+ */
+
+#include "dbus-types.h"
+
+#include <string>
+#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;
+}