Merge lp:~bregma/geis/lp-944822 into lp:geis

Proposed by Stephen M. Webb
Status: Merged
Merged at revision: 234
Proposed branch: lp:~bregma/geis/lp-944822
Merge into: lp:geis
Diff against target: 919 lines (+630/-45)
9 files modified
libutouch-geis/backend/grail/geis_grail_backend.c (+151/-42)
libutouch-geis/backend/grail/geis_ugsubscription_store.c (+39/-1)
libutouch-geis/backend/grail/geis_ugsubscription_store.h (+14/-0)
libutouch-geis/geis_filter_term.c (+123/-0)
libutouch-geis/geis_filter_term.h (+11/-0)
testsuite/geis2/gtest_devices.cpp (+182/-2)
testsuite/libutouch-geis/Makefile.am (+1/-0)
testsuite/libutouch-geis/check_filter_term.c (+107/-0)
testsuite/libutouch-geis/check_geis2_internals.c (+2/-0)
To merge this branch: bzr merge lp:~bregma/geis/lp-944822
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Review via email: mp+99851@code.launchpad.net

Description of the change

Adds handling of device additon and removal after subscriptions have been activated (lp: #944822).

To post a comment you must log in.
Revision history for this message
Chase Douglas (chasedouglas) wrote :

* In the integration test, you have "EXPECT_EQ(gesture_events_received, device_has_been_created);". If the device hasn't been created and no events are received we have failed, but this will pass. We need to be using EXPECT_TRUE on each individually.

* GTest test names shouldn't include underscores, according to: http://code.google.com/p/googletest/wiki/FAQ#Why_should_not_test_case_names_and_test_names_contain_underscore

Everything else looks good to me.

review: Needs Fixing
lp:~bregma/geis/lp-944822 updated
230. By Stephen M. Webb

Fixed test case names and conditions.

231. By Stephen M. Webb

Fixed problems with integration tests failing after GeisDeviceTests.removeDeviceSubscription was run.

Revision history for this message
Stephen M. Webb (bregma) wrote :

Test condition fixed, names changed, and test failures remedied.

Revision history for this message
Chase Douglas (chasedouglas) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libutouch-geis/backend/grail/geis_grail_backend.c'
2--- libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-28 21:31:54 +0000
3+++ libutouch-geis/backend/grail/geis_grail_backend.c 2012-03-29 18:37:22 +0000
4@@ -32,6 +32,7 @@
5 #include "geis_group.h"
6 #include "geis_logging.h"
7 #include "geis_private.h"
8+#include "geis_subscription.h"
9 #include "geis_test_api.h"
10 #include "geis_touch.h"
11 #include "geis_ugsubscription_store.h"
12@@ -89,6 +90,7 @@
13 GeisBag devices; /**< The list of known devices. */
14 GeisGrailWindowGrabStore window_grabs; /**< A collection of window inputs */
15 GeisBag slice_states; /**< Gesture slice states */
16+ GeisSubBag subscription_bag;
17
18 GeisGestureClass drag_class;
19 GeisGestureClass pinch_class;
20@@ -101,6 +103,12 @@
21 };
22
23
24+static GeisStatus
25+_grail_be_activate_for_device(GeisGrailBackend gbe,
26+ GeisFilter filter,
27+ GeisDevice device,
28+ GeisSubscription subscription);
29+
30 /**
31 * Hashes an ID from a UFDevice.
32 *
33@@ -640,6 +648,61 @@
34
35
36 /**
37+ * Activates active subscriptions for a newly-seen device.
38+ */
39+static void
40+_grail_be_subscribe_new_device(GeisGrailBackend gbe, GeisDevice device)
41+{
42+ for (GeisSubBagIterator it = geis_subscription_bag_begin(gbe->subscription_bag);
43+ it != geis_subscription_bag_end(gbe->subscription_bag);
44+ it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it))
45+ {
46+ for (GeisFilterIterator fit = geis_subscription_filter_begin(*it);
47+ fit != geis_subscription_filter_end(*it);
48+ fit = geis_subscription_filter_next(*it, fit))
49+ {
50+ GeisBoolean device_applies = GEIS_TRUE;
51+ for (GeisSize tindex = 0; tindex < geis_filter_term_count(*fit); ++tindex)
52+ {
53+ if (!geis_filter_term_match_device(geis_filter_term(*fit, tindex),
54+ device))
55+ {
56+ device_applies = GEIS_FALSE;
57+ break;
58+ }
59+ }
60+
61+ if (device_applies)
62+ {
63+ _grail_be_activate_for_device(gbe, *fit, device, *it);
64+ }
65+ }
66+ }
67+}
68+
69+
70+/**
71+ * Removes active subscriptions for recently-removed devices.
72+ */
73+static void
74+_grail_be_unsubscribe_removed_device(GeisGrailBackend gbe, UFDevice device)
75+{
76+ for (GeisSubBagIterator it = geis_subscription_bag_begin(gbe->subscription_bag);
77+ it != geis_subscription_bag_end(gbe->subscription_bag);
78+ it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it))
79+ {
80+ GeisUGSubscriptionStore ugstore = geis_subscription_pdata(*it);
81+ for (GeisFilterIterator fit = geis_subscription_filter_begin(*it);
82+ fit != geis_subscription_filter_end(*it);
83+ fit = geis_subscription_filter_next(*it, fit))
84+ {
85+ geis_ugsubscription_release_for_device(ugstore, *fit, device, gbe->window_grabs);
86+ }
87+ }
88+}
89+
90+
91+/**
92 * Reports an X11 device to the front end as a GEIS device.
93 */
94 static void
95@@ -738,7 +801,7 @@
96 / sizeof(struct GeisFilterableAttribute);
97
98 geis_register_device(gbe->geis, geis_device, attr_count, attrs);
99- goto final_exit;
100+ _grail_be_subscribe_new_device(gbe, geis_device);
101
102 final_exit:
103 return;
104@@ -758,6 +821,8 @@
105 return;
106 }
107
108+ _grail_be_unsubscribe_removed_device(gbe, frame_device);
109+
110 for (GeisSize i = 0; i < geis_bag_count(gbe->devices); ++i)
111 {
112 UFDevice *device = geis_bag_at(gbe->devices, i);
113@@ -1204,6 +1269,12 @@
114 goto unwind_grabs;
115 }
116
117+ gbe->subscription_bag = geis_subscription_bag_new(1);
118+ if (!gbe->subscription_bag)
119+ {
120+ goto unwind_slice_states;
121+ }
122+
123 geis_get_configuration(gbe->geis,
124 GEIS_CONFIG_SEND_TENTATIVE_EVENTS,
125 &gbe->send_tentative_events);
126@@ -1217,6 +1288,8 @@
127 _geis_grail_report_init_complete(gbe);
128 goto final_exit;
129
130+unwind_slice_states:
131+ geis_bag_delete(gbe->slice_states);
132 unwind_grabs:
133 geis_grail_window_grab_store_delete(gbe->window_grabs);
134 unwind_devices:
135@@ -1238,10 +1311,12 @@
136
137
138 static int
139-_grail_be_x_error_handler(Display* display GEIS_UNUSED,
140- XErrorEvent* event GEIS_UNUSED)
141+_grail_be_x_error_handler(Display* display,
142+ XErrorEvent* event)
143 {
144- geis_error("error in X detected");
145+ char buffer[512];
146+ XGetErrorText(display, (int)event->error_code, buffer, 511);
147+ geis_error("error %u in X detected: %s", (unsigned)event->error_code, buffer);
148 return 0;
149 }
150
151@@ -1255,6 +1330,7 @@
152 _geis_grail_backend_finalize(GeisBackend be)
153 {
154 GeisGrailBackend gbe = (GeisGrailBackend)be;
155+ geis_subscription_bag_delete(gbe->subscription_bag);
156 geis_bag_delete(gbe->slice_states);
157 geis_grail_window_grab_store_delete(gbe->window_grabs);
158 geis_bag_delete(gbe->devices);
159@@ -1630,51 +1706,44 @@
160 }
161
162
163-/**
164- * Activates a subscription for a list of devices.
165- */
166 static GeisStatus
167-_geis_grail_activate_for_devices(GeisGrailBackend gbe,
168- GeisFilter filter,
169- GeisDeviceBag device_bag,
170- GeisSubscription subscription)
171+_grail_be_activate_for_device(GeisGrailBackend gbe,
172+ GeisFilter filter,
173+ GeisDevice device,
174+ GeisSubscription subscription)
175 {
176 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
177- for (GeisSize d = 0; d < geis_device_bag_count(device_bag); ++d)
178+ GeisBoolean has_region_term = GEIS_FALSE;
179+ if (filter)
180 {
181- GeisDevice device = geis_device_bag_device(device_bag, d);
182- GeisBoolean has_region_term = GEIS_FALSE;
183- if (filter)
184+ for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i)
185 {
186- for (GeisSize i = 0; i < geis_filter_term_count(filter); ++i)
187+ GeisFilterTerm term = geis_filter_term(filter, i);
188+ if (GEIS_FILTER_REGION == geis_filter_term_facility(term))
189 {
190- GeisFilterTerm term = geis_filter_term(filter, i);
191- if (GEIS_FILTER_REGION == geis_filter_term_facility(term))
192- {
193- GeisInteger window_id = 0;
194- GeisAttr attr = geis_filter_term_attr(term);
195- GeisString name = geis_attr_name(attr);
196- GeisFilterOperation operation = geis_filter_term_operation(term);
197+ GeisInteger window_id = 0;
198+ GeisAttr attr = geis_filter_term_attr(term);
199+ GeisString name = geis_attr_name(attr);
200+ GeisFilterOperation operation = geis_filter_term_operation(term);
201
202- if (0 == strcmp(name, GEIS_REGION_ATTRIBUTE_WINDOWID)
203- && operation == GEIS_FILTER_OP_EQ)
204- {
205- window_id = geis_attr_value_to_integer(attr);
206- has_region_term = GEIS_TRUE;
207- status = _geis_grail_activate_for_device_region(gbe,
208- filter,
209- device,
210- window_id,
211- subscription);
212- if (status != GEIS_STATUS_SUCCESS)
213- {
214- goto final_exit;
215- }
216- }
217- else
218- {
219- geis_warning("unhandled region filter term");
220- }
221+ if (0 == strcmp(name, GEIS_REGION_ATTRIBUTE_WINDOWID)
222+ && operation == GEIS_FILTER_OP_EQ)
223+ {
224+ window_id = geis_attr_value_to_integer(attr);
225+ has_region_term = GEIS_TRUE;
226+ status = _geis_grail_activate_for_device_region(gbe,
227+ filter,
228+ device,
229+ window_id,
230+ subscription);
231+ if (status != GEIS_STATUS_SUCCESS)
232+ {
233+ goto final_exit;
234+ }
235+ }
236+ else
237+ {
238+ geis_warning("unhandled region filter term");
239 }
240 }
241 }
242@@ -1695,6 +1764,28 @@
243 return status;
244 }
245
246+
247+/**
248+ * Activates a subscription for a list of devices.
249+ */
250+static GeisStatus
251+_geis_grail_activate_for_devices(GeisGrailBackend gbe,
252+ GeisFilter filter,
253+ GeisDeviceBag device_bag,
254+ GeisSubscription subscription)
255+{
256+ GeisStatus status = GEIS_STATUS_SUCCESS;
257+ for (GeisSize d = 0; d < geis_device_bag_count(device_bag); ++d)
258+ {
259+ GeisDevice device = geis_device_bag_device(device_bag, d);
260+ status = _grail_be_activate_for_device(gbe, filter, device, subscription);
261+ if (status != GEIS_STATUS_SUCCESS)
262+ break;
263+ }
264+
265+ return status;
266+}
267+
268 static GeisStatus
269 _geis_grail_activate_with_filters(GeisGrailBackend gbe,
270 GeisSubscription subscription)
271@@ -1760,6 +1851,13 @@
272 {
273 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
274
275+ if (geis_subscription_bag_find(gbe->subscription_bag,
276+ geis_subscription_id(subscription)))
277+ {
278+ geis_warning("subscription is already activated");
279+ goto final_exit;
280+ }
281+
282 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);
283 if (ugstore == NULL)
284 {
285@@ -1784,6 +1882,8 @@
286 subscription);
287 }
288
289+ geis_subscription_bag_insert(gbe->subscription_bag, subscription);
290+
291 final_exit:
292 return status;
293 }
294@@ -1800,6 +1900,13 @@
295 {
296 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
297
298+ if (!geis_subscription_bag_find(gbe->subscription_bag,
299+ geis_subscription_id(subscription)))
300+ {
301+ geis_warning("deactivating a subscription that is not active");
302+ goto final_exit;
303+ }
304+
305 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);
306 if (ugstore)
307 {
308@@ -1824,9 +1931,11 @@
309 }
310
311 grail_subscription_deactivate(gbe->grail, ugsub);
312+ geis_subscription_bag_remove(gbe->subscription_bag, subscription);
313 }
314 }
315
316+final_exit:
317 return status;
318 }
319
320
321=== modified file 'libutouch-geis/backend/grail/geis_ugsubscription_store.c'
322--- libutouch-geis/backend/grail/geis_ugsubscription_store.c 2012-02-13 17:23:34 +0000
323+++ libutouch-geis/backend/grail/geis_ugsubscription_store.c 2012-03-29 18:37:22 +0000
324@@ -83,7 +83,7 @@
325 GeisSize index)
326 {
327 assert(index < geis_bag_count(store));
328- return *(UGSubscription*)geis_bag_at(store, index);
329+ return ((GeisUGSubscription)geis_bag_at(store, index))->ugsub;
330 }
331
332
333@@ -147,6 +147,44 @@
334 }
335
336
337+void
338+geis_ugsubscription_release_for_device(GeisUGSubscriptionStore store,
339+ GeisFilter filter,
340+ UFDevice device,
341+ GeisGrailWindowGrabStore window_grabs)
342+{
343+ GeisSize i = 0;
344+ while (i < geis_bag_count(store))
345+ {
346+ GeisUGSubscription s = (GeisUGSubscription)geis_bag_at(store, i);
347+ if (s->filter == filter && s->device == device)
348+ {
349+ UFWindowId ufwindow;
350+ UGStatus ugstatus;
351+ ugstatus = grail_subscription_get_property(s->ugsub,
352+ UGSubscriptionPropertyWindow,
353+ &ufwindow);
354+ if (ugstatus != UGStatusSuccess)
355+ {
356+ geis_warning("error %d getting subscription window", ugstatus);
357+ }
358+ else
359+ {
360+ Window window_id = frame_x11_get_window_id(ufwindow);
361+ geis_grail_window_grab_store_ungrab(window_grabs, window_id);
362+ }
363+
364+ grail_subscription_delete(s->ugsub);
365+ geis_bag_remove(store, i);
366+ }
367+ else
368+ {
369+ ++i;
370+ }
371+ }
372+}
373+
374+
375 /*
376 * Releses a UGSubscription from the store.
377 */
378
379=== modified file 'libutouch-geis/backend/grail/geis_ugsubscription_store.h'
380--- libutouch-geis/backend/grail/geis_ugsubscription_store.h 2012-02-10 04:26:23 +0000
381+++ libutouch-geis/backend/grail/geis_ugsubscription_store.h 2012-03-29 18:37:22 +0000
382@@ -22,6 +22,7 @@
383
384 #include "geis/geis.h"
385 #include "geis_bag.h"
386+#include "geis_grail_window_grab.h"
387 #include <utouch/grail.h>
388
389
390@@ -95,6 +96,19 @@
391 GeisInteger region_id);
392
393 /**
394+ * Releases all UGSubscriptions for a (filter, device).
395+ * @param[in] store The grail subscription store.
396+ * @param[in] filter Identifies a filter.
397+ * @param[in] device Identifies a device.
398+ * @param[in] window_grabs A window grab collection.
399+ */
400+void
401+geis_ugsubscription_release_for_device(GeisUGSubscriptionStore store,
402+ GeisFilter filter,
403+ UFDevice device,
404+ GeisGrailWindowGrabStore window_grabs);
405+
406+/**
407 * Releses a UGSubscription from the store.
408 * @param[in] store The grail subscription store.
409 * @param[in] ugsub The UGSubscription to release.
410
411=== modified file 'libutouch-geis/geis_filter_term.c'
412--- libutouch-geis/geis_filter_term.c 2011-10-18 18:41:30 +0000
413+++ libutouch-geis/geis_filter_term.c 2012-03-29 18:37:22 +0000
414@@ -369,3 +369,126 @@
415 }
416
417
418+/**
419+ * Indicates if an attr string value matches a given string and condition.
420+ *
421+ * @param[in] attr The attr with a string value.
422+ * @param[in] op A match condition.
423+ * @param[in] svalue A target string value to match.
424+ *
425+ * @returns GEIS_TRUE if the attr string value matches the target string and
426+ * condition, GEIS_FALSE otherwise.
427+ */
428+static GeisBoolean
429+_filter_matches_attr_string(GeisAttr attr,
430+ GeisFilterOperation op,
431+ GeisString svalue)
432+{
433+ GeisBoolean strings_match = GEIS_FALSE;
434+ GeisString attr_value = geis_attr_value_to_string(attr);
435+ if (attr_value)
436+ {
437+ strings_match = (0 == strcmp(attr_value, svalue));
438+ }
439+ return (op == GEIS_FILTER_OP_EQ && strings_match)
440+ || (op == GEIS_FILTER_OP_NE && !strings_match);
441+}
442+
443+
444+/**
445+ * Indicates if an attr boolean value matches a given value and condition.
446+ *
447+ * @param[in] attr The attr with a string value.
448+ * @param[in] op A match condition.
449+ * @param[in] bvalue A target boolean value to match.
450+ *
451+ * @returns GEIS_TRUE if the attr boolean value matches the target value and
452+ * condition, GEIS_FALSE otherwise.
453+ */
454+static GeisBoolean
455+_filter_matches_attr_boolean(GeisAttr attr,
456+ GeisFilterOperation op,
457+ GeisBoolean bvalue)
458+{
459+ GeisBoolean attr_value = geis_attr_value_to_boolean(attr);
460+ return (op == GEIS_FILTER_OP_EQ && attr_value == bvalue)
461+ || (op == GEIS_FILTER_OP_NE && attr_value != bvalue);
462+}
463+
464+
465+/**
466+ * Indicates if an attr integer value matches a given value and condition.
467+ *
468+ * @param[in] attr The attr with a string value.
469+ * @param[in] op A match condition.
470+ * @param[in] ivalue A target integer value to match.
471+ *
472+ * @returns GEIS_TRUE if the attr integer value matches the target value and
473+ * condition, GEIS_FALSE otherwise.
474+ */
475+static GeisBoolean
476+_filter_matches_attr_integer(GeisAttr attr,
477+ GeisFilterOperation op,
478+ GeisInteger ivalue)
479+{
480+ GeisInteger attr_value = geis_attr_value_to_integer(attr);
481+ return (op == GEIS_FILTER_OP_EQ && attr_value == ivalue)
482+ || (op == GEIS_FILTER_OP_NE && attr_value != ivalue)
483+ || (op == GEIS_FILTER_OP_GT && attr_value > ivalue)
484+ || (op == GEIS_FILTER_OP_GE && attr_value >= ivalue)
485+ || (op == GEIS_FILTER_OP_LE && attr_value <= ivalue)
486+ || (op == GEIS_FILTER_OP_LT && attr_value < ivalue);
487+}
488+
489+
490+/*
491+ * Indicates a filter passes a device.
492+ */
493+GeisBoolean
494+geis_filter_term_match_device(GeisFilterTerm term, GeisDevice device)
495+{
496+ if (geis_filter_term_facility(term) != GEIS_FILTER_DEVICE)
497+ {
498+ return GEIS_TRUE;
499+ }
500+
501+ GeisAttr filter_attr = geis_filter_term_attr(term);
502+ GeisString attr_name = geis_attr_name(filter_attr);
503+ GeisFilterOperation op = geis_filter_term_operation(term);
504+
505+ if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_NAME))
506+ {
507+ GeisString device_name = geis_device_name(device);
508+ if (device_name)
509+ {
510+ return _filter_matches_attr_string(filter_attr, op, device_name);
511+ }
512+ }
513+ else if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH)
514+ || 0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_INDEPENDENT_TOUCH))
515+ {
516+ GeisAttr device_attr = geis_device_attr_by_name(device, attr_name);
517+ if (device_attr)
518+ {
519+ GeisBoolean device_value = geis_attr_value_to_boolean(device_attr);
520+ return _filter_matches_attr_boolean(filter_attr, op, device_value);
521+ }
522+ }
523+ else if (0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_ID)
524+ || 0 == strcmp(attr_name, GEIS_DEVICE_ATTRIBUTE_TOUCHES))
525+ {
526+ GeisAttr device_attr = geis_device_attr_by_name(device, attr_name);
527+ if (device_attr)
528+ {
529+ GeisInteger device_value = geis_attr_value_to_integer(device_attr);
530+ /* legacy special case for device ID == 0: means ALL devices in v1 */
531+ if (device_value == 0)
532+ {
533+ return GEIS_TRUE;
534+ }
535+ return _filter_matches_attr_integer(filter_attr, op, device_value);
536+ }
537+ }
538+ return GEIS_FALSE;
539+}
540+
541
542=== modified file 'libutouch-geis/geis_filter_term.h'
543--- libutouch-geis/geis_filter_term.h 2011-10-13 17:49:59 +0000
544+++ libutouch-geis/geis_filter_term.h 2012-03-29 18:37:22 +0000
545@@ -93,6 +93,17 @@
546 */
547 GeisBoolean geis_filter_term_match_event(GeisFilterTerm term, GeisEvent event);
548
549+/**
550+ * Indicates a filter passes a device.
551+ *
552+ * @param[in] term The filter term.
553+ * @param[in] device A GEIS device.
554+ *
555+ * @returns GEIS_TRUE if the device is passed by the filter, GEIS_FALSE
556+ * otherwise.
557+ */
558+GeisBoolean geis_filter_term_match_device(GeisFilterTerm term, GeisDevice device);
559+
560 /** @} */
561
562 /**
563
564=== modified file 'testsuite/geis2/gtest_devices.cpp'
565--- testsuite/geis2/gtest_devices.cpp 2012-03-22 18:44:56 +0000
566+++ testsuite/geis2/gtest_devices.cpp 2012-03-29 18:37:22 +0000
567@@ -4,13 +4,20 @@
568 * Copyright 2012 Canonical Ltd.
569 */
570 #include "geis/geis.h"
571+#include "gtest_evemu_device.h"
572+#include "gtest_geis_fixture.h"
573 #include "libutouch-geis/geis_test_api.h"
574-#include "gtest_geis_fixture.h"
575+#include <memory>
576+#include <sys/select.h>
577+#include <sys/time.h>
578
579
580 namespace
581 {
582
583+static const std::string TEST_DEVICE_PROP_FILE("touchscreen_a.prop");
584+static const std::string TEST_DEVICE_EVENTS_FILE("touchscreen_a_rotate90.events");
585+
586 /**
587 * Fixture for testing device handling.
588 * This is a separate class because gtest uses Java reflection.
589@@ -29,7 +36,7 @@
590 };
591
592
593-TEST_F(GeisDeviceTests, filter_with_no_devices)
594+TEST_F(GeisDeviceTests, filterWithNoDevices)
595 {
596 GeisSubscription sub = geis_subscription_new(geis_,
597 "no devices",
598@@ -48,4 +55,177 @@
599 geis_subscription_delete(sub);
600 }
601
602+
603+/*
604+ * Test case 1 for lp:944822 -- device added after subscription activated.
605+ *
606+ * Creates a subscriptions with a device filter (there are no devices present in
607+ * the system). When initializatiom signalled as complete, device events are
608+ * reenabled in the geis instance and a new device is added. When the
609+ * device-added event is received, a recording is run through the device.
610+ * Gesture events should be detected.
611+ */
612+TEST_F(GeisDeviceTests, addDeviceSubscription)
613+{
614+ std::unique_ptr<Testsuite::EvemuDevice> new_device;
615+ GeisBoolean device_has_been_created = GEIS_FALSE;
616+ GeisBoolean gesture_events_received = GEIS_FALSE;
617+
618+ GeisSubscription sub = geis_subscription_new(geis_,
619+ "no devices",
620+ GEIS_SUBSCRIPTION_NONE);
621+ EXPECT_TRUE(sub != NULL) << "can not create subscription";
622+ GeisFilter filter = geis_filter_new(geis_, "rotate");
623+ EXPECT_TRUE(filter != NULL) << "can not create filter";
624+ GeisStatus fs = geis_filter_add_term(filter,
625+ GEIS_FILTER_DEVICE,
626+ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
627+ NULL);
628+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term";
629+ fs = geis_subscription_add_filter(sub, filter);
630+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term";
631+
632+ GeisStatus dispatch_status= geis_dispatch_events(geis_);
633+ while (dispatch_status == GEIS_STATUS_CONTINUE
634+ || dispatch_status == GEIS_STATUS_SUCCESS)
635+ {
636+ GeisEvent event;
637+ GeisStatus event_status = geis_next_event(geis_, &event);
638+ while (event_status == GEIS_STATUS_CONTINUE
639+ || event_status == GEIS_STATUS_SUCCESS)
640+ {
641+ switch (geis_event_type(event))
642+ {
643+ case GEIS_EVENT_INIT_COMPLETE:
644+ {
645+ EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub))
646+ << "can not activate subscription";
647+
648+ GeisBoolean off = GEIS_FALSE;
649+ geis_set_configuration(geis_,
650+ GEIS_CONFIG_DISCARD_DEVICE_MESSAGES,
651+ &off);
652+ new_device.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE));
653+ device_has_been_created = GEIS_TRUE;
654+ break;
655+ }
656+
657+ case GEIS_EVENT_DEVICE_AVAILABLE:
658+ new_device->play(TEST_DEVICE_EVENTS_FILE);
659+ break;
660+
661+ case GEIS_EVENT_GESTURE_BEGIN:
662+ case GEIS_EVENT_GESTURE_UPDATE:
663+ {
664+ EXPECT_EQ(device_has_been_created, GEIS_TRUE)
665+ << "gesture events without device";
666+ gesture_events_received = device_has_been_created;
667+ }
668+
669+ default:
670+ break;
671+ }
672+
673+ geis_event_delete(event);
674+ event_status = geis_next_event(geis_, &event);
675+ }
676+
677+ fd_set read_fds;
678+ FD_ZERO(&read_fds);
679+ FD_SET(geis_fd(), &read_fds);
680+ timeval tmo = { 5, 0 };
681+ int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo);
682+ EXPECT_GT(sstat, -1) << "error in select";
683+ if (sstat == 0)
684+ break;
685+ dispatch_status = geis_dispatch_events(geis_);
686+ }
687+
688+ EXPECT_TRUE(gesture_events_received) << "no gesture events received";
689+ EXPECT_TRUE(device_has_been_created) << "no device created";
690+ geis_filter_delete(filter);
691+ geis_subscription_delete(sub);
692+}
693+
694+
695+/*
696+ * Test case 2 for lp:944822 -- device removed after subscription activated.
697+ *
698+ * This test really just makes sure nothing segfaults on device removal.
699+ */
700+TEST_F(GeisDeviceTests, removeDeviceSubscription)
701+{
702+ std::unique_ptr<Testsuite::EvemuDevice> new_device;
703+
704+ GeisSubscription sub = geis_subscription_new(geis_,
705+ "remove devices",
706+ GEIS_SUBSCRIPTION_NONE);
707+ EXPECT_TRUE(sub != NULL) << "can not create subscription";
708+ GeisFilter filter = geis_filter_new(geis_, "rotate");
709+ EXPECT_TRUE(filter != NULL) << "can not create filter";
710+ GeisStatus fs = geis_filter_add_term(filter,
711+ GEIS_FILTER_DEVICE,
712+ GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, GEIS_FILTER_OP_EQ, GEIS_TRUE,
713+ NULL);
714+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term";
715+ fs = geis_subscription_add_filter(sub, filter);
716+ EXPECT_EQ(fs, GEIS_STATUS_SUCCESS) << "can not add device term";
717+
718+ GeisStatus dispatch_status= geis_dispatch_events(geis_);
719+ while (dispatch_status == GEIS_STATUS_CONTINUE
720+ || dispatch_status == GEIS_STATUS_SUCCESS)
721+ {
722+ GeisEvent event;
723+ GeisStatus event_status = geis_next_event(geis_, &event);
724+ while (event_status == GEIS_STATUS_CONTINUE
725+ || event_status == GEIS_STATUS_SUCCESS)
726+ {
727+ switch (geis_event_type(event))
728+ {
729+ case GEIS_EVENT_INIT_COMPLETE:
730+ {
731+ GeisBoolean off = GEIS_FALSE;
732+ geis_set_configuration(geis_,
733+ GEIS_CONFIG_DISCARD_DEVICE_MESSAGES,
734+ &off);
735+ new_device.reset(new Testsuite::EvemuDevice(TEST_DEVICE_PROP_FILE));
736+ break;
737+ }
738+
739+ case GEIS_EVENT_DEVICE_AVAILABLE:
740+ {
741+ EXPECT_EQ(GEIS_STATUS_SUCCESS, geis_subscription_activate(sub))
742+ << "can not activate subscription";
743+ new_device.reset();
744+ break;
745+ }
746+
747+ case GEIS_EVENT_GESTURE_BEGIN:
748+ case GEIS_EVENT_GESTURE_UPDATE:
749+ {
750+ }
751+
752+ default:
753+ break;
754+ }
755+
756+ geis_event_delete(event);
757+ event_status = geis_next_event(geis_, &event);
758+ }
759+
760+ fd_set read_fds;
761+ FD_ZERO(&read_fds);
762+ FD_SET(geis_fd(), &read_fds);
763+ timeval tmo = { 5, 0 };
764+ int sstat = select(geis_fd() + 1, &read_fds, NULL, NULL, &tmo);
765+ EXPECT_GT(sstat, -1) << "error in select";
766+ if (sstat == 0)
767+ break;
768+ dispatch_status = geis_dispatch_events(geis_);
769+ }
770+ geis_filter_delete(filter);
771+ geis_subscription_delete(sub);
772+}
773+
774+
775 } // anonymous namespace
776
777=== modified file 'testsuite/libutouch-geis/Makefile.am'
778--- testsuite/libutouch-geis/Makefile.am 2012-03-07 03:44:00 +0000
779+++ testsuite/libutouch-geis/Makefile.am 2012-03-29 18:37:22 +0000
780@@ -53,6 +53,7 @@
781 check_error_reporting.c \
782 check_event_queue.c \
783 check_filter.c \
784+ check_filter_term.c \
785 check_geis_private.c \
786 check_region.c \
787 check_subscription.c \
788
789=== added file 'testsuite/libutouch-geis/check_filter_term.c'
790--- testsuite/libutouch-geis/check_filter_term.c 1970-01-01 00:00:00 +0000
791+++ testsuite/libutouch-geis/check_filter_term.c 2012-03-29 18:37:22 +0000
792@@ -0,0 +1,107 @@
793+/**
794+ * @file check_filter_term.c
795+ * @brief unit tests for GEIS filter terms
796+ *
797+ * Copyright 2012 Canonical Ltd.
798+ */
799+#include <check.h>
800+#include "libutouch-geis/geis_attr.h"
801+#include "libutouch-geis/geis_device.h"
802+#include "libutouch-geis/geis_filter_term.h"
803+
804+/* verify filter term construction/destruction */
805+START_TEST(construct)
806+{
807+ GeisInteger ival = 0;
808+ GeisAttr attr = geis_attr_new("dummy", GEIS_ATTR_TYPE_INTEGER, &ival);
809+ fail_unless(attr != NULL, "failed to create filter term attr");
810+
811+ GeisFilterTerm term = geis_filter_term_new(GEIS_FILTER_SPECIAL,
812+ GEIS_FILTER_OP_NE,
813+ attr);
814+ fail_unless(term != NULL, "failed to create filter term");
815+
816+ geis_filter_term_unref(term);
817+}
818+END_TEST
819+
820+
821+/* verify device filtering capability */
822+START_TEST(device_filter)
823+{
824+ GeisString device_name = "direct";
825+ GeisAttr name_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_NAME,
826+ GEIS_ATTR_TYPE_STRING,
827+ (void *)device_name);
828+ fail_unless(name_attr != NULL, "failed to create name filter term attr");
829+ GeisFilterTerm name_term = geis_filter_term_new(GEIS_FILTER_DEVICE,
830+ GEIS_FILTER_OP_NE,
831+ name_attr);
832+ fail_unless(name_term != NULL, "failed to create id filter term");
833+
834+ GeisBoolean is_direct = GEIS_TRUE;
835+ GeisAttr direct_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH,
836+ GEIS_ATTR_TYPE_BOOLEAN,
837+ &is_direct);
838+ fail_unless(direct_attr != NULL, "failed to create direct filter term attr");
839+ GeisFilterTerm direct_term = geis_filter_term_new(GEIS_FILTER_DEVICE,
840+ GEIS_FILTER_OP_EQ,
841+ direct_attr);
842+ fail_unless(direct_term != NULL, "failed to create direct filter term");
843+
844+ GeisInteger id = 1;
845+ GeisAttr id_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_ID,
846+ GEIS_ATTR_TYPE_INTEGER,
847+ &id);
848+ fail_unless(id_attr != NULL, "failed to create id filter term attr");
849+ GeisFilterTerm id_term = geis_filter_term_new(GEIS_FILTER_DEVICE,
850+ GEIS_FILTER_OP_EQ,
851+ id_attr);
852+ fail_unless(id_term != NULL, "failed to create id filter term");
853+
854+ GeisDevice direct_device = geis_device_new(device_name, id);
855+ GeisAttr device_attr = geis_attr_new(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH,
856+ GEIS_ATTR_TYPE_BOOLEAN,
857+ &is_direct);
858+ fail_unless(device_attr != NULL, "failed to create direct filter term attr");
859+ geis_device_add_attr(direct_device, device_attr);
860+ GeisDevice indirect_device = geis_device_new("indirect", id + 1);
861+
862+ GeisBoolean passed = GEIS_FALSE;
863+ passed = geis_filter_term_match_device(name_term, direct_device);
864+ fail_unless(passed != GEIS_TRUE, "direct device was passed by name term");
865+ passed = geis_filter_term_match_device(name_term, indirect_device);
866+ fail_unless(passed == GEIS_TRUE, "indirect device was not passed by name term");
867+ passed = geis_filter_term_match_device(direct_term, direct_device);
868+ fail_unless(passed == GEIS_TRUE, "direct device was not passed by direct term");
869+ passed = geis_filter_term_match_device(direct_term, indirect_device);
870+ fail_unless(passed != GEIS_TRUE, "indirect device was passed by direct term");
871+ passed = geis_filter_term_match_device(id_term, direct_device);
872+ fail_unless(passed == GEIS_TRUE, "direct device was not passed by id term");
873+ passed = geis_filter_term_match_device(id_term, indirect_device);
874+ fail_unless(passed != GEIS_TRUE, "indirect device was passed by id term");
875+
876+ geis_device_unref(direct_device);
877+ geis_device_unref(indirect_device);
878+ geis_filter_term_unref(name_term);
879+ geis_filter_term_unref(direct_term);
880+ geis_filter_term_unref(id_term);
881+}
882+END_TEST
883+
884+/* boilerplate */
885+Suite *
886+make_filter_term_suite()
887+{
888+ Suite *s = suite_create("utouch-geis2-filter-term");
889+
890+ TCase *create = tcase_create("filter-term-creation");
891+ tcase_add_test(create, construct);
892+ suite_add_tcase(s, create);
893+
894+ TCase *usage = tcase_create("filter-term-usage");
895+ tcase_add_test(usage, device_filter);
896+ suite_add_tcase(s, usage);
897+
898+ return s;
899+}
900
901=== modified file 'testsuite/libutouch-geis/check_geis2_internals.c'
902--- testsuite/libutouch-geis/check_geis2_internals.c 2011-12-21 04:14:05 +0000
903+++ testsuite/libutouch-geis/check_geis2_internals.c 2012-03-29 18:37:22 +0000
904@@ -13,6 +13,7 @@
905 extern Suite *make_error_reporting_suite();
906 extern Suite *make_event_queue_suite();
907 extern Suite *make_filter_suite();
908+extern Suite *make_filter_term_suite();
909 extern Suite *make_gesture_class_suite();
910 extern Suite *make_region_suite();
911 extern Suite *make_select_devices_suite();
912@@ -38,6 +39,7 @@
913 srunner_add_suite(sr, make_gesture_class_suite());
914 srunner_add_suite(sr, make_region_suite());
915 srunner_add_suite(sr, make_filter_suite());
916+ srunner_add_suite(sr, make_filter_term_suite());
917 srunner_add_suite(sr, make_select_devices_suite());
918 srunner_add_suite(sr, make_subscription_suite());
919 srunner_add_suite(sr, make_timer_suite());

Subscribers

People subscribed via source and target branches