Merge lp:~laney/indicator-datetime/timedated-timezone-property into lp:indicator-datetime/15.10

Proposed by Iain Lane on 2015-09-01
Status: Rejected
Rejected by: Iain Lane on 2015-09-03
Proposed branch: lp:~laney/indicator-datetime/timedated-timezone-property
Merge into: lp:indicator-datetime/15.10
Diff against target: 1240 lines (+533/-351)
10 files modified
include/datetime/timezone-timedated.h (+10/-8)
include/datetime/timezones-live.h (+4/-4)
src/CMakeLists.txt (+2/-3)
src/main.cpp (+3/-3)
src/timezone-timedated.cpp (+155/-63)
src/timezones-live.cpp (+2/-3)
tests/CMakeLists.txt (+1/-1)
tests/test-live-actions.cpp (+21/-227)
tests/test-timezone-timedated.cpp (+34/-39)
tests/timedated-fixture.h (+301/-0)
To merge this branch: bzr merge lp:~laney/indicator-datetime/timedated-timezone-property
Reviewer Review Type Date Requested Status
Lars Karlitski (community) 2015-09-01 Needs Fixing on 2015-09-03
PS Jenkins bot (community) continuous-integration Approve on 2015-09-03
Indicator Applet Developers 2015-09-01 Pending
Review via email: mp+269732@code.launchpad.net

Description of the change

Use timedated's Timezone property to find out the current timezone and learn about changes to it

To post a comment you must log in.
Iain Lane (laney) wrote :

Some IRC chat reveals that a good option to read the initial state is to get this from /etc/timezone on disk directly, then use dbus after that.

424. By Iain Lane on 2015-09-03

Avoid nested GMainLoops by reading from the file on startup

Restore some tests for this functionality.

425. By Iain Lane on 2015-09-03

Make test-live-actions quit itself once the tz has been changed, the mock no longer does this

Iain Lane (laney) wrote :

Updated - please re-review.

Is taking a reference to the GDBusConnection sane? Without it the testsuite kills the connection and the AddMatch fails, which causes some criticals.

(process:12769): GLib-GIO-CRITICAL **: Error while sending AddMatch() message: The connection is closed

(process:12769): GLib-GIO-CRITICAL **: g_dbus_connection_call_finish_internal: assertion 'G_IS_DBUS_CONNECTION (connection)' failed

Maybe we don't care or there's a better way to ensure this can't fail?

Lars Karlitski (larsu) wrote :

Thanks for working on this!

It's causing some unnecessary bus traffic though:

 - watch org.freedesktop.timedate1
 - call GetProperties and fetch all properties of that object
 - subscribe to PropertiesChanged of all properties instead of just the one

Really all you need here is to add a match rule for PropertiesChanged for that *one* property you're interested in. Using g_dbus_connection_signal_subscribe() results in only one call to the daemon and you'll only get signals when the property you're interested in changes.

(By the way, the name_vanished() handler is called immediately when the name doesn't exist. Currently it's spewing some GObject warnings because you're trying to access the proxy without checking it for NULL. However, don't fix this if you stop watching the name anyway)

review: Needs Fixing
Iain Lane (laney) wrote :

There is no point in reviewing this.

I'm not working on this change. Get it in some other way.

Unmerged revisions

425. By Iain Lane on 2015-09-03

Make test-live-actions quit itself once the tz has been changed, the mock no longer does this

424. By Iain Lane on 2015-09-03

Avoid nested GMainLoops by reading from the file on startup

Restore some tests for this functionality.

423. By Iain Lane on 2015-09-01

Add some comments

422. By Iain Lane on 2015-09-01

Rename FileTimezone to TimedatedTimezone

421. By Iain Lane on 2015-09-01

Add a timeout so we can't hang forever

420. By Iain Lane on 2015-08-31

Use timedated's Timezone property instead of watching /etc/timezone

