Merge lp:~oif-team/geis/geis2_add_regions into lp:geis

Proposed by Stephen M. Webb
Status: Merged
Merged at revision: 96
Proposed branch: lp:~oif-team/geis/geis2_add_regions
Merge into: lp:geis
Diff against target: 778 lines (+660/-0)
12 files modified
ChangeLog (+21/-0)
include/geis/geis.h (+58/-0)
libutouch-geis/Makefile.am (+1/-0)
libutouch-geis/geis_region.c (+291/-0)
libutouch-geis/geis_region.h (+103/-0)
libutouch-geis/libutouch-geis.ver (+3/-0)
testsuite/geis2/Makefile.am (+1/-0)
testsuite/geis2/check_geis2_api.c (+2/-0)
testsuite/geis2/check_region.c (+65/-0)
testsuite/libutouch-geis/Makefile.am (+1/-0)
testsuite/libutouch-geis/check_geis2_internals.c (+2/-0)
testsuite/libutouch-geis/check_region.c (+112/-0)
To merge this branch: bzr merge lp:~oif-team/geis/geis2_add_regions
Reviewer Review Type Date Requested Status
Henrik Rydberg (community) Approve
Review via email: mp+43901@code.launchpad.net

Description of the change

Added GEIS v2.0 region module with accompanying unit test suites.

To post a comment you must log in.
Revision history for this message
Henrik Rydberg (rydberg) wrote :

//GeisRegion geis_region_new()
+ geis_error("error allocaring region");

