Merge lp:~xavi-garcia-mena/indicator-sound/bug-1213907-active-players-playback-control-unit-tests into lp:indicator-sound/15.10

Proposed by Xavi Garcia
Status: Needs review
Proposed branch: lp:~xavi-garcia-mena/indicator-sound/bug-1213907-active-players-playback-control-unit-tests
Merge into: lp:indicator-sound/15.10
Diff against target: 750 lines (+682/-0)
7 files modified
tests/integration/CMakeLists.txt (+1/-0)
tests/integration/indicator-sound-test-base.cpp (+5/-0)
tests/integration/indicator-sound-test-base.h (+1/-0)
tests/integration/test-indicator.cpp (+274/-0)
tests/integration/utils/gobj_memory.h (+200/-0)
tests/integration/utils/gsettings.cpp (+149/-0)
tests/integration/utils/gsettings.h (+52/-0)
To merge this branch: bzr merge lp:~xavi-garcia-mena/indicator-sound/bug-1213907-active-players-playback-control-unit-tests
Reviewer Review Type Date Requested Status
Charles Kerr (community) Needs Information
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+286183@code.launchpad.net

Commit message

This branch adds extra integration tests to the recently landed branch https://code.launchpad.net/~xavi-garcia-mena/indicator-sound/bug-1213907-active-players-playback-control

It adds GSettings tests and checks the last-running-player property.

Description of the change

This branch adds extra integration tests to the recently landed branch https://code.launchpad.net/~xavi-garcia-mena/indicator-sound/bug-1213907-active-players-playback-control

It adds GSettings tests and checks the last-running-player property.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
529. By Xavi Garcia

Integration test moved

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

Comments inline

review: Needs Information

Unmerged revisions

529. By Xavi Garcia

Integration test moved

528. By Xavi Garcia

