Merge lp:~xavi-garcia-mena/indicator-sound/bug-1213907-active-players-playback-control-unit-tests into lp:indicator-sound/15.10
- bug-1213907-active-players-playback-control-unit-tests
- Merge into trunk.15.10
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 |
Related bugs: |
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:/
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:/
It adds GSettings tests and checks the last-running-player property.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 529. By Xavi Garcia
-
Integration test moved
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:529
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Comments inline
Unmerged revisions
- 529. By Xavi Garcia
-
Integration test moved
- 528. By Xavi Garcia
-
Added integration tests
Preview Diff
1 | === modified file 'tests/integration/CMakeLists.txt' |
2 | --- tests/integration/CMakeLists.txt 2015-12-23 13:35:46 +0000 |
3 | +++ tests/integration/CMakeLists.txt 2016-02-17 09:23:14 +0000 |
4 | @@ -51,6 +51,7 @@ |
5 | indicator-sound-test-base.cpp |
6 | test-indicator.cpp |
7 | utils/dbus-pulse-volume.cpp |
8 | + utils/gsettings.cpp |
9 | main.cpp |
10 | ) |
11 | |
12 | |
13 | === modified file 'tests/integration/indicator-sound-test-base.cpp' |
14 | --- tests/integration/indicator-sound-test-base.cpp 2016-01-29 11:16:34 +0000 |
15 | +++ tests/integration/indicator-sound-test-base.cpp 2016-02-17 09:23:14 +0000 |
16 | @@ -380,6 +380,11 @@ |
17 | } |
18 | } |
19 | |
20 | +void IndicatorSoundTestBase::stopIndicator() |
21 | +{ |
22 | + indicator.reset(); |
23 | +} |
24 | + |
25 | mh::MenuMatcher::Parameters IndicatorSoundTestBase::desktopParameters() |
26 | { |
27 | return mh::MenuMatcher::Parameters( |
28 | |
29 | === modified file 'tests/integration/indicator-sound-test-base.h' |
30 | --- tests/integration/indicator-sound-test-base.h 2016-01-29 11:16:34 +0000 |
31 | +++ tests/integration/indicator-sound-test-base.h 2016-02-17 09:23:14 +0000 |
32 | @@ -72,6 +72,7 @@ |
33 | void TearDown() override; |
34 | |
35 | void startIndicator(); |
36 | + void stopIndicator(); |
37 | void startPulseDesktop(DevicePortType speakerPort=WIRED, DevicePortType headphonesPort=WIRED); |
38 | void startPulsePhone(DevicePortType speakerPort=WIRED, DevicePortType headphonesPort=WIRED); |
39 | void startAccountsService(); |
40 | |
41 | === modified file 'tests/integration/test-indicator.cpp' |
42 | --- tests/integration/test-indicator.cpp 2016-02-10 13:08:49 +0000 |
43 | +++ tests/integration/test-indicator.cpp 2016-02-17 09:23:14 +0000 |
44 | @@ -17,11 +17,15 @@ |
45 | */ |
46 | |
47 | #include <indicator-sound-test-base.h> |
48 | +#include <utils/gsettings.h> |
49 | |
50 | #include <QDebug> |
51 | #include <QTestEventLoop> |
52 | #include <QSignalSpy> |
53 | |
54 | +#include <chrono> |
55 | +#include <thread> |
56 | + |
57 | using namespace std; |
58 | using namespace testing; |
59 | namespace mh = unity::gmenuharness; |
60 | @@ -1553,4 +1557,274 @@ |
61 | checkPortDevicesLabels(HDMI, HDMI); |
62 | } |
63 | |
64 | +TEST_F(TestIndicator, DesktopMprisPlayersPlaybackControlsActive) |
65 | +{ |
66 | + double INITIAL_VOLUME = 0.0; |
67 | + |
68 | + ASSERT_NO_THROW(startAccountsService()); |
69 | + EXPECT_TRUE(clearGSettingsPlayers()); |
70 | + ASSERT_NO_THROW(startPulseDesktop()); |
71 | + |
72 | + // initialize volumes in pulseaudio |
73 | + EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME)); |
74 | + EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME)); |
75 | + |
76 | + // start the test player |
77 | + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); |
78 | + |
79 | + // start now the indicator, so it picks the new volumes |
80 | + ASSERT_NO_THROW(startIndicator()); |
81 | + |
82 | + // check that the player is added |
83 | + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) |
84 | + .item(mh::MenuItemMatcher() |
85 | + .action("indicator.root") |
86 | + .string_attribute("x-canonical-type", "com.canonical.indicator.root") |
87 | + .string_attribute("x-canonical-secondary-action", "indicator.mute") |
88 | + .mode(mh::MenuItemMatcher::Mode::all) |
89 | + .submenu() |
90 | + .item(mh::MenuItemMatcher() |
91 | + .section() |
92 | + .item(mh::MenuItemMatcher().checkbox() |
93 | + .label("Mute") |
94 | + ) |
95 | + .item(volumeSlider(INITIAL_VOLUME, "Volume")) |
96 | + ) |
97 | + .item(mh::MenuItemMatcher() |
98 | + .section() |
99 | + .item(mh::MenuItemMatcher() |
100 | + .action("indicator.testplayer1.desktop") |
101 | + .label("TestPlayer1") |
102 | + .themed_icon("icon", {"testplayer"}) |
103 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
104 | + ) |
105 | + .item(mh::MenuItemMatcher() |
106 | + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") |
107 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") |
108 | + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") |
109 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
110 | + ) |
111 | + ) |
112 | + .item(mh::MenuItemMatcher() |
113 | + .label("Sound Settings…") |
114 | + ) |
115 | + ).match()); |
116 | + |
117 | + // start the second test player |
118 | + EXPECT_TRUE(startTestMprisPlayer("testplayer2")); |
119 | + |
120 | + // check that the player is added |
121 | + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) |
122 | + .item(mh::MenuItemMatcher() |
123 | + .action("indicator.root") |
124 | + .string_attribute("x-canonical-type", "com.canonical.indicator.root") |
125 | + .string_attribute("x-canonical-secondary-action", "indicator.mute") |
126 | + .mode(mh::MenuItemMatcher::Mode::all) |
127 | + .submenu() |
128 | + .item(mh::MenuItemMatcher() |
129 | + .section() |
130 | + .item(mh::MenuItemMatcher().checkbox() |
131 | + .label("Mute") |
132 | + ) |
133 | + .item(volumeSlider(INITIAL_VOLUME, "Volume")) |
134 | + ) |
135 | + .item(mh::MenuItemMatcher() |
136 | + .section() |
137 | + .item(mh::MenuItemMatcher() |
138 | + .action("indicator.testplayer1.desktop") |
139 | + .label("TestPlayer1") |
140 | + .themed_icon("icon", {"testplayer"}) |
141 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
142 | + ) |
143 | + .item(mh::MenuItemMatcher() |
144 | + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") |
145 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") |
146 | + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") |
147 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
148 | + ) |
149 | + ) |
150 | + .item(mh::MenuItemMatcher() |
151 | + .section() |
152 | + .item(mh::MenuItemMatcher() |
153 | + .action("indicator.testplayer2.desktop") |
154 | + .label("TestPlayer2") |
155 | + .themed_icon("icon", {"testplayer"}) |
156 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
157 | + ) |
158 | + .item(mh::MenuItemMatcher() |
159 | + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop") |
160 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop") |
161 | + .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop") |
162 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
163 | + ) |
164 | + ) |
165 | + .item(mh::MenuItemMatcher() |
166 | + .label("Sound Settings…") |
167 | + ) |
168 | + ).match()); |
169 | + |
170 | + // stop the first player |
171 | + EXPECT_TRUE(stopTestMprisPlayer("testplayer1")); |
172 | + |
173 | + // check that the player's playback controls are removed |
174 | + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) |
175 | + .item(mh::MenuItemMatcher() |
176 | + .action("indicator.root") |
177 | + .string_attribute("x-canonical-type", "com.canonical.indicator.root") |
178 | + .string_attribute("x-canonical-secondary-action", "indicator.mute") |
179 | + .mode(mh::MenuItemMatcher::Mode::all) |
180 | + .submenu() |
181 | + .item(mh::MenuItemMatcher() |
182 | + .section() |
183 | + .item(mh::MenuItemMatcher().checkbox() |
184 | + .label("Mute") |
185 | + ) |
186 | + .item(volumeSlider(INITIAL_VOLUME, "Volume")) |
187 | + ) |
188 | + .item(mh::MenuItemMatcher() |
189 | + .section() |
190 | + .item(mh::MenuItemMatcher() |
191 | + .action("indicator.testplayer1.desktop") |
192 | + .label("TestPlayer1") |
193 | + .themed_icon("icon", {"testplayer"}) |
194 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
195 | + ) |
196 | + ) |
197 | + .item(mh::MenuItemMatcher() |
198 | + .section() |
199 | + .item(mh::MenuItemMatcher() |
200 | + .action("indicator.testplayer2.desktop") |
201 | + .label("TestPlayer2") |
202 | + .themed_icon("icon", {"testplayer"}) |
203 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
204 | + ) |
205 | + .item(mh::MenuItemMatcher() |
206 | + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop") |
207 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop") |
208 | + .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop") |
209 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
210 | + ) |
211 | + ) |
212 | + .item(mh::MenuItemMatcher() |
213 | + .label("Sound Settings…") |
214 | + ) |
215 | + ).match()); |
216 | + |
217 | + // stop the second player (it should be the last running one) |
218 | + EXPECT_TRUE(stopTestMprisPlayer("testplayer2")); |
219 | + |
220 | + // verify the players with gsettings |
221 | + Settings settings; |
222 | + |
223 | + int timeout = 1000; |
224 | + while (settings.get_last_running_player() != "testplayer2.desktop" && timeout) |
225 | + { |
226 | + std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
227 | + timeout -= 500; |
228 | + } |
229 | + EXPECT_EQ("testplayer2.desktop", settings.get_last_running_player()); |
230 | + |
231 | + timeout = 1000; |
232 | + while (settings.get_interested_media_players() != "[[ testplayer1.desktop ][ testplayer2.desktop ]]" && timeout) |
233 | + { |
234 | + std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
235 | + timeout -= 500; |
236 | + } |
237 | + EXPECT_EQ("[[ testplayer1.desktop ][ testplayer2.desktop ]]", settings.get_interested_media_players()); |
238 | + |
239 | + // restart the indicator |
240 | + // we should get the player 2 as the one with playback constrols. |
241 | + // In this case we only have the play button as the player is not running yet. |
242 | + startIndicator(); |
243 | + |
244 | + // check that the player 2 has the playback controls with play set. |
245 | + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) |
246 | + .item(mh::MenuItemMatcher() |
247 | + .action("indicator.root") |
248 | + .string_attribute("x-canonical-type", "com.canonical.indicator.root") |
249 | + .string_attribute("x-canonical-secondary-action", "indicator.mute") |
250 | + .mode(mh::MenuItemMatcher::Mode::all) |
251 | + .submenu() |
252 | + .item(mh::MenuItemMatcher() |
253 | + .section() |
254 | + .item(mh::MenuItemMatcher().checkbox() |
255 | + .label("Mute") |
256 | + ) |
257 | + .item(volumeSlider(INITIAL_VOLUME, "Volume")) |
258 | + ) |
259 | + .item(mh::MenuItemMatcher() |
260 | + .section() |
261 | + .item(mh::MenuItemMatcher() |
262 | + .action("indicator.testplayer1.desktop") |
263 | + .label("TestPlayer1") |
264 | + .themed_icon("icon", {"testplayer"}) |
265 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
266 | + ) |
267 | + ) |
268 | + .item(mh::MenuItemMatcher() |
269 | + .section() |
270 | + .item(mh::MenuItemMatcher() |
271 | + .action("indicator.testplayer2.desktop") |
272 | + .label("TestPlayer2") |
273 | + .themed_icon("icon", {"testplayer"}) |
274 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
275 | + ) |
276 | + .item(mh::MenuItemMatcher() |
277 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop") |
278 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
279 | + ) |
280 | + ) |
281 | + .item(mh::MenuItemMatcher() |
282 | + .label("Sound Settings…") |
283 | + ) |
284 | + ).match()); |
285 | + |
286 | + // now start the other player. |
287 | + // that should change the playback controls shown from player 2 to player 1 |
288 | + EXPECT_TRUE(startTestMprisPlayer("testplayer1")); |
289 | + |
290 | + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) |
291 | + .item(mh::MenuItemMatcher() |
292 | + .action("indicator.root") |
293 | + .string_attribute("x-canonical-type", "com.canonical.indicator.root") |
294 | + .string_attribute("x-canonical-secondary-action", "indicator.mute") |
295 | + .mode(mh::MenuItemMatcher::Mode::all) |
296 | + .submenu() |
297 | + .item(mh::MenuItemMatcher() |
298 | + .section() |
299 | + .item(mh::MenuItemMatcher().checkbox() |
300 | + .label("Mute") |
301 | + ) |
302 | + .item(volumeSlider(INITIAL_VOLUME, "Volume")) |
303 | + ) |
304 | + .item(mh::MenuItemMatcher() |
305 | + .section() |
306 | + .item(mh::MenuItemMatcher() |
307 | + .action("indicator.testplayer1.desktop") |
308 | + .label("TestPlayer1") |
309 | + .themed_icon("icon", {"testplayer"}) |
310 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
311 | + ) |
312 | + .item(mh::MenuItemMatcher() |
313 | + .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") |
314 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") |
315 | + .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") |
316 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
317 | + ) |
318 | + ) |
319 | + .item(mh::MenuItemMatcher() |
320 | + .section() |
321 | + .item(mh::MenuItemMatcher() |
322 | + .action("indicator.testplayer2.desktop") |
323 | + .label("TestPlayer2") |
324 | + .themed_icon("icon", {"testplayer"}) |
325 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
326 | + ) |
327 | + ) |
328 | + .item(mh::MenuItemMatcher() |
329 | + .label("Sound Settings…") |
330 | + ) |
331 | + ).match()); |
332 | +} |
333 | + |
334 | } // namespace |
335 | |
336 | === added file 'tests/integration/utils/gobj_memory.h' |
337 | --- tests/integration/utils/gobj_memory.h 1970-01-01 00:00:00 +0000 |
338 | +++ tests/integration/utils/gobj_memory.h 2016-02-17 09:23:14 +0000 |
339 | @@ -0,0 +1,200 @@ |
340 | +/* |
341 | + * Copyright (C) 2013 Canonical Ltd. |
342 | + * |
343 | + * This program is free software: you can redistribute it and/or modify |
344 | + * it under the terms of the GNU Lesser General Public License version 3 as |
345 | + * published by the Free Software Foundation. |
346 | + * |
347 | + * This program is distributed in the hope that it will be useful, |
348 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
349 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
350 | + * GNU Lesser General Public License for more details. |
351 | + * |
352 | + * You should have received a copy of the GNU Lesser General Public License |
353 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
354 | + * |
355 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
356 | + */ |
357 | + |
358 | +#pragma once |
359 | + |
360 | +#include <stdexcept> |
361 | + |
362 | +#pragma GCC diagnostic push |
363 | +#pragma GCC diagnostic ignored "-Wold-style-cast" |
364 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
365 | +#include <glib-object.h> |
366 | + |
367 | +#include <iostream> |
368 | + |
369 | +/** |
370 | + * This class is meant for automatically managing the lifetime of C objects derived |
371 | + * from gobject. Its API perfectly mirrors the API of unique_ptr except that you |
372 | + * can't define your own deleter function as it is always g_object_unref. |
373 | + * |
374 | + * API/ABI stability is not guaranteed. If you need to pass the object across an ABI |
375 | + * boundary, pass the plain gobject. |
376 | + * |
377 | + * This is how you would use gobj_ptr 99% of the time: |
378 | + * |
379 | + * gobj_ptr<GSomeType> o(g_some_type_new(...)); |
380 | + * |
381 | + * More specifically, the object will decrement the gobject reference count |
382 | + * of the object it points to when it goes out of scope. It will never increment it. |
383 | + * Thus you should only assign to it when already holding a reference. gobj_ptr |
384 | + * will then take ownership of that particular reference. |
385 | + * |
386 | + * Floating gobjects can not be put in this container as they are meant to be put |
387 | + * into native gobject aware containers immediately upon construction. Trying to insert |
388 | + * a floating gobject into a gobj_ptr will throw an invalid_argument exception. To |
389 | + * prevent accidental memory leaks, the floating gobject is unreffed in this case. |
390 | + */ |
391 | +template <typename T> |
392 | +class gobj_ptr final |
393 | +{ |
394 | +private: |
395 | + T* u; |
396 | + |
397 | + void validate_float(T* t) |
398 | + { |
399 | + if (t != nullptr && g_object_is_floating(G_OBJECT(t))) |
400 | + { |
401 | + // LCOV_EXCL_START // False negative from gcovr. |
402 | + throw std::invalid_argument("Tried to add a floating gobject into a gobj_ptr."); |
403 | + // LCOV_EXCL_STOP |
404 | + } |
405 | + } |
406 | + |
407 | +public: |
408 | + typedef T element_type; |
409 | + typedef T* pointer; |
410 | + typedef decltype(g_object_unref) deleter_type; |
411 | + |
412 | + constexpr gobj_ptr() noexcept : u(nullptr) |
413 | + { |
414 | + } |
415 | + explicit gobj_ptr(T* t) |
416 | + : u(t) |
417 | + { |
418 | + // What should we do if validate throws? Unreffing unknown objs |
419 | + // is dodgy but not unreffing runs the risk of |
420 | + // memory leaks. Currently unrefs as u is destroyed |
421 | + // when this exception is thrown. |
422 | + validate_float(t); |
423 | + } |
424 | + constexpr gobj_ptr(std::nullptr_t) noexcept : u(nullptr){}; |
425 | + gobj_ptr(gobj_ptr&& o) noexcept |
426 | + { |
427 | + u = o.u; |
428 | + o.u = nullptr; |
429 | + } |
430 | + gobj_ptr(const gobj_ptr& o) |
431 | + : u(nullptr) |
432 | + { |
433 | + *this = o; |
434 | + } |
435 | + gobj_ptr& operator=(const gobj_ptr& o) |
436 | + { |
437 | + if (o.u != nullptr) |
438 | + { |
439 | + g_object_ref(o.u); |
440 | + } |
441 | + reset(o.u); |
442 | + return *this; |
443 | + } |
444 | + ~gobj_ptr() |
445 | + { |
446 | + reset(); |
447 | + } |
448 | + |
449 | + deleter_type& get_deleter() noexcept |
450 | + { |
451 | + return g_object_unref; |
452 | + } |
453 | + deleter_type& get_deleter() const noexcept |
454 | + { |
455 | + return g_object_unref; |
456 | + } |
457 | + |
458 | + void swap(gobj_ptr<T>& o) noexcept |
459 | + { |
460 | + T* tmp = u; |
461 | + u = o.u; |
462 | + o.u = tmp; |
463 | + } |
464 | + void reset(pointer p = pointer()) |
465 | + { |
466 | + if (u != nullptr) |
467 | + { |
468 | + g_object_unref(G_OBJECT(u)); |
469 | + u = nullptr; |
470 | + } |
471 | + // Same throw dilemma as in pointer constructor. |
472 | + u = p; |
473 | + validate_float(p); |
474 | + } |
475 | + |
476 | + T* release() noexcept |
477 | + { |
478 | + T* r = u; |
479 | + u = nullptr; |
480 | + return r; |
481 | + } |
482 | + T* get() const noexcept |
483 | + { |
484 | + return u; |
485 | + } |
486 | + |
487 | + T& operator*() const |
488 | + { |
489 | + return *u; |
490 | + } |
491 | + T* operator->() const noexcept |
492 | + { |
493 | + return u; |
494 | + } |
495 | + explicit operator bool() const noexcept |
496 | + { |
497 | + return u != nullptr; |
498 | + } |
499 | + |
500 | + gobj_ptr& operator=(gobj_ptr&& o) noexcept |
501 | + { |
502 | + reset(); |
503 | + u = o.u; |
504 | + o.u = nullptr; |
505 | + return *this; |
506 | + } |
507 | + gobj_ptr& operator=(std::nullptr_t) noexcept |
508 | + { |
509 | + reset(); |
510 | + return *this; |
511 | + } |
512 | + bool operator==(const gobj_ptr<T>& o) const noexcept |
513 | + { |
514 | + return u == o.u; |
515 | + } |
516 | + bool operator!=(const gobj_ptr<T>& o) const noexcept |
517 | + { |
518 | + return u != o.u; |
519 | + } |
520 | + bool operator<(const gobj_ptr<T>& o) const noexcept |
521 | + { |
522 | + return u < o.u; |
523 | + } |
524 | + bool operator<=(const gobj_ptr<T>& o) const noexcept |
525 | + { |
526 | + return u <= o.u; |
527 | + } |
528 | + bool operator>(const gobj_ptr<T>& o) const noexcept |
529 | + { |
530 | + return u > o.u; |
531 | + } |
532 | + bool operator>=(const gobj_ptr<T>& o) const noexcept |
533 | + { |
534 | + return u >= o.u; |
535 | + } |
536 | +}; |
537 | + |
538 | +#pragma GCC diagnostic pop |
539 | + |
540 | |
541 | === added file 'tests/integration/utils/gsettings.cpp' |
542 | --- tests/integration/utils/gsettings.cpp 1970-01-01 00:00:00 +0000 |
543 | +++ tests/integration/utils/gsettings.cpp 2016-02-17 09:23:14 +0000 |
544 | @@ -0,0 +1,149 @@ |
545 | +/* |
546 | + * Copyright (C) 2016 Canonical Ltd. |
547 | + * |
548 | + * This program is free software: you can redistribute it and/or modify |
549 | + * it under the terms of the GNU General Public License version 3 as |
550 | + * published by the Free Software Foundation. |
551 | + * |
552 | + * This program is distributed in the hope that it will be useful, |
553 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
554 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
555 | + * GNU General Public License for more details. |
556 | + * |
557 | + * You should have received a copy of the GNU General Public License |
558 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
559 | + * |
560 | + * Authored by: Xavi Garcia <xavi.garcia.mena@canonical.com> |
561 | + */ |
562 | + |
563 | +#include "gsettings.h" |
564 | + |
565 | +//#include "settings-defaults.h" |
566 | + |
567 | +#pragma GCC diagnostic push |
568 | +#pragma GCC diagnostic ignored "-Wold-style-cast" |
569 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
570 | +#include <gio/gio.h> |
571 | +#pragma GCC diagnostic pop |
572 | +#include <QDebug> |
573 | + |
574 | +#include <memory> |
575 | + |
576 | +using namespace std; |
577 | + |
578 | +Settings::Settings() |
579 | + : Settings("com.canonical.indicator.sound") |
580 | +{ |
581 | +} |
582 | + |
583 | +Settings::Settings(string const& schema_name) |
584 | + : schema_(nullptr, &g_settings_schema_unref) |
585 | + , schema_name_(schema_name) |
586 | +{ |
587 | + GSettingsSchemaSource* src = g_settings_schema_source_get_default(); |
588 | + schema_.reset(g_settings_schema_source_lookup(src, schema_name.c_str(), true)); |
589 | + if (schema_) |
590 | + { |
591 | + settings_.reset(g_settings_new(schema_name.c_str())); |
592 | + } |
593 | + else |
594 | + { |
595 | + qCritical() << "The schema" << schema_name.c_str() << "is missing"; |
596 | + } |
597 | +} |
598 | + |
599 | +Settings::~Settings() = default; |
600 | + |
601 | +string Settings::get_last_running_player() const |
602 | +{ |
603 | + return get_string("last-running-player", ""); |
604 | +} |
605 | + |
606 | +string Settings::get_interested_media_players() const |
607 | +{ |
608 | + return get_string_array_as_string("interested-media-players", ""); |
609 | +} |
610 | + |
611 | +string Settings::get_string(char const* key, string const& default_value) const |
612 | +{ |
613 | + if (!settings_ || !g_settings_schema_has_key(schema_.get(), key)) |
614 | + { |
615 | + return default_value; |
616 | + } |
617 | + |
618 | + char *value = g_settings_get_string(settings_.get(), key); |
619 | + if (value) |
620 | + { |
621 | + string result = value; |
622 | + g_free(value); |
623 | + return result; |
624 | + } |
625 | + return default_value; // LCOV_EXCL_LINE |
626 | +} |
627 | + |
628 | +int Settings::get_positive_int(char const* key, int default_value) const |
629 | +{ |
630 | + int i = get_int(key, default_value); |
631 | + if (i <= 0) |
632 | + { |
633 | + throw domain_error(string("Settings::get_positive_int(): invalid zero or negative value for ") |
634 | + + key + ": " + to_string(i) + " in schema " + schema_name_); |
635 | + } |
636 | + return i; |
637 | +} |
638 | + |
639 | +int Settings::get_positive_or_zero_int(char const* key, int default_value) const |
640 | +{ |
641 | + int i = get_int(key, default_value); |
642 | + if (i < 0) |
643 | + { |
644 | + throw domain_error(string("Settings::get_positive_or_zero_int(): invalid negative value for ") |
645 | + + key + ": " + to_string(i) + " in schema " + schema_name_); |
646 | + } |
647 | + return i; |
648 | +} |
649 | + |
650 | +int Settings::get_int(char const* key, int default_value) const |
651 | +{ |
652 | + if (!settings_ || !g_settings_schema_has_key(schema_.get(), key)) |
653 | + { |
654 | + return default_value; |
655 | + } |
656 | + |
657 | + return g_settings_get_int(settings_.get(), key); |
658 | +} |
659 | + |
660 | +bool Settings::get_bool(char const* key, bool default_value) const |
661 | +{ |
662 | + if (!settings_ || !g_settings_schema_has_key(schema_.get(), key)) |
663 | + { |
664 | + return default_value; |
665 | + } |
666 | + |
667 | + return g_settings_get_boolean(settings_.get(), key); |
668 | +} |
669 | + |
670 | +std::string Settings::get_string_array_as_string(char const* key, std::string const& default_value) const |
671 | +{ |
672 | + if (!settings_ || !g_settings_schema_has_key(schema_.get(), key)) |
673 | + { |
674 | + return default_value; |
675 | + } |
676 | + gchar **values; |
677 | + values = g_settings_get_strv(settings_.get(), key); |
678 | + if (!values) |
679 | + { |
680 | + return default_value; |
681 | + } |
682 | + int length = 0; |
683 | + std::string res = "["; |
684 | + while (((gpointer*) values)[length]) |
685 | + { |
686 | + std::string test(values[length]); |
687 | + length++; |
688 | + res += "[ " + test + " ]"; |
689 | + } |
690 | + res += "]"; |
691 | + |
692 | + return res; |
693 | +} |
694 | |
695 | === added file 'tests/integration/utils/gsettings.h' |
696 | --- tests/integration/utils/gsettings.h 1970-01-01 00:00:00 +0000 |
697 | +++ tests/integration/utils/gsettings.h 2016-02-17 09:23:14 +0000 |
698 | @@ -0,0 +1,52 @@ |
699 | +/* |
700 | + * Copyright (C) 2016 Canonical Ltd. |
701 | + * |
702 | + * This program is free software: you can redistribute it and/or modify |
703 | + * it under the terms of the GNU General Public License version 3 as |
704 | + * published by the Free Software Foundation. |
705 | + * |
706 | + * This program is distributed in the hope that it will be useful, |
707 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
708 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
709 | + * GNU General Public License for more details. |
710 | + * |
711 | + * You should have received a copy of the GNU General Public License |
712 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
713 | + * |
714 | + * Authored by: Xavi Garcia <xavi.garcia.mena@canonical.com> |
715 | + */ |
716 | + |
717 | +#pragma once |
718 | + |
719 | +#include "gobj_memory.h" |
720 | + |
721 | +#include <memory> |
722 | +#include <string> |
723 | + |
724 | +typedef struct _GSettings GSettings; |
725 | +typedef struct _GSettingsSchema GSettingsSchema; |
726 | + |
727 | +class Settings |
728 | +{ |
729 | +public: |
730 | + Settings(); |
731 | + // This constructor is only for use in the tests. |
732 | + explicit Settings(std::string const& schema_name); |
733 | + ~Settings(); |
734 | + |
735 | + std::string get_last_running_player() const; |
736 | + |
737 | + std::string get_interested_media_players() const; |
738 | + |
739 | +private: |
740 | + std::string get_string(char const* key, std::string const& default_value) const; |
741 | + int get_positive_int(char const* key, int default_value) const; |
742 | + int get_positive_or_zero_int(char const* key, int default_value) const; |
743 | + int get_int(char const* key, int default_value) const; |
744 | + bool get_bool(char const* key, bool default_value) const; |
745 | + std::string get_string_array_as_string(char const* key, std::string const& default_value) const; |
746 | + |
747 | + std::unique_ptr<GSettingsSchema, void(*)(GSettingsSchema*)> schema_; |
748 | + std::string schema_name_; |
749 | + gobj_ptr<GSettings> settings_; |
750 | +}; |
FAILED: Continuous integration, rev:528 jenkins. qa.ubuntu. com/job/ indicator- sound-ci/ 310/ jenkins. qa.ubuntu. com/job/ indicator- sound-wily- amd64-ci/ 85/console jenkins. qa.ubuntu. com/job/ indicator- sound-wily- armhf-ci/ 86/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/indicator- sound-ci/ 310/rebuild
http://