Merge lp:~gordallott/unity/unity-ubus into lp:unity

Proposed by Gord Allott
Status: Merged
Approved by: Neil J. Patel
Approved revision: no longer in the source branch.
Merged at revision: 629
Proposed branch: lp:~gordallott/unity/unity-ubus
Merge into: lp:unity
Diff against target: 786 lines (+611/-15)
7 files modified
libunity/CMakeLists.txt (+1/-1)
libunity/ubus-server.c (+361/-0)
libunity/ubus-server.h (+74/-0)
services/panel-service.c (+16/-12)
tests/CMakeLists.txt (+4/-1)
tests/unit/TestMain.cpp (+3/-1)
tests/unit/TestUBus.cpp (+152/-0)
To merge this branch: bzr merge lp:~gordallott/unity/unity-ubus
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Review via email: mp+41856@code.launchpad.net

Description of the change

adds UBus Support into unity, a simple message broadcasting service to allow for simple inter component communication without introducing dependencies.

Comes with tests because tests are awesome

To post a comment you must log in.
Revision history for this message
Neil J. Patel (njpatel) wrote :

- g_hash_table_destroy does what you want it to and won't break if they use g_slice to allocate hashtable struct in the future

- Tab indenting in a bunch of places

- The first server you create has a ref count of 2 because it's not initially unowned (hence returns from g_object_new with ref_count = 1) and then your ref it again before retuning; Maybe make it derive from GInitiallyUnowned and return g_object_ref_sink (service)

- Like the singleton approach, haven't seen that in a while ;)

review: Needs Fixing
Revision history for this message
Gord Allott (gordallott) wrote :

fixed the hash tab indenting
regarding the reference counting, I think its best to just hold on to our own reference and own it completely, no real reason to start increasing/decreasing the reference count because we can only initialize the object once in the programs lifetime. we want it to stick around :) so i'm just holding on to one reference now and not passing any back to whatever calls get_default ()

Revision history for this message
Neil J. Patel (njpatel) :
review: Approve
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

+UBusMessageInfo *
+ubus_message_info_new (const gchar *message, GVariant *data)
+{
+ UBusMessageInfo *info = g_new (UBusMessageInfo, 1);
+ info->message = g_strdup (message);
+ info->data = data;
+
+ if (data != NULL)
+ g_variant_ref (data);
+ return info;
+}

You probably want to g_variant_ref_sink() instead so one can pass a
floating ref to send() without leaking.

+ if (info->data != NULL)
+ g_variant_unref (info->data);
+ g_free (info);

You're leaking the message string. Why not use the
ubus_message_info_free() function you implemented above?

Static modifiers are missing on all private functions in the .c files.
Right now you exporting all the unnamespaced utility functions.

If we expect the message names to not contain variations like
"unity_msg_N" for random 0 < N < 9999999999 then, ie. constant string
like "Unity.ShowDash", then it's a big waste go g_strdup() the message
in the UBusMessageInfo constructor. Just use a GStringChunk and save
all the reallocations.

