Merge lp:~charlesk/indicator-datetime/lp-1560960-use-dbusmock-timedated-template into lp:indicator-datetime/15.10

Proposed by Charles Kerr
Status: Merged
Approved by: Renato Araujo Oliveira Filho
Approved revision: 448
Merged at revision: 443
Proposed branch: lp:~charlesk/indicator-datetime/lp-1560960-use-dbusmock-timedated-template
Merge into: lp:indicator-datetime/15.10
Prerequisite: lp:~charlesk/indicator-datetime/always-get-initial-tzid-from-timedate1
Diff against target: 847 lines (+212/-394)
6 files modified
include/datetime/dbus-shared.h (+0/-8)
src/actions-live.cpp (+5/-4)
tests/glib-fixture.h (+16/-13)
tests/test-live-actions.cpp (+76/-18)
tests/test-timezone-timedated.cpp (+7/-100)
tests/timedated-fixture.h (+108/-251)
To merge this branch: bzr merge lp:~charlesk/indicator-datetime/lp-1560960-use-dbusmock-timedated-template
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
Renato Araujo Oliveira Filho (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+291446@code.launchpad.net

Commit message

Use dbusmock's timedated template in our tests

Description of the change

Minor patch on top of https://code.launchpad.net/~charlesk/indicator-datetime/always-get-initial-tzid-from-timedate1/+merge/291421 .

That branch added a test fixture which uses dbusmock's timedated template. This branch promotes that up to a shared test header where it can be reused by test-live-actions, and removes test-live-actions' previous handrolled timedated mock.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

looks good.

review: Approve
Revision history for this message
Charles Kerr (charlesk) wrote :

re-approving because the r449 was already approved in prerequisite branch

Revision history for this message
Charles Kerr (charlesk) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/datetime/dbus-shared.h'
--- include/datetime/dbus-shared.h 2016-04-12 17:27:17 +0000
+++ include/datetime/dbus-shared.h 2016-04-12 17:27:17 +0000
@@ -28,10 +28,6 @@
28#define BUS_POWERD_PATH "/com/canonical/powerd"28#define BUS_POWERD_PATH "/com/canonical/powerd"
29#define BUS_POWERD_INTERFACE "com.canonical.powerd"29#define BUS_POWERD_INTERFACE "com.canonical.powerd"
3030
31namespace unity {
32namespace indicator {
33namespace datetime {
34
35namespace Bus31namespace Bus
36{32{
37 namespace Timedate133 namespace Timedate1
@@ -67,8 +63,4 @@
67 }63 }
68}64}
6965
70} // namespace datetime
71} // namespace indicator
72} // namespace unity
73
74#endif /* INDICATOR_DATETIME_DBUS_SHARED_H */66#endif /* INDICATOR_DATETIME_DBUS_SHARED_H */
7567
=== modified file 'src/actions-live.cpp'
--- src/actions-live.cpp 2016-04-05 21:00:09 +0000
+++ src/actions-live.cpp 2016-04-12 17:27:17 +0000
@@ -17,6 +17,7 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include <datetime/dbus-shared.h>
20#include <datetime/actions-live.h>21#include <datetime/actions-live.h>
2122
22#include <url-dispatcher.h>23#include <url-dispatcher.h>
@@ -252,7 +253,7 @@
252 else253 else
253 {254 {
254 g_dbus_proxy_call(proxy,255 g_dbus_proxy_call(proxy,
255 "SetTimezone",256 Bus::Timedate1::Methods::SET_TIMEZONE,
256 g_variant_new ("(sb)", data->tzid.c_str(), TRUE),257 g_variant_new ("(sb)", data->tzid.c_str(), TRUE),
257 G_DBUS_CALL_FLAGS_NONE,258 G_DBUS_CALL_FLAGS_NONE,
258 -1,259 -1,
@@ -280,9 +281,9 @@
280 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,281 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
281 G_DBUS_PROXY_FLAGS_NONE,282 G_DBUS_PROXY_FLAGS_NONE,
282 nullptr,283 nullptr,
283 "org.freedesktop.timedate1",284 Bus::Timedate1::BUSNAME,
284 "/org/freedesktop/timedate1",285 Bus::Timedate1::ADDR,
285 "org.freedesktop.timedate1",286 Bus::Timedate1::IFACE,
286 nullptr,287 nullptr,
287 on_datetime1_proxy_ready,288 on_datetime1_proxy_ready,
288 data);289 data);
289290
=== modified file 'tests/glib-fixture.h'
--- tests/glib-fixture.h 2016-02-10 20:47:39 +0000
+++ tests/glib-fixture.h 2016-04-12 17:27:17 +0000
@@ -125,10 +125,11 @@
125 }125 }
126 }126 }
127127
128 bool wait_for_name_owned(GDBusConnection* connection,128 bool wait_for_name_owned(
129 const gchar* name,129 GDBusConnection* connection,
130 guint timeout_msec=1000,130 const gchar* name,
131 GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START)131 guint timeout_msec=1000,
132 GBusNameWatcherFlags flags=G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
132 {133 {
133 struct Data {134 struct Data {
134 GMainLoop* loop = nullptr;135 GMainLoop* loop = nullptr;
@@ -139,8 +140,7 @@
139 auto on_name_appeared = [](GDBusConnection* /*connection*/,140 auto on_name_appeared = [](GDBusConnection* /*connection*/,
140 const gchar* /*name_*/,141 const gchar* /*name_*/,
141 const gchar* name_owner,142 const gchar* name_owner,
142 gpointer gdata)143 gpointer gdata){
143 {
144 if (name_owner == nullptr)144 if (name_owner == nullptr)
145 return;145 return;
146 auto tmp = static_cast<Data*>(gdata);146 auto tmp = static_cast<Data*>(gdata);
@@ -150,13 +150,16 @@
150150
151 const auto timeout_id = g_timeout_add(timeout_msec, wait_msec__timeout, loop);151 const auto timeout_id = g_timeout_add(timeout_msec, wait_msec__timeout, loop);
152 data.loop = loop;152 data.loop = loop;
153 const auto watch_id = g_bus_watch_name_on_connection(connection,153 const auto watch_id = g_bus_watch_name_on_connection(
154 name,154 connection,
155 flags,155 name,
156 on_name_appeared,156 flags,
157 nullptr, /* name_vanished */157 on_name_appeared,
158 &data,158 nullptr, // name_vanished
159 nullptr); /* user_data_free_func */159 &data,
160 nullptr // user_data_free_func
161 );
162
160 g_main_loop_run(loop);163 g_main_loop_run(loop);
161164
162 g_bus_unwatch_name(watch_id);165 g_bus_unwatch_name(watch_id);
163166
=== modified file 'tests/test-live-actions.cpp'
--- tests/test-live-actions.cpp 2016-03-21 17:32:39 +0000
+++ tests/test-live-actions.cpp 2016-04-12 17:27:17 +0000
@@ -17,18 +17,75 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include "state-mock.h"
20#include "timedated-fixture.h"21#include "timedated-fixture.h"
2122
23#include <datetime/actions-live.h>
24
25using namespace unity::indicator::datetime;
26
27class MockLiveActions: public LiveActions
28{
29public:
30 std::string last_cmd;
31 std::string last_url;
32 explicit MockLiveActions(const std::shared_ptr<State>& state_in): LiveActions(state_in) {}
33 ~MockLiveActions() {}
34
35protected:
36 void dispatch_url(const std::string& url) override { last_url = url; }
37 void execute_command(const std::string& cmd) override { last_cmd = cmd; }
38};
39
40class TestLiveActionsFixture: public TimedatedFixture
41{
42private:
43
44 using super = TimedatedFixture;
45
46protected:
47
48 std::shared_ptr<MockState> m_mock_state;
49 std::shared_ptr<State> m_state;
50 std::shared_ptr<MockLiveActions> m_live_actions;
51 std::shared_ptr<Actions> m_actions;
52
53 void SetUp() override
54 {
55 super::SetUp();
56
57 // create the State and Actions
58 m_mock_state.reset(new MockState);
59 m_mock_state->settings.reset(new Settings);
60 m_state = std::dynamic_pointer_cast<State>(m_mock_state);
61 m_live_actions.reset(new MockLiveActions(m_state));
62 m_actions = std::dynamic_pointer_cast<Actions>(m_live_actions);
63
64 // start the timedate1 dbusmock
65 start_timedate1("Etc/Utc");
66 }
67
68 void TearDown() override
69 {
70 m_actions.reset();
71 m_live_actions.reset();
72 m_state.reset();
73 m_mock_state.reset();
74
75 super::TearDown();
76 }
77};
78
22/***79/***
23****80****
24***/81***/
2582
26TEST_F(TimedateFixture, HelloWorld)83TEST_F(TestLiveActionsFixture, HelloWorld)
27{84{
28 EXPECT_TRUE(true);85 EXPECT_TRUE(true);
29}86}
3087
31TEST_F(TimedateFixture, SetLocation)88TEST_F(TestLiveActionsFixture, SetLocation)
32{89{
33 const std::string tzid = "America/Chicago";90 const std::string tzid = "America/Chicago";
34 const std::string name = "Oklahoma City";91 const std::string name = "Oklahoma City";
@@ -36,30 +93,31 @@
3693
37 EXPECT_NE(expected, m_state->settings->timezone_name.get());94 EXPECT_NE(expected, m_state->settings->timezone_name.get());
3895
96 std::string new_name;
97 m_state->settings->timezone_name.changed().connect(
98 [&new_name](const std::string& n){new_name = n;}
99 );
100
39 m_actions->set_location(tzid, name);101 m_actions->set_location(tzid, name);
40 m_state->settings->timezone_name.changed().connect(
41 [this](const std::string&){
42 g_main_loop_quit(loop);
43 });
44 g_main_loop_run(loop);
45 EXPECT_EQ(attempted_tzid, tzid);
46 wait_msec();
47102
103 EXPECT_TRUE(wait_for([&new_name](){return !new_name.empty();}));
104 EXPECT_EQ(expected, new_name);
48 EXPECT_EQ(expected, m_state->settings->timezone_name.get());105 EXPECT_EQ(expected, m_state->settings->timezone_name.get());
106 EXPECT_EQ(tzid, get_timedate1_timezone());
49}107}
50108
51/***109/***
52****110****
53***/111***/
54112
55TEST_F(TimedateFixture, DesktopOpenAlarmApp)113TEST_F(TestLiveActionsFixture, DesktopOpenAlarmApp)
56{114{
57 m_actions->desktop_open_alarm_app();115 m_actions->desktop_open_alarm_app();
58 const std::string expected = "evolution -c calendar";116 const std::string expected = "evolution -c calendar";
59 EXPECT_EQ(expected, m_live_actions->last_cmd);117 EXPECT_EQ(expected, m_live_actions->last_cmd);
60}118}
61119
62TEST_F(TimedateFixture, DesktopOpenAppointment)120TEST_F(TestLiveActionsFixture, DesktopOpenAppointment)
63{121{
64 Appointment a;122 Appointment a;
65 a.uid = "some-uid";123 a.uid = "some-uid";
@@ -69,14 +127,14 @@
69 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);127 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);
70}128}
71129
72TEST_F(TimedateFixture, DesktopOpenCalendarApp)130TEST_F(TestLiveActionsFixture, DesktopOpenCalendarApp)
73{131{
74 m_actions->desktop_open_calendar_app(DateTime::NowLocal());132 m_actions->desktop_open_calendar_app(DateTime::NowLocal());
75 const std::string expected_substr = "evolution \"calendar:///?startdate=";133 const std::string expected_substr = "evolution \"calendar:///?startdate=";
76 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);134 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);
77}135}
78136
79TEST_F(TimedateFixture, DesktopOpenSettingsApp)137TEST_F(TestLiveActionsFixture, DesktopOpenSettingsApp)
80{138{
81 m_actions->desktop_open_settings_app();139 m_actions->desktop_open_settings_app();
82 const std::string expected_substr = "control-center";140 const std::string expected_substr = "control-center";
@@ -92,13 +150,13 @@
92 const std::string clock_app_url = "appid://com.ubuntu.clock/clock/current-user-version";150 const std::string clock_app_url = "appid://com.ubuntu.clock/clock/current-user-version";
93}151}
94152
95TEST_F(TimedateFixture, PhoneOpenAlarmApp)153TEST_F(TestLiveActionsFixture, PhoneOpenAlarmApp)
96{154{
97 m_actions->phone_open_alarm_app();155 m_actions->phone_open_alarm_app();
98 EXPECT_EQ(clock_app_url, m_live_actions->last_url);156 EXPECT_EQ(clock_app_url, m_live_actions->last_url);
99}157}
100158
101TEST_F(TimedateFixture, PhoneOpenAppointment)159TEST_F(TestLiveActionsFixture, PhoneOpenAppointment)
102{160{
103 Appointment a;161 Appointment a;
104162
@@ -116,7 +174,7 @@
116 EXPECT_EQ(clock_app_url, m_live_actions->last_url);174 EXPECT_EQ(clock_app_url, m_live_actions->last_url);
117}175}
118176
119TEST_F(TimedateFixture, PhoneOpenCalendarApp)177TEST_F(TestLiveActionsFixture, PhoneOpenCalendarApp)
120{178{
121 auto now = DateTime::NowLocal();179 auto now = DateTime::NowLocal();
122 m_actions->phone_open_calendar_app(now);180 m_actions->phone_open_calendar_app(now);
@@ -125,7 +183,7 @@
125}183}
126184
127185
128TEST_F(TimedateFixture, PhoneOpenSettingsApp)186TEST_F(TestLiveActionsFixture, PhoneOpenSettingsApp)
129{187{
130 m_actions->phone_open_settings_app();188 m_actions->phone_open_settings_app();
131 const std::string expected = "settings:///system/time-date";189 const std::string expected = "settings:///system/time-date";
@@ -136,7 +194,7 @@
136****194****
137***/195***/
138196
139TEST_F(TimedateFixture, CalendarState)197TEST_F(TestLiveActionsFixture, CalendarState)
140{198{
141 // init the clock199 // init the clock
142 auto now = DateTime::Local(2014, 1, 1, 0, 0, 0);200 auto now = DateTime::Local(2014, 1, 1, 0, 0, 0);
143201
=== modified file 'tests/test-timezone-timedated.cpp'
--- tests/test-timezone-timedated.cpp 2016-04-12 17:27:17 +0000
+++ tests/test-timezone-timedated.cpp 2016-04-12 17:27:17 +0000
@@ -18,119 +18,26 @@
18 * Ted Gould <ted.gould@canonical.com>18 * Ted Gould <ted.gould@canonical.com>
19 */19 */
2020
21#include "glib-fixture.h"21#include "timedated-fixture.h"
2222
23#include <datetime/dbus-shared.h>
24#include <datetime/timezone-timedated.h>23#include <datetime/timezone-timedated.h>
2524
26#include <gio/gio.h>
27
28
29using namespace unity::indicator::datetime;25using namespace unity::indicator::datetime;
3026
3127using TestTimedatedFixture = TimedatedFixture;
32struct Timedate1Fixture: public GlibFixture
33{
34private:
35
36 typedef GlibFixture super;
37
38protected:
39
40 GDBusConnection* m_bus {};
41 GTestDBus* m_test_bus {};
42
43 void SetUp() override
44 {
45 super::SetUp();
46
47 // use a fake bus
48 m_test_bus = g_test_dbus_new(G_TEST_DBUS_NONE);
49 g_test_dbus_up(m_test_bus);
50 const char * address = g_test_dbus_get_bus_address(m_test_bus);
51 g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true);
52 g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);
53 g_debug("test_dbus's address is %s", address);
54
55 // get the bus
56 m_bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
57 g_dbus_connection_set_exit_on_close(m_bus, FALSE);
58 }
59
60 void TearDown() override
61 {
62 // tear down the bus
63 bool bus_finished = false;
64 g_object_weak_ref(
65 G_OBJECT(m_bus),
66 [](gpointer gbus_finished, GObject*){*static_cast<bool*>(gbus_finished) = true;},
67 &bus_finished
68 );
69 g_clear_object(&m_bus);
70 EXPECT_TRUE(wait_for([&bus_finished](){return bus_finished;}));
71
72 // tear down test bus
73 g_clear_object(&m_test_bus);
74
75 super::TearDown();
76 }
77
78 void start_timedate1(const std::string& tzid)
79 {
80 // start dbusmock with the timedated template
81 auto json_parameters = g_strdup_printf("{\"Timezone\": \"%s\"}", tzid.c_str());
82 const gchar* child_argv[] = { "python3", "-m", "dbusmock", "--template", "timedated", "--parameters", json_parameters, nullptr };
83 GError* error = nullptr;
84 g_spawn_async(nullptr, (gchar**)child_argv, nullptr, G_SPAWN_SEARCH_PATH, nullptr, nullptr, nullptr, &error);
85 g_assert_no_error(error);
86 g_free(json_parameters);
87
88 // wait for it to appear on the bus
89 wait_for_name_owned(m_bus, Bus::Timedate1::BUSNAME);
90 }
91
92 bool wait_for_tzid(const std::string& tzid, Timezone& tz)
93 {
94 return wait_for([&tzid, &tz](){return tzid == tz.timezone.get();});
95 }
96
97 void set_timedate1_timezone(const std::string& tzid)
98 {
99 GError* error {};
100 auto v = g_dbus_connection_call_sync(
101 m_bus,
102 Bus::Timedate1::BUSNAME,
103 Bus::Timedate1::ADDR,
104 Bus::Timedate1::IFACE,
105 Bus::Timedate1::Methods::SET_TIMEZONE,
106 g_variant_new("(sb)", tzid.c_str(), FALSE),
107 nullptr,
108 G_DBUS_CALL_FLAGS_NONE,
109 -1,
110 nullptr,
111 &error);
112 g_clear_pointer(&v, g_variant_unref);
113 g_assert_no_error(error);
114 }
115};
116
117#define EXPECT_TZID(expected_tzid, tmp) \
118 EXPECT_TRUE(wait_for_tzid(expected_tzid, tmp)) \
119 << "expected " << expected_tzid \
120 << " got " << tmp.timezone.get();
12128
122/***29/***
123****30****
124***/31***/
12532
126TEST_F(Timedate1Fixture, HelloWorld)33TEST_F(TestTimedatedFixture, HelloWorld)
127{34{
128}35}
12936
130/**37/**
131 * Test that the tzid is right if timedated isn't available38 * Test that the tzid is right if timedated isn't available
132 */39 */
133TEST_F(Timedate1Fixture, DefaultTimezone)40TEST_F(TestTimedatedFixture, DefaultTimezone)
134{41{
135 const std::string expected_tzid{"Etc/Utc"};42 const std::string expected_tzid{"Etc/Utc"};
13643
@@ -141,7 +48,7 @@
141/**48/**
142 * Test that the tzid is right if timedated shows BEFORE we start49 * Test that the tzid is right if timedated shows BEFORE we start
143 */50 */
144TEST_F(Timedate1Fixture, Timedate1First)51TEST_F(TestTimedatedFixture, Timedate1First)
145{52{
146 const std::string expected_tzid{"America/Chicago"};53 const std::string expected_tzid{"America/Chicago"};
14754
@@ -153,7 +60,7 @@
153/**60/**
154 * Test that the tzid is right if timedated shows AFTER we start61 * Test that the tzid is right if timedated shows AFTER we start
155 */62 */
156TEST_F(Timedate1Fixture, Timedate1Last)63TEST_F(TestTimedatedFixture, Timedate1Last)
157{64{
158 const std::string expected_tzid("America/Los_Angeles");65 const std::string expected_tzid("America/Los_Angeles");
15966
@@ -165,7 +72,7 @@
165/**72/**
166 * Test that the tzid is right if timedated's property changes73 * Test that the tzid is right if timedated's property changes
167 */74 */
168TEST_F(Timedate1Fixture, TimezoneChange)75TEST_F(TestTimedatedFixture, TimezoneChange)
169{76{
170 const std::vector<std::string> expected_tzids{"America/Los_Angeles", "America/Chicago", "Etc/Utc"};77 const std::vector<std::string> expected_tzids{"America/Los_Angeles", "America/Chicago", "Etc/Utc"};
17178
17279
=== modified file 'tests/timedated-fixture.h'
--- tests/timedated-fixture.h 2015-09-03 09:54:20 +0000
+++ tests/timedated-fixture.h 2016-04-12 17:27:17 +0000
@@ -17,285 +17,142 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#ifndef INDICATOR_DATETIME_TESTS_TIMEDATED_FIXTURE_H20#pragma once
21#define INDICATOR_DATETIME_TESTS_TIMEDATED_FIXTURE_H
2221
23#include <datetime/actions-live.h>22#include <datetime/actions-live.h>
2423
25#include "state-mock.h"
26#include "glib-fixture.h"24#include "glib-fixture.h"
2725
28using namespace unity::indicator::datetime;26#include <datetime/dbus-shared.h>
2927#include <datetime/timezone.h>
30class MockLiveActions: public LiveActions
31{
32public:
33 std::string last_cmd;
34 std::string last_url;
35 explicit MockLiveActions(const std::shared_ptr<State>& state_in): LiveActions(state_in) {}
36 ~MockLiveActions() {}
37
38protected:
39 void dispatch_url(const std::string& url) override { last_url = url; }
40 void execute_command(const std::string& cmd) override { last_cmd = cmd; }
41};
4228
43/***29/***
44****30****
45***/31***/
4632
47using namespace unity::indicator::datetime;33struct TimedatedFixture: public GlibFixture
48
49class TimedateFixture: public GlibFixture
50{34{
51private:35private:
5236
53 typedef GlibFixture super;37 using super = GlibFixture;
54
55 static GVariant * timedate1_get_properties (GDBusConnection * /*connection*/ ,
56 const gchar * /*sender*/,
57 const gchar * /*object_path*/,
58 const gchar * /*interface_name*/,
59 const gchar *property_name,
60 GError ** /*error*/,
61 gpointer gself)
62
63 {
64 auto self = static_cast<TimedateFixture*>(gself);
65 g_debug("get_properties called");
66 if (g_strcmp0(property_name, "Timezone") == 0)
67 {
68 g_debug("timezone requested, giving '%s'",
69 self->attempted_tzid.c_str());
70 return g_variant_new_string(self->attempted_tzid.c_str());
71 }
72 return nullptr;
73 }
74
75
76 static void on_bus_acquired(GDBusConnection* conn,
77 const gchar* name,
78 gpointer gself)
79 {
80 auto self = static_cast<TimedateFixture*>(gself);
81 g_debug("bus acquired: %s, connection is %p", name, conn);
82
83 /* Set up a fake timedated which handles setting and getting the
84 ** timezone
85 */
86 static const GDBusInterfaceVTable vtable = {
87 timedate1_handle_method_call,
88 timedate1_get_properties, /* GetProperty */
89 nullptr, /* SetProperty */
90 };
91
92 self->connection = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(conn)));
93
94 GError* error = nullptr;
95 self->object_register_id = g_dbus_connection_register_object(
96 conn,
97 "/org/freedesktop/timedate1",
98 self->node_info->interfaces[0],
99 &vtable,
100 self,
101 nullptr,
102 &error);
103 g_assert_no_error(error);
104 }
105
106 static void on_name_acquired(GDBusConnection* conn,
107 const gchar* name,
108 gpointer gself)
109 {
110 g_debug("on_name_acquired");
111 auto self = static_cast<TimedateFixture*>(gself);
112 self->name_acquired = true;
113 self->proxy = g_dbus_proxy_new_sync(conn,
114 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
115 nullptr,
116 name,
117 "/org/freedesktop/timedate1",
118 "org.freedesktop.timedate1",
119 nullptr,
120 nullptr);
121 g_main_loop_quit(self->loop);
122 }
123
124 static void on_name_lost(GDBusConnection* /*conn*/,
125 const gchar* /*name*/,
126 gpointer gself)
127 {
128 g_debug("on_name_lost");
129 auto self = static_cast<TimedateFixture*>(gself);
130 self->name_acquired = false;
131 }
132
133 static void on_bus_closed(GObject* /*object*/,
134 GAsyncResult* res,
135 gpointer gself)
136 {
137 g_debug("on_bus_closed");
138 auto self = static_cast<TimedateFixture*>(gself);
139 GError* err = nullptr;
140 g_dbus_connection_close_finish(self->connection, res, &err);
141 g_assert_no_error(err);
142 g_main_loop_quit(self->loop);
143 }
144
145 static void
146 timedate1_handle_method_call(GDBusConnection * connection,
147 const gchar * /*sender*/,
148 const gchar * object_path,
149 const gchar * interface_name,
150 const gchar * method_name,
151 GVariant * parameters,
152 GDBusMethodInvocation * invocation,
153 gpointer gself)
154 {
155 g_assert(!g_strcmp0(method_name, "SetTimezone"));
156 g_assert(g_variant_is_of_type(parameters, G_VARIANT_TYPE_TUPLE));
157 g_assert(2 == g_variant_n_children(parameters));
158
159 auto child = g_variant_get_child_value(parameters, 0);
160 g_assert(g_variant_is_of_type(child, G_VARIANT_TYPE_STRING));
161 auto self = static_cast<TimedateFixture*>(gself);
162 self->attempted_tzid = g_variant_get_string(child, nullptr);
163 g_debug("set tz (dbus side): '%s'", self->attempted_tzid.c_str());
164 g_dbus_method_invocation_return_value(invocation, nullptr);
165
166 /* Send PropertiesChanged */
167 GError * local_error = nullptr;
168 auto builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
169 g_variant_builder_add (builder,
170 "{sv}",
171 "Timezone",
172 g_variant_new_string(
173 self->attempted_tzid.c_str()));
174 g_dbus_connection_emit_signal (connection,
175 NULL,
176 object_path,
177 "org.freedesktop.DBus.Properties",
178 "PropertiesChanged",
179 g_variant_new ("(sa{sv}as)",
180 interface_name,
181 builder,
182 NULL),
183 &local_error);
184 g_assert_no_error (local_error);
185 g_variant_unref(child);
186 }
18738
188protected:39protected:
18940
190 std::shared_ptr<MockState> m_mock_state;41 GDBusConnection* m_bus {};
191 std::shared_ptr<State> m_state;42 GTestDBus* m_test_bus {};
192 std::shared_ptr<MockLiveActions> m_live_actions;43
193 std::shared_ptr<Actions> m_actions;44 virtual void SetUp() override
194
195 bool name_acquired;
196 std::string attempted_tzid;
197
198 GTestDBus* bus;
199 guint own_name;
200 GDBusConnection* connection;
201 GDBusNodeInfo* node_info;
202 int object_register_id;
203 GDBusProxy *proxy;
204
205 void SetUp()
206 {45 {
207 super::SetUp();46 super::SetUp();
208 g_debug("SetUp");47
20948 // use a fake bus
210 name_acquired = false;49 m_test_bus = g_test_dbus_new(G_TEST_DBUS_NONE);
211 attempted_tzid.clear();50 g_test_dbus_up(m_test_bus);
212 connection = nullptr;51 const char * address = g_test_dbus_get_bus_address(m_test_bus);
213 node_info = nullptr;
214 object_register_id = 0;
215 own_name = 0;
216 proxy = nullptr;
217
218 // bring up the test bus
219 bus = g_test_dbus_new(G_TEST_DBUS_NONE);
220 g_test_dbus_up(bus);
221 const auto address = g_test_dbus_get_bus_address(bus);
222 g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true);52 g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true);
223 g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);53 g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);
224 g_debug("test_dbus's address is %s", address);54 g_debug("test_dbus's address is %s", address);
22555
226 // parse the org.freedesktop.timedate1 interface56 // get the bus
227 const gchar introspection_xml[] =57 m_bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
228 "<node>"58 g_dbus_connection_set_exit_on_close(m_bus, FALSE);
229 " <interface name='org.freedesktop.timedate1'>"59 g_object_add_weak_pointer(G_OBJECT(m_bus), (gpointer*)&m_bus);
230 " <property name='Timezone' type='s' access='read' />"
231 " <method name='SetTimezone'>"
232 " <arg name='timezone' type='s' direction='in'/>"
233 " <arg name='user_interaction' type='b' direction='in'/>"
234 " </method>"
235 " </interface>"
236 "</node>";
237 node_info = g_dbus_node_info_new_for_xml(introspection_xml, nullptr);
238 ASSERT_TRUE(node_info != nullptr);
239 ASSERT_TRUE(node_info->interfaces != nullptr);
240 ASSERT_TRUE(node_info->interfaces[0] != nullptr);
241 ASSERT_TRUE(node_info->interfaces[1] == nullptr);
242 ASSERT_STREQ("org.freedesktop.timedate1", node_info->interfaces[0]->name);
243
244 // own the bus
245 own_name = g_bus_own_name(G_BUS_TYPE_SYSTEM,
246 "org.freedesktop.timedate1",
247 G_BUS_NAME_OWNER_FLAGS_NONE,
248 on_bus_acquired, on_name_acquired, on_name_lost,
249 this, nullptr);
250 ASSERT_TRUE(object_register_id == 0);
251 ASSERT_FALSE(name_acquired);
252 ASSERT_TRUE(connection == nullptr);
253 g_main_loop_run(loop);
254 ASSERT_TRUE(object_register_id != 0);
255 ASSERT_TRUE(name_acquired);
256 ASSERT_TRUE(G_IS_DBUS_CONNECTION(connection));
257
258 // create the State and Actions
259 m_mock_state.reset(new MockState);
260 m_mock_state->settings.reset(new Settings);
261 m_state = std::dynamic_pointer_cast<State>(m_mock_state);
262 m_live_actions.reset(new MockLiveActions(m_state));
263 m_actions = std::dynamic_pointer_cast<Actions>(m_live_actions);
264 }60 }
26561
266 void TearDown()62 virtual void TearDown() override
267 {63 {
268 g_debug("TearDown");64 // take down the bus
269 m_actions.reset();65 bool bus_finished = false;
270 m_live_actions.reset();66 g_object_weak_ref(
271 m_state.reset();67 G_OBJECT(m_bus),
272 m_mock_state.reset();68 [](gpointer gbus_finished, GObject*){*static_cast<bool*>(gbus_finished) = true;},
273 g_dbus_connection_unregister_object(connection, object_register_id);69 &bus_finished
274 g_object_unref(proxy);70 );
275 g_dbus_node_info_unref(node_info);71 g_clear_object(&m_bus);
276 g_bus_unown_name(own_name);72 EXPECT_TRUE(wait_for([&bus_finished](){return bus_finished;}));
277 g_dbus_connection_close(connection, nullptr, on_bus_closed, this);73
278 g_main_loop_run(loop);74 // take down the GTestBus
279 g_clear_object(&connection);75 g_clear_object(&m_test_bus);
280 g_test_dbus_down(bus);
281 g_clear_object(&bus);
28276
283 super::TearDown();77 super::TearDown();
284 }78 }
285public:79
286 void set_timezone(std::string tz)80 void start_timedate1(const std::string& tzid)
287 {81 {
288 g_debug("set_timezone: '%s'", tz.c_str());82 // start dbusmock with the timedated template
289 g_dbus_proxy_call_sync(proxy,83 auto json_parameters = g_strdup_printf("{\"Timezone\": \"%s\"}", tzid.c_str());
290 "SetTimezone",84 const gchar* child_argv[] = {
291 g_variant_new("(sb)",85 "python3", "-m", "dbusmock",
292 tz.c_str(),86 "--template", "timedated",
293 FALSE),87 "--parameters", json_parameters,
294 G_DBUS_CALL_FLAGS_NONE,88 nullptr
295 500,89 };
296 nullptr,90 GError* error = nullptr;
297 nullptr);91 g_spawn_async(nullptr, (gchar**)child_argv, nullptr, G_SPAWN_SEARCH_PATH, nullptr, nullptr, nullptr, &error);
92 g_assert_no_error(error);
93 g_free(json_parameters);
94
95 // wait for it to appear on the bus
96 wait_for_name_owned(m_bus, Bus::Timedate1::BUSNAME);
97 }
98
99 bool wait_for_tzid(const std::string& tzid, unity::indicator::datetime::Timezone& tz)
100 {
101 return wait_for([&tzid, &tz](){return tzid == tz.timezone.get();});
102 }
103
104 void set_timedate1_timezone(const std::string& tzid)
105 {
106 GError* error {};
107 auto v = g_dbus_connection_call_sync(
108 m_bus,
109 Bus::Timedate1::BUSNAME,
110 Bus::Timedate1::ADDR,
111 Bus::Timedate1::IFACE,
112 Bus::Timedate1::Methods::SET_TIMEZONE,
113 g_variant_new("(sb)", tzid.c_str(), FALSE),
114 nullptr,
115 G_DBUS_CALL_FLAGS_NONE,
116 -1,
117 nullptr,
118 &error);
119 g_assert_no_error(error);
120
121 g_clear_pointer(&v, g_variant_unref);
122 }
123
124 std::string get_timedate1_timezone()
125 {
126 GError* error {};
127 auto v = g_dbus_connection_call_sync(
128 m_bus,
129 Bus::Timedate1::BUSNAME,
130 Bus::Timedate1::ADDR,
131 Bus::Properties::IFACE,
132 Bus::Properties::Methods::GET,
133 g_variant_new("(ss)", Bus::Timedate1::IFACE, Bus::Timedate1::Properties::TIMEZONE),
134 G_VARIANT_TYPE("(v)"),
135 G_DBUS_CALL_FLAGS_NONE,
136 -1,
137 nullptr,
138 &error);
139 g_assert_no_error(error);
140
141 GVariant* tzv {};
142 g_variant_get(v, "(v)", &tzv);
143 std::string tzid;
144 const char* tz = g_variant_get_string(tzv, nullptr);
145 if (tz != nullptr)
146 tzid = tz;
147
148 g_clear_pointer(&tzv, g_variant_unref);
149 g_clear_pointer(&v, g_variant_unref);
150 return tzid;
298 }151 }
299};152};
300153
301#endif154#define EXPECT_TZID(expected_tzid, tmp) \
155 EXPECT_TRUE(wait_for_tzid(expected_tzid, tmp)) \
156 << "expected " << expected_tzid \
157 << " got " << tmp.timezone.get();
158

Subscribers

People subscribed via source and target branches