Merge lp:~smspillaz/compiz-libcompizconfig/compiz-libcompizconfig.ccs-object into lp:~compiz-team/compiz-libcompizconfig/0.9.8

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/compiz-libcompizconfig/compiz-libcompizconfig.ccs-object
Merge into: lp:~compiz-team/compiz-libcompizconfig/0.9.8
Diff against target: 547 lines (+470/-1)
6 files modified
CMakeLists.txt (+1/-0)
include/ccs.h (+63/-1)
src/CMakeLists.txt (+3/-0)
src/main.c (+140/-0)
tests/CMakeLists.txt (+56/-0)
tests/test-ccs-object.cpp (+207/-0)
To merge this branch: bzr merge lp:~smspillaz/compiz-libcompizconfig/compiz-libcompizconfig.ccs-object
Reviewer Review Type Date Requested Status
Compiz Maintainers Pending
Review via email: mp+103993@code.launchpad.net

This proposal has been superseded by a proposal from 2012-04-29.

Description of the change

This is all about bug 990690.

!! - It probably isn't a good idea to test this branch in isolation, as it is part of a pipeline to get compiz-libcompizconfig under test. If you want to test the result of this work, you should probably look at testing

lp:~smspillaz/compiz-libcompizconfig/compiz-libcompizconfig.mock-context
lp:~smspillaz/compiz-compizconfig-python/compiz-compizconfig-python.setting-api
lp:~smspillaz/compiz-compizconfig-gconf/compiz-compizconfig-gconf.adapt-to-new-interfaces

.. that's all !!

This branch introduces some preliminary work in a series of branches to get libcompizconfig under test. In order to test the objects properly, we need to abstract away their interfaces into replacable structs so you can test the interaction between the various classes.

This would be awkward to do correctly if we didn't have a suitable object system to handle interface implementation, referencing, private storage etc.

As such, a new struct CCSObject is introduced. It is similar in design to GObject, but with a much smaller feature set centered mostly around the handling of interfaces and composition / indirection. A type registrar is also included (also very simple).

Tests are included.

To post a comment you must log in.

Unmerged revisions

433. By Sam Spilsbury

Added a simple type registrar

432. By Sam Spilsbury

Added a ccsObjectFinalize function which frees everything in CCSObject storage

431. By Sam Spilsbury

Added tests for CCSObject

430. By Sam Spilsbury

Added some testing code

429. By Sam Spilsbury