Other than that nice work :-)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libunity/CMakeLists.txt'
--- libunity/CMakeLists.txt 2010-11-19 12:06:29 +0000
+++ libunity/CMakeLists.txt 2010-11-25 14:26:39 +0000
@@ -56,7 +56,7 @@
56 GENERATE_VAPI unity56 GENERATE_VAPI unity
57)57)
5858
59add_library (${PKGNAME} SHARED ${VALA_C})59add_library (${PKGNAME} SHARED ${VALA_C} ubus-server.c)
60set_target_properties (${PKGNAME} PROPERTIES60set_target_properties (${PKGNAME} PROPERTIES
61 VERSION ${libunity_VERSION}61 VERSION ${libunity_VERSION}
62 SOVERSION ${libunity_SOVERSION}62 SOVERSION ${libunity_SOVERSION}
6363
=== added file 'libunity/ubus-server.c'
--- libunity/ubus-server.c 1970-01-01 00:00:00 +0000
+++ libunity/ubus-server.c 2010-11-25 14:26:39 +0000
@@ -0,0 +1,361 @@
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2/*
3 * u-bus-server.c
4 * Copyright (C) 2010 Canonical, Ltd.
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License
8 * version 3.0 as published by the Free Software Foundation.
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
13 * GNU Lesser General Public License version 3.0 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, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * Authored by Gordon Allott <gord.allott@canonical.com>
20 */
21
22#include "ubus-server.h"
23#include <string.h>
24#include <stdlib.h>
25#include <glib.h>
26
27#define UBUS_SERVER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
28 UBUS_TYPE_SERVER, \
29 UBusServerPrivate))
30
31struct _UBusServerPrivate
32{
33 GHashTable *message_interest_table;
34 GHashTable *dispatch_table;
35
36 GQueue *message_queue;
37
38 gulong id_sequencial_number;
39 gboolean message_pump_queued;
40};
41
42
43G_DEFINE_TYPE (UBusServer, ubus_server, G_TYPE_INITIALLY_UNOWNED);
44
45struct _UBusDispatchInfo
46{
47 gulong id;
48 UBusCallback callback;
49 gchar *message;
50 gpointer *user_data;
51};
52typedef struct _UBusDispatchInfo UBusDispatchInfo;
53
54UBusDispatchInfo *
55ubus_dispatch_info_new (UBusServer* server, const gchar *message,
56 UBusCallback callback, gpointer user_data)
57{
58 g_return_val_if_fail (UBUS_IS_SERVER (server), NULL);
59 UBusServerPrivate *priv = server->priv;
60 UBusDispatchInfo *info;
61
62 if (priv->id_sequencial_number < 1)
63 {
64 g_critical (G_STRLOC ": ID's are overflowing");
65 }
66
67 info = g_new (UBusDispatchInfo, 1);
68 info->id = priv->id_sequencial_number++;
69 info->callback = callback;
70 info->message = g_strdup (message);
71 info->user_data = user_data;
72
73 return info;
74}
75
76void
77ubus_dispatch_info_free (UBusDispatchInfo *info)
78{
79 g_free (info->message);
80 g_free (info);
81}
82
83struct _UBusMessageInfo
84{
85 gchar *message;
86 GVariant *data;
87};
88
89typedef struct _UBusMessageInfo UBusMessageInfo;
90
91UBusMessageInfo *
92ubus_message_info_new (const gchar *message, GVariant *data)
93{
94 UBusMessageInfo *info = g_new (UBusMessageInfo, 1);
95 info->message = g_strdup (message);
96 info->data = data;
97
98 if (data != NULL)
99 g_variant_ref (data);
100 return info;
101}
102
103void
104ubus_message_info_free (UBusMessageInfo *info)
105{
106 g_variant_unref (info->data);
107 g_free (info->message);
108 g_free (info);
109}
110
111gboolean
112ulong_equal (gconstpointer v1,
113 gconstpointer v2)
114{
115 return *((const gulong*) v1) == *((const gulong*) v2);
116}
117
118guint
119ulong_hash (gconstpointer v)
120{
121 return (guint) *(const gulong*) v;
122}
123
124static void
125ubus_server_init (UBusServer *server)
126{
127 UBusServerPrivate *priv;
128 priv = server->priv = UBUS_SERVER_GET_PRIVATE (server);
129
130 // message_interest_table holds the message/DispatchInfo relationship
131 priv->message_interest_table = g_hash_table_new_full (g_str_hash, g_str_equal,
132 g_free,
133 (GDestroyNotify)g_sequence_free);
134 // dispatch table holds the individial id/DispatchInfo pairs
135 priv->dispatch_table = g_hash_table_new_full (ulong_hash, ulong_equal,
136 g_free,
137 (GDestroyNotify)ubus_dispatch_info_free);
138
139 // for anyone thats wondering (hi kamstrup!), there are two hash tables so
140 // that lookups are fast when sending messages and removing handlers
141
142 priv->message_queue = g_queue_new ();
143 priv->id_sequencial_number = 1;
144}
145
146static void
147ubus_server_finalize (GObject *object)
148{
149 UBusServer *server = UBUS_SERVER (object);
150 UBusServerPrivate *priv = server->priv;
151 g_hash_table_destroy (priv->message_interest_table);
152 g_hash_table_destroy (priv->dispatch_table);
153
154 UBusMessageInfo *info = g_queue_pop_tail (priv->message_queue);
155 for (; info != NULL; info = g_queue_pop_tail (priv->message_queue))
156 {
157 if (info->data != NULL)
158 g_variant_unref (info->data);
159 g_free (info);
160 }
161
162 g_queue_free (priv->message_queue);
163
164 G_OBJECT_CLASS (ubus_server_parent_class)->finalize (object);
165}
166
167static void
168ubus_server_class_init (UBusServerClass *klass)
169{
170 GObjectClass* object_class = G_OBJECT_CLASS (klass);
171 g_type_class_add_private (klass, sizeof (UBusServerPrivate));
172 object_class->finalize = ubus_server_finalize;
173}
174
175UBusServer *
176ubus_server_get_default ()
177{
178 static gsize singleton;
179 if (g_once_init_enter (&singleton))
180 {
181 UBusServer *server;
182 server = g_object_new (UBUS_TYPE_SERVER, NULL);
183 g_object_ref_sink (server);
184 g_once_init_leave (&singleton, (gsize) server);
185 }
186
187 // we actually just want to hold our own reference and not let anything
188 // else reference us, because we never want to lose that reference, we are
189 // only allowed to initalise once
190 return (UBusServer *)singleton;
191}
192
193gulong
194ubus_server_register_interest (UBusServer* server, const gchar *message,
195 UBusCallback callback, gpointer user_data)
196{
197 g_return_val_if_fail (UBUS_IS_SERVER (server), 0);
198 g_return_val_if_fail (message != NULL, 0);
199
200 UBusServerPrivate *priv = server->priv;
201 GSequence *dispatch_list = g_hash_table_lookup (priv->message_interest_table,
202 message);
203 UBusDispatchInfo *info;
204
205 if (dispatch_list == NULL)
206 {
207 // not had this message before so add a new entry to the message_interest table
208 gchar *key = g_strdup (message);
209 dispatch_list = g_sequence_new (NULL); // we use a sequence because its a stable pointer
210 g_hash_table_insert (priv->message_interest_table, key, dispatch_list);
211 }
212
213 // add the callback to the dispatch table
214 info = ubus_dispatch_info_new (server, message, callback, user_data);
215 gulong *id = g_malloc (sizeof (gulong));
216 *id = info->id;
217 g_hash_table_insert (priv->dispatch_table, id, info);
218
219 // add the dispatch info to the dispatch list in the message interest table
220 g_sequence_append (dispatch_list, info);
221
222 return info->id;
223}
224
225gboolean
226ubus_server_pump_message_queue (UBusServer *server)
227{
228 g_return_val_if_fail (UBUS_IS_SERVER (server), FALSE);
229 UBusServerPrivate *priv = server->priv;
230 UBusMessageInfo *info;
231
232 priv->message_pump_queued = TRUE;
233
234 // loop through each message queued and call the dispatch functions associated
235 // with it. something in the back of my mind says it would be quicker in some
236 // situations to sort the queue first so that duplicate messages can re-use
237 // the same dispatch_list lookups.. but thats a specific case.
238
239
240 info = g_queue_pop_tail (priv->message_queue);
241 for (; info != NULL; info = g_queue_pop_tail (priv->message_queue))
242 {
243 GSequence *dispatch_list;
244 dispatch_list = g_hash_table_lookup (priv->message_interest_table,
245 info->message);
246
247 if (dispatch_list == NULL)
248 continue; // no handlers for this message
249
250 GSequenceIter *iter = g_sequence_get_begin_iter (dispatch_list);
251 GSequenceIter *end = g_sequence_get_end_iter (dispatch_list);
252
253 while (iter != end)
254 {
255 GSequenceIter *next = g_sequence_iter_next (iter);
256 UBusDispatchInfo *dispatch_info = g_sequence_get (iter);
257 UBusCallback callback = dispatch_info->callback;
258
259 (*callback) (info->data, dispatch_info->user_data);
260
261 iter = next;
262 }
263
264 if (info->data != NULL)
265 g_variant_unref (info->data);
266 g_free (info);
267 }
268
269 return FALSE;
270}
271
272void
273ubus_server_queue_message_pump (UBusServer *server)
274{
275 g_return_if_fail (UBUS_IS_SERVER (server));
276 UBusServerPrivate *priv = server->priv;
277
278 if (priv->message_pump_queued)
279 return;
280
281 g_idle_add ((GSourceFunc)ubus_server_pump_message_queue, server);
282 priv->message_pump_queued = TRUE;
283}
284
285void
286ubus_server_send_message (UBusServer *server, const gchar *message,
287 GVariant *data)
288{
289 g_return_if_fail (UBUS_IS_SERVER (server));
290 g_return_if_fail (message != NULL);
291 UBusServerPrivate *priv = server->priv;
292
293 UBusMessageInfo *message_info = ubus_message_info_new (message, data);
294 g_queue_push_head (priv->message_queue, message_info);
295
296 ubus_server_queue_message_pump (server);
297}
298
299void
300ubus_server_unregister_interest (UBusServer* server, gulong handle)
301{
302 g_return_if_fail (UBUS_IS_SERVER (server));
303 g_return_if_fail (handle > 0);
304 UBusServerPrivate *priv = server->priv;
305 UBusDispatchInfo *info;
306 GSequence *dispatch_list;
307
308 // get our info
309 info = g_hash_table_lookup (priv->dispatch_table, &handle);
310
311 if (info == NULL)
312 {
313 g_warning (G_STRLOC ": Handle %lu does not exist", handle);
314 return;
315 }
316
317 // now the slightly sucky bit, we have to remove from our message-interest
318 // table, but we can only find it by itterating through a sequence
319 // but this is not so bad because we know *which* sequence its in
320
321 dispatch_list = g_hash_table_lookup (priv->message_interest_table,
322 info->message);
323
324 if (dispatch_list == NULL)
325 {
326 g_critical (G_STRLOC ": Handle exists but not dispatch list, ubus has "\
327 "become unstable");
328 return;
329 }
330
331 GSequenceIter *iter = g_sequence_get_begin_iter (dispatch_list);
332 GSequenceIter *end = g_sequence_get_end_iter (dispatch_list);
333 while (iter != end)
334 {
335 GSequenceIter *next = g_sequence_iter_next (iter);
336 UBusDispatchInfo *info_test = g_sequence_get (iter);
337
338 if (info_test->id == handle)
339 {
340 g_sequence_remove (iter);
341 }
342
343 iter = next;
344 }
345
346 if (g_sequence_get_length (dispatch_list) == 0)
347 {
348 // free the key/value pair
349 g_hash_table_remove (priv->message_interest_table, info->message);
350 }
351
352 // finally remove the dispatch_table hash table.
353 g_hash_table_remove (priv->dispatch_table, &handle);
354
355}
356
357void
358ubus_server_force_message_pump (UBusServer* server)
359{
360 ubus_server_pump_message_queue (server);
361}
0362
=== added file 'libunity/ubus-server.h'
--- libunity/ubus-server.h 1970-01-01 00:00:00 +0000
+++ libunity/ubus-server.h 2010-11-25 14:26:39 +0000
@@ -0,0 +1,74 @@
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2/*
3 * u-bus-server.h
4 * Copyright (C) 2010 Canonical, Ltd.
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License
8 * version 3.0 as published by the Free Software Foundation.
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
13 * GNU Lesser General Public License version 3.0 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, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * Authored by Gordon Allott <gord.allott@canonical.com>
20 */
21
22#ifndef _U_BUS_SERVER_H_
23#define _U_BUS_SERVER_H_
24
25#include <glib-object.h>
26#include <glib.h>
27G_BEGIN_DECLS
28
29#define UBUS_TYPE_SERVER (ubus_server_get_type ())
30#define UBUS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UBUS_TYPE_SERVER, UBusServer))
31#define UBUS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UBUS_TYPE_SERVER, UBusServerClass))
32#define UBUS_IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UBUS_TYPE_SERVER))
33#define UBUS_IS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UBUS_TYPE_SERVER))
34#define UBUS_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UBUS_TYPE_SERVER, UBusServerClass))
35
36typedef struct _UBusServerClass UBusServerClass;
37typedef struct _UBusServer UBusServer;
38typedef struct _UBusServerPrivate UBusServerPrivate;
39
40struct _UBusServerClass
41{
42 GObjectClass parent_class;
43
44 /* padding */
45 void (*_unity_padding1) (void);
46 void (*_unity_padding2) (void);
47 void (*_unity_padding3) (void);
48 void (*_unity_padding4) (void);
49 void (*_unity_padding5) (void);
50 void (*_unity_padding6) (void);
51};
52
53struct _UBusServer
54{
55 GObject parent_instance;
56
57 UBusServerPrivate *priv;
58};
59
60typedef void (*UBusCallback) (GVariant *data, gpointer *user_data);
61
62GType ubus_server_get_type (void) G_GNUC_CONST;
63UBusServer *ubus_server_get_default ();
64void ubus_server_prime_context (UBusServer* server, GMainContext *context);
65gulong ubus_server_register_interest (UBusServer* server, const gchar *message,
66 UBusCallback callback, gpointer user_data);
67void ubus_server_send_message (UBusServer* server, const gchar *message,
68 GVariant *data);
69void ubus_server_unregister_interest (UBusServer* server, gulong handle);
70void ubus_server_force_message_pump (UBusServer* server);
71
72G_END_DECLS
73
74#endif /* _U_BUS_SERVER_H_ */
075
=== modified file 'services/panel-service.c'
--- services/panel-service.c 2010-11-17 23:53:21 +0000
+++ services/panel-service.c 2010-11-25 14:26:39 +0000
@@ -158,7 +158,7 @@
158 GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (self->priv->last_menu));158 GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (self->priv->last_menu));
159 if (window == NULL)159 if (window == NULL)
160 return GDK_FILTER_CONTINUE;160 return GDK_FILTER_CONTINUE;
161 161
162 Window xwindow = gdk_x11_drawable_get_xid (GDK_DRAWABLE (window));162 Window xwindow = gdk_x11_drawable_get_xid (GDK_DRAWABLE (window));
163163
164 if (xwindow == 0)164 if (xwindow == 0)
@@ -236,7 +236,10 @@
236static gboolean236static gboolean
237initial_resync (PanelService *self)237initial_resync (PanelService *self)
238{238{
239 g_signal_emit (self, _service_signals[RE_SYNC], 0, "");239 if (PANEL_IS_SERVICE (self))
240 g_signal_emit (self, _service_signals[RE_SYNC], 0, "");
241
242
240 return FALSE;243 return FALSE;
241}244}
242245
@@ -264,7 +267,7 @@
264panel_service_get_default ()267panel_service_get_default ()
265{268{
266 static PanelService *service = NULL;269 static PanelService *service = NULL;
267 270
268 if (service == NULL || !PANEL_IS_SERVICE (service))271 if (service == NULL || !PANEL_IS_SERVICE (service))
269 service = g_object_new (PANEL_TYPE_SERVICE, NULL);272 service = g_object_new (PANEL_TYPE_SERVICE, NULL);
270273
@@ -293,13 +296,14 @@
293296
294 return g_slist_length (self->priv->indicators);297 return g_slist_length (self->priv->indicators);
295}298}
296 299
297/*300/*
298 * Private Methods301 * Private Methods
299 */302 */
300static gboolean303static gboolean
301actually_notify_object (IndicatorObject *object)304actually_notify_object (IndicatorObject *object)
302{305{
306 if (!INDICATOR_IS_OBJECT (object)) return;
303 PanelService *self;307 PanelService *self;
304 PanelServicePrivate *priv;308 PanelServicePrivate *priv;
305 gint position;309 gint position;
@@ -310,7 +314,7 @@
310 position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "position"));314 position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "position"));
311 priv->timeouts[position] = SYNC_WAITING;315 priv->timeouts[position] = SYNC_WAITING;
312316
313 if (!suppress_signals);317 if (!suppress_signals)
314 g_signal_emit (self, _service_signals[RE_SYNC],318 g_signal_emit (self, _service_signals[RE_SYNC],
315 0, g_object_get_data (G_OBJECT (object), "id"));319 0, g_object_get_data (G_OBJECT (object), "id"));
316320
@@ -392,7 +396,7 @@
392 G_CALLBACK (on_entry_changed), object);396 G_CALLBACK (on_entry_changed), object);
393 g_signal_connect (entry->label, "hide",397 g_signal_connect (entry->label, "hide",
394 G_CALLBACK (on_entry_changed), object);398 G_CALLBACK (on_entry_changed), object);
395 399
396 }400 }
397 if (GTK_IS_IMAGE (entry->image))401 if (GTK_IS_IMAGE (entry->image))
398 {402 {
@@ -452,7 +456,7 @@
452 priv->indicators = g_slist_append (priv->indicators, object);456 priv->indicators = g_slist_append (priv->indicators, object);
453457
454 g_object_set_data_full (G_OBJECT (object), "id", g_strdup (name), g_free);458 g_object_set_data_full (G_OBJECT (object), "id", g_strdup (name), g_free);
455 459
456 g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,460 g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,
457 G_CALLBACK (on_entry_added), self);461 G_CALLBACK (on_entry_added), self);
458 g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED,462 g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED,
@@ -535,7 +539,7 @@
535539
536 s1 = g_object_get_data (G_OBJECT (o1), "id");540 s1 = g_object_get_data (G_OBJECT (o1), "id");
537 s2 = g_object_get_data (G_OBJECT (o2), "id");541 s2 = g_object_get_data (G_OBJECT (o2), "id");
538 542
539 i1 = name2order (s1);543 i1 = name2order (s1);
540 i2 = name2order (s2);544 i2 = name2order (s2);
541545
@@ -573,7 +577,7 @@
573 GError *error = NULL;577 GError *error = NULL;
574578
575 pixbuf = gtk_image_get_pixbuf (image);579 pixbuf = gtk_image_get_pixbuf (image);
576 580
577 if (gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &buffer_size, "png", &error, NULL))581 if (gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &buffer_size, "png", &error, NULL))
578 {582 {
579 ret = g_base64_encode ((const guchar *)buffer, buffer_size);583 ret = g_base64_encode ((const guchar *)buffer, buffer_size);
@@ -623,7 +627,7 @@
623 gboolean is_label = GTK_IS_LABEL (entry->label);627 gboolean is_label = GTK_IS_LABEL (entry->label);
624 gboolean is_image = GTK_IS_IMAGE (entry->image);628 gboolean is_image = GTK_IS_IMAGE (entry->image);
625 gchar *image_data = NULL;629 gchar *image_data = NULL;
626 630
627 g_variant_builder_add (b, "(sssbbusbb)",631 g_variant_builder_add (b, "(sssbbusbb)",
628 indicator_id,632 indicator_id,
629 id,633 id,
@@ -729,7 +733,7 @@
729 /* Set the sync back to neutral */733 /* Set the sync back to neutral */
730 position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (i->data), "position"));734 position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (i->data), "position"));
731 self->priv->timeouts[position] = SYNC_NEUTRAL;735 self->priv->timeouts[position] = SYNC_NEUTRAL;
732 736
733 indicator_object_to_variant (i->data, indicator_id, &b);737 indicator_object_to_variant (i->data, indicator_id, &b);
734 }738 }
735739
@@ -776,7 +780,7 @@
776{780{
777 PanelServicePrivate *priv = self->priv;781 PanelServicePrivate *priv = self->priv;
778 IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);782 IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);
779 783
780 if (GTK_IS_MENU (priv->last_menu))784 if (GTK_IS_MENU (priv->last_menu))
781 {785 {
782 priv->last_x = 0;786 priv->last_x = 0;
783787
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2010-11-24 16:36:23 +0000
+++ tests/CMakeLists.txt 2010-11-25 14:26:39 +0000
@@ -16,7 +16,7 @@
16 ${TEST_UNIT_DEPS_CFLAGS_OTHER}16 ${TEST_UNIT_DEPS_CFLAGS_OTHER}
17 "-DGETTEXT_PACKAGE=\"unity\""17 "-DGETTEXT_PACKAGE=\"unity\""
18 "-DINDICATORDIR=\"${CMAKE_BINARY_DIR}/tests\""18 "-DINDICATORDIR=\"${CMAKE_BINARY_DIR}/tests\""
19 "-DINDICATORICONDIR=\"${CMAKE_BINARY_DIR}/tests\"" 19 "-DINDICATORICONDIR=\"${CMAKE_BINARY_DIR}/tests\""
20 )20 )
21add_definitions (${CFLAGS})21add_definitions (${CFLAGS})
2222
@@ -35,6 +35,9 @@
35 unit/TestFavoriteStoreGSettings.cpp35 unit/TestFavoriteStoreGSettings.cpp
36 unit/TestPanelService.cpp36 unit/TestPanelService.cpp
37 unit/TestMain.cpp37 unit/TestMain.cpp
38 unit/TestUBus.cpp
39 ../libunity/ubus-server.c
40 ../libunity/ubus-server.h
38 ../services/panel-service.c41 ../services/panel-service.c
39 ../services/panel-service.h42 ../services/panel-service.h
40 ../src/FavoriteStore.cpp43 ../src/FavoriteStore.cpp
4144
=== modified file 'tests/unit/TestMain.cpp'
--- tests/unit/TestMain.cpp 2010-11-17 21:38:57 +0000
+++ tests/unit/TestMain.cpp 2010-11-25 14:26:39 +0000
@@ -24,6 +24,7 @@
2424
25void TestFavoriteStoreGSettingsCreateSuite (void);25void TestFavoriteStoreGSettingsCreateSuite (void);
26void TestPanelServiceCreateSuite (void);26void TestPanelServiceCreateSuite (void);
27void TestUBusCreateSuite (void);
2728
28int29int
29main (int argc, char **argv)30main (int argc, char **argv)
@@ -32,12 +33,13 @@
3233
33 g_type_init ();34 g_type_init ();
34 g_thread_init (NULL);35 g_thread_init (NULL);
35 36
36 g_test_init (&argc, &argv, NULL);37 g_test_init (&argc, &argv, NULL);
3738
38 //Keep alphabetical please39 //Keep alphabetical please
39 TestFavoriteStoreGSettingsCreateSuite ();40 TestFavoriteStoreGSettingsCreateSuite ();
40 TestPanelServiceCreateSuite ();41 TestPanelServiceCreateSuite ();
42 TestUBusCreateSuite ();
4143
42 return g_test_run ();44 return g_test_run ();
43}45}
4446
=== added file 'tests/unit/TestUBus.cpp'
--- tests/unit/TestUBus.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit/TestUBus.cpp 2010-11-25 14:26:39 +0000
@@ -0,0 +1,152 @@
1/*
2 * Copyright 2010 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
14 * version 3 along with this program. If not, see
15 * <http://www.gnu.org/licenses/>
16 *
17 * Authored by: Gordon Allott <gord.allott@canonical.com>
18 *
19 */
20
21
22#include "config.h"
23#include "libunity/ubus-server.h"
24
25#define MESSAGE1 "TEST MESSAGE ONE"
26#define MESSAGE2 "ՄᕅᏆⲤꙨႧΈ Ϊટ ಗשׁຣ໐ɱË‼‼❢"
27
28static void TestAllocation (void);
29static void TestMainLoop (void);
30static void TestPropagation (void);
31
32void
33TestUBusCreateSuite ()
34{
35#define _DOMAIN "/Unit/UBus"
36 g_test_add_func (_DOMAIN"/Allocation", TestAllocation);
37 g_test_add_func (_DOMAIN"/Propagation", TestPropagation);
38 g_test_add_func (_DOMAIN"/MainLoop", TestMainLoop);
39}
40
41static void
42TestAllocation ()
43{
44 UBusServer *serv_1 = ubus_server_get_default ();
45 UBusServer *serv_2 = ubus_server_get_default ();
46
47 g_assert (serv_1 != NULL);
48 g_assert (serv_2 != NULL);
49
50 // i used a different way of making a singleton than i am used to
51 // so i'm not 100% confident in it yet
52 g_assert (serv_1 == serv_2);
53}
54
55void
56test_handler_inc_counter (GVariant *data, gpointer *val)
57{
58 // inc a counter when we get called
59 gint *counter = (gint*)val;
60 *counter = *counter + 1;
61}
62
63void
64test_handler_inc_counter_2 (GVariant *data, gpointer *val)
65{
66 // inc a counter by two when called
67 gint *counter = (gint*)val;
68 *counter = *counter + 2;
69}
70
71static void
72TestPropagation ()
73{
74 UBusServer *ubus = ubus_server_get_default ();
75 gint counter = 0;
76 gulong handler1 = ubus_server_register_interest (ubus, MESSAGE1,
77 test_handler_inc_counter,
78 &counter);
79
80 gulong handler2 = ubus_server_register_interest (ubus, MESSAGE2, // tests UNICODE
81 test_handler_inc_counter_2,
82 &counter);
83
84 gint i;
85 for (i=0; i<1000; i++)
86 {
87 ubus_server_send_message (ubus, MESSAGE1, NULL);
88 }
89
90 ubus_server_force_message_pump (ubus);
91
92 counter = 0;
93 for (i=0; i<1000; i++)
94 {
95 ubus_server_send_message (ubus, MESSAGE1, NULL);
96 ubus_server_send_message (ubus, MESSAGE2, NULL);
97 }
98 ubus_server_force_message_pump (ubus);
99
100 g_assert (counter == 3000);
101
102 ubus_server_unregister_interest (ubus, handler1);
103 ubus_server_unregister_interest (ubus, handler2);
104
105 counter = 0;
106 ubus_server_send_message (ubus, MESSAGE1, NULL);
107 ubus_server_send_message (ubus, MESSAGE2, NULL);
108
109 ubus_server_force_message_pump (ubus);
110
111 g_assert (counter == 0);
112}
113
114gboolean
115main_loop_bailout (gpointer data)
116{
117 GMainLoop *mainloop = (GMainLoop*)data;
118 g_main_quit (mainloop);
119 return FALSE;
120}
121
122void
123test_handler_mainloop (GVariant *data, gpointer *val)
124{
125 // inc a counter when we get called
126 gint *counter = (gint*)val;
127 *counter = *counter + 1;
128
129}
130
131static void
132TestMainLoop ()
133{
134 GMainLoop *mainloop;
135 UBusServer *ubus = ubus_server_get_default ();
136 gint counter = 0;
137
138 mainloop = g_main_loop_new (NULL, TRUE);
139 g_timeout_add_seconds (1, main_loop_bailout, mainloop);
140
141 ubus_server_register_interest (ubus, MESSAGE1,
142 test_handler_mainloop,
143 &counter);
144
145 ubus_server_send_message (ubus, MESSAGE1, NULL);
146 g_main_loop_run (mainloop);
147
148 g_assert (counter == 1);
149
150}
151
152