Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright © 2018 Endless Mobile, Inc.
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Lesser General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2.1 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : : *
19 : : * Authors:
20 : : * - Philip Withnall <withnall@endlessm.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include <glib.h>
26 : : #include <glib-object.h>
27 : : #include <glib/gi18n-lib.h>
28 : : #include <gio/gio.h>
29 : : #include <libmogwai-schedule/connection-monitor.h>
30 : : #include <libmogwai-schedule/tests/connection-monitor-dummy.h>
31 : :
32 : :
33 : : static void
34 : 307 : connection_details_copy (const MwsConnectionDetails *details,
35 : : MwsConnectionDetails *copy)
36 : : {
37 : 307 : copy->metered = details->metered;
38 : 307 : copy->allow_downloads_when_metered = details->allow_downloads_when_metered;
39 : 307 : copy->allow_downloads = details->allow_downloads;
40 [ + + ]: 307 : copy->tariff = (details->tariff != NULL) ? g_object_ref (details->tariff) : NULL;
41 : 307 : }
42 : :
43 : : static void
44 : 105 : connection_details_free (MwsConnectionDetails *details)
45 : : {
46 : 105 : mws_connection_details_clear (details);
47 : 105 : g_free (details);
48 : 105 : }
49 : :
50 : : static void mws_connection_monitor_dummy_connection_monitor_init (MwsConnectionMonitorInterface *iface);
51 : :
52 : : static void mws_connection_monitor_dummy_finalize (GObject *object);
53 : :
54 : : static const gchar * const *mws_connection_monitor_dummy_get_connection_ids (MwsConnectionMonitor *monitor);
55 : : static gboolean mws_connection_monitor_dummy_get_connection_details (MwsConnectionMonitor *monitor,
56 : : const gchar *id,
57 : : MwsConnectionDetails *out_details);
58 : :
59 : : /**
60 : : * MwsConnectionMonitorDummy:
61 : : *
62 : : * An implementation of the #MwsConnectionMonitor interface which returns dummy
63 : : * results provided using mws_connection_monitor_dummy_update_connections() and
64 : : * mws_connection_monitor_dummy_update_connection(). To be used for testing
65 : : * only.
66 : : *
67 : : * Since: 0.1.0
68 : : */
69 : : struct _MwsConnectionMonitorDummy
70 : : {
71 : : GObject parent;
72 : :
73 : : GHashTable *connections; /* (owned) (element-type utf8 MwsConnectionDetails) */
74 : : const gchar **cached_connection_ids; /* (owned) (nullable) */
75 : : };
76 : :
77 [ + + + - : 730 : G_DEFINE_TYPE_WITH_CODE (MwsConnectionMonitorDummy, mws_connection_monitor_dummy, G_TYPE_OBJECT,
+ + ]
78 : : G_IMPLEMENT_INTERFACE (MWS_TYPE_CONNECTION_MONITOR,
79 : : mws_connection_monitor_dummy_connection_monitor_init))
80 : : static void
81 : 2 : mws_connection_monitor_dummy_class_init (MwsConnectionMonitorDummyClass *klass)
82 : : {
83 : 2 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
84 : :
85 : 2 : object_class->finalize = mws_connection_monitor_dummy_finalize;
86 : 2 : }
87 : :
88 : : static void
89 : 2 : mws_connection_monitor_dummy_connection_monitor_init (MwsConnectionMonitorInterface *iface)
90 : : {
91 : 2 : iface->get_connection_ids = mws_connection_monitor_dummy_get_connection_ids;
92 : 2 : iface->get_connection_details = mws_connection_monitor_dummy_get_connection_details;
93 : 2 : }
94 : :
95 : : static void
96 : 48 : mws_connection_monitor_dummy_init (MwsConnectionMonitorDummy *self)
97 : : {
98 : 48 : self->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
99 : : (GDestroyNotify) connection_details_free);
100 : 48 : self->cached_connection_ids = NULL;
101 : 48 : }
102 : :
103 : : static void
104 : 47 : mws_connection_monitor_dummy_finalize (GObject *object)
105 : : {
106 : 47 : MwsConnectionMonitorDummy *self = MWS_CONNECTION_MONITOR_DUMMY (object);
107 : :
108 [ + - ]: 47 : g_clear_pointer (&self->connections, g_hash_table_unref);
109 [ + - ]: 47 : g_clear_pointer (&self->cached_connection_ids, g_free);
110 : :
111 : 47 : G_OBJECT_CLASS (mws_connection_monitor_dummy_parent_class)->finalize (object);
112 : 47 : }
113 : :
114 : : static const gchar * const *
115 : 235 : mws_connection_monitor_dummy_get_connection_ids (MwsConnectionMonitor *monitor)
116 : : {
117 : 235 : MwsConnectionMonitorDummy *self = MWS_CONNECTION_MONITOR_DUMMY (monitor);
118 : :
119 [ + + ]: 235 : if (self->cached_connection_ids == NULL)
120 : 145 : self->cached_connection_ids =
121 : 145 : (const gchar **) g_hash_table_get_keys_as_array (self->connections, NULL);
122 : :
123 : 235 : return self->cached_connection_ids;
124 : : }
125 : :
126 : : static gboolean
127 : 202 : mws_connection_monitor_dummy_get_connection_details (MwsConnectionMonitor *monitor,
128 : : const gchar *id,
129 : : MwsConnectionDetails *out_details)
130 : : {
131 : 202 : MwsConnectionMonitorDummy *self = MWS_CONNECTION_MONITOR_DUMMY (monitor);
132 : :
133 : 202 : const MwsConnectionDetails *found_details = g_hash_table_lookup (self->connections, id);
134 : :
135 [ + - ]: 202 : if (found_details != NULL)
136 : : {
137 : 202 : connection_details_copy (found_details, out_details);
138 : 202 : return TRUE;
139 : : }
140 : : else
141 : : {
142 : 0 : return FALSE;
143 : : }
144 : : }
145 : :
146 : : /**
147 : : * mws_connection_monitor_dummy_new:
148 : : *
149 : : * Create a #MwsConnectionMonitorDummy object.
150 : : *
151 : : * Returns: (transfer full): a new #MwsConnectionMonitorDummy
152 : : * Since: 0.1.0
153 : : */
154 : : MwsConnectionMonitorDummy *
155 : 48 : mws_connection_monitor_dummy_new (void)
156 : : {
157 : 48 : return g_object_new (MWS_TYPE_CONNECTION_MONITOR_DUMMY, NULL);
158 : : }
159 : :
160 : : /**
161 : : * mws_connection_monitor_dummy_update_connections:
162 : : * @self: a #MwsConnectionMonitorDummy
163 : : * @added: (element-type utf8 MwsConnectionDetails) (transfer none) (nullable):
164 : : * mock connections to add to the connection monitor, mapping connection ID
165 : : * to connection details, or %NULL to not add any
166 : : * @removed: (element-type utf8) (transfer none) (nullable): connection IDs of
167 : : * mock connections to remove from the connection monitor, or %NULL to not
168 : : * remove any
169 : : *
170 : : * Update the set of mock connections exported by the connection monitor,
171 : : * removing those in @removed and then adding those in @added. It is an error to
172 : : * try to remove a connection ID which is not currently in the connection
173 : : * monitor; similarly, it is an error to try to add a connection ID which
174 : : * already exists in the connection monitor.
175 : : *
176 : : * If @added or @removed were non-empty,
177 : : * #MwsConnectionMonitor::connections-changed is emitted after all changes have
178 : : * been made.
179 : : *
180 : : * Since: 0.1.0
181 : : */
182 : : void
183 : 27 : mws_connection_monitor_dummy_update_connections (MwsConnectionMonitorDummy *self,
184 : : GHashTable *added,
185 : : GPtrArray *removed)
186 : : {
187 [ - + ]: 27 : g_return_if_fail (MWS_IS_CONNECTION_MONITOR_DUMMY (self));
188 : :
189 : 54 : g_autoptr(GPtrArray) actually_added = g_ptr_array_new_with_free_func (NULL);
190 : 54 : g_autoptr(GPtrArray) actually_removed = g_ptr_array_new_with_free_func (NULL);
191 : :
192 [ - + - - ]: 27 : for (gsize i = 0; removed != NULL && i < removed->len; i++)
193 : : {
194 : 0 : const gchar *id = g_ptr_array_index (removed, i);
195 [ # # ]: 0 : g_assert (g_hash_table_remove (self->connections, id));
196 : 0 : g_ptr_array_add (actually_removed, id);
197 : : }
198 : :
199 [ + - ]: 27 : if (added != NULL)
200 : : {
201 : : GHashTableIter iter;
202 : : gpointer key, value;
203 : 27 : g_hash_table_iter_init (&iter, added);
204 : :
205 [ + + ]: 62 : while (g_hash_table_iter_next (&iter, &key, &value))
206 : : {
207 : 35 : const gchar *id = key;
208 : 35 : const MwsConnectionDetails *details = value;
209 : :
210 : : /* Note: We don’t do autoptrs properly here, because #MwsConnectionDetails
211 : : * is supposed to be stack allocated. */
212 : 35 : MwsConnectionDetails *details_copy = g_new0 (MwsConnectionDetails, 1);
213 : 35 : connection_details_copy (details, details_copy);
214 : :
215 [ - + ]: 35 : g_assert (g_hash_table_insert (self->connections, g_strdup (id), g_steal_pointer (&details_copy)));
216 : 35 : g_ptr_array_add (actually_added, id);
217 : : }
218 : : }
219 : :
220 [ - + - - ]: 27 : if (actually_added->len > 0 || actually_removed->len > 0)
221 : : {
222 [ + - ]: 27 : g_clear_pointer (&self->cached_connection_ids, g_free);
223 : 27 : g_signal_emit_by_name (self, "connections-changed", actually_added, actually_removed);
224 : : }
225 : : }
226 : :
227 : : /**
228 : : * mws_connection_monitor_dummy_update_connection:
229 : : * @self: a #MwsConnectionMonitorDummy
230 : : * @connection_id: ID of the connection to update
231 : : * @details: new details for the connection
232 : : *
233 : : * Update the details of the existing connection identified by @connection_id
234 : : * in the connection monitor.
235 : : *
236 : : * It is an error to call this with a @connection_id which does not exist in the
237 : : * connection monitor.
238 : : *
239 : : * The #MwsConnectionMonitor::connection-details-changed signal will be emitted
240 : : * once the changes have been made in the connection monitor.
241 : : *
242 : : * Since: 0.1.0
243 : : */
244 : : void
245 : 70 : mws_connection_monitor_dummy_update_connection (MwsConnectionMonitorDummy *self,
246 : : const gchar *connection_id,
247 : : const MwsConnectionDetails *details)
248 : : {
249 [ - + ]: 70 : g_return_if_fail (MWS_IS_CONNECTION_MONITOR_DUMMY (self));
250 [ - + ]: 70 : g_return_if_fail (connection_id != NULL);
251 [ - + ]: 70 : g_return_if_fail (details != NULL);
252 : :
253 [ - + ]: 70 : g_assert (g_hash_table_lookup (self->connections, connection_id) != NULL);
254 : :
255 : : /* Note: We don’t do autoptrs properly here, because #MwsConnectionDetails
256 : : * is supposed to be stack allocated. */
257 : 70 : MwsConnectionDetails *details_copy = g_new0 (MwsConnectionDetails, 1);
258 : 70 : connection_details_copy (details, details_copy);
259 : :
260 [ - + ]: 70 : g_assert (!g_hash_table_replace (self->connections, g_strdup (connection_id),
261 : : g_steal_pointer (&details_copy)));
262 : :
263 [ + - ]: 70 : g_clear_pointer (&self->cached_connection_ids, g_free);
264 : 70 : g_signal_emit_by_name (self, "connection-details-changed", connection_id);
265 : : }
|