Added integration tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/integration/CMakeLists.txt'
--- tests/integration/CMakeLists.txt 2015-12-23 13:35:46 +0000
+++ tests/integration/CMakeLists.txt 2016-02-17 09:23:14 +0000
@@ -51,6 +51,7 @@
51 indicator-sound-test-base.cpp51 indicator-sound-test-base.cpp
52 test-indicator.cpp52 test-indicator.cpp
53 utils/dbus-pulse-volume.cpp53 utils/dbus-pulse-volume.cpp
54 utils/gsettings.cpp
54 main.cpp55 main.cpp
55)56)
5657
5758
=== modified file 'tests/integration/indicator-sound-test-base.cpp'
--- tests/integration/indicator-sound-test-base.cpp 2016-01-29 11:16:34 +0000
+++ tests/integration/indicator-sound-test-base.cpp 2016-02-17 09:23:14 +0000
@@ -380,6 +380,11 @@
380 }380 }
381}381}
382382
383void IndicatorSoundTestBase::stopIndicator()
384{
385 indicator.reset();
386}
387
383mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters()388mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters()
384{389{
385 return mh::MenuMatcher::Parameters(390 return mh::MenuMatcher::Parameters(
386391
=== modified file 'tests/integration/indicator-sound-test-base.h'
--- tests/integration/indicator-sound-test-base.h 2016-01-29 11:16:34 +0000
+++ tests/integration/indicator-sound-test-base.h 2016-02-17 09:23:14 +0000
@@ -72,6 +72,7 @@
72 void TearDown() override;72 void TearDown() override;
7373
74 void startIndicator();74 void startIndicator();
75 void stopIndicator();
75 void startPulseDesktop(DevicePortType speakerPort=WIRED, DevicePortType headphonesPort=WIRED);76 void startPulseDesktop(DevicePortType speakerPort=WIRED, DevicePortType headphonesPort=WIRED);
76 void startPulsePhone(DevicePortType speakerPort=WIRED, DevicePortType headphonesPort=WIRED);77 void startPulsePhone(DevicePortType speakerPort=WIRED, DevicePortType headphonesPort=WIRED);
77 void startAccountsService();78 void startAccountsService();
7879
=== modified file 'tests/integration/test-indicator.cpp'
--- tests/integration/test-indicator.cpp 2016-02-10 13:08:49 +0000
+++ tests/integration/test-indicator.cpp 2016-02-17 09:23:14 +0000
@@ -17,11 +17,15 @@
17 */17 */
1818
19#include <indicator-sound-test-base.h>19#include <indicator-sound-test-base.h>
20#include <utils/gsettings.h>
2021
21#include <QDebug>22#include <QDebug>
22#include <QTestEventLoop>23#include <QTestEventLoop>
23#include <QSignalSpy>24#include <QSignalSpy>
2425
26#include <chrono>
27#include <thread>
28
25using namespace std;29using namespace std;
26using namespace testing;30using namespace testing;
27namespace mh = unity::gmenuharness;31namespace mh = unity::gmenuharness;
@@ -1553,4 +1557,274 @@
1553 checkPortDevicesLabels(HDMI, HDMI);1557 checkPortDevicesLabels(HDMI, HDMI);
1554}1558}
15551559
1560TEST_F(TestIndicator, DesktopMprisPlayersPlaybackControlsActive)
1561{
1562 double INITIAL_VOLUME = 0.0;
1563
1564 ASSERT_NO_THROW(startAccountsService());
1565 EXPECT_TRUE(clearGSettingsPlayers());
1566 ASSERT_NO_THROW(startPulseDesktop());
1567
1568 // initialize volumes in pulseaudio
1569 EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME));
1570 EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME));
1571
1572 // start the test player
1573 EXPECT_TRUE(startTestMprisPlayer("testplayer1"));
1574
1575 // start now the indicator, so it picks the new volumes
1576 ASSERT_NO_THROW(startIndicator());
1577
1578 // check that the player is added
1579 EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
1580 .item(mh::MenuItemMatcher()
1581 .action("indicator.root")
1582 .string_attribute("x-canonical-type", "com.canonical.indicator.root")
1583 .string_attribute("x-canonical-secondary-action", "indicator.mute")
1584 .mode(mh::MenuItemMatcher::Mode::all)
1585 .submenu()
1586 .item(mh::MenuItemMatcher()
1587 .section()
1588 .item(mh::MenuItemMatcher().checkbox()
1589 .label("Mute")
1590 )
1591 .item(volumeSlider(INITIAL_VOLUME, "Volume"))
1592 )
1593 .item(mh::MenuItemMatcher()
1594 .section()
1595 .item(mh::MenuItemMatcher()
1596 .action("indicator.testplayer1.desktop")
1597 .label("TestPlayer1")
1598 .themed_icon("icon", {"testplayer"})
1599 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1600 )
1601 .item(mh::MenuItemMatcher()
1602 .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
1603 .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
1604 .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
1605 .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
1606 )
1607 )
1608 .item(mh::MenuItemMatcher()
1609 .label("Sound Settingsā€¦")
1610 )
1611 ).match());
1612
1613 // start the second test player
1614 EXPECT_TRUE(startTestMprisPlayer("testplayer2"));
1615
1616 // check that the player is added
1617 EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
1618 .item(mh::MenuItemMatcher()
1619 .action("indicator.root")
1620 .string_attribute("x-canonical-type", "com.canonical.indicator.root")
1621 .string_attribute("x-canonical-secondary-action", "indicator.mute")
1622 .mode(mh::MenuItemMatcher::Mode::all)
1623 .submenu()
1624 .item(mh::MenuItemMatcher()
1625 .section()
1626 .item(mh::MenuItemMatcher().checkbox()
1627 .label("Mute")
1628 )
1629 .item(volumeSlider(INITIAL_VOLUME, "Volume"))
1630 )
1631 .item(mh::MenuItemMatcher()
1632 .section()
1633 .item(mh::MenuItemMatcher()
1634 .action("indicator.testplayer1.desktop")
1635 .label("TestPlayer1")
1636 .themed_icon("icon", {"testplayer"})
1637 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1638 )
1639 .item(mh::MenuItemMatcher()
1640 .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
1641 .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
1642 .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
1643 .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
1644 )
1645 )
1646 .item(mh::MenuItemMatcher()
1647 .section()
1648 .item(mh::MenuItemMatcher()
1649 .action("indicator.testplayer2.desktop")
1650 .label("TestPlayer2")
1651 .themed_icon("icon", {"testplayer"})
1652 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1653 )
1654 .item(mh::MenuItemMatcher()
1655 .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop")
1656 .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop")
1657 .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop")
1658 .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
1659 )
1660 )
1661 .item(mh::MenuItemMatcher()
1662 .label("Sound Settingsā€¦")
1663 )
1664 ).match());
1665
1666 // stop the first player
1667 EXPECT_TRUE(stopTestMprisPlayer("testplayer1"));
1668
1669 // check that the player's playback controls are removed
1670 EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
1671 .item(mh::MenuItemMatcher()
1672 .action("indicator.root")
1673 .string_attribute("x-canonical-type", "com.canonical.indicator.root")
1674 .string_attribute("x-canonical-secondary-action", "indicator.mute")
1675 .mode(mh::MenuItemMatcher::Mode::all)
1676 .submenu()
1677 .item(mh::MenuItemMatcher()
1678 .section()
1679 .item(mh::MenuItemMatcher().checkbox()
1680 .label("Mute")
1681 )
1682 .item(volumeSlider(INITIAL_VOLUME, "Volume"))
1683 )
1684 .item(mh::MenuItemMatcher()
1685 .section()
1686 .item(mh::MenuItemMatcher()
1687 .action("indicator.testplayer1.desktop")
1688 .label("TestPlayer1")
1689 .themed_icon("icon", {"testplayer"})
1690 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1691 )
1692 )
1693 .item(mh::MenuItemMatcher()
1694 .section()
1695 .item(mh::MenuItemMatcher()
1696 .action("indicator.testplayer2.desktop")
1697 .label("TestPlayer2")
1698 .themed_icon("icon", {"testplayer"})
1699 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1700 )
1701 .item(mh::MenuItemMatcher()
1702 .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop")
1703 .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop")
1704 .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop")
1705 .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
1706 )
1707 )
1708 .item(mh::MenuItemMatcher()
1709 .label("Sound Settingsā€¦")
1710 )
1711 ).match());
1712
1713 // stop the second player (it should be the last running one)
1714 EXPECT_TRUE(stopTestMprisPlayer("testplayer2"));
1715
1716 // verify the players with gsettings
1717 Settings settings;
1718
1719 int timeout = 1000;
1720 while (settings.get_last_running_player() != "testplayer2.desktop" && timeout)
1721 {
1722 std::this_thread::sleep_for(std::chrono::milliseconds(500));
1723 timeout -= 500;
1724 }
1725 EXPECT_EQ("testplayer2.desktop", settings.get_last_running_player());
1726
1727 timeout = 1000;
1728 while (settings.get_interested_media_players() != "[[ testplayer1.desktop ][ testplayer2.desktop ]]" && timeout)
1729 {
1730 std::this_thread::sleep_for(std::chrono::milliseconds(500));
1731 timeout -= 500;
1732 }
1733 EXPECT_EQ("[[ testplayer1.desktop ][ testplayer2.desktop ]]", settings.get_interested_media_players());
1734
1735 // restart the indicator
1736 // we should get the player 2 as the one with playback constrols.
1737 // In this case we only have the play button as the player is not running yet.
1738 startIndicator();
1739
1740 // check that the player 2 has the playback controls with play set.
1741 EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
1742 .item(mh::MenuItemMatcher()
1743 .action("indicator.root")
1744 .string_attribute("x-canonical-type", "com.canonical.indicator.root")
1745 .string_attribute("x-canonical-secondary-action", "indicator.mute")
1746 .mode(mh::MenuItemMatcher::Mode::all)
1747 .submenu()
1748 .item(mh::MenuItemMatcher()
1749 .section()
1750 .item(mh::MenuItemMatcher().checkbox()
1751 .label("Mute")
1752 )
1753 .item(volumeSlider(INITIAL_VOLUME, "Volume"))
1754 )
1755 .item(mh::MenuItemMatcher()
1756 .section()
1757 .item(mh::MenuItemMatcher()
1758 .action("indicator.testplayer1.desktop")
1759 .label("TestPlayer1")
1760 .themed_icon("icon", {"testplayer"})
1761 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1762 )
1763 )
1764 .item(mh::MenuItemMatcher()
1765 .section()
1766 .item(mh::MenuItemMatcher()
1767 .action("indicator.testplayer2.desktop")
1768 .label("TestPlayer2")
1769 .themed_icon("icon", {"testplayer"})
1770 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1771 )
1772 .item(mh::MenuItemMatcher()
1773 .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop")
1774 .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
1775 )
1776 )
1777 .item(mh::MenuItemMatcher()
1778 .label("Sound Settingsā€¦")
1779 )
1780 ).match());
1781
1782 // now start the other player.
1783 // that should change the playback controls shown from player 2 to player 1
1784 EXPECT_TRUE(startTestMprisPlayer("testplayer1"));
1785
1786 EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
1787 .item(mh::MenuItemMatcher()
1788 .action("indicator.root")
1789 .string_attribute("x-canonical-type", "com.canonical.indicator.root")
1790 .string_attribute("x-canonical-secondary-action", "indicator.mute")
1791 .mode(mh::MenuItemMatcher::Mode::all)
1792 .submenu()
1793 .item(mh::MenuItemMatcher()
1794 .section()
1795 .item(mh::MenuItemMatcher().checkbox()
1796 .label("Mute")
1797 )
1798 .item(volumeSlider(INITIAL_VOLUME, "Volume"))
1799 )
1800 .item(mh::MenuItemMatcher()
1801 .section()
1802 .item(mh::MenuItemMatcher()
1803 .action("indicator.testplayer1.desktop")
1804 .label("TestPlayer1")
1805 .themed_icon("icon", {"testplayer"})
1806 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1807 )
1808 .item(mh::MenuItemMatcher()
1809 .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
1810 .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
1811 .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
1812 .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
1813 )
1814 )
1815 .item(mh::MenuItemMatcher()
1816 .section()
1817 .item(mh::MenuItemMatcher()
1818 .action("indicator.testplayer2.desktop")
1819 .label("TestPlayer2")
1820 .themed_icon("icon", {"testplayer"})
1821 .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
1822 )
1823 )
1824 .item(mh::MenuItemMatcher()
1825 .label("Sound Settingsā€¦")
1826 )
1827 ).match());
1828}
1829
1556} // namespace1830} // namespace
15571831
=== added file 'tests/integration/utils/gobj_memory.h'
--- tests/integration/utils/gobj_memory.h 1970-01-01 00:00:00 +0000
+++ tests/integration/utils/gobj_memory.h 2016-02-17 09:23:14 +0000
@@ -0,0 +1,200 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
17 */
18
19#pragma once
20
21#include <stdexcept>
22
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wold-style-cast"
25#pragma GCC diagnostic ignored "-Wcast-qual"
26#include <glib-object.h>
27
28#include <iostream>
29
30/**
31 * This class is meant for automatically managing the lifetime of C objects derived
32 * from gobject. Its API perfectly mirrors the API of unique_ptr except that you
33 * can't define your own deleter function as it is always g_object_unref.
34 *
35 * API/ABI stability is not guaranteed. If you need to pass the object across an ABI
36 * boundary, pass the plain gobject.
37 *
38 * This is how you would use gobj_ptr 99% of the time:
39 *
40 * gobj_ptr<GSomeType> o(g_some_type_new(...));
41 *
42 * More specifically, the object will decrement the gobject reference count
43 * of the object it points to when it goes out of scope. It will never increment it.
44 * Thus you should only assign to it when already holding a reference. gobj_ptr
45 * will then take ownership of that particular reference.
46 *
47 * Floating gobjects can not be put in this container as they are meant to be put
48 * into native gobject aware containers immediately upon construction. Trying to insert
49 * a floating gobject into a gobj_ptr will throw an invalid_argument exception. To
50 * prevent accidental memory leaks, the floating gobject is unreffed in this case.
51 */
52template <typename T>
53class gobj_ptr final
54{
55private:
56 T* u;
57
58 void validate_float(T* t)
59 {
60 if (t != nullptr && g_object_is_floating(G_OBJECT(t)))
61 {
62 // LCOV_EXCL_START // False negative from gcovr.
63 throw std::invalid_argument("Tried to add a floating gobject into a gobj_ptr.");
64 // LCOV_EXCL_STOP
65 }
66 }
67
68public:
69 typedef T element_type;
70 typedef T* pointer;
71 typedef decltype(g_object_unref) deleter_type;
72
73 constexpr gobj_ptr() noexcept : u(nullptr)
74 {
75 }
76 explicit gobj_ptr(T* t)
77 : u(t)
78 {
79 // What should we do if validate throws? Unreffing unknown objs
80 // is dodgy but not unreffing runs the risk of
81 // memory leaks. Currently unrefs as u is destroyed
82 // when this exception is thrown.
83 validate_float(t);
84 }
85 constexpr gobj_ptr(std::nullptr_t) noexcept : u(nullptr){};
86 gobj_ptr(gobj_ptr&& o) noexcept
87 {
88 u = o.u;
89 o.u = nullptr;
90 }
91 gobj_ptr(const gobj_ptr& o)
92 : u(nullptr)
93 {
94 *this = o;
95 }
96 gobj_ptr& operator=(const gobj_ptr& o)
97 {
98 if (o.u != nullptr)
99 {
100 g_object_ref(o.u);
101 }
102 reset(o.u);
103 return *this;
104 }
105 ~gobj_ptr()
106 {
107 reset();
108 }
109
110 deleter_type& get_deleter() noexcept
111 {
112 return g_object_unref;
113 }
114 deleter_type& get_deleter() const noexcept
115 {
116 return g_object_unref;
117 }
118
119 void swap(gobj_ptr<T>& o) noexcept
120 {
121 T* tmp = u;
122 u = o.u;
123 o.u = tmp;
124 }
125 void reset(pointer p = pointer())
126 {
127 if (u != nullptr)
128 {
129 g_object_unref(G_OBJECT(u));
130 u = nullptr;
131 }
132 // Same throw dilemma as in pointer constructor.
133 u = p;
134 validate_float(p);
135 }
136
137 T* release() noexcept
138 {
139 T* r = u;
140 u = nullptr;
141 return r;
142 }
143 T* get() const noexcept
144 {
145 return u;
146 }
147
148 T& operator*() const
149 {
150 return *u;
151 }
152 T* operator->() const noexcept
153 {
154 return u;
155 }
156 explicit operator bool() const noexcept
157 {
158 return u != nullptr;
159 }
160
161 gobj_ptr& operator=(gobj_ptr&& o) noexcept
162 {
163 reset();
164 u = o.u;
165 o.u = nullptr;
166 return *this;
167 }
168 gobj_ptr& operator=(std::nullptr_t) noexcept
169 {
170 reset();
171 return *this;
172 }
173 bool operator==(const gobj_ptr<T>& o) const noexcept
174 {
175 return u == o.u;
176 }
177 bool operator!=(const gobj_ptr<T>& o) const noexcept
178 {
179 return u != o.u;
180 }
181 bool operator<(const gobj_ptr<T>& o) const noexcept
182 {
183 return u < o.u;
184 }
185 bool operator<=(const gobj_ptr<T>& o) const noexcept
186 {
187 return u <= o.u;
188 }
189 bool operator>(const gobj_ptr<T>& o) const noexcept
190 {
191 return u > o.u;
192 }
193 bool operator>=(const gobj_ptr<T>& o) const noexcept
194 {
195 return u >= o.u;
196 }
197};
198
199#pragma GCC diagnostic pop
200
0201
=== added file 'tests/integration/utils/gsettings.cpp'
--- tests/integration/utils/gsettings.cpp 1970-01-01 00:00:00 +0000
+++ tests/integration/utils/gsettings.cpp 2016-02-17 09:23:14 +0000
@@ -0,0 +1,149 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Xavi Garcia <xavi.garcia.mena@canonical.com>
17 */
18
19#include "gsettings.h"
20
21//#include "settings-defaults.h"
22
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wold-style-cast"
25#pragma GCC diagnostic ignored "-Wcast-qual"
26#include <gio/gio.h>
27#pragma GCC diagnostic pop
28#include <QDebug>
29
30#include <memory>
31
32using namespace std;
33
34Settings::Settings()
35 : Settings("com.canonical.indicator.sound")
36{
37}
38
39Settings::Settings(string const& schema_name)
40 : schema_(nullptr, &g_settings_schema_unref)
41 , schema_name_(schema_name)
42{
43 GSettingsSchemaSource* src = g_settings_schema_source_get_default();
44 schema_.reset(g_settings_schema_source_lookup(src, schema_name.c_str(), true));
45 if (schema_)
46 {
47 settings_.reset(g_settings_new(schema_name.c_str()));
48 }
49 else
50 {
51 qCritical() << "The schema" << schema_name.c_str() << "is missing";
52 }
53}
54
55Settings::~Settings() = default;
56
57string Settings::get_last_running_player() const
58{
59 return get_string("last-running-player", "");
60}
61
62string Settings::get_interested_media_players() const
63{
64 return get_string_array_as_string("interested-media-players", "");
65}
66
67string Settings::get_string(char const* key, string const& default_value) const
68{
69 if (!settings_ || !g_settings_schema_has_key(schema_.get(), key))
70 {
71 return default_value;
72 }
73
74 char *value = g_settings_get_string(settings_.get(), key);
75 if (value)
76 {
77 string result = value;
78 g_free(value);
79 return result;
80 }
81 return default_value; // LCOV_EXCL_LINE
82}
83
84int Settings::get_positive_int(char const* key, int default_value) const
85{
86 int i = get_int(key, default_value);
87 if (i <= 0)
88 {
89 throw domain_error(string("Settings::get_positive_int(): invalid zero or negative value for ")
90 + key + ": " + to_string(i) + " in schema " + schema_name_);
91 }
92 return i;
93}
94
95int Settings::get_positive_or_zero_int(char const* key, int default_value) const
96{
97 int i = get_int(key, default_value);
98 if (i < 0)
99 {
100 throw domain_error(string("Settings::get_positive_or_zero_int(): invalid negative value for ")
101 + key + ": " + to_string(i) + " in schema " + schema_name_);
102 }
103 return i;
104}
105
106int Settings::get_int(char const* key, int default_value) const
107{
108 if (!settings_ || !g_settings_schema_has_key(schema_.get(), key))
109 {
110 return default_value;
111 }
112
113 return g_settings_get_int(settings_.get(), key);
114}
115
116bool Settings::get_bool(char const* key, bool default_value) const
117{
118 if (!settings_ || !g_settings_schema_has_key(schema_.get(), key))
119 {
120 return default_value;
121 }
122
123 return g_settings_get_boolean(settings_.get(), key);
124}
125
126std::string Settings::get_string_array_as_string(char const* key, std::string const& default_value) const
127{
128 if (!settings_ || !g_settings_schema_has_key(schema_.get(), key))
129 {
130 return default_value;
131 }
132 gchar **values;
133 values = g_settings_get_strv(settings_.get(), key);
134 if (!values)
135 {
136 return default_value;
137 }
138 int length = 0;
139 std::string res = "[";
140 while (((gpointer*) values)[length])
141 {
142 std::string test(values[length]);
143 length++;
144 res += "[ " + test + " ]";
145 }
146 res += "]";
147
148 return res;
149}
0150
=== added file 'tests/integration/utils/gsettings.h'
--- tests/integration/utils/gsettings.h 1970-01-01 00:00:00 +0000
+++ tests/integration/utils/gsettings.h 2016-02-17 09:23:14 +0000
@@ -0,0 +1,52 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Xavi Garcia <xavi.garcia.mena@canonical.com>
17 */
18
19#pragma once
20
21#include "gobj_memory.h"
22
23#include <memory>
24#include <string>
25
26typedef struct _GSettings GSettings;
27typedef struct _GSettingsSchema GSettingsSchema;
28
29class Settings
30{
31public:
32 Settings();
33 // This constructor is only for use in the tests.
34 explicit Settings(std::string const& schema_name);
35 ~Settings();
36
37 std::string get_last_running_player() const;
38
39 std::string get_interested_media_players() const;
40
41private:
42 std::string get_string(char const* key, std::string const& default_value) const;
43 int get_positive_int(char const* key, int default_value) const;
44 int get_positive_or_zero_int(char const* key, int default_value) const;
45 int get_int(char const* key, int default_value) const;
46 bool get_bool(char const* key, bool default_value) const;
47 std::string get_string_array_as_string(char const* key, std::string const& default_value) const;
48
49 std::unique_ptr<GSettingsSchema, void(*)(GSettingsSchema*)> schema_;
50 std::string schema_name_;
51 gobj_ptr<GSettings> settings_;
52};

Subscribers

People subscribed via source and target branches