Merge lp:~ted/indicator-sound/eventually-testing into lp:indicator-sound/15.10

Proposed by Ted Gould
Status: Merged
Approved by: Charles Kerr
Approved revision: 505
Merged at revision: 497
Proposed branch: lp:~ted/indicator-sound/eventually-testing
Merge into: lp:indicator-sound/15.10
Diff against target: 249 lines (+142/-20)
2 files modified
debian/changelog (+6/-0)
tests/media-player-user.cc (+136/-20)
To merge this branch: bzr merge lp:~ted/indicator-sound/eventually-testing
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+260373@code.launchpad.net

Commit message

Using eventually to avoid arbitrary timeouts in tests

To post a comment you must log in.
504. By Ted Gould

Dumping the bus, old school style

505. By Ted Gould

For Launchpad

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:503
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~ted/indicator-sound/eventually-testing/+merge/260373/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/indicator-sound-ci/225/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/indicator-sound-wily-amd64-ci/1/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/indicator-sound-wily-armhf-ci/1
        deb: http://jenkins.qa.ubuntu.com/job/indicator-sound-wily-armhf-ci/1/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/indicator-sound-ci/225/rebuild

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

Nice improvements all around.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2015-05-07 15:27:00 +0000
3+++ debian/changelog 2015-05-28 15:03:10 +0000
4@@ -1,3 +1,9 @@
5+indicator-sound (12.10.2+15.10.20150507+eventually4-0ubuntu1) wily; urgency=medium
6+
7+ * Using eventually to avoid arbitrary timeouts in tests
8+
9+ -- Ted Gould <ted@ubuntu.com> Wed, 27 May 2015 11:11:19 -0500
10+
11 indicator-sound (12.10.2+15.10.20150507-0ubuntu1) wily; urgency=medium
12
13 [ Charles Kerr ]
14
15=== modified file 'tests/media-player-user.cc'
16--- tests/media-player-user.cc 2015-01-30 16:05:10 +0000
17+++ tests/media-player-user.cc 2015-05-28 15:03:10 +0000
18@@ -17,6 +17,9 @@
19 * Ted Gould <ted@canonical.com>
20 */
21
22+#include <chrono>
23+#include <future>
24+
25 #include <gtest/gtest.h>
26 #include <gio/gio.h>
27 #include <libdbustest/dbus-test.h>
28@@ -31,24 +34,55 @@
29 {
30
31 protected:
32- DbusTestService * service = NULL;
33+ DbusTestService * testsystem = NULL;
34 AccountsServiceMock service_mock;
35
36+ DbusTestService * testsession = NULL;
37+
38+ DbusTestProcess * systemmonitor = nullptr;
39+ DbusTestProcess * sessionmonitor = nullptr;
40+
41 GDBusConnection * system = NULL;
42+ GDBusConnection * session = NULL;
43 GDBusProxy * proxy = NULL;
44
45+ std::chrono::milliseconds _eventuallyTime = std::chrono::seconds{5};
46+
47 virtual void SetUp() {
48- service = dbus_test_service_new(NULL);
49- dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SYSTEM);
50-
51- dbus_test_service_add_task(service, (DbusTestTask*)service_mock);
52- dbus_test_service_start_tasks(service);
53+ /* System Bus */
54+ testsystem = dbus_test_service_new(NULL);
55+ dbus_test_service_set_bus(testsystem, DBUS_TEST_SERVICE_BUS_SYSTEM);
56+
57+ systemmonitor = dbus_test_process_new("dbus-monitor");
58+ dbus_test_process_append_param(systemmonitor, "--system");
59+ dbus_test_task_set_name(DBUS_TEST_TASK(systemmonitor), "System");
60+ dbus_test_service_add_task(testsystem, DBUS_TEST_TASK(systemmonitor));
61+
62+ dbus_test_service_add_task(testsystem, (DbusTestTask*)service_mock);
63+ dbus_test_service_start_tasks(testsystem);
64
65 system = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
66 ASSERT_NE(nullptr, system);
67 g_dbus_connection_set_exit_on_close(system, FALSE);
68 g_object_add_weak_pointer(G_OBJECT(system), (gpointer *)&system);
69
70+ /* Session Bus */
71+ testsession = dbus_test_service_new(NULL);
72+ dbus_test_service_set_bus(testsession, DBUS_TEST_SERVICE_BUS_SESSION);
73+
74+ sessionmonitor = dbus_test_process_new("dbus-monitor");
75+ dbus_test_process_append_param(sessionmonitor, "--session");
76+ dbus_test_task_set_name(DBUS_TEST_TASK(sessionmonitor), "Session");
77+ dbus_test_service_add_task(testsession, DBUS_TEST_TASK(sessionmonitor));
78+
79+ dbus_test_service_start_tasks(testsession);
80+
81+ session = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
82+ ASSERT_NE(nullptr, session);
83+ g_dbus_connection_set_exit_on_close(session, FALSE);
84+ g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session);
85+
86+ /* Setup proxy */
87 proxy = g_dbus_proxy_new_sync(system,
88 G_DBUS_PROXY_FLAGS_NONE,
89 NULL,
90@@ -60,10 +94,15 @@
91 }
92
93 virtual void TearDown() {
94+ g_clear_object(&sessionmonitor);
95+ g_clear_object(&systemmonitor);
96+
97 g_clear_object(&proxy);
98- g_clear_object(&service);
99+ g_clear_object(&testsystem);
100+ g_clear_object(&testsession);
101
102 g_object_unref(system);
103+ g_object_unref(session);
104
105 #if 0
106 /* Accounts Service keeps a bunch of references around so we
107@@ -95,8 +134,78 @@
108 void set_property (const gchar * name, GVariant * value) {
109 dbus_test_dbus_mock_object_update_property((DbusTestDbusMock *)service_mock, service_mock.get_sound(), name, value, NULL);
110 }
111+
112+ testing::AssertionResult expectEventually (std::function<testing::AssertionResult(void)> &testfunc) {
113+ auto loop = std::shared_ptr<GMainLoop>(g_main_loop_new(nullptr, FALSE), [](GMainLoop * loop) { if (loop != nullptr) g_main_loop_unref(loop); });
114+
115+ std::promise<testing::AssertionResult> retpromise;
116+ auto retfuture = retpromise.get_future();
117+ auto start = std::chrono::steady_clock::now();
118+
119+ /* The core of the idle function as an object so we can use the C++-isms
120+ of attaching the variables and make this code reasonably readable */
121+ std::function<void(void)> idlefunc = [&loop, &retpromise, &testfunc, &start, this]() -> void {
122+ auto result = testfunc();
123+
124+ if (result == false && _eventuallyTime > (std::chrono::steady_clock::now() - start)) {
125+ return;
126+ }
127+
128+ retpromise.set_value(result);
129+ g_main_loop_quit(loop.get());
130+ };
131+
132+ auto idlesrc = g_idle_add([](gpointer data) -> gboolean {
133+ auto func = reinterpret_cast<std::function<void(void)> *>(data);
134+ (*func)();
135+ return G_SOURCE_CONTINUE;
136+ }, &idlefunc);
137+
138+ g_main_loop_run(loop.get());
139+ g_source_remove(idlesrc);
140+
141+ return retfuture.get();
142+ }
143+
144+ /* Eventually Helpers */
145+ #define _EVENTUALLY_HELPER(oper) \
146+ template <typename... Args> testing::AssertionResult expectEventually##oper (Args&& ... args) { \
147+ std::function<testing::AssertionResult(void)> func = [&]() { \
148+ return testing::internal::CmpHelper##oper(std::forward<Args>(args)...); \
149+ }; \
150+ return expectEventually(func); \
151+ }
152+
153+ _EVENTUALLY_HELPER(EQ);
154+ _EVENTUALLY_HELPER(NE);
155+ _EVENTUALLY_HELPER(LT);
156+ _EVENTUALLY_HELPER(GT);
157+ _EVENTUALLY_HELPER(STREQ);
158+ _EVENTUALLY_HELPER(STRNE);
159+
160+ #undef _EVENTUALLY_HELPER
161 };
162
163+/* Helpers */
164+#define EXPECT_EVENTUALLY_EQ(expected, actual) \
165+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyEQ, expected, actual)
166+
167+#define EXPECT_EVENTUALLY_NE(expected, actual) \
168+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyNE, expected, actual)
169+
170+#define EXPECT_EVENTUALLY_LT(expected, actual) \
171+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyLT, expected, actual)
172+
173+#define EXPECT_EVENTUALLY_GT(expected, actual) \
174+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyGT, expected, actual)
175+
176+#define EXPECT_EVENTUALLY_STREQ(expected, actual) \
177+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallySTREQ, expected, actual)
178+
179+#define EXPECT_EVENTUALLY_STRNE(expected, actual) \
180+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallySTRNE, expected, actual)
181+
182+
183 TEST_F(MediaPlayerUserTest, BasicObject) {
184 MediaPlayerUser * player = media_player_user_new("user");
185 ASSERT_NE(nullptr, player);
186@@ -125,6 +234,11 @@
187 g_clear_object(&player);
188 }
189
190+void
191+running_update (GObject * obj, GParamSpec * pspec, bool * running) {
192+ *running = media_player_get_is_running(MEDIA_PLAYER(obj)) == TRUE;
193+};
194+
195 TEST_F(MediaPlayerUserTest, DataSet) {
196 /* Put data into Acts */
197 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));
198@@ -141,11 +255,11 @@
199 MediaPlayerUser * player = media_player_user_new("user");
200 ASSERT_NE(nullptr, player);
201
202- /* Get the proxy -- and it's precious precious data -- oh, my, precious! */
203- loop(100);
204-
205 /* Ensure even with the proxy we don't have anything */
206- EXPECT_TRUE(media_player_get_is_running(MEDIA_PLAYER(player)));
207+ bool running = false;
208+ g_signal_connect(G_OBJECT(player), "notify::is-running", G_CALLBACK(running_update), &running);
209+ running_update(G_OBJECT(player), nullptr, &running);
210+ EXPECT_EVENTUALLY_EQ(true, running);
211 EXPECT_TRUE(media_player_get_can_raise(MEDIA_PLAYER(player)));
212 EXPECT_STREQ("user", media_player_get_id(MEDIA_PLAYER(player)));
213 EXPECT_STREQ("The Player Formerly Known as Prince", media_player_get_name(MEDIA_PLAYER(player)));
214@@ -180,24 +294,26 @@
215 set_property("Album", g_variant_new_string("Vinyl is dead"));
216 set_property("ArtUrl", g_variant_new_string("http://art.url"));
217
218- /* Ensure the properties get set before we pull them */
219- loop(100);
220-
221 /* Build our media player */
222 MediaPlayerUser * player = media_player_user_new("user");
223 ASSERT_NE(nullptr, player);
224
225- /* Get the proxy -- and the old data, so old, like forever */
226- loop(100);
227+ bool running = false;
228+ g_signal_connect(G_OBJECT(player), "notify::is-running", G_CALLBACK(running_update), &running);
229+ running_update(G_OBJECT(player), nullptr, &running);
230
231 /* Ensure that we show up as not running */
232- EXPECT_FALSE(media_player_get_is_running(MEDIA_PLAYER(player)));
233+ EXPECT_EVENTUALLY_EQ(false, running);
234
235 /* Update to make running */
236 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));
237- loop(100);
238-
239- EXPECT_TRUE(media_player_get_is_running(MEDIA_PLAYER(player)));
240+
241+ EXPECT_EVENTUALLY_EQ(true, running);
242+
243+ /* Clear to not run */
244+ set_property("Timestamp", g_variant_new_uint64(1));
245+
246+ EXPECT_EVENTUALLY_EQ(false, running);
247
248 g_clear_object(&in_icon);
249 g_clear_object(&player);

Subscribers

People subscribed via source and target branches