Still need to rename everything to not use "timezone-file"

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== renamed file 'include/datetime/timezone-file.h' => 'include/datetime/timezone-timedated.h'
--- include/datetime/timezone-file.h 2014-09-13 20:45:23 +0000
+++ include/datetime/timezone-timedated.h 2015-09-03 10:03:17 +0000
@@ -17,8 +17,10 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#ifndef INDICATOR_DATETIME_FILE_TIMEZONE_H20#ifndef INDICATOR_DATETIME_TIMEDATED_TIMEZONE_H
21#define INDICATOR_DATETIME_FILE_TIMEZONE_H21#define INDICATOR_DATETIME_TIMEDATED_TIMEZONE_H
22
23#define DEFAULT_FILENAME "/etc/timezone"
2224
23#include <datetime/timezone.h> // base class25#include <datetime/timezone.h> // base class
2426
@@ -31,11 +33,11 @@
31/**33/**
32 * \brief A #Timezone that gets its information from monitoring a file, such as /etc/timezone34 * \brief A #Timezone that gets its information from monitoring a file, such as /etc/timezone
33 */35 */
34class FileTimezone: public Timezone36class TimedatedTimezone: public Timezone
35{37{
36public:38public:
37 FileTimezone(const std::string& filename);39 TimedatedTimezone(std::string filename = DEFAULT_FILENAME);
38 ~FileTimezone();40 ~TimedatedTimezone();
3941
40private:42private:
41 class Impl;43 class Impl;
@@ -43,12 +45,12 @@
43 std::unique_ptr<Impl> impl;45 std::unique_ptr<Impl> impl;
4446
45 // we have pointers in here, so disable copying47 // we have pointers in here, so disable copying
46 FileTimezone(const FileTimezone&) =delete;48 TimedatedTimezone(const TimedatedTimezone&) =delete;
47 FileTimezone& operator=(const FileTimezone&) =delete;49 TimedatedTimezone& operator=(const TimedatedTimezone&) =delete;
48};50};
4951
50} // namespace datetime52} // namespace datetime
51} // namespace indicator53} // namespace indicator
52} // namespace unity54} // namespace unity
5355
54#endif // INDICATOR_DATETIME_FILE_TIMEZONE_H56#endif // INDICATOR_DATETIME_TIMEDATED_TIMEZONE_H
5557
=== modified file 'include/datetime/timezones-live.h'
--- include/datetime/timezones-live.h 2014-01-30 19:44:12 +0000
+++ include/datetime/timezones-live.h 2015-09-03 10:03:17 +0000
@@ -22,8 +22,8 @@
2222
23#include <datetime/settings.h>23#include <datetime/settings.h>
24#include <datetime/timezones.h>24#include <datetime/timezones.h>
25#include <datetime/timezone-file.h>
26#include <datetime/timezone-geoclue.h>25#include <datetime/timezone-geoclue.h>
26#include <datetime/timezone-timedated.h>
2727
28#include <memory> // shared_ptr<>28#include <memory> // shared_ptr<>
2929
@@ -32,19 +32,19 @@
32namespace datetime {32namespace datetime {
3333
34/**34/**
35 * \brief #Timezones object that uses a #FileTimezone and #GeoclueTimezone35 * \brief #Timezones object that uses a #TimedatedTimezone and #GeoclueTimezone
36 * to detect what timezone we're in36 * to detect what timezone we're in
37 */37 */
38class LiveTimezones: public Timezones38class LiveTimezones: public Timezones
39{39{
40public:40public:
41 LiveTimezones(const std::shared_ptr<const Settings>& settings, const std::string& filename);41 LiveTimezones(const std::shared_ptr<const Settings>& settings);
4242
43private:43private:
44 void update_geolocation();44 void update_geolocation();
45 void update_timezones();45 void update_timezones();
4646
47 FileTimezone m_file;47 TimedatedTimezone m_file;
48 std::shared_ptr<const Settings> m_settings;48 std::shared_ptr<const Settings> m_settings;
49 std::shared_ptr<GeoclueTimezone> m_geo;49 std::shared_ptr<GeoclueTimezone> m_geo;
50};50};
5151
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2015-01-21 20:25:52 +0000
+++ src/CMakeLists.txt 2015-09-03 10:03:17 +0000
@@ -1,8 +1,7 @@
1set (SERVICE_LIB "indicatordatetimeservice")1set (SERVICE_LIB "indicatordatetimeservice")
2set (SERVICE_EXEC "indicator-datetime-service")2set (SERVICE_EXEC "indicator-datetime-service")
33
4add_definitions (-DTIMEZONE_FILE="/etc/timezone"4add_definitions (-DG_LOG_DOMAIN="Indicator-Datetime")
5 -DG_LOG_DOMAIN="Indicator-Datetime")
65
7# handwritten sources6# handwritten sources
8set (SERVICE_C_SOURCES7set (SERVICE_C_SOURCES
@@ -34,9 +33,9 @@
34 settings-live.cpp33 settings-live.cpp
35 snap.cpp34 snap.cpp
36 sound.cpp35 sound.cpp
37 timezone-file.cpp
38 timezone-geoclue.cpp36 timezone-geoclue.cpp
39 timezones-live.cpp37 timezones-live.cpp
38 timezone-timedated.cpp
40 utils.c39 utils.c
41 wakeup-timer-mainloop.cpp40 wakeup-timer-mainloop.cpp
42 wakeup-timer-powerd.cpp)41 wakeup-timer-powerd.cpp)
4342
=== modified file 'src/main.cpp'
--- src/main.cpp 2015-04-03 18:11:39 +0000
+++ src/main.cpp 2015-09-03 10:03:17 +0000
@@ -31,8 +31,8 @@
31#include <datetime/settings-live.h>31#include <datetime/settings-live.h>
32#include <datetime/snap.h>32#include <datetime/snap.h>
33#include <datetime/state.h>33#include <datetime/state.h>
34#include <datetime/timezone-file.h>
35#include <datetime/timezones-live.h>34#include <datetime/timezones-live.h>
35#include <datetime/timezone-timedated.h>
36#include <datetime/wakeup-timer-powerd.h>36#include <datetime/wakeup-timer-powerd.h>
37#include <notifications/notifications.h>37#include <notifications/notifications.h>
3838
@@ -68,7 +68,7 @@
68 {68 {
69 // create the live objects69 // create the live objects
70 auto live_settings = std::make_shared<LiveSettings>();70 auto live_settings = std::make_shared<LiveSettings>();
71 auto live_timezones = std::make_shared<LiveTimezones>(live_settings, TIMEZONE_FILE);71 auto live_timezones = std::make_shared<LiveTimezones>(live_settings);
72 auto live_clock = std::make_shared<LiveClock>(timezone_);72 auto live_clock = std::make_shared<LiveClock>(timezone_);
7373
74 // create a full-month planner currently pointing to the current month74 // create a full-month planner currently pointing to the current month
@@ -128,7 +128,7 @@
128 textdomain(GETTEXT_PACKAGE);128 textdomain(GETTEXT_PACKAGE);
129129
130 auto engine = create_engine();130 auto engine = create_engine();
131 auto timezone_ = std::make_shared<FileTimezone>(TIMEZONE_FILE);131 auto timezone_ = std::make_shared<TimedatedTimezone>();
132 auto state = create_state(engine, timezone_);132 auto state = create_state(engine, timezone_);
133 auto actions = std::make_shared<LiveActions>(state);133 auto actions = std::make_shared<LiveActions>(state);
134 MenuFactory factory(actions, state);134 MenuFactory factory(actions, state);
135135
=== renamed file 'src/timezone-file.cpp' => 'src/timezone-timedated.cpp'
--- src/timezone-file.cpp 2014-09-13 20:45:23 +0000
+++ src/timezone-timedated.cpp 2015-09-03 10:03:17 +0000
@@ -17,7 +17,7 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include <datetime/timezone-file.h>20#include <datetime/timezone-timedated.h>
2121
22#include <gio/gio.h>22#include <gio/gio.h>
2323
@@ -32,14 +32,16 @@
32****32****
33***/33***/
3434
35class FileTimezone::Impl35class TimedatedTimezone::Impl
36{36{
37public:37public:
3838
39 Impl(FileTimezone& owner, const std::string& filename):39 Impl(TimedatedTimezone& owner, std::string filename):
40 m_owner(owner)40 m_owner(owner),
41 m_filename(filename)
41 {42 {
42 set_filename(filename);43 g_debug("Filename is '%s'", filename.c_str());
44 monitor_timezone_property();
43 }45 }
4446
45 ~Impl()47 ~Impl()
@@ -51,65 +53,152 @@
5153
52 void clear()54 void clear()
53 {55 {
54 if (m_monitor_handler_id)56 if (m_bus_watch_id)
55 g_signal_handler_disconnect(m_monitor, m_monitor_handler_id);57 {
5658 g_bus_unwatch_name (m_bus_watch_id);
57 g_clear_object (&m_monitor);59 m_bus_watch_id = 0;
5860 }
59 m_filename.clear();61
60 }62 if (m_properties_changed_id)
6163 {
62 void set_filename(const std::string& filename)64 g_signal_handler_disconnect(m_proxy, m_properties_changed_id);
63 {65 m_properties_changed_id = 0;
64 clear();66 }
6567
66 auto tmp = realpath(filename.c_str(), nullptr);68 g_clear_object(&m_proxy);
67 if(tmp != nullptr)69 }
68 {70
69 m_filename = tmp;71 static void on_properties_changed(GDBusProxy *proxy G_GNUC_UNUSED,
70 free(tmp);72 GVariant *changed_properties /* a{sv} */,
71 }73 GStrv invalidated_properties G_GNUC_UNUSED,
72 else74 gpointer gself)
73 {75 {
74 g_warning("Unable to resolve path '%s': %s", filename.c_str(), g_strerror(errno));76 auto self = static_cast<Impl*>(gself);
75 m_filename = filename; // better than nothing?77 char *tz;
76 }78
7779 if (g_variant_lookup(changed_properties, "Timezone", "s", &tz, NULL))
78 auto file = g_file_new_for_path(m_filename.c_str());80 {
79 GError * err = nullptr;81 g_debug("on_properties_changed: got timezone '%s'", tz);
80 m_monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, nullptr, &err);82 self->notify_timezone(tz);
81 g_object_unref(file);83 g_free (tz);
84 }
85 }
86
87 static void on_proxy_ready(GObject *object G_GNUC_UNUSED,
88 GAsyncResult *res,
89 gpointer gself)
90 {
91 auto self = static_cast<Impl*>(gself);
92 GError *error = nullptr;
93 self->m_proxy = g_dbus_proxy_new_finish(res, &error);
94
95 if (error)
96 {
97 g_warning ("Couldn't create proxy to read timezone: %s", error->message);
98 goto out;
99 }
100
101 /* Read the property */
102 GVariant *prop;
103 prop = g_dbus_proxy_get_cached_property(self->m_proxy, "Timezone");
104
105 if (!prop || !g_variant_is_of_type(prop, G_VARIANT_TYPE_STRING))
106 {
107 g_warning("Couldn't read the Timezone property, defaulting to Etc/Utc");
108 self->notify_timezone("Etc/Utc");
109 goto out;
110 }
111
112 const gchar *tz;
113 tz = g_variant_get_string(prop, nullptr);
114
115 self->notify_timezone(tz);
116
117 self->m_properties_changed_id = g_signal_connect(self->m_proxy,
118 "g-properties-changed",
119 (GCallback) on_properties_changed,
120 gself);
121
122out:
123 g_clear_pointer(&error, g_error_free);
124 g_clear_pointer(&prop, g_variant_unref);
125 }
126
127 static void on_name_appeared(GDBusConnection *connection,
128 const gchar *name,
129 const gchar *name_owner G_GNUC_UNUSED,
130 gpointer gself G_GNUC_UNUSED)
131 {
132 g_debug ("timedate1 appeared");
133 g_dbus_proxy_new(connection,
134 G_DBUS_PROXY_FLAGS_NONE,
135 NULL,
136 name,
137 "/org/freedesktop/timedate1",
138 "org.freedesktop.timedate1",
139 nullptr,
140 on_proxy_ready,
141 gself);
142 }
143
144 static void on_name_vanished(GDBusConnection *connection G_GNUC_UNUSED,
145 const gchar *name G_GNUC_UNUSED,
146 gpointer gself)
147 {
148 auto self = static_cast<Impl*>(gself);
149 g_debug ("timedate1 vanished");
150
151 g_signal_handler_disconnect(self->m_proxy,
152 self->m_properties_changed_id);
153 self->m_properties_changed_id = 0;
154 g_clear_object(&self->m_proxy);
155 g_clear_pointer(&self->m_proxy, g_main_loop_unref);
156 }
157
158 void monitor_timezone_property()
159 {
160 GError *err = nullptr;
161 GDBusConnection *conn;
162
163 /*
164 * There is an unlikely race which happens if there is an activation
165 * and timezone change before our match rule is added.
166 */
167 notify_timezone(get_timezone_from_file(m_filename));
168
169 /*
170 * Make sure the bus is around at least until we add the match rules,
171 * otherwise things (tests) are sad.
172 */
173 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM,
174 nullptr,
175 &err);
176
82 if (err)177 if (err)
83 {178 {
84 g_warning("%s Unable to monitor timezone file '%s': %s", G_STRLOC, TIMEZONE_FILE, err->message);179 g_warning("Couldn't get bus connection: '%s'", err->message);
85 g_error_free(err);180 g_error_free(err);
86 }181 return;
87 else182 }
88 {183
89 m_monitor_handler_id = g_signal_connect_swapped(m_monitor, "changed", G_CALLBACK(on_file_changed), this);184 m_bus_watch_id = g_bus_watch_name_on_connection(conn,
90 g_debug("%s Monitoring timezone file '%s'", G_STRLOC, m_filename.c_str());185 "org.freedesktop.timedate1",
91 }186 G_BUS_NAME_WATCHER_FLAGS_NONE,
92187 on_name_appeared,
93 reload();188 on_name_vanished,
94 }189 this,
95190 nullptr);
96 static void on_file_changed(gpointer gself)191
97 {192 g_object_unref (conn);
98 static_cast<Impl*>(gself)->reload();193 }
99 }194
100195 void notify_timezone(std::string new_timezone)
101 void reload()196 {
102 {197 g_debug("notify_timezone '%s'", new_timezone.c_str());
103 const auto new_timezone = get_timezone_from_file(m_filename);
104
105 if (!new_timezone.empty())198 if (!new_timezone.empty())
106 m_owner.timezone.set(new_timezone);199 m_owner.timezone.set(new_timezone);
107 }200 }
108201
109 /***
110 ****
111 ***/
112
113 std::string get_timezone_from_file(const std::string& filename)202 std::string get_timezone_from_file(const std::string& filename)
114 {203 {
115 GError * error;204 GError * error;
@@ -143,7 +232,9 @@
143 }232 }
144233
145 g_string_free(line, true);234 g_string_free(line, true);
146 }235 } else
236 /* Default to UTC */
237 ret = "Etc/Utc";
147238
148 if (io_channel != nullptr)239 if (io_channel != nullptr)
149 {240 {
@@ -164,22 +255,23 @@
164 ****255 ****
165 ***/256 ***/
166257
167 FileTimezone & m_owner;258 TimedatedTimezone & m_owner;
259 unsigned long m_properties_changed_id = 0;
260 unsigned long m_bus_watch_id = 0;
261 GDBusProxy *m_proxy = nullptr;
168 std::string m_filename;262 std::string m_filename;
169 GFileMonitor * m_monitor = nullptr;
170 unsigned long m_monitor_handler_id = 0;
171};263};
172264
173/***265/***
174****266****
175***/267***/
176268
177FileTimezone::FileTimezone(const std::string& filename):269TimedatedTimezone::TimedatedTimezone(std::string filename):
178 impl(new Impl{*this, filename})270 impl(new Impl{*this, filename})
179{271{
180}272}
181273
182FileTimezone::~FileTimezone()274TimedatedTimezone::~TimedatedTimezone()
183{275{
184}276}
185277
186278
=== modified file 'src/timezones-live.cpp'
--- src/timezones-live.cpp 2014-01-30 19:44:12 +0000
+++ src/timezones-live.cpp 2015-09-03 10:03:17 +0000
@@ -25,9 +25,8 @@
25namespace indicator {25namespace indicator {
26namespace datetime {26namespace datetime {
2727
28LiveTimezones::LiveTimezones(const std::shared_ptr<const Settings>& settings,28LiveTimezones::LiveTimezones(const std::shared_ptr<const Settings>& settings):
29 const std::string& filename):29 m_file(),
30 m_file(filename),
31 m_settings(settings)30 m_settings(settings)
32{31{
33 m_file.timezone.changed().connect([this](const std::string&){update_timezones();});32 m_file.timezone.changed().connect([this](const std::string&){update_timezones();});
3433
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2015-07-22 12:00:11 +0000
+++ tests/CMakeLists.txt 2015-09-03 10:03:17 +0000
@@ -58,7 +58,7 @@
58add_test_by_name(test-menus)58add_test_by_name(test-menus)
59add_test_by_name(test-planner)59add_test_by_name(test-planner)
60add_test_by_name(test-settings)60add_test_by_name(test-settings)
61add_test_by_name(test-timezone-file)61add_test_by_name(test-timezone-timedated)
62add_test_by_name(test-utils)62add_test_by_name(test-utils)
6363
64set (TEST_NAME manual-test-snap)64set (TEST_NAME manual-test-snap)
6565
=== modified file 'tests/test-live-actions.cpp'
--- tests/test-live-actions.cpp 2015-03-31 23:54:04 +0000
+++ tests/test-live-actions.cpp 2015-09-03 10:03:17 +0000
@@ -17,228 +17,18 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include <datetime/actions-live.h>20#include "timedated-fixture.h"
2121
22#include "state-mock.h"22/***
23#include "glib-fixture.h"23****
2424***/
25/***25
26****26TEST_F(TimedateFixture, HelloWorld)
27***/
28
29using namespace unity::indicator::datetime;
30
31class MockLiveActions: public LiveActions
32{
33public:
34 std::string last_cmd;
35 std::string last_url;
36 explicit MockLiveActions(const std::shared_ptr<State>& state_in): LiveActions(state_in) {}
37 ~MockLiveActions() {}
38
39protected:
40 void dispatch_url(const std::string& url) override { last_url = url; }
41 void execute_command(const std::string& cmd) override { last_cmd = cmd; }
42};
43
44/***
45****
46***/
47
48using namespace unity::indicator::datetime;
49
50class LiveActionsFixture: public GlibFixture
51{
52private:
53
54 typedef GlibFixture super;
55
56 static void on_bus_acquired(GDBusConnection* conn,
57 const gchar* name,
58 gpointer gself)
59 {
60 auto self = static_cast<LiveActionsFixture*>(gself);
61 g_debug("bus acquired: %s, connection is %p", name, conn);
62
63 // Set up a mock GSD.
64 // All it really does is wait for calls to GetDevice and
65 // returns the get_devices_retval variant
66 static const GDBusInterfaceVTable vtable = {
67 timedate1_handle_method_call,
68 nullptr, /* GetProperty */
69 nullptr, /* SetProperty */
70 };
71
72 self->connection = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(conn)));
73
74 GError* error = nullptr;
75 self->object_register_id = g_dbus_connection_register_object(
76 conn,
77 "/org/freedesktop/timedate1",
78 self->node_info->interfaces[0],
79 &vtable,
80 self,
81 nullptr,
82 &error);
83 g_assert_no_error(error);
84 }
85
86 static void on_name_acquired(GDBusConnection* /*conn*/,
87 const gchar* /*name*/,
88 gpointer gself)
89 {
90 auto self = static_cast<LiveActionsFixture*>(gself);
91 self->name_acquired = true;
92 g_main_loop_quit(self->loop);
93 }
94
95 static void on_name_lost(GDBusConnection* /*conn*/,
96 const gchar* /*name*/,
97 gpointer gself)
98 {
99 auto self = static_cast<LiveActionsFixture*>(gself);
100 self->name_acquired = false;
101 }
102
103 static void on_bus_closed(GObject* /*object*/,
104 GAsyncResult* res,
105 gpointer gself)
106 {
107 auto self = static_cast<LiveActionsFixture*>(gself);
108 GError* err = nullptr;
109 g_dbus_connection_close_finish(self->connection, res, &err);
110 g_assert_no_error(err);
111 g_main_loop_quit(self->loop);
112 }
113
114 static void
115 timedate1_handle_method_call(GDBusConnection * /*connection*/,
116 const gchar * /*sender*/,
117 const gchar * /*object_path*/,
118 const gchar * /*interface_name*/,
119 const gchar * method_name,
120 GVariant * parameters,
121 GDBusMethodInvocation * invocation,
122 gpointer gself)
123 {
124 g_assert(!g_strcmp0(method_name, "SetTimezone"));
125 g_assert(g_variant_is_of_type(parameters, G_VARIANT_TYPE_TUPLE));
126 g_assert(2 == g_variant_n_children(parameters));
127
128 auto child = g_variant_get_child_value(parameters, 0);
129 g_assert(g_variant_is_of_type(child, G_VARIANT_TYPE_STRING));
130 auto self = static_cast<LiveActionsFixture*>(gself);
131 self->attempted_tzid = g_variant_get_string(child, nullptr);
132 g_variant_unref(child);
133
134 g_dbus_method_invocation_return_value(invocation, nullptr);
135 g_main_loop_quit(self->loop);
136 }
137
138protected:
139
140 std::shared_ptr<MockState> m_mock_state;
141 std::shared_ptr<State> m_state;
142 std::shared_ptr<MockLiveActions> m_live_actions;
143 std::shared_ptr<Actions> m_actions;
144
145 bool name_acquired;
146 std::string attempted_tzid;
147
148 GTestDBus* bus;
149 guint own_name;
150 GDBusConnection* connection;
151 GDBusNodeInfo* node_info;
152 int object_register_id;
153
154 void SetUp()
155 {
156 super::SetUp();
157
158 name_acquired = false;
159 attempted_tzid.clear();
160 connection = nullptr;
161 node_info = nullptr;
162 object_register_id = 0;
163 own_name = 0;
164
165 // bring up the test bus
166 bus = g_test_dbus_new(G_TEST_DBUS_NONE);
167 g_test_dbus_up(bus);
168 const auto address = g_test_dbus_get_bus_address(bus);
169 g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true);
170 g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);
171 g_debug("test_dbus's address is %s", address);
172
173 // parse the org.freedesktop.timedate1 interface
174 const gchar introspection_xml[] =
175 "<node>"
176 " <interface name='org.freedesktop.timedate1'>"
177 " <method name='SetTimezone'>"
178 " <arg name='timezone' type='s' direction='in'/>"
179 " <arg name='user_interaction' type='b' direction='in'/>"
180 " </method>"
181 " </interface>"
182 "</node>";
183 node_info = g_dbus_node_info_new_for_xml(introspection_xml, nullptr);
184 ASSERT_TRUE(node_info != nullptr);
185 ASSERT_TRUE(node_info->interfaces != nullptr);
186 ASSERT_TRUE(node_info->interfaces[0] != nullptr);
187 ASSERT_TRUE(node_info->interfaces[1] == nullptr);
188 ASSERT_STREQ("org.freedesktop.timedate1", node_info->interfaces[0]->name);
189
190 // own the bus
191 own_name = g_bus_own_name(G_BUS_TYPE_SYSTEM,
192 "org.freedesktop.timedate1",
193 G_BUS_NAME_OWNER_FLAGS_NONE,
194 on_bus_acquired, on_name_acquired, on_name_lost,
195 this, nullptr);
196 ASSERT_TRUE(object_register_id == 0);
197 ASSERT_FALSE(name_acquired);
198 ASSERT_TRUE(connection == nullptr);
199 g_main_loop_run(loop);
200 ASSERT_TRUE(object_register_id != 0);
201 ASSERT_TRUE(name_acquired);
202 ASSERT_TRUE(G_IS_DBUS_CONNECTION(connection));
203
204 // create the State and Actions
205 m_mock_state.reset(new MockState);
206 m_mock_state->settings.reset(new Settings);
207 m_state = std::dynamic_pointer_cast<State>(m_mock_state);
208 m_live_actions.reset(new MockLiveActions(m_state));
209 m_actions = std::dynamic_pointer_cast<Actions>(m_live_actions);
210 }
211
212 void TearDown()
213 {
214 m_actions.reset();
215 m_live_actions.reset();
216 m_state.reset();
217 m_mock_state.reset();
218
219 g_dbus_connection_unregister_object(connection, object_register_id);
220 g_dbus_node_info_unref(node_info);
221 g_bus_unown_name(own_name);
222 g_dbus_connection_close(connection, nullptr, on_bus_closed, this);
223 g_main_loop_run(loop);
224 g_clear_object(&connection);
225 g_test_dbus_down(bus);
226 g_clear_object(&bus);
227
228 super::TearDown();
229 }
230};
231
232/***
233****
234***/
235
236TEST_F(LiveActionsFixture, HelloWorld)
237{27{
238 EXPECT_TRUE(true);28 EXPECT_TRUE(true);
239}29}
24030
241TEST_F(LiveActionsFixture, SetLocation)31TEST_F(TimedateFixture, SetLocation)
242{32{
243 const std::string tzid = "America/Chicago";33 const std::string tzid = "America/Chicago";
244 const std::string name = "Oklahoma City";34 const std::string name = "Oklahoma City";
@@ -247,6 +37,10 @@
247 EXPECT_NE(expected, m_state->settings->timezone_name.get());37 EXPECT_NE(expected, m_state->settings->timezone_name.get());
24838
249 m_actions->set_location(tzid, name);39 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 });
250 g_main_loop_run(loop);44 g_main_loop_run(loop);
251 EXPECT_EQ(attempted_tzid, tzid);45 EXPECT_EQ(attempted_tzid, tzid);
252 wait_msec();46 wait_msec();
@@ -258,14 +52,14 @@
258****52****
259***/53***/
26054
261TEST_F(LiveActionsFixture, DesktopOpenAlarmApp)55TEST_F(TimedateFixture, DesktopOpenAlarmApp)
262{56{
263 m_actions->desktop_open_alarm_app();57 m_actions->desktop_open_alarm_app();
264 const std::string expected = "evolution -c calendar";58 const std::string expected = "evolution -c calendar";
265 EXPECT_EQ(expected, m_live_actions->last_cmd);59 EXPECT_EQ(expected, m_live_actions->last_cmd);
266}60}
26761
268TEST_F(LiveActionsFixture, DesktopOpenAppointment)62TEST_F(TimedateFixture, DesktopOpenAppointment)
269{63{
270 Appointment a;64 Appointment a;
271 a.uid = "some-uid";65 a.uid = "some-uid";
@@ -275,14 +69,14 @@
275 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);69 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);
276}70}
27771
278TEST_F(LiveActionsFixture, DesktopOpenCalendarApp)72TEST_F(TimedateFixture, DesktopOpenCalendarApp)
279{73{
280 m_actions->desktop_open_calendar_app(DateTime::NowLocal());74 m_actions->desktop_open_calendar_app(DateTime::NowLocal());
281 const std::string expected_substr = "evolution \"calendar:///?startdate=";75 const std::string expected_substr = "evolution \"calendar:///?startdate=";
282 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);76 EXPECT_NE(m_live_actions->last_cmd.find(expected_substr), std::string::npos);
283}77}
28478
285TEST_F(LiveActionsFixture, DesktopOpenSettingsApp)79TEST_F(TimedateFixture, DesktopOpenSettingsApp)
286{80{
287 m_actions->desktop_open_settings_app();81 m_actions->desktop_open_settings_app();
288 const std::string expected_substr = "control-center";82 const std::string expected_substr = "control-center";
@@ -300,13 +94,13 @@
300 const std::string calendar_app_url = "appid://com.ubuntu.calendar/calendar/current-user-version";94 const std::string calendar_app_url = "appid://com.ubuntu.calendar/calendar/current-user-version";
301}95}
30296
303TEST_F(LiveActionsFixture, PhoneOpenAlarmApp)97TEST_F(TimedateFixture, PhoneOpenAlarmApp)
304{98{
305 m_actions->phone_open_alarm_app();99 m_actions->phone_open_alarm_app();
306 EXPECT_EQ(clock_app_url, m_live_actions->last_url);100 EXPECT_EQ(clock_app_url, m_live_actions->last_url);
307}101}
308102
309TEST_F(LiveActionsFixture, PhoneOpenAppointment)103TEST_F(TimedateFixture, PhoneOpenAppointment)
310{104{
311 Appointment a;105 Appointment a;
312106
@@ -321,14 +115,14 @@
321 EXPECT_EQ(clock_app_url, m_live_actions->last_url);115 EXPECT_EQ(clock_app_url, m_live_actions->last_url);
322}116}
323117
324TEST_F(LiveActionsFixture, PhoneOpenCalendarApp)118TEST_F(TimedateFixture, PhoneOpenCalendarApp)
325{119{
326 m_actions->phone_open_calendar_app(DateTime::NowLocal());120 m_actions->phone_open_calendar_app(DateTime::NowLocal());
327 const std::string expected = "appid://com.ubuntu.calendar/calendar/current-user-version";121 const std::string expected = "appid://com.ubuntu.calendar/calendar/current-user-version";
328 EXPECT_EQ(expected, m_live_actions->last_url);122 EXPECT_EQ(expected, m_live_actions->last_url);
329}123}
330124
331TEST_F(LiveActionsFixture, PhoneOpenSettingsApp)125TEST_F(TimedateFixture, PhoneOpenSettingsApp)
332{126{
333 m_actions->phone_open_settings_app();127 m_actions->phone_open_settings_app();
334 const std::string expected = "settings:///system/time-date";128 const std::string expected = "settings:///system/time-date";
@@ -339,7 +133,7 @@
339****133****
340***/134***/
341135
342TEST_F(LiveActionsFixture, CalendarState)136TEST_F(TimedateFixture, CalendarState)
343{137{
344 // init the clock138 // init the clock
345 auto now = DateTime::Local(2014, 1, 1, 0, 0, 0);139 auto now = DateTime::Local(2014, 1, 1, 0, 0, 0);
346140
=== renamed file 'tests/test-timezone-file.cpp' => 'tests/test-timezone-timedated.cpp'
--- tests/test-timezone-file.cpp 2014-09-17 16:51:51 +0000
+++ tests/test-timezone-timedated.cpp 2015-09-03 10:03:17 +0000
@@ -18,25 +18,11 @@
18 * with this program. If not, see <http://www.gnu.org/licenses/>.18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */19 */
2020
21#include "glib-fixture.h"21#include "timedated-fixture.h"
2222
23#include <datetime/timezone-file.h>23#include <datetime/timezone-timedated.h>
2424
25//#include <condition_variable>25using unity::indicator::datetime::TimedatedTimezone;
26//#include <mutex>
27//#include <queue>
28//#include <string>
29//#include <thread>
30//#include <iostream>
31//#include <istream>
32//#include <fstream>
33
34#include <cstdio> // fopen()
35//#include <sys/stat.h> // chmod()
36#include <unistd.h> // sync()
37
38using unity::indicator::datetime::FileTimezone;
39
4026
41/***27/***
42****28****
@@ -44,11 +30,11 @@
4430
45#define TIMEZONE_FILE (SANDBOX"/timezone")31#define TIMEZONE_FILE (SANDBOX"/timezone")
4632
47class TimezoneFixture: public GlibFixture33class TimezoneFixture: public TimedateFixture
48{34{
49 private:35 private:
5036
51 typedef GlibFixture super;37 typedef TimedateFixture super;
5238
53 protected:39 protected:
5440
@@ -67,6 +53,7 @@
67 /* convenience func to set the timezone file */53 /* convenience func to set the timezone file */
68 void set_file(const std::string& text)54 void set_file(const std::string& text)
69 {55 {
56 g_debug("set_file %s %s", TIMEZONE_FILE, text.c_str());
70 auto fp = fopen(TIMEZONE_FILE, "w+");57 auto fp = fopen(TIMEZONE_FILE, "w+");
71 fprintf(fp, "%s\n", text.c_str());58 fprintf(fp, "%s\n", text.c_str());
72 fclose(fp);59 fclose(fp);
@@ -74,46 +61,56 @@
74 }61 }
75};62};
7663
77
78/**64/**
79 * Test that timezone-file warns, but doesn't crash, if the timezone file doesn't exist65 * Test that timezone-timedated warns, but doesn't crash, if the timezone file doesn't exist
80 */66 */
81TEST_F(TimezoneFixture, NoFile)67TEST_F(TimezoneFixture, NoFile)
82{68{
83 remove(TIMEZONE_FILE);69 remove(TIMEZONE_FILE);
84 ASSERT_FALSE(g_file_test(TIMEZONE_FILE, G_FILE_TEST_EXISTS));70 ASSERT_FALSE(g_file_test(TIMEZONE_FILE, G_FILE_TEST_EXISTS));
8571
86 FileTimezone tz(TIMEZONE_FILE);72 TimedatedTimezone tz(TIMEZONE_FILE);
87 testLogCount(G_LOG_LEVEL_WARNING, 1);73 testLogCount(G_LOG_LEVEL_WARNING, 1);
88}74}
8975
9076/**
91/**77 * Test that timezone-timedated gives a default of UTC if the file doesn't exist
92 * Test that timezone-file picks up the initial value78 */
79TEST_F(TimezoneFixture, DefaultValueNoFile)
80{
81 const std::string expected_timezone = "Etc/Utc";
82 remove(TIMEZONE_FILE);
83 ASSERT_FALSE(g_file_test(TIMEZONE_FILE, G_FILE_TEST_EXISTS));
84
85 TimedatedTimezone tz(TIMEZONE_FILE);
86 ASSERT_EQ(expected_timezone, tz.timezone.get());
87}
88
89/**
90 * Test that timezone-timedated picks up the initial value
93 */91 */
94TEST_F(TimezoneFixture, InitialValue)92TEST_F(TimezoneFixture, InitialValue)
95{93{
96 const std::string expected_timezone = "America/Chicago";94 const std::string expected_timezone = "America/Chicago";
97 set_file(expected_timezone);95 set_file(expected_timezone);
98 FileTimezone tz(TIMEZONE_FILE);96 TimedatedTimezone tz(TIMEZONE_FILE);
99 ASSERT_EQ(expected_timezone, tz.timezone.get());
100}97}
10198
102
103/**99/**
104 * Test that clearing the timezone results in an empty string100 * Test that changing the tz after we are running works.
105 */101 */
106TEST_F(TimezoneFixture, ChangedValue)102TEST_F(TimezoneFixture, ChangedValue)
107{103{
108 const std::string initial_timezone = "America/Chicago";104 const std::string initial_timezone = "America/Chicago";
109 const std::string changed_timezone = "America/New_York";105 const std::string changed_timezone = "America/New_York";
106
110 set_file(initial_timezone);107 set_file(initial_timezone);
111108
112 FileTimezone tz(TIMEZONE_FILE);109 TimedatedTimezone tz(TIMEZONE_FILE);
113 ASSERT_EQ(initial_timezone, tz.timezone.get());110 ASSERT_EQ(initial_timezone, tz.timezone.get());
114111
115 bool changed = false;112 bool changed = false;
116 auto connection = tz.timezone.changed().connect(113 tz.timezone.changed().connect(
117 [&changed, this](const std::string& s){114 [&changed, this](const std::string& s){
118 g_message("timezone changed to %s", s.c_str());115 g_message("timezone changed to %s", s.c_str());
119 changed = true;116 changed = true;
@@ -121,10 +118,9 @@
121 });118 });
122119
123 g_idle_add([](gpointer gself){120 g_idle_add([](gpointer gself){
124 static_cast<TimezoneFixture*>(gself)->set_file("America/New_York");121 static_cast<TimedateFixture*>(gself)->set_timezone("America/New_York");
125 // static_cast<FileTimezone*>(gtz)->timezone.set("America/New_York");
126 return G_SOURCE_REMOVE;122 return G_SOURCE_REMOVE;
127 }, this);//&tz);123 }, this);
128124
129 g_main_loop_run(loop);125 g_main_loop_run(loop);
130126
@@ -132,15 +128,14 @@
132 ASSERT_EQ(changed_timezone, tz.timezone.get());128 ASSERT_EQ(changed_timezone, tz.timezone.get());
133}129}
134130
135
136/**131/**
137 * Test that timezone-file picks up the initial value132 * Test that timezone-timedated picks up the initial value
138 */133 */
139TEST_F(TimezoneFixture, IgnoreComments)134TEST_F(TimezoneFixture, IgnoreComments)
140{135{
141 const std::string comment = "# Created by cloud-init v. 0.7.5 on Thu, 24 Apr 2014 14:03:29 +0000";136 const std::string comment = "# Created by cloud-init v. 0.7.5 on Thu, 24 Apr 2014 14:03:29 +0000";
142 const std::string expected_timezone = "Europe/Berlin";137 const std::string expected_timezone = "Europe/Berlin";
143 set_file(comment + "\n" + expected_timezone);138 set_file(comment + "\n" + expected_timezone);
144 FileTimezone tz(TIMEZONE_FILE);139 TimedatedTimezone tz(TIMEZONE_FILE);
145 ASSERT_EQ(expected_timezone, tz.timezone.get());140 ASSERT_EQ(expected_timezone, tz.timezone.get());
146}141}
147142
=== added file 'tests/timedated-fixture.h'
--- tests/timedated-fixture.h 1970-01-01 00:00:00 +0000
+++ tests/timedated-fixture.h 2015-09-03 10:03:17 +0000
@@ -0,0 +1,301 @@
1/*
2 * Copyright 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef INDICATOR_DATETIME_TESTS_TIMEDATED_FIXTURE_H
21#define INDICATOR_DATETIME_TESTS_TIMEDATED_FIXTURE_H
22
23#include <datetime/actions-live.h>
24
25#include "state-mock.h"
26#include "glib-fixture.h"
27
28using namespace unity::indicator::datetime;
29
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};
42
43/***
44****
45***/
46
47using namespace unity::indicator::datetime;
48
49class TimedateFixture: public GlibFixture
50{
51private:
52
53 typedef GlibFixture super;
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 }
187
188protected:
189
190 std::shared_ptr<MockState> m_mock_state;
191 std::shared_ptr<State> m_state;
192 std::shared_ptr<MockLiveActions> m_live_actions;
193 std::shared_ptr<Actions> m_actions;
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 {
207 super::SetUp();
208 g_debug("SetUp");
209
210 name_acquired = false;
211 attempted_tzid.clear();
212 connection = nullptr;
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);
223 g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);
224 g_debug("test_dbus's address is %s", address);
225
226 // parse the org.freedesktop.timedate1 interface
227 const gchar introspection_xml[] =
228 "<node>"
229 " <interface name='org.freedesktop.timedate1'>"
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 }
265
266 void TearDown()
267 {
268 g_debug("TearDown");
269 m_actions.reset();
270 m_live_actions.reset();
271 m_state.reset();
272 m_mock_state.reset();
273 g_dbus_connection_unregister_object(connection, object_register_id);
274 g_object_unref(proxy);
275 g_dbus_node_info_unref(node_info);
276 g_bus_unown_name(own_name);
277 g_dbus_connection_close(connection, nullptr, on_bus_closed, this);
278 g_main_loop_run(loop);
279 g_clear_object(&connection);
280 g_test_dbus_down(bus);
281 g_clear_object(&bus);
282
283 super::TearDown();
284 }
285public:
286 void set_timezone(std::string tz)
287 {
288 g_debug("set_timezone: '%s'", tz.c_str());
289 g_dbus_proxy_call_sync(proxy,
290 "SetTimezone",
291 g_variant_new("(sb)",
292 tz.c_str(),
293 FALSE),
294 G_DBUS_CALL_FLAGS_NONE,
295 500,
296 nullptr,
297 nullptr);
298 }
299};
300
301#endif

Subscribers

People subscribed via source and target branches