Added CCSObject

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2011-07-07 12:23:21 +0000
3+++ CMakeLists.txt 2012-04-28 18:57:19 +0000
4@@ -141,6 +141,7 @@
5 add_subdirectory (src)
6 add_subdirectory (include)
7 add_subdirectory (cmake)
8+add_subdirectory (tests)
9
10 compiz_print_configure_header ("CompizConfig Library")
11 compiz_color_message ("\n${_escape}[4mOptional features:${_escape}[0m\n")
12
13=== modified file 'include/ccs.h'
14--- include/ccs.h 2011-08-20 19:03:37 +0000
15+++ include/ccs.h 2012-04-28 18:57:19 +0000
16@@ -19,10 +19,14 @@
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20-
21 #ifndef _CSS_H
22 #define _CSS_H
23
24+#ifdef __cplusplus
25+extern "C"
26+{
27+#endif
28+
29 #define D_NONE 0
30 #define D_NORMAL 1
31 #define D_FULL 2
32@@ -124,6 +128,60 @@
33 CCSLIST_HDR (StrRestriction, CCSStrRestriction)
34 CCSLIST_HDR (StrExtension, CCSStrExtension)
35
36+typedef struct _CCSInterface CCSInterface; /* Dummy typedef */
37+typedef struct _CCSPrivate CCSPrivate; /* Dummy typedef */
38+typedef struct _CCSObject CCSObject;
39+
40+struct _CCSObject
41+{
42+ CCSPrivate *priv; /* Private pointer for object storage */
43+
44+ const CCSInterface **interfaces; /* An array of interfaces that this object implements */
45+ int *interface_types; /* An array of interface types */
46+ unsigned int n_interfaces;
47+
48+ unsigned int refcnt; /* Reference count of this object */
49+};
50+
51+Bool
52+ccsObjectAddInterface (CCSObject *object, const CCSInterface *interface, int interface_type);
53+
54+Bool
55+ccsObjectRemoveInterface (CCSObject *object, int interface_type);
56+
57+const CCSInterface * ccsObjectGetInterface (CCSObject *object, int interface_type);
58+
59+void
60+ccsObjectRef (CCSObject *object);
61+
62+void
63+ccsObjectUnref (CCSObject *object);
64+
65+CCSPrivate *
66+ccsObjectGetPrivate (CCSObject *object);
67+
68+void
69+ccsObjectSetPrivate (CCSObject *object, CCSPrivate *priv);
70+
71+void
72+ccsObjectFinalize (CCSObject *object);
73+
74+unsigned int
75+ccsAllocateType ();
76+
77+#define GET_INTERFACE_TYPE(Interface) \
78+ ccs##Interface##GetType ();
79+
80+#define INTERFACE_TYPE(Interface) \
81+ inline unsigned int ccs##Interface##GetType () \
82+ { \
83+ static unsigned int type_id = 0; \
84+ if (!type_id) \
85+ type_id = ccsAllocateType (); \
86+ \
87+ return type_id; \
88+ }
89+
90 /**
91 * reference counting
92 *
93@@ -913,4 +971,8 @@
94 /* Checks if settings need to be constrained */
95 Bool ccsContextNeedsConstraining (CCSContext *context);
96
97+#ifdef __cplusplus
98+}
99+#endif
100+
101 #endif
102
103=== modified file 'src/CMakeLists.txt'
104--- src/CMakeLists.txt 2011-10-15 07:28:45 +0000
105+++ src/CMakeLists.txt 2012-04-28 18:57:19 +0000
106@@ -35,6 +35,9 @@
107 ${LIBCOMPIZCONFIG_FILES}
108 compizconfig.pb.cc
109 )
110+ set (LIBCOMPIZCONFIG_LIBRARIES
111+ ${LIBCOMPIZCONFIG_LIBRARIES}
112+ protobuf)
113 add_definitions (
114 -DUSE_PROTOBUF
115 )
116
117=== modified file 'src/main.c'
118--- src/main.c 2011-11-10 00:58:18 +0000
119+++ src/main.c 2012-04-28 18:57:19 +0000
120@@ -39,6 +39,134 @@
121 #include "ccs-private.h"
122 #include "iniparser.h"
123
124+/* CCSObject stuff */
125+Bool
126+ccsObjectAddInterface (CCSObject *object, const CCSInterface *interface, int interface_type)
127+{
128+ object->n_interfaces++;
129+ object->interfaces = realloc (object->interfaces, object->n_interfaces * sizeof (CCSInterface *));
130+
131+ if (!object->interfaces)
132+ {
133+ object->n_interfaces--;
134+ return FALSE;
135+ }
136+
137+ object->interface_types = realloc (object->interface_types, object->n_interfaces * sizeof (int));
138+
139+ if (!object->interface_types)
140+ {
141+ object->n_interfaces--;
142+ return FALSE;
143+ }
144+
145+ object->interfaces[object->n_interfaces - 1] = interface;
146+ object->interface_types[object->n_interfaces - 1] = interface_type;
147+
148+ return TRUE;
149+}
150+
151+Bool
152+ccsObjectRemoveInterface (CCSObject *object, int interface_type)
153+{
154+ unsigned int i = 0;
155+
156+ if (!object->n_interfaces)
157+ return FALSE;
158+
159+ const void *o = *object->interfaces;
160+ int *type = object->interface_types;
161+
162+ for (; i < object->n_interfaces; i++, o++, type++)
163+ {
164+ if (object->interface_types[i] == interface_type)
165+ break;
166+ }
167+
168+ if (i >= object->n_interfaces)
169+ return FALSE;
170+
171+ /* Now clear this section and move everything back */
172+ object->interfaces[i] = NULL;
173+
174+ i++;
175+
176+ void *oLast = (void *) o;
177+ int *typeLast = type;
178+
179+ o++;
180+ type++;
181+
182+ memmove (oLast, o, (object->n_interfaces - i) * sizeof (CCSInterface *));
183+ memmove (typeLast, type, (object->n_interfaces - i) * sizeof (int));
184+
185+ object->n_interfaces--;
186+ object->interfaces = realloc (object->interfaces, object->n_interfaces * sizeof (CCSInterface *));
187+ object->interface_types = realloc (object->interface_types, object->n_interfaces * sizeof (int));
188+
189+ return TRUE;
190+}
191+
192+const CCSInterface *
193+ccsObjectGetInterface (CCSObject *object, int interface_type)
194+{
195+ unsigned int i = 0;
196+
197+ for (; i < object->n_interfaces; i++)
198+ {
199+ if (object->interface_types[i] == interface_type)
200+ return object->interfaces[i];
201+ }
202+
203+ return NULL;
204+}
205+
206+CCSPrivate *
207+ccsObjectGetPrivate (CCSObject *object)
208+{
209+ return object->priv;
210+}
211+
212+void
213+ccsObjectSetPrivate (CCSObject *object, CCSPrivate *priv)
214+{
215+ object->priv = priv;
216+}
217+
218+void
219+ccsObjectFinalize (CCSObject *object)
220+{
221+ if (object->priv)
222+ {
223+ free (object->priv);
224+ object->priv = NULL;
225+ }
226+
227+ if (object->interfaces)
228+ {
229+ free (object->interfaces);
230+ object->interfaces = NULL;
231+ }
232+
233+ if (object->interface_types)
234+ {
235+ free (object->interface_types);
236+ object->interface_types = NULL;
237+ }
238+
239+ object->n_interfaces = 0;
240+}
241+
242+unsigned int
243+ccsAllocateType ()
244+{
245+ static unsigned int start = 0;
246+
247+ start++;
248+
249+ return start;
250+}
251+
252 Bool basicMetadata = FALSE;
253
254 void
255@@ -592,6 +720,18 @@
256 CCSREF (StrRestriction, CCSStrRestriction)
257 CCSREF (StrExtension, CCSStrExtension)
258
259+#define CCSREF_OBJ(type,dtype) \
260+ void ccs##type##Ref (dtype *d) \
261+ { \
262+ ((CCSObject *) d)->refcnt++; \
263+ } \
264+ void ccs##type##Unref (dtype *d) \
265+ { \
266+ ((CCSObject *) d)->refcnt--; \
267+ if (((CCSObject *) d)->refcnt == 0) \
268+ ccsFree##type (d); \
269+ } \
270+
271 static void *
272 openBackend (char *backend)
273 {
274
275=== added directory 'tests'
276=== added file 'tests/CMakeLists.txt'
277--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
278+++ tests/CMakeLists.txt 2012-04-28 18:57:19 +0000
279@@ -0,0 +1,56 @@
280+# Build Google Test and make its headers known
281+find_package (GTest)
282+
283+if (NOT GTEST_FOUND)
284+
285+ # Check for google test and build it locally
286+ set (GTEST_ROOT_DIR
287+ "/usr/src/gtest" # Default value, adjustable by user with e.g., ccmake
288+ CACHE
289+ PATH
290+ "Path to Google test srcs"
291+ )
292+
293+ find_path (GTEST_INCLUDE_DIR gtest/gtest.h)
294+
295+ if (GTEST_INCLUDE_DIR)
296+ #FIXME - hardcoded is bad!
297+ add_subdirectory (${GTEST_ROOT_DIR}
298+ gtest)
299+ endif(GTEST_INCLUDE_DIR)
300+
301+ set (GTEST_BOTH_LIBRARIES gtest gtest_main)
302+ set (GTEST_FOUND TRUE)
303+
304+endif (NOT GTEST_FOUND)
305+
306+find_library (GMOCK_LIBRARY gmock)
307+find_library (GMOCK_MAIN_LIBRARY gmock_main)
308+
309+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
310+ message ("Google Mock and Google Test not found - cannot build tests!")
311+ set (COMPIZ_BUILD_TESTING OFF)
312+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
313+
314+include_directories (${GTEST_INCLUDE_DIRS})
315+include_directories (${CMAKE_SOURCE_DIR}/include)
316+link_directories (${CMAKE_INSTALL_PREFIX}/lib)
317+
318+add_executable (test-ccs-object
319+ ${CMAKE_CURRENT_SOURCE_DIR}/test-ccs-object.cpp)
320+
321+if (HAVE_PROTOBUF)
322+ set (LIBCOMPIZCONFIG_LIBRARIES
323+ ${LIBCOMPIZCONFIG_LIBRARIES}
324+ protobuf)
325+endif (HAVE_PROTOBUF)
326+
327+target_link_libraries (test-ccs-object
328+ ${GTEST_BOTH_LIBRARIES}
329+ ${GMOCK_LIBRARY}
330+ ${GMOCK_MAIN_LIBRARY}
331+ ${CMAKE_THREAD_LIBS_INIT}
332+ ${LIBCOMPIZCONFIG_LIBRARIES}
333+ compizconfig)
334+
335+gtest_add_tests (test-ccs-object "" ${CMAKE_CURRENT_SOURCE_DIR}/test-ccs-object.cpp)
336
337=== added file 'tests/test-ccs-object.cpp'
338--- tests/test-ccs-object.cpp 1970-01-01 00:00:00 +0000
339+++ tests/test-ccs-object.cpp 2012-04-28 18:57:19 +0000
340@@ -0,0 +1,207 @@
341+#include <gtest/gtest.h>
342+#include <gmock/gmock.h>
343+#include <ccs.h>
344+#include <cstdio>
345+
346+using ::testing::_;
347+using ::testing::Return;
348+
349+class CCSObjectTest :
350+ public ::testing::Test
351+{
352+};
353+
354+struct TestingObjectWrapper
355+{
356+ CCSObject object;
357+};
358+
359+typedef void (*dummyFunc) (void);
360+
361+struct DummyInterface
362+{
363+ dummyFunc dummy;
364+};
365+
366+struct Dummy2Interface
367+{
368+ dummyFunc dummy;
369+};
370+
371+class GoogleMockDummyInterface
372+{
373+ public:
374+
375+ virtual ~GoogleMockDummyInterface () {};
376+
377+ virtual void dummyFunc () = 0;
378+ virtual void freeTestingObjectWrapper (TestingObjectWrapper *) = 0;
379+};
380+
381+class GoogleMockDummy :
382+ public GoogleMockDummyInterface
383+{
384+ public:
385+
386+ MOCK_METHOD0 (dummyFunc, void ());
387+ MOCK_METHOD1 (freeTestingObjectWrapper, void (TestingObjectWrapper *));
388+ public:
389+
390+ static void thunkDummyFunc () { return _mockDummy.dummyFunc (); }
391+ static GoogleMockDummy _mockDummy;
392+};
393+
394+GoogleMockDummy GoogleMockDummy::_mockDummy;
395+
396+const struct DummyInterface SomeDummyInterface =
397+{
398+ GoogleMockDummy::thunkDummyFunc
399+};
400+
401+#define CCS_INTERFACE_TYPE_DUMMY GET_INTERFACE_TYPE (DummyInterface)
402+#define CCS_INTERFACE_TYPE_DUMMY2 GET_INTERFACE_TYPE (Dummy2Interface)
403+
404+INTERFACE_TYPE (DummyInterface)
405+INTERFACE_TYPE (Dummy2Interface)
406+
407+TEST(CCSObjectTest, TestTypeAllocation)
408+{
409+ unsigned int i = CCS_INTERFACE_TYPE_DUMMY;
410+ unsigned int j = CCS_INTERFACE_TYPE_DUMMY;
411+ unsigned int k = CCS_INTERFACE_TYPE_DUMMY2;
412+
413+ EXPECT_EQ (i, 1);
414+ EXPECT_EQ (j ,1);
415+ EXPECT_EQ (k, 2);
416+}
417+
418+TEST(CCSObjectTest, InterfaceAdd)
419+{
420+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
421+
422+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
423+
424+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
425+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
426+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
427+
428+ free (to);
429+}
430+
431+TEST(CCSObjectTest, InterfaceRemove)
432+{
433+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
434+
435+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
436+
437+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
438+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
439+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
440+
441+ ccsObjectRemoveInterface ((CCSObject *) to, 1);
442+
443+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
444+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
445+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
446+
447+ free (to);
448+}
449+
450+TEST(CCSObjectTest, InterfaceFetchCall)
451+{
452+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
453+
454+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
455+
456+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
457+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
458+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
459+
460+ const DummyInterface *myDummyInterface = (const DummyInterface *) ccsObjectGetInterface ((CCSObject *) to, 1);
461+
462+ EXPECT_CALL (GoogleMockDummy::_mockDummy, dummyFunc ());
463+
464+ (*myDummyInterface->dummy) ();
465+
466+ ccsObjectRemoveInterface ((CCSObject *) to, 1);
467+
468+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
469+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
470+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
471+
472+ free (to);
473+}
474+
475+TEST(CCSObjectTest, SetPrivateGetPrivate)
476+{
477+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
478+
479+ int i = 1;
480+
481+ ccsObjectSetPrivate ((CCSObject *) to, (CCSPrivate *) &i);
482+
483+ CCSPrivate *p = ccsObjectGetPrivate ((CCSObject *) to);
484+
485+ EXPECT_EQ (&i, (int *) p);
486+ EXPECT_EQ (i, (*((int *) p)));
487+}
488+
489+void ccsFreeTestingObjectWrapper (TestingObjectWrapper *wrapper)
490+{
491+ GoogleMockDummy::_mockDummy.freeTestingObjectWrapper (wrapper);
492+}
493+
494+#define CCSREF_OBJ(type,dtype) \
495+ void ccs##type##Ref (dtype *d) \
496+ { \
497+ ((CCSObject *) d)->refcnt++; \
498+ } \
499+ void ccs##type##Unref (dtype *d) \
500+ { \
501+ ((CCSObject *) d)->refcnt--; \
502+ if (((CCSObject *) d)->refcnt == 0) \
503+ ccsFree##type (d); \
504+ } \
505+
506+CCSREF_HDR(TestingObjectWrapper, TestingObjectWrapper);
507+CCSREF_OBJ(TestingObjectWrapper, TestingObjectWrapper);
508+
509+TEST(CCSObjectTest, TestRefUnrefFreesObject)
510+{
511+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
512+
513+ ccsTestingObjectWrapperRef (to);
514+
515+ EXPECT_CALL (GoogleMockDummy::_mockDummy, freeTestingObjectWrapper (to));
516+
517+ ccsTestingObjectWrapperUnref (to);
518+}
519+
520+TEST(CCSObjectTest, TestFinalizeFreesEverything)
521+{
522+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
523+
524+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
525+
526+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
527+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
528+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
529+
530+ int *i = (int *) malloc (sizeof (int));
531+
532+ *i = 1;
533+
534+ ccsObjectSetPrivate ((CCSObject *) to, (CCSPrivate *) i);
535+
536+ CCSPrivate *p = ccsObjectGetPrivate ((CCSObject *) to);
537+
538+ EXPECT_EQ (i, (int *) p);
539+ EXPECT_EQ (*i, (*((int *) p)));
540+
541+ ccsObjectFinalize ((CCSObject *) to);
542+
543+ EXPECT_EQ (NULL, ((CCSObject *) to)->priv);
544+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
545+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
546+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
547+}

Subscribers

People subscribed via source and target branches