aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2015-06-05 19:50:04 +0000
committerCI Train Bot <ci-train-bot@canonical.com>2015-06-05 19:50:04 +0000
commit6b1f1eecaa38dd71822541ac06c3337393c98199 (patch)
tree4e9022ed7cb12f01314b5eca83f878e8c1284716
parent0a1022595e419c0dd06007329a6e95619d21f4fd (diff)
parent52b6aaeede8ec6192844a5b9813f7509bd313b60 (diff)
downloadayatana-indicator-sound-6b1f1eecaa38dd71822541ac06c3337393c98199.tar.gz
ayatana-indicator-sound-6b1f1eecaa38dd71822541ac06c3337393c98199.tar.bz2
ayatana-indicator-sound-6b1f1eecaa38dd71822541ac06c3337393c98199.zip
Using eventually to avoid arbitrary timeouts in tests
Approved by: Charles Kerr, PS Jenkins bot
-rw-r--r--debian/changelog6
-rw-r--r--tests/media-player-user.cc152
2 files changed, 140 insertions, 18 deletions
diff --git a/debian/changelog b/debian/changelog
index 4d0314b..c360efd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+indicator-sound (12.10.2+15.10.20150507+eventually4-0ubuntu1) wily; urgency=medium
+
+ * Using eventually to avoid arbitrary timeouts in tests
+
+ -- Ted Gould <ted@ubuntu.com> Wed, 27 May 2015 11:11:19 -0500
+
indicator-sound (12.10.2+15.10.20150507-0ubuntu1) wily; urgency=medium
[ Charles Kerr ]
diff --git a/tests/media-player-user.cc b/tests/media-player-user.cc
index 8d2fcb1..ca20b5f 100644
--- a/tests/media-player-user.cc
+++ b/tests/media-player-user.cc
@@ -17,6 +17,9 @@
* Ted Gould <ted@canonical.com>
*/
+#include <chrono>
+#include <future>
+
#include <gtest/gtest.h>
#include <gio/gio.h>
#include <libdbustest/dbus-test.h>
@@ -31,24 +34,55 @@ class MediaPlayerUserTest : public ::testing::Test
{
protected:
- DbusTestService * service = NULL;
+ DbusTestService * testsystem = NULL;
AccountsServiceMock service_mock;
+ DbusTestService * testsession = NULL;
+
+ DbusTestProcess * systemmonitor = nullptr;
+ DbusTestProcess * sessionmonitor = nullptr;
+
GDBusConnection * system = NULL;
+ GDBusConnection * session = NULL;
GDBusProxy * proxy = NULL;
+ std::chrono::milliseconds _eventuallyTime = std::chrono::seconds{5};
+
virtual void SetUp() {
- service = dbus_test_service_new(NULL);
- dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SYSTEM);
+ /* System Bus */
+ testsystem = dbus_test_service_new(NULL);
+ dbus_test_service_set_bus(testsystem, DBUS_TEST_SERVICE_BUS_SYSTEM);
+
+ systemmonitor = dbus_test_process_new("dbus-monitor");
+ dbus_test_process_append_param(systemmonitor, "--system");
+ dbus_test_task_set_name(DBUS_TEST_TASK(systemmonitor), "System");
+ dbus_test_service_add_task(testsystem, DBUS_TEST_TASK(systemmonitor));
- dbus_test_service_add_task(service, (DbusTestTask*)service_mock);
- dbus_test_service_start_tasks(service);
+ dbus_test_service_add_task(testsystem, (DbusTestTask*)service_mock);
+ dbus_test_service_start_tasks(testsystem);
system = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
ASSERT_NE(nullptr, system);
g_dbus_connection_set_exit_on_close(system, FALSE);
g_object_add_weak_pointer(G_OBJECT(system), (gpointer *)&system);
+ /* Session Bus */
+ testsession = dbus_test_service_new(NULL);
+ dbus_test_service_set_bus(testsession, DBUS_TEST_SERVICE_BUS_SESSION);
+
+ sessionmonitor = dbus_test_process_new("dbus-monitor");
+ dbus_test_process_append_param(sessionmonitor, "--session");
+ dbus_test_task_set_name(DBUS_TEST_TASK(sessionmonitor), "Session");
+ dbus_test_service_add_task(testsession, DBUS_TEST_TASK(sessionmonitor));
+
+ dbus_test_service_start_tasks(testsession);
+
+ session = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
+ ASSERT_NE(nullptr, session);
+ g_dbus_connection_set_exit_on_close(session, FALSE);
+ g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session);
+
+ /* Setup proxy */
proxy = g_dbus_proxy_new_sync(system,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
@@ -60,10 +94,15 @@ class MediaPlayerUserTest : public ::testing::Test
}
virtual void TearDown() {
+ g_clear_object(&sessionmonitor);
+ g_clear_object(&systemmonitor);
+
g_clear_object(&proxy);
- g_clear_object(&service);
+ g_clear_object(&testsystem);
+ g_clear_object(&testsession);
g_object_unref(system);
+ g_object_unref(session);
#if 0
/* Accounts Service keeps a bunch of references around so we
@@ -95,8 +134,78 @@ class MediaPlayerUserTest : public ::testing::Test
void set_property (const gchar * name, GVariant * value) {
dbus_test_dbus_mock_object_update_property((DbusTestDbusMock *)service_mock, service_mock.get_sound(), name, value, NULL);
}
+
+ testing::AssertionResult expectEventually (std::function<testing::AssertionResult(void)> &testfunc) {
+ auto loop = std::shared_ptr<GMainLoop>(g_main_loop_new(nullptr, FALSE), [](GMainLoop * loop) { if (loop != nullptr) g_main_loop_unref(loop); });
+
+ std::promise<testing::AssertionResult> retpromise;
+ auto retfuture = retpromise.get_future();
+ auto start = std::chrono::steady_clock::now();
+
+ /* The core of the idle function as an object so we can use the C++-isms
+ of attaching the variables and make this code reasonably readable */
+ std::function<void(void)> idlefunc = [&loop, &retpromise, &testfunc, &start, this]() -> void {
+ auto result = testfunc();
+
+ if (result == false && _eventuallyTime > (std::chrono::steady_clock::now() - start)) {
+ return;
+ }
+
+ retpromise.set_value(result);
+ g_main_loop_quit(loop.get());
+ };
+
+ auto idlesrc = g_idle_add([](gpointer data) -> gboolean {
+ auto func = reinterpret_cast<std::function<void(void)> *>(data);
+ (*func)();
+ return G_SOURCE_CONTINUE;
+ }, &idlefunc);
+
+ g_main_loop_run(loop.get());
+ g_source_remove(idlesrc);
+
+ return retfuture.get();
+ }
+
+ /* Eventually Helpers */
+ #define _EVENTUALLY_HELPER(oper) \
+ template <typename... Args> testing::AssertionResult expectEventually##oper (Args&& ... args) { \
+ std::function<testing::AssertionResult(void)> func = [&]() { \
+ return testing::internal::CmpHelper##oper(std::forward<Args>(args)...); \
+ }; \
+ return expectEventually(func); \
+ }
+
+ _EVENTUALLY_HELPER(EQ);
+ _EVENTUALLY_HELPER(NE);
+ _EVENTUALLY_HELPER(LT);
+ _EVENTUALLY_HELPER(GT);
+ _EVENTUALLY_HELPER(STREQ);
+ _EVENTUALLY_HELPER(STRNE);
+
+ #undef _EVENTUALLY_HELPER
};
+/* Helpers */
+#define EXPECT_EVENTUALLY_EQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyEQ, expected, actual)
+
+#define EXPECT_EVENTUALLY_NE(expected, actual) \
+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyNE, expected, actual)
+
+#define EXPECT_EVENTUALLY_LT(expected, actual) \
+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyLT, expected, actual)
+
+#define EXPECT_EVENTUALLY_GT(expected, actual) \
+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyGT, expected, actual)
+
+#define EXPECT_EVENTUALLY_STREQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallySTREQ, expected, actual)
+
+#define EXPECT_EVENTUALLY_STRNE(expected, actual) \
+ EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallySTRNE, expected, actual)
+
+
TEST_F(MediaPlayerUserTest, BasicObject) {
MediaPlayerUser * player = media_player_user_new("user");
ASSERT_NE(nullptr, player);
@@ -125,6 +234,11 @@ TEST_F(MediaPlayerUserTest, BasicObject) {
g_clear_object(&player);
}
+void
+running_update (GObject * obj, GParamSpec * pspec, bool * running) {
+ *running = media_player_get_is_running(MEDIA_PLAYER(obj)) == TRUE;
+};
+
TEST_F(MediaPlayerUserTest, DataSet) {
/* Put data into Acts */
set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));
@@ -141,11 +255,11 @@ TEST_F(MediaPlayerUserTest, DataSet) {
MediaPlayerUser * player = media_player_user_new("user");
ASSERT_NE(nullptr, player);
- /* Get the proxy -- and it's precious precious data -- oh, my, precious! */
- loop(100);
-
/* Ensure even with the proxy we don't have anything */
- EXPECT_TRUE(media_player_get_is_running(MEDIA_PLAYER(player)));
+ bool running = false;
+ g_signal_connect(G_OBJECT(player), "notify::is-running", G_CALLBACK(running_update), &running);
+ running_update(G_OBJECT(player), nullptr, &running);
+ EXPECT_EVENTUALLY_EQ(true, running);
EXPECT_TRUE(media_player_get_can_raise(MEDIA_PLAYER(player)));
EXPECT_STREQ("user", media_player_get_id(MEDIA_PLAYER(player)));
EXPECT_STREQ("The Player Formerly Known as Prince", media_player_get_name(MEDIA_PLAYER(player)));
@@ -180,24 +294,26 @@ TEST_F(MediaPlayerUserTest, TimeoutTest) {
set_property("Album", g_variant_new_string("Vinyl is dead"));
set_property("ArtUrl", g_variant_new_string("http://art.url"));
- /* Ensure the properties get set before we pull them */
- loop(100);
-
/* Build our media player */
MediaPlayerUser * player = media_player_user_new("user");
ASSERT_NE(nullptr, player);
- /* Get the proxy -- and the old data, so old, like forever */
- loop(100);
+ bool running = false;
+ g_signal_connect(G_OBJECT(player), "notify::is-running", G_CALLBACK(running_update), &running);
+ running_update(G_OBJECT(player), nullptr, &running);
/* Ensure that we show up as not running */
- EXPECT_FALSE(media_player_get_is_running(MEDIA_PLAYER(player)));
+ EXPECT_EVENTUALLY_EQ(false, running);
/* Update to make running */
set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));
- loop(100);
- EXPECT_TRUE(media_player_get_is_running(MEDIA_PLAYER(player)));
+ EXPECT_EVENTUALLY_EQ(true, running);
+
+ /* Clear to not run */
+ set_property("Timestamp", g_variant_new_uint64(1));
+
+ EXPECT_EVENTUALLY_EQ(false, running);
g_clear_object(&in_icon);
g_clear_object(&player);