+ while (init_arg_name)
+ {
+ if (0 == strcmp(init_arg_name, GEIS_REGION_X11_ROOT))
+ {
+ region->type = strdup(init_arg_name);
+ geis_debug("using X11 root");

a break here would make it more apparent that type is normally assigned once

+ }
+ else if (0 == strcmp(init_arg_name, GEIS_REGION_X11_WINDOWID))
+ {
+ region->type = strdup(init_arg_name);
+ region->data.windowid = va_arg(varargs, int);
+ geis_debug("using X11 windowid 0x%08x", region->data.windowid);

ditto

+ }

//GeisStatus geis_region_delete(GeisRegion region)
+{
+ --region->ref_count;
+ if (0 == region->ref_count)

With this construct, we will have to be careful when using threads operating under mutexes against a single geis instance. If two threads happen to queue for the same code path... boom.

Reading on, I see you already warn about this in the text.

A way around this is to split the ref counting from the actual freeing, and keep old regions around for recycling.

+ {
+ if (region->name)
+ free((char *)region->name);
+ free((char *)region->type);
+ free(region);
+ }
+ return GEIS_STATUS_SUCCESS;
+}

Thanks!

review: Needs Fixing
lp:~oif-team/geis/geis2_add_regions updated
96. By Stephen M. Webb

Added GEIS v2.0 region module.

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

Fixed the comment typo, added the missing duplicate checks, and made the refcounting atomic to avoid threading issues. The container is still not threadsafe, that can come later.

Revision history for this message
Henrik Rydberg (rydberg) wrote :

Very nice! The "if (region->name)" is redundant, but never mind.

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

I know this has been merged, but I would like to see geis_region_delete() renamed to something like geis_region_deref() or geis_region_release(). Delete implies that the object will be freed immediately, which is not what happens here if a reference is held elsewhere.

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

On Tue, 2010-12-21 at 18:28 +0000, Chase Douglas wrote:
> I know this has been merged, but I would like to see geis_region_delete() renamed to something
> like geis_region_deref() or geis_region_release(). Delete implies that the object will be freed
> immediately, which is not what happens here if a reference is held elsewhere.

That would be awfully confusing for the library user, considering there
is no geis_region_ref() anywhere in sight. In fact, the library user
has no idea this is a reference counted object. As far as they are
concerned, when they call geis_region_delete(), the object is deleted
and is no longer valid.

The refcounting is an internal feature of this particular object to
ensure persistence event though lifetime control is in the user's hands.
The refcounting is explicit on other objects because they are created by
the API rather than the user.

The rest of the library uses _new() and _delete() as the construction
and destruction calls where object lifetime is under the control of the
user. Consistency in an API is a good thing.

I'm less worried about what has to go on under the hood to make things
easier for the library user, since I'm assuming anyone who is
maintaining the library is capable of figuring things out by reading the
code. The typical library user should not have to read the code.

--
Stephen M. Webb <email address hidden>
Canonical Ltd.

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

Ahh, I thought the _ref() function was public. I'm fine with it as is then.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2010-12-15 01:48:35 +0000
3+++ ChangeLog 2010-12-17 02:59:09 +0000
4@@ -1,3 +1,24 @@
5+2010-12-15 Stephen M. Webb <stephen.webb@canonical.com>
6+
7+ Added GEIS v2.0 region module.
8+
9+ * libutouch-geis/geis_region.c: new file
10+ * libutouch-geis/geis_region.h: new file
11+ * testsuite/geis2/check_region.c: new test suite
12+ * testsuite/libutouch-geis/check_region.c: new test suite
13+ * include/geis/geis.h (GeisRegion): new typedef
14+ (GEIS_REGION_X11_ROOT): new region initialization constant
15+ (GEIS_REGION_X11_WINDOWID): new region initialization constant
16+ (geis_region_new): new function
17+ (geis_region_delete): new function
18+ (geis_region_name): new function
19+ * libutouch-geis/Makefile.am: added new files
20+ * libutouch-geis/libutouch-geis.ver: added new symbols
21+ * testsuite/geis2/Makefile.am: added new test suite files
22+ * testsuite/geis2/check_geis2_api.c: added new test suite
23+ * testsuite/libutouch-geis/Makefile.am: added new test suite files
24+ * testsuite/libutouch-geis/check_geis2_internals.c: added new test suite
25+
26 2010-12-12 Stephen M. Webb <stephen.webb@canonical.com>
27
28 Fixed some container expansion errors.
29
30=== modified file 'include/geis/geis.h'
31--- include/geis/geis.h 2010-12-15 01:48:35 +0000
32+++ include/geis/geis.h 2010-12-17 02:59:09 +0000
33@@ -636,6 +636,64 @@
34 /* @} */
35
36 /**
37+ * @defgroup geis2_region Gesture Regions (GEIS v2.0)
38+ * @{
39+ */
40+
41+typedef struct _GeisRegion *GeisRegion;
42+
43+/**
44+ * @defgroup geis2_region_init_args Gesture Region Initialization Arguments
45+ *
46+ * Gesture regions are created to describe a particular display/feedback region.
47+ * The type of the region can not be changed after creation (just create a new
48+ * region for that). The types of regions are platform specific and each type
49+ * may require addition arguments.
50+ *
51+ * The following region initialization argument names are required by the
52+ * GEIS v2.0 specification.
53+ *
54+ * @{
55+ */
56+#define GEIS_REGION_X11_ROOT "org.libgeis.region.x11.root"
57+#define GEIS_REGION_X11_WINDOWID "org.libgeis.region.x11.windowid"
58+
59+/* @} */
60+
61+/**
62+ * Creates a new GEIS v2.0 region.
63+ *
64+ * @param[in] geis The GEIS API instance.
65+ * @param[in] name A name. Used for diagnostics.
66+ * @param[in] init_arg_name The name of the first initialization argument.
67+ *
68+ * The initialization argument list must be terminated by a NULL.
69+ *
70+ * @returns a newly created region, or NULL on failure.
71+ */
72+GEIS_API GeisRegion geis_region_new(Geis geis,
73+ GeisString name,
74+ GeisString init_arg_name, ...);
75+
76+/**
77+ * Destroys a GEIS v2.0 region.
78+ *
79+ * @param[in] region The region.
80+ */
81+GEIS_API GeisStatus geis_region_delete(GeisRegion region);
82+
83+/**
84+ * Gets the name of a GEIS v2.0 region.
85+ *
86+ * @param[in] region The region.
87+ *
88+ * Returns the @p name value used when creating the region.
89+ */
90+GEIS_API GeisString geis_region_name(GeisRegion region);
91+
92+/* @} */
93+
94+/**
95 * @defgroup geis2_subscription Gesture Subscription (GEIS v2.0)
96 * @{
97 */
98
99=== modified file 'libutouch-geis/Makefile.am'
100--- libutouch-geis/Makefile.am 2010-12-09 16:14:15 +0000
101+++ libutouch-geis/Makefile.am 2010-12-17 02:59:09 +0000
102@@ -32,6 +32,7 @@
103 geis_event.h geis_event.c \
104 geis_event_queue.h geis_event_queue.c \
105 geis_logging.h geis_logging.c \
106+ geis_region.h geis_region.c \
107 geis_subscription.h geis_subscription.c \
108 geis_private.h geis.c
109
110
111=== added file 'libutouch-geis/geis_region.c'
112--- libutouch-geis/geis_region.c 1970-01-01 00:00:00 +0000
113+++ libutouch-geis/geis_region.c 2010-12-17 02:59:09 +0000
114@@ -0,0 +1,291 @@
115+/**
116+ * @file libutouch-geis/geis_region.c
117+ * @brief implementation of the uTouch GEIS v2.0 API region module
118+ *
119+ * Copyright 2010 Canonical Ltd.
120+ *
121+ * This library is free software; you can redistribute it and/or modify it under
122+ * the terms of the GNU Lesser General Public License as published by the Free
123+ * Software Foundation; either version 3 of the License, or (at your option) any
124+ * later version.
125+ *
126+ * This library is distributed in the hope that it will be useful, but WITHOUT
127+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
128+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
129+ * details.
130+ *
131+ * You should have received a copy of the GNU Lesser General Public License
132+ * along with this program; if not, write to the Free Software Foundation, Inc.,
133+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
134+ */
135+#include "geis_config.h"
136+#include "geis_region.h"
137+
138+#include "geis_error.h"
139+#include "geis_logging.h"
140+#include <string.h>
141+#include <stdarg.h>
142+#include <stdlib.h>
143+
144+
145+struct _GeisRegion
146+{
147+ int ref_count;
148+ GeisString type;
149+ GeisString name;
150+ union {
151+ int windowid;
152+ } data;
153+};
154+
155+struct _GeisRegionBag
156+{
157+ GeisRegion *region_store;
158+ GeisSize region_store_size;
159+ GeisSize region_count;
160+};
161+
162+static const int region_bag_growth_constant = 2;
163+
164+
165+/*
166+ * Constructs a region bag.
167+ */
168+GeisRegionBag
169+geis_region_bag_new()
170+{
171+ GeisRegionBag bag = calloc(1, sizeof(struct _GeisRegionBag));
172+ if (!bag)
173+ {
174+ geis_error("failed to allocate region bag");
175+ goto final_exit;
176+ }
177+
178+ bag->region_store_size = 3;
179+ bag->region_count = 0;
180+ bag->region_store = calloc(bag->region_store_size, sizeof(GeisRegion));
181+ if (!bag->region_store)
182+ {
183+ geis_error("failed to allocate region bag store");
184+ goto unwind_bag;
185+ }
186+ goto final_exit;
187+
188+unwind_bag:
189+ free(bag);
190+final_exit:
191+ return bag;
192+}
193+
194+
195+/*
196+ * Destroys a region bag.
197+ */
198+void
199+geis_region_bag_delete(GeisRegionBag bag)
200+{
201+ GeisSize i;
202+ for (i = bag->region_count; i > 0; --i)
203+ {
204+ geis_region_delete(bag->region_store[i-1]);
205+ }
206+ free(bag);
207+}
208+
209+
210+/*
211+ * Gets the number of regions held in a bag.
212+ */
213+GeisSize
214+geis_region_bag_count(GeisRegionBag bag)
215+{
216+ return bag->region_count;
217+}
218+
219+
220+/*
221+ * Gets an indicated region from a bag.
222+ */
223+GeisRegion
224+geis_region_bag_region(GeisRegionBag bag, GeisSize index)
225+{
226+ GeisRegion region = NULL;
227+ if (index < bag->region_count)
228+ {
229+ region = bag->region_store[index];
230+ }
231+ return region;
232+}
233+
234+
235+/*
236+ * Puts a region into a bag.
237+ */
238+GeisStatus
239+geis_region_bag_insert(GeisRegionBag bag, GeisRegion region)
240+{
241+ GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
242+ if (bag->region_count >= bag->region_store_size)
243+ {
244+ GeisSize new_store_size = bag->region_store_size * region_bag_growth_constant;
245+ GeisRegion *new_store = realloc(bag->region_store,
246+ new_store_size * sizeof(struct _GeisRegion));
247+ if (!new_store)
248+ {
249+ geis_error("failed to reallocate region bag");
250+ goto error_exit;
251+ }
252+ bag->region_store = new_store;
253+ bag->region_store_size = new_store_size;
254+ }
255+ bag->region_store[bag->region_count++] = region;
256+ status = GEIS_STATUS_SUCCESS;
257+
258+error_exit:
259+ return status;
260+}
261+
262+
263+/**
264+ * Takes a region out of a bag.
265+ */
266+GeisStatus
267+geis_region_bag_remove(GeisRegionBag bag, GeisRegion region)
268+{
269+ GeisSize i;
270+ GeisStatus status = GEIS_STATUS_SUCCESS;
271+ for (i = 0; i < bag->region_count; ++i)
272+ {
273+ if (bag->region_store[i] == region)
274+ {
275+ GeisSize j;
276+ geis_region_delete(bag->region_store[i]);
277+ --bag->region_count;
278+ for (j = i; j < bag->region_count; ++j)
279+ {
280+ bag->region_store[j] = bag->region_store[j+1];
281+ }
282+ break;
283+ }
284+ }
285+ return status;
286+}
287+
288+
289+/*
290+ * Constructs a region.
291+ */
292+GeisRegion
293+geis_region_new(Geis geis,
294+ GeisString name,
295+ GeisString init_arg_name, ...)
296+{
297+ GeisRegion region = NULL;
298+ va_list varargs;
299+
300+ region = calloc(1, sizeof(struct _GeisRegion));
301+ if (!region)
302+ {
303+ geis_error_push(geis, GEIS_STATUS_UNKNOWN_ERROR);
304+ geis_error("error allocating region");
305+ goto final_exit;
306+ }
307+
308+ va_start(varargs, init_arg_name);
309+ while (init_arg_name)
310+ {
311+ if (0 == strcmp(init_arg_name, GEIS_REGION_X11_ROOT))
312+ {
313+ if (region->type)
314+ {
315+ geis_warning("multiple region types requested, only using the first");
316+ break;
317+ }
318+ region->type = strdup(init_arg_name);
319+ geis_debug("using X11 root");
320+ }
321+ else if (0 == strcmp(init_arg_name, GEIS_REGION_X11_WINDOWID))
322+ {
323+ if (region->type)
324+ {
325+ geis_warning("multiple region types requested, only using the first");
326+ break;
327+ }
328+ region->type = strdup(init_arg_name);
329+ region->data.windowid = va_arg(varargs, int);
330+ geis_debug("using X11 windowid 0x%08x", region->data.windowid);
331+ }
332+
333+ init_arg_name = va_arg(varargs, GeisString);
334+ }
335+ va_end(varargs);
336+
337+ ++region->ref_count;
338+ region->name = strdup(name);
339+
340+final_exit:
341+ return region;
342+}
343+
344+
345+/*
346+ * Destroys a GEIS v2.0 region.
347+ */
348+GeisStatus
349+geis_region_delete(GeisRegion region)
350+{
351+ if (0 == __sync_sub_and_fetch(&region->ref_count, 1))
352+ {
353+ if (region->name)
354+ free((char *)region->name);
355+ free((char *)region->type);
356+ free(region);
357+ }
358+ return GEIS_STATUS_SUCCESS;
359+}
360+
361+
362+/**
363+ * Gets the name of a GEIS v2.0 region.
364+ *
365+ * @param[in] region The region.
366+ *
367+ * Returns the @p name value used when creating the region.
368+ */
369+GeisString
370+geis_region_name(GeisRegion region)
371+{
372+ return region->name;
373+}
374+
375+
376+/*
377+ * Adds a reference to a region.
378+ */
379+void
380+geis_region_ref(GeisRegion region)
381+{
382+ __sync_add_and_fetch(&region->ref_count, 1);
383+}
384+
385+
386+/*
387+ * Gets the type of the region.
388+ */
389+GeisString
390+geis_region_type(GeisRegion region)
391+{
392+ return region->type;
393+}
394+
395+
396+/*
397+ * Gets the data (if any) associated with the region type.
398+ */
399+void *
400+geis_region_data(GeisRegion region)
401+{
402+ return &region->data;
403+}
404+
405+
406
407=== added file 'libutouch-geis/geis_region.h'
408--- libutouch-geis/geis_region.h 1970-01-01 00:00:00 +0000
409+++ libutouch-geis/geis_region.h 2010-12-17 02:59:09 +0000
410@@ -0,0 +1,103 @@
411+/**
412+ * @file geis_region.h
413+ * @brief internal uTouch Geis region module private interface
414+ *
415+ * Copyright 2010 Canonical Ltd.
416+ *
417+ * This library is free software; you can redistribute it and/or modify it under
418+ * the terms of the GNU Lesser General Public License as published by the Free
419+ * Software Foundation; either version 3 of the License, or (at your option) any
420+ * later version.
421+ *
422+ * This library is distributed in the hope that it will be useful, but WITHOUT
423+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
424+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
425+ * details.
426+ *
427+ * You should have received a copy of the GNU Lesser General Public License
428+ * along with this program; if not, write to the Free Software Foundation, Inc.,
429+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
430+ */
431+#ifndef GEIS_REGION_H_
432+#define GEIS_REGION_H_
433+
434+#include "geis/geis.h"
435+
436+/**
437+ * @struct _GeisRegion
438+ *
439+ * This is a refcounted object: using the internal function geis_region_ref()
440+ * will increment the reference count on the object, and geis_region_delete()
441+ * will decrement the reference count and destroy the object when the reference
442+ * count is set to zero.
443+ *
444+ * If you are handed a GeisRegion and want to keep it around, you need to ref it
445+ * and then delete it when you're done, otherwise it could disappear out from
446+ * under you.
447+ *
448+ * Because GeisRegion lifetime is affected explicitly by application action
449+ * (new and delete calls are under application control), the refcount mechanism
450+ * has been made threadsafe.
451+ */
452+
453+/**
454+ * Contains regions in no particular order, with no duplicate checking.
455+ *
456+ * @note This container is not threadsafe.
457+ */
458+typedef struct _GeisRegionBag *GeisRegionBag;
459+
460+/**
461+ * Creates a new region bag.
462+ */
463+GeisRegionBag geis_region_bag_new();
464+
465+/**
466+ * Destroys a region bag.
467+ *
468+ * @param[in] bag The region bag.
469+ */
470+void geis_region_bag_delete(GeisRegionBag bag);
471+
472+/**
473+ * Gets the number of regions held in a bag.
474+ */
475+GeisSize geis_region_bag_count(GeisRegionBag bag);
476+
477+/**
478+ * Gets an indicated region from a bag.
479+ */
480+GeisRegion geis_region_bag_region(GeisRegionBag bag, GeisSize index);
481+
482+/**
483+ * Puts a region into a bag.
484+ */
485+GeisStatus geis_region_bag_insert(GeisRegionBag bag, GeisRegion region);
486+
487+/**
488+ * Takes a region out of a bag.
489+ */
490+GeisStatus geis_region_bag_remove(GeisRegionBag bag, GeisRegion region);
491+
492+/**
493+ * Adds a reference to a region.
494+ *
495+ * @param[in] region A region.
496+ */
497+void geis_region_ref(GeisRegion);
498+
499+/**
500+ * Gets the type of the region.
501+ *
502+ * @param[in] region A region.
503+ */
504+GeisString geis_region_type(GeisRegion region);
505+
506+/**
507+ * Gets the data (if any) associated with the region type.
508+ *
509+ * @param[in] region A region.
510+ */
511+void *geis_region_data(GeisRegion region);
512+
513+#endif /* GEIS_REGION_H_ */
514
515=== modified file 'libutouch-geis/libutouch-geis.ver'
516--- libutouch-geis/libutouch-geis.ver 2010-12-15 01:48:35 +0000
517+++ libutouch-geis/libutouch-geis.ver 2010-12-17 02:59:09 +0000
518@@ -27,6 +27,9 @@
519 geis_get_configuration;
520 geis_new;
521 geis_next_event;
522+ geis_region_delete;
523+ geis_region_name;
524+ geis_region_new;
525 geis_register_event_callback;
526 geis_set_configuration;
527 geis_subscription_activate;
528
529=== modified file 'testsuite/geis2/Makefile.am'
530--- testsuite/geis2/Makefile.am 2010-11-29 02:16:02 +0000
531+++ testsuite/geis2/Makefile.am 2010-12-17 02:59:09 +0000
532@@ -18,6 +18,7 @@
533 check_error_codes.c \
534 check_geis_new.c \
535 check_general_types.c \
536+ check_region.c \
537 check_subscription.c \
538 check_version_macro.c \
539 check_geis2_api.c
540
541=== modified file 'testsuite/geis2/check_geis2_api.c'
542--- testsuite/geis2/check_geis2_api.c 2010-11-29 02:16:02 +0000
543+++ testsuite/geis2/check_geis2_api.c 2010-12-17 02:59:09 +0000
544@@ -9,6 +9,7 @@
545 extern Suite *geis2_error_codes_suite_new();
546 extern Suite *geis2_geis_new_suite_new();
547 extern Suite *geis2_config_suite_new();
548+extern Suite *geis2_region_suite_new();
549 extern Suite *geis2_subscription_suite_new();
550
551 int
552@@ -24,6 +25,7 @@
553 srunner_add_suite(sr, geis2_error_codes_suite_new());
554 srunner_add_suite(sr, geis2_geis_new_suite_new());
555 srunner_add_suite(sr, geis2_config_suite_new());
556+ srunner_add_suite(sr, geis2_region_suite_new());
557 srunner_add_suite(sr, geis2_subscription_suite_new());
558
559 srunner_set_log(sr, "geis2_api.log");
560
561=== added file 'testsuite/geis2/check_region.c'
562--- testsuite/geis2/check_region.c 1970-01-01 00:00:00 +0000
563+++ testsuite/geis2/check_region.c 2010-12-17 02:59:09 +0000
564@@ -0,0 +1,65 @@
565+/**
566+ * Unit tests for GEIS v2.0 region module
567+ */
568+#include <check.h>
569+
570+#include <geis/geis.h>
571+#include <string.h>
572+
573+
574+/* fixtures */
575+static Geis g_geis;
576+
577+/* fixture setup */
578+static void
579+construct_geis()
580+{
581+ g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, NULL);
582+}
583+
584+/* fixture teardown */
585+static void
586+destroy_geis()
587+{
588+ geis_delete(g_geis);
589+}
590+
591+
592+/* compile-time test to ensure required types are defined */
593+START_TEST(region_constants)
594+{
595+ GeisString ini;
596+ ini = GEIS_REGION_X11_ROOT;
597+ ini = GEIS_REGION_X11_WINDOWID;
598+}
599+END_TEST
600+
601+START_TEST(construction)
602+{
603+ GeisRegion sub = geis_region_new(g_geis, "name", GEIS_REGION_X11_ROOT, NULL);
604+ fail_unless(sub != NULL,
605+ "failed to create region");
606+ fail_unless(0 == strcmp(geis_region_name(sub), "name"),
607+ "unexpected region name returned");
608+ geis_region_delete(sub);
609+}
610+END_TEST
611+
612+/* boilerplate */
613+Suite *
614+geis2_region_suite_new()
615+{
616+ Suite *s = suite_create("geis2_region");
617+
618+ TCase *create = tcase_create("region-constants");
619+ tcase_add_test(create, region_constants);
620+ suite_add_tcase(s, create);
621+
622+ TCase *usage = tcase_create("region-usage");
623+ tcase_add_checked_fixture(usage, construct_geis, destroy_geis);
624+ tcase_add_test(usage, construction);
625+ suite_add_tcase(s, usage);
626+
627+ return s;
628+}
629+
630
631=== modified file 'testsuite/libutouch-geis/Makefile.am'
632--- testsuite/libutouch-geis/Makefile.am 2010-12-13 03:53:15 +0000
633+++ testsuite/libutouch-geis/Makefile.am 2010-12-17 02:59:09 +0000
634@@ -36,6 +36,7 @@
635 check_backend_multiplexor.c \
636 check_error_reporting.c \
637 check_event_queue.c \
638+ check_region.c \
639 check_subscription.c \
640 check_geis2_internals.c
641
642
643=== modified file 'testsuite/libutouch-geis/check_geis2_internals.c'
644--- testsuite/libutouch-geis/check_geis2_internals.c 2010-12-09 16:14:15 +0000
645+++ testsuite/libutouch-geis/check_geis2_internals.c 2010-12-17 02:59:09 +0000
646@@ -10,6 +10,7 @@
647 extern Suite *make_backend_multiplexor_suite();
648 extern Suite *make_error_reporting_suite();
649 extern Suite *make_event_queue_suite();
650+extern Suite *make_region_suite();
651 extern Suite *make_subscription_suite();
652
653
654@@ -26,6 +27,7 @@
655 srunner_add_suite(sr, make_event_queue_suite());
656 srunner_add_suite(sr, make_backend_multiplexor_suite());
657 srunner_add_suite(sr, make_backend_event_posting_suite());
658+ srunner_add_suite(sr, make_region_suite());
659 srunner_add_suite(sr, make_subscription_suite());
660
661 srunner_set_log(sr, LOGFILE_PREFIX".log");
662
663=== added file 'testsuite/libutouch-geis/check_region.c'
664--- testsuite/libutouch-geis/check_region.c 1970-01-01 00:00:00 +0000
665+++ testsuite/libutouch-geis/check_region.c 2010-12-17 02:59:09 +0000
666@@ -0,0 +1,112 @@
667+/**
668+ * internal unit tests for the uTouch GEIS v2.0 region module
669+ *
670+ * Note the public API is checked through the geis2 testsuite.
671+ */
672+#include <check.h>
673+
674+#include "geis/geis.h"
675+#include "libutouch-geis/geis_region.h"
676+#include <stdio.h>
677+
678+
679+/* fixtures */
680+static Geis g_geis;
681+static GeisRegionBag g_region_bag;
682+static uint16_t g_sample_windowid = 0x11;
683+
684+/* fixture setup */
685+static void
686+construct_bag()
687+{
688+ g_geis = geis_new(GEIS_INIT_UTOUCH_MOCK_ENGINE, NULL);
689+ g_region_bag = geis_region_bag_new(1);
690+}
691+
692+/* fixture teardown */
693+static void
694+destroy_bag()
695+{
696+ geis_region_bag_delete(g_region_bag);
697+ geis_delete(g_geis);
698+}
699+
700+
701+START_TEST(region_access)
702+{
703+ GeisRegion region;
704+ region = geis_region_new(g_geis, "test01",
705+ GEIS_REGION_X11_WINDOWID, g_sample_windowid,
706+ NULL);
707+ fail_unless(0 == strcmp(geis_region_type(region), GEIS_REGION_X11_WINDOWID),
708+ "bad region type");
709+ fail_unless(g_sample_windowid == *(int *)geis_region_data(region),
710+ "bad region data");
711+}
712+END_TEST
713+
714+/* verify bag construction/destruction */
715+START_TEST(bag_construction)
716+{
717+ GeisRegionBag bag = geis_region_bag_new();
718+ fail_unless(bag != NULL,
719+ "failed to create region bag");
720+ fail_unless(geis_region_bag_count(bag) == 0,
721+ "unexpected size");
722+ geis_region_bag_delete(bag);
723+}
724+END_TEST
725+
726+
727+/* verify bag insertion */
728+START_TEST(bag_insertion)
729+{
730+ GeisRegion region;
731+ region = geis_region_new(g_geis, "test02", GEIS_REGION_X11_ROOT, NULL);
732+ geis_region_bag_insert(g_region_bag, region);
733+ fail_unless(geis_region_bag_count(g_region_bag) == 1,
734+ "unexpected bag size after insertion");
735+}
736+END_TEST
737+
738+
739+START_TEST(bag_expansion)
740+{
741+ int i;
742+ GeisRegion region;
743+ for (i = 0; i < 24; ++i)
744+ {
745+ char name[32];
746+ sprintf(name, "%04d", i);
747+ region = geis_region_new(g_geis, name, GEIS_REGION_X11_ROOT, NULL);
748+ geis_region_bag_insert(g_region_bag, region);
749+ int size = geis_region_bag_count(g_region_bag);
750+ fail_if((size - 1) != i, "expected region bag size %d, got %d", i, size);
751+ }
752+}
753+END_TEST
754+
755+
756+/* boilerplate */
757+Suite *
758+make_region_suite()
759+{
760+ Suite *s = suite_create("utouch-geis2-region");
761+
762+ TCase *create = tcase_create("region-access");
763+ tcase_add_test(create, region_access);
764+ suite_add_tcase(s, create);
765+
766+ TCase *bag_create = tcase_create("region-bag-creation");
767+ tcase_add_test(bag_create, bag_construction);
768+ suite_add_tcase(s, bag_create);
769+
770+ TCase *bag_usage = tcase_create("region-bag-usage");
771+ tcase_add_checked_fixture(bag_usage, construct_bag, destroy_bag);
772+ tcase_add_test(bag_usage, bag_insertion);
773+ tcase_add_test(bag_usage, bag_expansion);
774+ suite_add_tcase(s, bag_usage);
775+
776+ return s;
777+}
778+

Subscribers

People subscribed via source and target branches

to all changes: