Merge lp:~aacid/unity/do_not_reuse_menus_on_order_change into lp:unity
- do_not_reuse_menus_on_order_change
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Marco Trevisan (Treviño) |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2815 |
Proposed branch: | lp:~aacid/unity/do_not_reuse_menus_on_order_change |
Merge into: | lp:unity |
Diff against target: |
662 lines (+471/-6) 11 files modified
UnityCore/DBusIndicators.cpp (+28/-5) UnityCore/DBusIndicators.h (+4/-0) UnityCore/Indicator.cpp (+15/-0) UnityCore/Indicator.h (+1/-0) tests/CMakeLists.txt (+4/-1) tests/test_dbus_indicators.cpp (+99/-0) tests/test_indicator.cpp (+3/-0) tests/test_service_main.c (+4/-0) tests/test_service_panel.c (+253/-0) tests/test_service_panel.h (+46/-0) tests/test_utils.h (+14/-0) |
To merge this branch: | bzr merge lp:~aacid/unity/do_not_reuse_menus_on_order_change |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marco Trevisan (Treviño) | Approve | ||
Review via email: mp+128243@code.launchpad.net |
Commit message
Do not reuse the menu entries if their order changes
Since the indicators api only have "add" and "remove" signals, if we reuse an entry that is not in the correct order it will case the menus or whatever this indicator represents to be in the wrong order
Description of the change
Do not reuse the menu entries if their order changes
Since the indicators api only have "add" and "remove" signals, if we reuse an entry that is not in the correct order it will case the menus or whatever this indicator represents to be in the wrong order
Albert Astals Cid (aacid) wrote : | # |
Albert Astals Cid (aacid) wrote : | # |
Unit test added
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
112 + DBusIndicators(
In unity we prefer to use this syntax instead:
std::string const& dbus_name
8 -const std::string SERVICE_
However, probably instead of adding an optional parameter, I would add another one (better if protected, so that you'll make accessible only in a test mock class) that takes the service name parameter.
91 + : connected(false), pimpl(new Impl(dbus_name, this))
Better two lines here.
115 + nux::Property<bool> connected;
Don't use a property here, for two reasons: a non-RO property like is this one, is meant to be editable, while you only use to store a value; also you don't really need that... Just add an IsConnected() (protected as well?) method that proxies gproxy_
On the testing side, yes... That's what I meant: good! :)
However, on code side you can be more clean by using the TestDBusIndicators class: so, add in the constructor (or in a SetUp() function) the calls you're duplicating in the tests to initialize them, and the cleanup calls in a TearDown() method.
Also instead of using g_timeout, you can use glib::Timeout, since probably you won't able to use utils::WaitUntil
+ session = g_bus_get_
I guess that using a glib::DbusProxy would be better here.
182 === added file 'tests/
I'd prefer it to be named test_dbus_
PS: also cleanup the commented code in test.
Albert Astals Cid (aacid) wrote : | # |
ok, all suggestions should be implemented if i did not miss something
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
331 + DBusIndicatorsTest* dbus_indicators;
Would be nice to have DBusIndicators::Ptr instead, so you don't need to worry about destruction (unless it must be done before unreffing the loop)
336 +TEST_F(
337 +{
338 + SetUp();
357 + TearDown();
358 +}
No need to do this... GTest will do this automatically, so forget about setting-up and tearing-down once you've defined these testing::Test functions.
341 + auto timeout_check = [&] () -> bool
342 + {
343 + nChecks++;
344 + bool quit_loop = dbus_indicators
345 + if (quit_loop)
346 + g_main_
347 + return !quit_loop;
348 + };
349
350 + nChecks = 0;
351 + timeout.reset(new glib::Timeout(100, timeout_check));
352 +
353 + g_main_
No need to repeat this for every test...
Just do it in the SetUp function, and probably instead of quitting the loop is enough to add an ASSERT there.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
108 + GVariant *CallSync(string const& method_name,
109 + GVariant* parameters,
Ah, please also add the * near to the typename (i.e. GVariant*) and, fix the parameters indentation.
Albert Astals Cid (aacid) wrote : | # |
Second round of updates hope i did not miss anything :-)
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Thanks a lot for your changes (and patience), it looks very nice now! ;)
Unity Merger (unity-merger) wrote : | # |
The Jenkins job https:/
Not merging it.
Preview Diff
1 | === modified file 'UnityCore/DBusIndicators.cpp' |
2 | --- UnityCore/DBusIndicators.cpp 2012-06-18 02:57:23 +0000 |
3 | +++ UnityCore/DBusIndicators.cpp 2012-10-08 14:36:19 +0000 |
4 | @@ -48,7 +48,7 @@ |
5 | class DBusIndicators::Impl |
6 | { |
7 | public: |
8 | - Impl(DBusIndicators* owner); |
9 | + Impl(std::string const& dbus_name, DBusIndicators* owner); |
10 | |
11 | void CheckLocalService(); |
12 | void RequestSyncAll(); |
13 | @@ -84,9 +84,9 @@ |
14 | |
15 | |
16 | // Public Methods |
17 | -DBusIndicators::Impl::Impl(DBusIndicators* owner) |
18 | +DBusIndicators::Impl::Impl(std::string const& dbus_name, DBusIndicators* owner) |
19 | : owner_(owner) |
20 | - , gproxy_(SERVICE_NAME, SERVICE_PATH, SERVICE_IFACE, |
21 | + , gproxy_(dbus_name, SERVICE_PATH, SERVICE_IFACE, |
22 | G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES) |
23 | { |
24 | gproxy_.Connect("ReSync", sigc::mem_fun(this, &DBusIndicators::Impl::OnReSync)); |
25 | @@ -276,6 +276,8 @@ |
26 | return; |
27 | |
28 | std::map<Indicator::Ptr, Indicator::Entries> indicators; |
29 | + int wantedIndex = 0; |
30 | + bool anyIndexDifferent = false; |
31 | |
32 | g_variant_get(args, "(a(ssssbbusbbi))", &iter); |
33 | while (g_variant_iter_loop(iter, "(ssssbbusbbi)", |
34 | @@ -305,7 +307,18 @@ |
35 | // Null entries (entry_id == "") are empty indicators. |
36 | if (entry != "") |
37 | { |
38 | - Entry::Ptr e = indicator->GetEntry(entry_id); |
39 | + Entry::Ptr e; |
40 | + if (!anyIndexDifferent) |
41 | + { |
42 | + // Indicators can only add or remove entries, so if |
43 | + // there is a index change we can't reuse the existing ones |
44 | + // after that index |
45 | + int existingEntryIndex = indicator->EntryIndex(entry_id); |
46 | + if (wantedIndex == existingEntryIndex) |
47 | + e = indicator->GetEntry(entry_id); |
48 | + else |
49 | + anyIndexDifferent = true; |
50 | + } |
51 | |
52 | if (!e) |
53 | { |
54 | @@ -321,6 +334,7 @@ |
55 | } |
56 | |
57 | entries.push_back(e); |
58 | + wantedIndex++; |
59 | } |
60 | } |
61 | g_variant_iter_free(iter); |
62 | @@ -393,12 +407,21 @@ |
63 | } |
64 | |
65 | DBusIndicators::DBusIndicators() |
66 | - : pimpl(new Impl(this)) |
67 | + : pimpl(new Impl(SERVICE_NAME, this)) |
68 | +{} |
69 | + |
70 | +DBusIndicators::DBusIndicators(std::string const& dbus_name) |
71 | + : pimpl(new Impl(dbus_name, this)) |
72 | {} |
73 | |
74 | DBusIndicators::~DBusIndicators() |
75 | {} |
76 | |
77 | +bool DBusIndicators::IsConnected() const |
78 | +{ |
79 | + return pimpl->gproxy_.IsConnected(); |
80 | +} |
81 | + |
82 | void DBusIndicators::SyncGeometries(std::string const& name, |
83 | EntryLocationMap const& locations) |
84 | { |
85 | |
86 | === modified file 'UnityCore/DBusIndicators.h' |
87 | --- UnityCore/DBusIndicators.h 2012-06-18 02:57:23 +0000 |
88 | +++ UnityCore/DBusIndicators.h 2012-10-08 14:36:19 +0000 |
89 | @@ -50,6 +50,10 @@ |
90 | virtual void OnShowAppMenu(unsigned int xid, int x, int y, |
91 | unsigned int timestamp); |
92 | |
93 | +protected: |
94 | + DBusIndicators(std::string const& dbus_name); |
95 | + bool IsConnected() const; |
96 | + |
97 | private: |
98 | class Impl; |
99 | std::unique_ptr<Impl> pimpl; |
100 | |
101 | === modified file 'UnityCore/Indicator.cpp' |
102 | --- UnityCore/Indicator.cpp 2012-08-08 06:57:43 +0000 |
103 | +++ UnityCore/Indicator.cpp 2012-10-08 14:36:19 +0000 |
104 | @@ -115,6 +115,21 @@ |
105 | return Entry::Ptr(); |
106 | } |
107 | |
108 | +int Indicator::EntryIndex(std::string const& entry_id) const |
109 | +{ |
110 | + int i = 0; |
111 | + for (auto entry : entries_) |
112 | + { |
113 | + if (entry->id() == entry_id) |
114 | + { |
115 | + return i; |
116 | + } |
117 | + ++i; |
118 | + } |
119 | + |
120 | + return -1; |
121 | +} |
122 | + |
123 | void Indicator::OnEntryShowMenu(std::string const& entry_id, unsigned int xid, |
124 | int x, int y, unsigned int button, unsigned int timestamp) |
125 | { |
126 | |
127 | === modified file 'UnityCore/Indicator.h' |
128 | --- UnityCore/Indicator.h 2012-06-18 02:57:23 +0000 |
129 | +++ UnityCore/Indicator.h 2012-10-08 14:36:19 +0000 |
130 | @@ -48,6 +48,7 @@ |
131 | |
132 | void Sync(Entries const& new_entries); |
133 | Entry::Ptr GetEntry(std::string const& entry_id) const; |
134 | + int EntryIndex(std::string const& entry_id) const; |
135 | Entries GetEntries() const; |
136 | |
137 | // Signals |
138 | |
139 | === modified file 'tests/CMakeLists.txt' |
140 | --- tests/CMakeLists.txt 2012-10-08 06:36:17 +0000 |
141 | +++ tests/CMakeLists.txt 2012-10-08 14:36:19 +0000 |
142 | @@ -110,7 +110,9 @@ |
143 | test_service_lens.h |
144 | test_service_main.c |
145 | test_service_model.c |
146 | - test_service_model.h) |
147 | + test_service_model.h |
148 | + test_service_panel.c |
149 | + test_service_panel.c) |
150 | target_link_libraries(test-gtest-service unity-shared ${LIBS}) |
151 | add_dependencies (test-gtest-service unity-core-${UNITY_API_VERSION} gtest) |
152 | |
153 | @@ -194,6 +196,7 @@ |
154 | test_utils.h |
155 | test_ratings_filter.cpp |
156 | test_results.cpp |
157 | + test_dbus_indicators.cpp |
158 | ) |
159 | target_link_libraries(test-gtest-dbus gtest unity-shared ${LIBS}) |
160 | add_test(UnityGTestDBus test-gtest-dbus) |
161 | |
162 | === added file 'tests/test_dbus_indicators.cpp' |
163 | --- tests/test_dbus_indicators.cpp 1970-01-01 00:00:00 +0000 |
164 | +++ tests/test_dbus_indicators.cpp 2012-10-08 14:36:19 +0000 |
165 | @@ -0,0 +1,99 @@ |
166 | +#include <gtest/gtest.h> |
167 | + |
168 | +#include <UnityCore/GLibDBusProxy.h> |
169 | +#include <UnityCore/GLibSource.h> |
170 | +#include <UnityCore/GLibWrapper.h> |
171 | +#include <UnityCore/DBusIndicators.h> |
172 | + |
173 | +#include "test_utils.h" |
174 | + |
175 | +using namespace unity; |
176 | +using namespace unity::indicator; |
177 | + |
178 | +namespace |
179 | +{ |
180 | + |
181 | +class DBusIndicatorsTest : public DBusIndicators |
182 | +{ |
183 | +public: |
184 | + DBusIndicatorsTest() : DBusIndicators("com.canonical.Unity.Test") |
185 | + { |
186 | + } |
187 | + |
188 | + bool HasIndicators() const |
189 | + { |
190 | + return !GetIndicators().empty(); |
191 | + } |
192 | + |
193 | + using DBusIndicators::IsConnected; |
194 | +}; |
195 | + |
196 | +class TestDBusIndicators : public ::testing::Test |
197 | +{ |
198 | +public: |
199 | + void SetUp() |
200 | + { |
201 | + session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
202 | + g_dbus_connection_set_exit_on_close(session, FALSE); |
203 | + |
204 | + dbus_indicators.reset(new DBusIndicatorsTest ()); |
205 | + |
206 | + // wait until the dbus indicator has connected to the panel service |
207 | + Utils::WaitUntil(sigc::mem_fun(*dbus_indicators, &DBusIndicatorsTest::IsConnected)); |
208 | + } |
209 | + |
210 | + bool TriggerResync1Sent() const |
211 | + { |
212 | + GVariant *ret = CallPanelMethod("TriggerResync1Sent"); |
213 | + return g_variant_get_boolean(g_variant_get_child_value(ret, 0)); |
214 | + } |
215 | + |
216 | + GVariant* CallPanelMethod(std::string const& name) const |
217 | + { |
218 | + return g_dbus_connection_call_sync(session, |
219 | + "com.canonical.Unity.Test", |
220 | + "/com/canonical/Unity/Panel/Service", |
221 | + "com.canonical.Unity.Panel.Service", |
222 | + name.c_str(), |
223 | + NULL, |
224 | + NULL, |
225 | + G_DBUS_CALL_FLAGS_NONE, |
226 | + -1, |
227 | + NULL, |
228 | + NULL); |
229 | + } |
230 | + |
231 | + glib::Object<GDBusConnection> session; |
232 | + std::shared_ptr<DBusIndicatorsTest> dbus_indicators; |
233 | +}; |
234 | + |
235 | +TEST_F(TestDBusIndicators, TestConstruction) |
236 | +{ |
237 | + EXPECT_EQ(dbus_indicators->IsConnected(), true); |
238 | +} |
239 | + |
240 | +TEST_F(TestDBusIndicators, TestSync) |
241 | +{ |
242 | + // wait until the dbus indicator gets any indicator from the panel service |
243 | + Utils::WaitUntil(sigc::mem_fun(*dbus_indicators, &DBusIndicatorsTest::HasIndicators)); |
244 | + |
245 | + EXPECT_EQ(dbus_indicators->GetIndicators().size(), 1); |
246 | + EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().size(), 2); |
247 | + EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().front()->id(), "test_entry_id"); |
248 | + EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().back()->id(), "test_entry_id2"); |
249 | + |
250 | + // Tell the service to trigger a resync and to send the entries in the reverse order |
251 | + CallPanelMethod("TriggerResync1"); |
252 | + |
253 | + Utils::WaitUntil(sigc::mem_fun(this, &TestDBusIndicators::TriggerResync1Sent)); |
254 | + // We know the resync has been sent, but it may have not been processed |
255 | + // so do one interation of the main loop more |
256 | + g_main_context_iteration(g_main_context_get_thread_default(), TRUE); |
257 | + |
258 | + EXPECT_EQ(dbus_indicators->GetIndicators().size(), 1); |
259 | + EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().size(), 2); |
260 | + EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().front()->id(), "test_entry_id2"); |
261 | + EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().back()->id(), "test_entry_id"); |
262 | +} |
263 | + |
264 | +} |
265 | |
266 | === modified file 'tests/test_indicator.cpp' |
267 | --- tests/test_indicator.cpp 2012-02-01 01:55:05 +0000 |
268 | +++ tests/test_indicator.cpp 2012-10-08 14:36:19 +0000 |
269 | @@ -35,6 +35,7 @@ |
270 | EXPECT_EQ(indicator.name(), "indicator-test"); |
271 | EXPECT_FALSE(indicator.IsAppmenu()); |
272 | EXPECT_EQ(indicator.GetEntry("test-entry"), nullptr); |
273 | + EXPECT_EQ(indicator.EntryIndex("test-entry"), -1); |
274 | EXPECT_TRUE(indicator.GetEntries().empty()); |
275 | } |
276 | |
277 | @@ -76,6 +77,7 @@ |
278 | indicator.Sync(sync_data); |
279 | EXPECT_EQ(indicator.GetEntries().size(), 3); |
280 | EXPECT_EQ(indicator.GetEntry("test-entry-2"), entry2); |
281 | + EXPECT_EQ(indicator.EntryIndex("test-entry-2"), 1); |
282 | EXPECT_EQ(added.size(), 3); |
283 | EXPECT_EQ(added.front()->id(), "test-entry-1"); |
284 | EXPECT_EQ(added.back()->id(), "test-entry-3"); |
285 | @@ -91,6 +93,7 @@ |
286 | indicator.Sync(sync_data); |
287 | EXPECT_EQ(indicator.GetEntries().size(), 2); |
288 | EXPECT_EQ(indicator.GetEntry("test-entry-2"), nullptr); |
289 | + EXPECT_EQ(indicator.EntryIndex("test-entry-2"), -1); |
290 | EXPECT_EQ(added.size(), 0); |
291 | EXPECT_EQ(removed.size(), 1); |
292 | EXPECT_EQ(removed.front(), entry2->id()); |
293 | |
294 | === modified file 'tests/test_service_main.c' |
295 | --- tests/test_service_main.c 2012-03-14 06:24:18 +0000 |
296 | +++ tests/test_service_main.c 2012-10-08 14:36:19 +0000 |
297 | @@ -3,6 +3,7 @@ |
298 | #include "test_service_lens.h" |
299 | #include "test_service_model.h" |
300 | #include "test_service_hud.h" |
301 | +#include "test_service_panel.h" |
302 | #include "test_service_gdbus_wrapper.h" |
303 | |
304 | static void on_bus_aquired(GDBusConnection* conn, const gchar* name, gpointer null); |
305 | @@ -37,6 +38,7 @@ |
306 | static ServiceLens* lens_ = NULL; |
307 | static ServiceModel* model_ = NULL; |
308 | static ServiceHud* hud_ = NULL; |
309 | +static ServicePanel* panel_ = NULL; |
310 | static ServiceGDBusWrapper* gdbus_wrapper_ = NULL; |
311 | gint |
312 | main(gint argc, gchar** argv) |
313 | @@ -48,6 +50,7 @@ |
314 | lens_ = service_lens_new(); |
315 | model_ = service_model_new(); |
316 | hud_ = service_hud_new(); |
317 | + panel_ = service_panel_new(); |
318 | gdbus_wrapper_ = service_gdbus_wrapper_new(); |
319 | |
320 | g_bus_own_name(G_BUS_TYPE_SESSION, |
321 | @@ -65,6 +68,7 @@ |
322 | //g_object_unref(lens_); |
323 | //g_object_unref(model_); |
324 | g_object_unref(hud_); |
325 | + g_object_unref(panel_); |
326 | g_dbus_node_info_unref(introspection_data); |
327 | |
328 | return 0; |
329 | |
330 | === added file 'tests/test_service_panel.c' |
331 | --- tests/test_service_panel.c 1970-01-01 00:00:00 +0000 |
332 | +++ tests/test_service_panel.c 2012-10-08 14:36:19 +0000 |
333 | @@ -0,0 +1,253 @@ |
334 | +#include "test_service_panel.h" |
335 | +#include <unity.h> |
336 | +#include <gio/gio.h> |
337 | + |
338 | +static const char * panel_interface = |
339 | +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
340 | +"<node name=\"/\">\n" |
341 | +" <interface name=\"com.canonical.Unity.Panel.Service\">\n" |
342 | +"\n" |
343 | +"<!-- Begin of real methods/signals -->\n" |
344 | +" <method name='Sync'>" |
345 | +" <arg type='a(ssssbbusbbi)' name='state' direction='out'/>" |
346 | +" </method>" |
347 | +"\n" |
348 | +" <signal name='ReSync'>" |
349 | +" <arg type='s' name='indicator_id' />" |
350 | +" </signal>" |
351 | +"\n" |
352 | +"<!-- Begin of test only methods/signals -->\n" |
353 | +"\n" |
354 | +" <method name='TriggerResync1' />" |
355 | +"\n" |
356 | +" <method name='TriggerResync1Sent'>" |
357 | +" <arg type='b' name='sent' direction='out'/>" |
358 | +" </method>" |
359 | +"\n" |
360 | +" </interface>\n" |
361 | +"</node>\n" |
362 | +; |
363 | +static void bus_got_cb (GObject *object, GAsyncResult * res, gpointer user_data); |
364 | +static void bus_method (GDBusConnection *connection, |
365 | + const gchar *sender, |
366 | + const gchar *object_path, |
367 | + const gchar *interface_name, |
368 | + const gchar *method_name, |
369 | + GVariant *parameters, |
370 | + GDBusMethodInvocation *invocation, |
371 | + gpointer user_data); |
372 | + |
373 | +G_DEFINE_TYPE(ServicePanel, service_panel, G_TYPE_OBJECT); |
374 | +static GDBusNodeInfo * node_info = NULL; |
375 | +static GDBusInterfaceInfo * iface_info = NULL; |
376 | +static GDBusInterfaceVTable bus_vtable = { |
377 | + method_call: bus_method, |
378 | + get_property: NULL, |
379 | + set_property: NULL, |
380 | +}; |
381 | + |
382 | +struct _ServicePanelPrivate |
383 | +{ |
384 | + GDBusConnection * bus; |
385 | + GCancellable * bus_lookup; |
386 | + guint bus_registration; |
387 | + guint sig_emission_handle; |
388 | +}; |
389 | + |
390 | +static void |
391 | +service_panel_dispose(GObject* object) |
392 | +{ |
393 | + ServicePanel* self = SERVICE_PANEL(object); |
394 | + if (self->priv->bus_lookup != NULL) { |
395 | + g_cancellable_cancel(self->priv->bus_lookup); |
396 | + g_object_unref(self->priv->bus_lookup); |
397 | + self->priv->bus_lookup = NULL; |
398 | + } |
399 | + |
400 | + if (self->priv->bus_registration != 0) { |
401 | + g_dbus_connection_unregister_object(self->priv->bus, self->priv->bus_registration); |
402 | + self->priv->bus_registration = 0; |
403 | + } |
404 | + |
405 | + if (self->priv->bus != NULL) { |
406 | + g_object_unref(self->priv->bus); |
407 | + self->priv->bus = NULL; |
408 | + } |
409 | + |
410 | + if (self->priv->sig_emission_handle) { |
411 | + g_source_remove(self->priv->sig_emission_handle); |
412 | + self->priv->sig_emission_handle = 0; |
413 | + } |
414 | + |
415 | +} |
416 | + |
417 | +static void |
418 | +service_panel_class_init(ServicePanelClass* klass) |
419 | +{ |
420 | + G_OBJECT_CLASS(klass)->dispose = service_panel_dispose; |
421 | + g_type_class_add_private (klass, sizeof (ServicePanelPrivate)); |
422 | + |
423 | + if (node_info == NULL) |
424 | + { |
425 | + GError * error = NULL; |
426 | + |
427 | + node_info = g_dbus_node_info_new_for_xml(panel_interface, &error); |
428 | + if (error != NULL) |
429 | + { |
430 | + g_error("Unable to parse Panel interface: %s", error->message); |
431 | + g_error_free(error); |
432 | + } |
433 | + } |
434 | + |
435 | + if (node_info != NULL && iface_info == NULL) |
436 | + { |
437 | + iface_info = g_dbus_node_info_lookup_interface(node_info,"com.canonical.Unity.Panel.Service"); |
438 | + if (iface_info == NULL) |
439 | + { |
440 | + g_error("Unable to find interface 'com.canonical.Unity.Panel.Service'"); |
441 | + } |
442 | + } |
443 | + |
444 | +} |
445 | + |
446 | +static void |
447 | +service_panel_init(ServicePanel* self) |
448 | +{ |
449 | + self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, SERVICE_TYPE_PANEL, ServicePanelPrivate); |
450 | + self->priv->bus = NULL; |
451 | + self->priv->bus_lookup = NULL; |
452 | + self->priv->bus_registration = 0; |
453 | + |
454 | + self->priv->bus_lookup = g_cancellable_new(); |
455 | + g_bus_get(G_BUS_TYPE_SESSION, self->priv->bus_lookup, bus_got_cb, self); |
456 | +} |
457 | + |
458 | +ServicePanel* |
459 | +service_panel_new() |
460 | +{ |
461 | + return g_object_new(SERVICE_TYPE_PANEL, NULL); |
462 | +} |
463 | + |
464 | +static void |
465 | +bus_got_cb (GObject *object, GAsyncResult * res, gpointer user_data) |
466 | +{ |
467 | + GError * error = NULL; |
468 | + ServicePanel * self = SERVICE_PANEL(user_data); |
469 | + GDBusConnection * bus; |
470 | + |
471 | + bus = g_bus_get_finish(res, &error); |
472 | + if (error != NULL) { |
473 | + g_critical("Unable to get bus: %s", error->message); |
474 | + g_error_free(error); |
475 | + return; |
476 | + } |
477 | + |
478 | + self->priv->bus = bus; |
479 | + |
480 | + /* Register object */ |
481 | + self->priv->bus_registration = g_dbus_connection_register_object(bus, |
482 | + /* path */ "/com/canonical/Unity/Panel/Service", |
483 | + /* interface */ iface_info, |
484 | + /* vtable */ &bus_vtable, |
485 | + /* userdata */ self, |
486 | + /* destroy */ NULL, |
487 | + /* error */ &error); |
488 | + |
489 | + if (error != NULL) { |
490 | + g_critical ("Unable to create bus connection object, %s", error->message); |
491 | + g_error_free(error); |
492 | + return; |
493 | + } |
494 | + |
495 | + return; |
496 | +} |
497 | + |
498 | +static void |
499 | +add_entry_id(GVariantBuilder *b) |
500 | +{ |
501 | + g_variant_builder_add (b, "(ssssbbusbbi)", |
502 | + "test_indicator_id", |
503 | + "test_entry_id", |
504 | + "test_entry_name_hint", |
505 | + "test_entry_label", |
506 | + TRUE, /* label sensitive */ |
507 | + TRUE, /* label visible */ |
508 | + 0, /* image type */ |
509 | + "", /* image_data */ |
510 | + TRUE, /* image sensitive */ |
511 | + TRUE, /* image visible */ |
512 | + 1 /* priority */); |
513 | +} |
514 | + |
515 | +static void |
516 | +add_entry_id_2(GVariantBuilder *b) |
517 | +{ |
518 | + g_variant_builder_add (b, "(ssssbbusbbi)", |
519 | + "test_indicator_id", |
520 | + "test_entry_id2", |
521 | + "test_entry_name_hint2", |
522 | + "test_entry_label2", |
523 | + TRUE, /* label sensitive */ |
524 | + TRUE, /* label visible */ |
525 | + 0, /* image type */ |
526 | + "", /* image_data */ |
527 | + TRUE, /* image sensitive */ |
528 | + TRUE, /* image visible */ |
529 | + 1 /* priority */); |
530 | +} |
531 | + |
532 | +static int sync_return_mode = 0; |
533 | +static int trigger_resync1_sent = FALSE; |
534 | + |
535 | +static void |
536 | +bus_method (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) |
537 | +{ |
538 | + if (g_strcmp0(method_name, "Sync") == 0) |
539 | + { |
540 | + GVariantBuilder b; |
541 | + |
542 | + g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssssbbusbbi))")); |
543 | + g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssssbbusbbi)")); |
544 | + |
545 | + if (sync_return_mode == 0) |
546 | + { |
547 | + add_entry_id(&b); |
548 | + add_entry_id_2(&b); |
549 | + } |
550 | + else if (sync_return_mode == 1) |
551 | + { |
552 | + add_entry_id_2(&b); |
553 | + add_entry_id(&b); |
554 | + } |
555 | + |
556 | + g_variant_builder_close (&b); |
557 | + |
558 | + g_dbus_method_invocation_return_value(invocation, g_variant_builder_end (&b)); |
559 | + |
560 | + if (sync_return_mode == 1) |
561 | + { |
562 | + trigger_resync1_sent = TRUE; |
563 | + } |
564 | + } |
565 | + else if (g_strcmp0(method_name, "TriggerResync1") == 0) |
566 | + { |
567 | + sync_return_mode = 1; |
568 | + trigger_resync1_sent = FALSE; |
569 | + |
570 | + g_dbus_method_invocation_return_value(invocation, NULL); |
571 | + GVariantBuilder ret_builder; |
572 | + g_variant_builder_init(&ret_builder, G_VARIANT_TYPE_TUPLE); |
573 | + g_variant_builder_add_value(&ret_builder, g_variant_new_string("")); |
574 | + g_dbus_connection_emit_signal (connection, NULL, "/com/canonical/Unity/Panel/Service", "com.canonical.Unity.Panel.Service", "ReSync", g_variant_builder_end(&ret_builder), NULL); |
575 | + } |
576 | + else if (g_strcmp0(method_name, "TriggerResync1Sent") == 0) |
577 | + { |
578 | + GVariantBuilder ret_builder; |
579 | + g_variant_builder_init(&ret_builder, G_VARIANT_TYPE ("(b)")); |
580 | + g_variant_builder_add_value (&ret_builder, g_variant_new_boolean(trigger_resync1_sent)); |
581 | + g_dbus_method_invocation_return_value(invocation, g_variant_builder_end (&ret_builder)); |
582 | + } |
583 | + |
584 | + return; |
585 | +} |
586 | + |
587 | |
588 | === added file 'tests/test_service_panel.h' |
589 | --- tests/test_service_panel.h 1970-01-01 00:00:00 +0000 |
590 | +++ tests/test_service_panel.h 2012-10-08 14:36:19 +0000 |
591 | @@ -0,0 +1,46 @@ |
592 | +#ifndef _SERVICE_PANEL_H_ |
593 | +#define _SERVICE_PANEL_H_ |
594 | + |
595 | +#include <glib-object.h> |
596 | +G_BEGIN_DECLS |
597 | + |
598 | +#define SERVICE_TYPE_PANEL (service_panel_get_type ()) |
599 | + |
600 | +#define SERVICE_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ |
601 | + SERVICE_TYPE_PANEL, ServicePanel)) |
602 | + |
603 | +#define SERVICE_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ |
604 | + SERVICE_TYPE_PANEL, ServicePanelClass)) |
605 | + |
606 | +#define SERVICE_IS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ |
607 | + SERVICE_TYPE_PANEL)) |
608 | + |
609 | +#define SERVICE_IS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\ |
610 | + SERVICE_TYPE_PANEL)) |
611 | + |
612 | +#define ServicePanel_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ |
613 | + SERVICE_TYPE_PANEL, ServicePanelClass)) |
614 | + |
615 | +typedef struct _ServicePanel ServicePanel; |
616 | +typedef struct _ServicePanelClass ServicePanelClass; |
617 | +typedef struct _ServicePanelPrivate ServicePanelPrivate; |
618 | + |
619 | +struct _ServicePanel |
620 | +{ |
621 | + GObject parent; |
622 | + |
623 | + ServicePanelPrivate *priv; |
624 | +}; |
625 | + |
626 | +struct _ServicePanelClass |
627 | +{ |
628 | + GObjectClass parent_class; |
629 | +}; |
630 | + |
631 | +GType service_panel_get_type(void) G_GNUC_CONST; |
632 | + |
633 | +ServicePanel* service_panel_new(void); |
634 | + |
635 | +G_END_DECLS |
636 | + |
637 | +#endif /* _SERVICE_PANEL_H_ */ |
638 | |
639 | === modified file 'tests/test_utils.h' |
640 | --- tests/test_utils.h 2012-05-19 05:21:05 +0000 |
641 | +++ tests/test_utils.h 2012-10-08 14:36:19 +0000 |
642 | @@ -46,6 +46,20 @@ |
643 | EXPECT_TRUE(success); |
644 | } |
645 | |
646 | + static void WaitUntil(std::function<bool()> check_function, bool result = true, unsigned int max_wait = 10) |
647 | + { |
648 | + bool timeout_reached = false; |
649 | + guint32 timeout_id = ScheduleTimeout(&timeout_reached, max_wait * 1000); |
650 | + |
651 | + while (!check_function() && !timeout_reached) |
652 | + g_main_context_iteration(g_main_context_get_thread_default(), TRUE); |
653 | + |
654 | + if (check_function()) |
655 | + g_source_remove(timeout_id); |
656 | + |
657 | + EXPECT_EQ(check_function(), result); |
658 | + } |
659 | + |
660 | static guint32 ScheduleTimeout(bool* timeout_reached, unsigned int timeout_duration = 10) |
661 | { |
662 | return g_timeout_add(timeout_duration, TimeoutCallback, timeout_reached); |
Working in a unittest