Merge lp:~smspillaz/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/ccs-object
Merge into: lp:~compiz-team/compiz-libcompizconfig/0.9.8
Diff against target: 672 lines (+595/-1)
6 files modified
CMakeLists.txt (+1/-0)
include/ccs.h (+82/-1)
src/CMakeLists.txt (+3/-0)
src/main.c (+179/-0)
tests/CMakeLists.txt (+56/-0)
tests/test-ccs-object.cpp (+274/-0)
To merge this branch: bzr merge lp:~smspillaz/compiz-libcompizconfig/ccs-object
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Fixing
Review via email: mp+104024@code.launchpad.net

This proposal supersedes a proposal from 2012-04-28.

This proposal has been superseded by a proposal from 2012-05-02.

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/setting-mock
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.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I know it is common (and may be a project style) but there is no advantage to having different names to refer to the same thing in different namespaces. That is not:

    typedef struct _CCSObject CCSObject;

    struct _CCSObject
    {
    ...
    };

but:

    typedef struct CCSObject
    {
    ...
    } CCSObject;

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> I know it is common (and may be a project style) but there is no advantage to
> having different names to refer to the same thing in different namespaces.
> That is not:
>
> typedef struct _CCSObject CCSObject;
>
> struct _CCSObject
> {
> ...
> };
>
> but:
>
> typedef struct CCSObject
> {
> ...
> } CCSObject;

Actually, it doesn't seem that client code should be interested in the members of [_]CCSObject, so why not a completely opaque type? Vis:

    typedef struct CCSObject CCSObject;

in the header. And move the definition to the .c file.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I don't like the style of coding in ccsObjectAddInterface() - if either realloc fails then the object is hosed. Admittedly FALSE is returned to inform the caller, but I'd prefer the object to remain viable and just the call to fail. Anything else can cause nasty surprises in client code. (Admittedly, if realloc fails there are probably worse problems to deal with.)

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> I don't like the style of coding in ccsObjectAddInterface() - if either
> realloc fails then the object is hosed. Admittedly FALSE is returned to
> inform the caller, but I'd prefer the object to remain viable and just the
> call to fail. Anything else can cause nasty surprises in client code.
> (Admittedly, if realloc fails there are probably worse problems to deal with.)

Forgot to mention: the cost of calling realloc in ccsObjectRemoveInterface probably outweighs any saving of memory that results.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> > I know it is common (and may be a project style) but there is no advantage
> to
> > having different names to refer to the same thing in different namespaces.
> > That is not:
> >
> > typedef struct _CCSObject CCSObject;
> >
> > struct _CCSObject
> > {
> > ...
> > };
> >
> > but:
> >
> > typedef struct CCSObject
> > {
> > ...
> > } CCSObject;
>
> Actually, it doesn't seem that client code should be interested in the members
> of [_]CCSObject, so why not a completely opaque type? Vis:
>
> typedef struct CCSObject CCSObject;
>
> in the header. And move the definition to the .c file.

I think the struct can't be opaque because of the way that we actually access the object data (eg, casting it to a CCSObject * and accessing the data in the CCSObject in the first part of the struct).

As for realloc - I agree and had similar concerns, and will change that.

434. By Sam Spilsbury

Don't reallocate all the time. Also handle realloc failures better

435. By Sam Spilsbury

Make the CCSObject API a bit more typesafe

436. By Sam Spilsbury

Don't use reserved name

437. By Sam Spilsbury

Free interfaces once objects are removed

438. By Sam Spilsbury

Fix potential macro problems

439. By Sam Spilsbury

Lose the ;

440. By Sam Spilsbury

Added a free thread

441. By Sam Spilsbury

Also test for free

Unmerged revisions

441. By Sam Spilsbury

Also test for free

440. By Sam Spilsbury

Added a free thread

439. By Sam Spilsbury

Lose the ;

438. By Sam Spilsbury

Fix potential macro problems

437. By Sam Spilsbury

Free interfaces once objects are removed

436. By Sam Spilsbury

Don't use reserved name

435. By Sam Spilsbury

Make the CCSObject API a bit more typesafe

434. By Sam Spilsbury

Don't reallocate all the time. Also handle realloc failures better

433. By Sam Spilsbury

Added a simple type registrar

432. By Sam Spilsbury

Added a ccsObjectFinalize function which frees everything in CCSObject storage

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-05-02 21:44: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-05-02 21:44: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,79 @@
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+typedef void * (*reallocProc) (void *, size_t);
41+typedef void * (*mallocProc) (size_t);
42+typedef void * (*callocProc) (size_t, size_t);
43+
44+typedef struct _CCSObjectAllocationInterface
45+{
46+ reallocProc realloc;
47+ mallocProc malloc;
48+ callocProc calloc;
49+} CCSObjectAllocationInterface;
50+
51+extern CCSObjectAllocationInterface ccsDefaultObjectAllocator;
52+
53+struct _CCSObject
54+{
55+ CCSPrivate *priv; /* Private pointer for object storage */
56+
57+ const CCSInterface **interfaces; /* An array of interfaces that this object implements */
58+ int *interface_types; /* An array of interface types */
59+ unsigned int n_interfaces;
60+ unsigned int n_allocated_interfaces;
61+
62+ CCSObjectAllocationInterface *object_allocation;
63+
64+ unsigned int refcnt; /* Reference count of this object */
65+};
66+
67+Bool
68+ccsObjectInit (void *object, CCSObjectAllocationInterface *interface);
69+
70+Bool
71+ccsObjectAddInterface (CCSObject *object, const CCSInterface *interface, int interface_type);
72+
73+Bool
74+ccsObjectRemoveInterface (CCSObject *object, int interface_type);
75+
76+const CCSInterface * ccsObjectGetInterface (CCSObject *object, int interface_type);
77+
78+void
79+ccsObjectRef (CCSObject *object);
80+
81+void
82+ccsObjectUnref (CCSObject *object);
83+
84+CCSPrivate *
85+ccsObjectGetPrivate (CCSObject *object);
86+
87+void
88+ccsObjectSetPrivate (CCSObject *object, CCSPrivate *priv);
89+
90+void
91+ccsObjectFinalize (CCSObject *object);
92+
93+unsigned int
94+ccsAllocateType ();
95+
96+#define GET_INTERFACE_TYPE(Interface) \
97+ ccs##Interface##GetType ();
98+
99+#define INTERFACE_TYPE(Interface) \
100+ inline unsigned int ccs##Interface##GetType () \
101+ { \
102+ static unsigned int type_id = 0; \
103+ if (!type_id) \
104+ type_id = ccsAllocateType (); \
105+ \
106+ return type_id; \
107+ }
108+
109 /**
110 * reference counting
111 *
112@@ -913,4 +990,8 @@
113 /* Checks if settings need to be constrained */
114 Bool ccsContextNeedsConstraining (CCSContext *context);
115
116+#ifdef __cplusplus
117+}
118+#endif
119+
120 #endif
121
122=== modified file 'src/CMakeLists.txt'
123--- src/CMakeLists.txt 2011-10-15 07:28:45 +0000
124+++ src/CMakeLists.txt 2012-05-02 21:44:19 +0000
125@@ -35,6 +35,9 @@
126 ${LIBCOMPIZCONFIG_FILES}
127 compizconfig.pb.cc
128 )
129+ set (LIBCOMPIZCONFIG_LIBRARIES
130+ ${LIBCOMPIZCONFIG_LIBRARIES}
131+ protobuf)
132 add_definitions (
133 -DUSE_PROTOBUF
134 )
135
136=== modified file 'src/main.c'
137--- src/main.c 2011-11-10 00:58:18 +0000
138+++ src/main.c 2012-05-02 21:44:19 +0000
139@@ -39,6 +39,173 @@
140 #include "ccs-private.h"
141 #include "iniparser.h"
142
143+CCSObjectAllocationInterface ccsDefaultObjectAllocator =
144+{
145+ realloc,
146+ malloc,
147+ calloc
148+};
149+
150+/* CCSObject stuff */
151+Bool
152+ccsObjectInit(void *object, CCSObjectAllocationInterface *object_allocation)
153+{
154+ CCSObject *cObject = (CCSObject *) object;
155+
156+ cObject->priv = NULL;
157+ cObject->n_interfaces = 0;
158+ cObject->n_allocated_interfaces = 0;
159+ cObject->interfaces = NULL;
160+ cObject->interface_types = NULL;
161+ cObject->object_allocation = object_allocation;
162+ cObject->refcnt = 0;
163+
164+ return TRUE;
165+}
166+
167+Bool
168+ccsObjectAddInterface (CCSObject *object, const CCSInterface *interface, int interface_type)
169+{
170+ object->n_interfaces++;
171+
172+ if (object->n_allocated_interfaces < object->n_interfaces)
173+ {
174+ unsigned int old_allocated_interfaces = object->n_allocated_interfaces;
175+ object->n_allocated_interfaces = object->n_interfaces;
176+ CCSInterface **ifaces = (*object->object_allocation->realloc) (object->interfaces, object->n_allocated_interfaces * sizeof (CCSInterface *));
177+ int *iface_types = (*object->object_allocation->realloc) (object->interface_types, object->n_allocated_interfaces * sizeof (int));
178+
179+ if (!ifaces || !iface_types)
180+ {
181+ if (ifaces)
182+ free (ifaces);
183+
184+ if (iface_types)
185+ free (iface_types);
186+
187+ object->n_interfaces--;
188+ object->n_allocated_interfaces = old_allocated_interfaces;
189+ return FALSE;
190+ }
191+ else
192+ {
193+ object->interfaces = (const CCSInterface **) ifaces;
194+ object->interface_types = iface_types;
195+ }
196+ }
197+
198+ object->interfaces[object->n_interfaces - 1] = interface;
199+ object->interface_types[object->n_interfaces - 1] = interface_type;
200+
201+ return TRUE;
202+}
203+
204+Bool
205+ccsObjectRemoveInterface (CCSObject *object, int interface_type)
206+{
207+ unsigned int i = 0;
208+
209+ if (!object->n_interfaces)
210+ return FALSE;
211+
212+ const CCSInterface **o = object->interfaces;
213+ int *type = object->interface_types;
214+
215+ for (; i < object->n_interfaces; i++, o++, type++)
216+ {
217+ if (object->interface_types[i] == interface_type)
218+ break;
219+ }
220+
221+ if (i >= object->n_interfaces)
222+ return FALSE;
223+
224+ /* Now clear this section and move everything back */
225+ object->interfaces[i] = NULL;
226+
227+ i++;
228+
229+ const CCSInterface **oLast = o;
230+ int *typeLast = type;
231+
232+ o++;
233+ type++;
234+
235+ memmove ((void *) oLast, (void *)o, (object->n_interfaces - i) * sizeof (CCSInterface *));
236+ memmove ((void *) typeLast, (void *) type, (object->n_interfaces - i) * sizeof (int));
237+
238+ object->n_interfaces--;
239+
240+ if (!object->n_interfaces)
241+ {
242+ object->interfaces = NULL;
243+ object->interface_types = NULL;
244+ object->n_allocated_interfaces = 0;
245+ }
246+
247+ return TRUE;
248+}
249+
250+const CCSInterface *
251+ccsObjectGetInterface (CCSObject *object, int interface_type)
252+{
253+ unsigned int i = 0;
254+
255+ for (; i < object->n_interfaces; i++)
256+ {
257+ if (object->interface_types[i] == interface_type)
258+ return object->interfaces[i];
259+ }
260+
261+ return NULL;
262+}
263+
264+CCSPrivate *
265+ccsObjectGetPrivate (CCSObject *object)
266+{
267+ return object->priv;
268+}
269+
270+void
271+ccsObjectSetPrivate (CCSObject *object, CCSPrivate *priv)
272+{
273+ object->priv = priv;
274+}
275+
276+void
277+ccsObjectFinalize (CCSObject *object)
278+{
279+ if (object->priv)
280+ {
281+ free (object->priv);
282+ object->priv = NULL;
283+ }
284+
285+ if (object->interfaces)
286+ {
287+ free (object->interfaces);
288+ object->interfaces = NULL;
289+ }
290+
291+ if (object->interface_types)
292+ {
293+ free (object->interface_types);
294+ object->interface_types = NULL;
295+ }
296+
297+ object->n_interfaces = 0;
298+}
299+
300+unsigned int
301+ccsAllocateType ()
302+{
303+ static unsigned int start = 0;
304+
305+ start++;
306+
307+ return start;
308+}
309+
310 Bool basicMetadata = FALSE;
311
312 void
313@@ -592,6 +759,18 @@
314 CCSREF (StrRestriction, CCSStrRestriction)
315 CCSREF (StrExtension, CCSStrExtension)
316
317+#define CCSREF_OBJ(type,dtype) \
318+ void ccs##type##Ref (dtype *d) \
319+ { \
320+ ((CCSObject *) d)->refcnt++; \
321+ } \
322+ void ccs##type##Unref (dtype *d) \
323+ { \
324+ ((CCSObject *) d)->refcnt--; \
325+ if (((CCSObject *) d)->refcnt == 0) \
326+ ccsFree##type (d); \
327+ } \
328+
329 static void *
330 openBackend (char *backend)
331 {
332
333=== added directory 'tests'
334=== added file 'tests/CMakeLists.txt'
335--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
336+++ tests/CMakeLists.txt 2012-05-02 21:44:19 +0000
337@@ -0,0 +1,56 @@
338+# Build Google Test and make its headers known
339+find_package (GTest)
340+
341+if (NOT GTEST_FOUND)
342+
343+ # Check for google test and build it locally
344+ set (GTEST_ROOT_DIR
345+ "/usr/src/gtest" # Default value, adjustable by user with e.g., ccmake
346+ CACHE
347+ PATH
348+ "Path to Google test srcs"
349+ )
350+
351+ find_path (GTEST_INCLUDE_DIR gtest/gtest.h)
352+
353+ if (GTEST_INCLUDE_DIR)
354+ #FIXME - hardcoded is bad!
355+ add_subdirectory (${GTEST_ROOT_DIR}
356+ gtest)
357+ endif(GTEST_INCLUDE_DIR)
358+
359+ set (GTEST_BOTH_LIBRARIES gtest gtest_main)
360+ set (GTEST_FOUND TRUE)
361+
362+endif (NOT GTEST_FOUND)
363+
364+find_library (GMOCK_LIBRARY gmock)
365+find_library (GMOCK_MAIN_LIBRARY gmock_main)
366+
367+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
368+ message ("Google Mock and Google Test not found - cannot build tests!")
369+ set (COMPIZ_BUILD_TESTING OFF)
370+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
371+
372+include_directories (${GTEST_INCLUDE_DIRS})
373+include_directories (${CMAKE_SOURCE_DIR}/include)
374+link_directories (${CMAKE_INSTALL_PREFIX}/lib)
375+
376+add_executable (test-ccs-object
377+ ${CMAKE_CURRENT_SOURCE_DIR}/test-ccs-object.cpp)
378+
379+if (HAVE_PROTOBUF)
380+ set (LIBCOMPIZCONFIG_LIBRARIES
381+ ${LIBCOMPIZCONFIG_LIBRARIES}
382+ protobuf)
383+endif (HAVE_PROTOBUF)
384+
385+target_link_libraries (test-ccs-object
386+ ${GTEST_BOTH_LIBRARIES}
387+ ${GMOCK_LIBRARY}
388+ ${GMOCK_MAIN_LIBRARY}
389+ ${CMAKE_THREAD_LIBS_INIT}
390+ ${LIBCOMPIZCONFIG_LIBRARIES}
391+ compizconfig)
392+
393+gtest_add_tests (test-ccs-object "" ${CMAKE_CURRENT_SOURCE_DIR}/test-ccs-object.cpp)
394
395=== added file 'tests/test-ccs-object.cpp'
396--- tests/test-ccs-object.cpp 1970-01-01 00:00:00 +0000
397+++ tests/test-ccs-object.cpp 2012-05-02 21:44:19 +0000
398@@ -0,0 +1,274 @@
399+#include <gtest/gtest.h>
400+#include <gmock/gmock.h>
401+#include <ccs.h>
402+#include <cstdio>
403+
404+using ::testing::_;
405+using ::testing::Return;
406+
407+class CCSObjectTest :
408+ public ::testing::Test
409+{
410+};
411+
412+struct TestingObjectWrapper
413+{
414+ CCSObject object;
415+};
416+
417+typedef void (*dummyFunc) (void);
418+
419+struct DummyInterface
420+{
421+ dummyFunc dummy;
422+};
423+
424+struct Dummy2Interface
425+{
426+ dummyFunc dummy;
427+};
428+
429+class GoogleMockDummyInterface
430+{
431+ public:
432+
433+ virtual ~GoogleMockDummyInterface () {};
434+
435+ virtual void dummyFunc () = 0;
436+ virtual void freeTestingObjectWrapper (TestingObjectWrapper *) = 0;
437+};
438+
439+class GoogleMockDummy :
440+ public GoogleMockDummyInterface
441+{
442+ public:
443+
444+ MOCK_METHOD0 (dummyFunc, void ());
445+ MOCK_METHOD1 (freeTestingObjectWrapper, void (TestingObjectWrapper *));
446+ public:
447+
448+ static void thunkDummyFunc () { return _mockDummy.dummyFunc (); }
449+ static GoogleMockDummy _mockDummy;
450+};
451+
452+GoogleMockDummy GoogleMockDummy::_mockDummy;
453+
454+const struct DummyInterface SomeDummyInterface =
455+{
456+ GoogleMockDummy::thunkDummyFunc
457+};
458+
459+#define CCS_INTERFACE_TYPE_DUMMY GET_INTERFACE_TYPE (DummyInterface)
460+#define CCS_INTERFACE_TYPE_DUMMY2 GET_INTERFACE_TYPE (Dummy2Interface)
461+
462+INTERFACE_TYPE (DummyInterface)
463+INTERFACE_TYPE (Dummy2Interface)
464+
465+TEST(CCSObjectTest, TestTypeAllocation)
466+{
467+ unsigned int i = CCS_INTERFACE_TYPE_DUMMY;
468+ unsigned int j = CCS_INTERFACE_TYPE_DUMMY;
469+ unsigned int k = CCS_INTERFACE_TYPE_DUMMY2;
470+
471+ EXPECT_EQ (i, 1);
472+ EXPECT_EQ (j ,1);
473+ EXPECT_EQ (k, 2);
474+}
475+
476+TEST(CCSObjectTest, InterfaceAdd)
477+{
478+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
479+
480+ ccsObjectInit (to, &ccsDefaultObjectAllocator);
481+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
482+
483+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
484+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
485+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
486+
487+ free (to);
488+}
489+
490+TEST(CCSObjectTest, InterfaceRemove)
491+{
492+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
493+
494+ ccsObjectInit (to, &ccsDefaultObjectAllocator);
495+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
496+
497+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
498+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
499+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
500+
501+ ccsObjectRemoveInterface ((CCSObject *) to, 1);
502+
503+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
504+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
505+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
506+
507+ free (to);
508+}
509+
510+TEST(CCSObjectTest, InterfaceFetchCall)
511+{
512+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
513+
514+ ccsObjectInit (to, &ccsDefaultObjectAllocator);
515+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
516+
517+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
518+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
519+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
520+
521+ const DummyInterface *myDummyInterface = (const DummyInterface *) ccsObjectGetInterface ((CCSObject *) to, 1);
522+
523+ EXPECT_CALL (GoogleMockDummy::_mockDummy, dummyFunc ());
524+
525+ (*myDummyInterface->dummy) ();
526+
527+ ccsObjectRemoveInterface ((CCSObject *) to, 1);
528+
529+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
530+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
531+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
532+
533+ free (to);
534+}
535+
536+TEST(CCSObjectTest, SetPrivateGetPrivate)
537+{
538+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
539+
540+ int i = 1;
541+
542+ ccsObjectInit (to, &ccsDefaultObjectAllocator);
543+ ccsObjectSetPrivate ((CCSObject *) to, (CCSPrivate *) &i);
544+
545+ CCSPrivate *p = ccsObjectGetPrivate ((CCSObject *) to);
546+
547+ EXPECT_EQ (&i, (int *) p);
548+ EXPECT_EQ (i, (*((int *) p)));
549+}
550+
551+void ccsFreeTestingObjectWrapper (TestingObjectWrapper *wrapper)
552+{
553+ GoogleMockDummy::_mockDummy.freeTestingObjectWrapper (wrapper);
554+}
555+
556+#define CCSREF_OBJ(type,dtype) \
557+ void ccs##type##Ref (dtype *d) \
558+ { \
559+ ((CCSObject *) d)->refcnt++; \
560+ } \
561+ void ccs##type##Unref (dtype *d) \
562+ { \
563+ ((CCSObject *) d)->refcnt--; \
564+ if (((CCSObject *) d)->refcnt == 0) \
565+ ccsFree##type (d); \
566+ } \
567+
568+CCSREF_HDR(TestingObjectWrapper, TestingObjectWrapper);
569+CCSREF_OBJ(TestingObjectWrapper, TestingObjectWrapper);
570+
571+TEST(CCSObjectTest, TestRefUnrefFreesObject)
572+{
573+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
574+
575+ ccsObjectInit (to, &ccsDefaultObjectAllocator);
576+ ccsTestingObjectWrapperRef (to);
577+
578+ EXPECT_CALL (GoogleMockDummy::_mockDummy, freeTestingObjectWrapper (to));
579+
580+ ccsTestingObjectWrapperUnref (to);
581+}
582+
583+TEST(CCSObjectTest, TestFinalizeFreesEverything)
584+{
585+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
586+
587+ ccsObjectInit (to, &ccsDefaultObjectAllocator);
588+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
589+
590+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
591+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
592+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
593+
594+ int *i = (int *) malloc (sizeof (int));
595+
596+ *i = 1;
597+
598+ ccsObjectSetPrivate ((CCSObject *) to, (CCSPrivate *) i);
599+
600+ CCSPrivate *p = ccsObjectGetPrivate ((CCSObject *) to);
601+
602+ EXPECT_EQ (i, (int *) p);
603+ EXPECT_EQ (*i, (*((int *) p)));
604+
605+ ccsObjectFinalize ((CCSObject *) to);
606+
607+ EXPECT_EQ (NULL, ((CCSObject *) to)->priv);
608+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
609+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
610+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
611+}
612+
613+void *
614+failingRealloc (void *p, size_t n)
615+{
616+ return NULL;
617+}
618+
619+CCSObjectAllocationInterface failingAllocator =
620+{
621+ failingRealloc,
622+ malloc,
623+ calloc
624+};
625+
626+TEST(CCSObjectTest, TestReallocFailures)
627+{
628+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
629+
630+ ccsObjectInit (to, &failingAllocator);
631+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
632+
633+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
634+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
635+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
636+
637+ free (to);
638+}
639+
640+TEST(CCSObjectTest, TestAllocatedMemoryOnRemove)
641+{
642+ TestingObjectWrapper *to = (TestingObjectWrapper *) calloc (1, sizeof (TestingObjectWrapper));
643+
644+ ccsObjectInit (to, &ccsDefaultObjectAllocator);
645+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 1);
646+
647+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
648+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
649+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
650+
651+ ccsObjectAddInterface ((CCSObject *) to, (const CCSInterface *) &SomeDummyInterface, 2);
652+
653+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
654+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 2);
655+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 1);
656+
657+ ccsObjectRemoveInterface ((CCSObject *) to, 1);
658+
659+ EXPECT_EQ (*((CCSObject *) to)->interfaces, (const CCSInterface *) (&SomeDummyInterface));
660+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 1);
661+ EXPECT_EQ (((CCSObject *) to)->n_allocated_interfaces, 2);
662+ EXPECT_EQ (*((CCSObject *) to)->interface_types, 2);
663+
664+ ccsObjectRemoveInterface ((CCSObject *) to, 2);
665+
666+ EXPECT_EQ (NULL, ((CCSObject *) to)->interfaces);
667+ EXPECT_EQ (((CCSObject *) to)->n_interfaces, 0);
668+ EXPECT_EQ (((CCSObject *) to)->n_allocated_interfaces, 0);
669+ EXPECT_EQ (NULL, ((CCSObject *) to)->interface_types);
670+
671+ free (to);
672+}

Subscribers

People subscribed via source and target branches