Merge lp:~compiz-team/compiz/compiz.fix_1101026.1 into lp:compiz/0.9.10

Proposed by Sam Spilsbury
Status: Merged
Approved by: Brandon Schaefer
Approved revision: 3727
Merged at revision: 3729
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1101026.1
Merge into: lp:compiz/0.9.10
Diff against target: 1492 lines (+892/-155)
15 files modified
.bzrignore (+1/-0)
include/core/abiversion.h (+1/-1)
include/core/plugin.h (+184/-52)
plugins/animation/src/animation.cpp (+1/-1)
plugins/composite/src/composite.cpp (+1/-1)
plugins/cube/src/cube.cpp (+1/-1)
plugins/opengl/src/opengl.cpp (+1/-1)
plugins/scale/src/scale.cpp (+1/-1)
src/plugin.cpp (+16/-0)
src/plugin/tests/test-plugin.cpp (+484/-71)
src/pluginclasshandler/include/core/pluginclasshandler.h (+97/-1)
src/pluginclasshandler/tests/construct/src/test-pch-construct.cpp (+40/-17)
src/pluginclasshandler/tests/get/src/test-pch-get.cpp (+38/-1)
src/pluginclasshandler/tests/test-pluginclasshandler.h (+18/-0)
src/privatescreen/tests/test-privatescreen.cpp (+8/-7)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1101026.1
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Brandon Schaefer (community) Approve
MC Return Pending
Review via email: mp+166155@code.launchpad.net

This proposal supersedes a proposal from 2013-05-26.

Commit message

Added some new hooks to PluginClassHandler to allow a VTable to specify if loaded.

PluginClassHandler::get () was designed to simply instantiate an instance of that
class for the core structure, but it did this without checking if the plugin was
loaded.

Added some new methods to PluginClassHandler exposed by LoadedPluginClassBridge
and only accessible by those who implement PluginKey to specify globally
whether or not a plugin is actually loaded, so that PluginClassHandler can
return accordingly.

Integration and unit tests added as appropriate

(LP: #1169620)
(LP: #1101026)

Description of the change

Added some new hooks to PluginClassHandler to allow a VTable to specify if loaded.

PluginClassHandler::get () was designed to simply instantiate an instance of that
class for the core structure, but it did this without checking if the plugin was
loaded.

Added some new methods to PluginClassHandler exposed by LoadedPluginClassBridge
and only accessible by those who implement PluginKey to specify globally
whether or not a plugin is actually loaded, so that PluginClassHandler can
return accordingly.

I note that the LoadedPluginBridge / PluginKey abstraction is a little weird. I'd like to make it so that CompPlugin::VTable had access to a specific interface on PluginClassHandler to mark certain classes as loaded and unloaded. Unfortunately, in order to do that it would require substantial changes of the API - and I don't really want to do that.

Integration and unit tests added as appropriate

(LP: #1169620)
(LP: #1101026)

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

This MP sounds very promising.
I guess this: 9 +#define CORE_ABIVERSION 20130415 means all plugins will have to be recompiled ?

Maybe adding 2 newlines here, after public and protected ?:

520 + public:
521 + virtual bool
522 + LoadPlugin(CompPlugin *p, const char *path, const char *name) const = 0;
523 +
524 + virtual void
525 + UnloadPlugin(CompPlugin *p) const = 0;
526 +
527 + static PluginFilesystem const* instance;
528 +
529 + protected:
530 + PluginFilesystem();
531 + virtual ~PluginFilesystem() {}

One whitespace too much here:

1124 + * declare PluginKey, which users should inherit from and take

Other than that, I still need to test this, "Abstain" for now.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

I am on the one hand very excited about this one, but on the other hand this means for me personally, that my self-compiled non-trunk plugins will probably all need fixing, then each branch will have to merge with trunk, then I will
have to recompile all those branches again, then copy the compiled binaries, before I can start to use them again ->

I would really like to see screenshot merged to trunk at least, before this one gets merged...

Abstain for now...

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

Sam, I have linked the 2 corresponding bug reports to this MP.

Revision history for this message
MC Return (mc-return) wrote : Posted in a previous version of this proposal

A huge change. :)

Forces me to finally merge trunk with my working branch and fix all the conflicts.
Forces me to recompile all plugins not yet merged with trunk.
Forces me to do a lot of things.

Could not find anything in the code looking bad though and it is great you fixed those nasty bugs with this MP, so this forces me to "Approve" this thingy... ;)

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal

Hmm strange:

/home/bschaefer/src/compiz.fix_1101026.1/src/plugin/tests/test-plugin.cpp: In member function ‘virtual void PluginClassIntegrationTest_get_plugin_structure_null_on_not_loaded_Test<gtest_TypeParam_>::TestBody()’:
/home/bschaefer/src/compiz.fix_1101026.1/src/plugin/tests/test-plugin.cpp:588:52: error: typedef ‘TestParam’ locally defined but not used [-Werror=unused-local-typedefs]
     typedef PluginClassIntegrationTest <TypeParam> TestParam;
                                                    ^
At global scope:
cc1plus: error: unrecognized command line option "-Wno-unused-private-field" [-Werror]
cc1plus: error: unrecognized command line option "-Wno-unused-private-field" [-Werror]
cc1plus: error: unrecognized command line option "-Wno-unused-private-field" [-Werror]
cc1plus: error: unrecognized command line option "-Wno-unused-private-field" [-Werror]
cc1plus: all warnings being treated as errors

I've not had a huge amount of time to look into why this fails (or if I cmaked it wrong :)

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

Saucy's compiler added a new warning. CI isn't yet running on saucy. All fixed, tests passing.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

538 + PluginFilesystem();

You shouldn't need this, the default ctor should be work...(though ive started getting to use to c++0x11), but it really doesn't matter.

Though annoyingly I keep getting this test failing (on trunk compiz):
The following tests FAILED:
  15 - GWDMockSettingsTest.TestMock (Failed)
Errors while running CTest

Still not this branches problem :).

Overall looks good to me.

review: Approve
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

On a side note theres still some crashes when enabling/disabling plugins :(, though im guessing its an unloading/loading problem which is different then this branch!

Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote :

On a side note, this breaks Unity, see bug #1185778.

7 === modified file 'include/core/abiversion.h'
8 --- include/core/abiversion.h 2013-01-28 17:54:50 +0000
9 +++ include/core/abiversion.h 2013-05-28 23:39:25 +0000
10 @@ -5,6 +5,6 @@
11 # error Conflicting definitions of CORE_ABIVERSION
12 #endif
13
14 -#define CORE_ABIVERSION 20130125
15 +#define CORE_ABIVERSION 20130415

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2013-05-28 23:39:25 +0000
4@@ -0,0 +1,1 @@
5+.bzr-repo
6
7=== modified file 'include/core/abiversion.h'
8--- include/core/abiversion.h 2013-01-28 17:54:50 +0000
9+++ include/core/abiversion.h 2013-05-28 23:39:25 +0000
10@@ -5,6 +5,6 @@
11 # error Conflicting definitions of CORE_ABIVERSION
12 #endif
13
14-#define CORE_ABIVERSION 20130125
15+#define CORE_ABIVERSION 20130415
16
17 #endif // COMPIZ_ABIVERSION_H
18
19=== modified file 'include/core/plugin.h'
20--- include/core/plugin.h 2013-01-24 14:18:03 +0000
21+++ include/core/plugin.h 2013-05-28 23:39:25 +0000
22@@ -29,6 +29,7 @@
23 #include <core/string.h>
24 #include <core/option.h>
25 #include <core/privateunion.h>
26+#include <core/pluginclasshandler.h>
27
28 #include <string.h>
29
30@@ -70,6 +71,37 @@
31 extern UnloadPluginProc loaderUnloadPlugin;
32 extern ListPluginsProc loaderListPlugins;
33
34+namespace compiz
35+{
36+namespace plugin
37+{
38+namespace internal
39+{
40+class VTableBase;
41+
42+/**
43+ * Provide a definition for PluginKey, with a protected
44+ * constructor which is a friend of VTableBase */
45+class PluginKey
46+{
47+ protected:
48+
49+ PluginKey () {}
50+
51+ friend class VTableBase;
52+};
53+
54+class VTableBase :
55+ public PluginKey
56+{
57+ public:
58+
59+ virtual ~VTableBase () {};
60+};
61+}
62+}
63+}
64+
65 /**
66 * Base plug-in interface for Compiz. All plugins must implement this
67 * interface, which provides basics for loading, unloading, options,
68@@ -77,8 +109,11 @@
69 */
70 class CompPlugin {
71 public:
72- class VTable {
73+ class VTable :
74+ public compiz::plugin::internal::VTableBase
75+ {
76 public:
77+
78 VTable ();
79 virtual ~VTable ();
80
81@@ -91,9 +126,14 @@
82 const CompString &name () const;
83
84 virtual bool init () = 0;
85-
86 virtual void fini ();
87
88+ /* Mark the plugin as ready to be instantiated */
89+ virtual void markReadyToInstantiate () = 0;
90+
91+ /* Mark the plugin as disallowing further instantiation */
92+ virtual void markNoFurtherInstantiation () = 0;
93+
94 virtual bool initScreen (CompScreen *s);
95
96 virtual void finiScreen (CompScreen *s);
97@@ -111,36 +151,53 @@
98 VTable **mSelf;
99 };
100
101- /**
102- * TODO (or not?)
103- */
104- template <typename T, typename T2>
105- class VTableForScreenAndWindow : public VTable {
106- bool initScreen (CompScreen *s);
107-
108- void finiScreen (CompScreen *s);
109-
110- bool initWindow (CompWindow *w);
111-
112- void finiWindow (CompWindow *w);
113-
114- CompOption::Vector & getOptions ();
115-
116- bool setOption (const CompString &name, CompOption::Value &value);
117+ /**
118+ * TODO (or not?)
119+ */
120+ template <typename T, typename T2, int ABI = 0>
121+ class VTableForScreenAndWindow :
122+ public VTable
123+ {
124+ public:
125+
126+ bool initScreen (CompScreen *s);
127+ void finiScreen (CompScreen *s);
128+ bool initWindow (CompWindow *w);
129+ void finiWindow (CompWindow *w);
130+ CompOption::Vector & getOptions ();
131+ bool setOption (const CompString &name,
132+ CompOption::Value &value);
133+
134+ private:
135+
136+ /* Mark the plugin as ready to be instantiated */
137+ void markReadyToInstantiate ();
138+
139+ /* Mark the plugin as disallowing further instantiation */
140+ void markNoFurtherInstantiation ();
141 };
142
143- /**
144- * TODO (or not?)
145- */
146- template <typename T>
147- class VTableForScreen : public VTable {
148- bool initScreen (CompScreen *s);
149-
150- void finiScreen (CompScreen *s);
151-
152- CompOption::Vector & getOptions ();
153-
154- bool setOption (const CompString &name, CompOption::Value &value);
155+ /**
156+ * TODO (or not?)
157+ */
158+ template <typename T, int ABI = 0>
159+ class VTableForScreen :
160+ public VTable
161+ {
162+ public:
163+
164+ bool initScreen (CompScreen *s);
165+ void finiScreen (CompScreen *s);
166+ CompOption::Vector & getOptions ();
167+ bool setOption (const CompString &name, CompOption::Value &value);
168+
169+ private:
170+
171+ /* Mark the plugin as ready to be instantiated */
172+ void markReadyToInstantiate ();
173+
174+ /* Mark the plugin as disallowing further instantiation */
175+ void markNoFurtherInstantiation ();
176 };
177
178 typedef std::map<CompString, CompPlugin *> Map;
179@@ -211,9 +268,47 @@
180
181 };
182
183-
184-template <typename T, typename T2>
185-bool CompPlugin::VTableForScreenAndWindow<T,T2>::initScreen (CompScreen *s)
186+/**
187+ * Mark the plugin class handlers as ready to be initialized
188+ */
189+template <typename T, typename T2, int ABI>
190+void
191+CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::markReadyToInstantiate ()
192+{
193+ namespace cpi = compiz::plugin::internal;
194+
195+ typedef typename T::ClassPluginBaseType ScreenBase;
196+ typedef typename T2::ClassPluginBaseType WindowBase;
197+
198+ typedef cpi::LoadedPluginClassBridge <T, ScreenBase, ABI> ScreenBridge;
199+ typedef cpi::LoadedPluginClassBridge <T2, WindowBase, ABI> WindowBridge;
200+
201+ ScreenBridge::allowInstantiations (*this);
202+ WindowBridge::allowInstantiations (*this);
203+}
204+
205+/**
206+ * Allow no further class handler initialization
207+ */
208+template <typename T, typename T2, int ABI>
209+void
210+CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::markNoFurtherInstantiation ()
211+{
212+ namespace cpi = compiz::plugin::internal;
213+
214+ typedef typename T::ClassPluginBaseType ScreenBase;
215+ typedef typename T2::ClassPluginBaseType WindowBase;
216+
217+ typedef cpi::LoadedPluginClassBridge <T, ScreenBase, ABI> ScreenBridge;
218+ typedef cpi::LoadedPluginClassBridge <T2, WindowBase, ABI> WindowBridge;
219+
220+ ScreenBridge::disallowInstantiations (*this);
221+ WindowBridge::disallowInstantiations (*this);
222+}
223+
224+template <typename T, typename T2, int ABI>
225+bool
226+CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::initScreen (CompScreen *s)
227 {
228 T * ps = T::get (s);
229 if (!ps)
230@@ -222,15 +317,17 @@
231 return true;
232 }
233
234-template <typename T, typename T2>
235-void CompPlugin::VTableForScreenAndWindow<T,T2>::finiScreen (CompScreen *s)
236+template <typename T, typename T2, int ABI>
237+void
238+CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::finiScreen (CompScreen *s)
239 {
240 T * ps = T::get (s);
241 delete ps;
242 }
243
244-template <typename T, typename T2>
245-bool CompPlugin::VTableForScreenAndWindow<T,T2>::initWindow (CompWindow *w)
246+template <typename T, typename T2, int ABI>
247+bool
248+CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::initWindow (CompWindow *w)
249 {
250 T2 * pw = T2::get (w);
251 if (!pw)
252@@ -239,15 +336,16 @@
253 return true;
254 }
255
256-template <typename T, typename T2>
257-void CompPlugin::VTableForScreenAndWindow<T,T2>::finiWindow (CompWindow *w)
258+template <typename T, typename T2, int ABI>
259+void
260+CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::finiWindow (CompWindow *w)
261 {
262 T2 * pw = T2::get (w);
263 delete pw;
264 }
265
266-template <typename T, typename T2>
267-CompOption::Vector & CompPlugin::VTableForScreenAndWindow<T,T2>::getOptions ()
268+template <typename T, typename T2, int ABI>
269+CompOption::Vector & CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::getOptions ()
270 {
271 CompOption::Class *oc = dynamic_cast<CompOption::Class *> (T::get (screen));
272 if (!oc)
273@@ -255,9 +353,10 @@
274 return oc->getOptions ();
275 }
276
277-template <typename T, typename T2>
278-bool CompPlugin::VTableForScreenAndWindow<T,T2>::setOption (const CompString &name,
279- CompOption::Value &value)
280+template <typename T, typename T2, int ABI>
281+bool
282+CompPlugin::VTableForScreenAndWindow<T, T2, ABI>::setOption (const CompString &name,
283+ CompOption::Value &value)
284 {
285 CompOption::Class *oc = dynamic_cast<CompOption::Class *> (T::get (screen));
286 if (!oc)
287@@ -265,8 +364,39 @@
288 return oc->setOption (name, value);
289 }
290
291-template <typename T>
292-bool CompPlugin::VTableForScreen<T>::initScreen (CompScreen *s)
293+/**
294+ * Mark the plugin class handlers as ready to be initialized
295+ */
296+template <typename T, int ABI>
297+void
298+CompPlugin::VTableForScreen<T, ABI>::markReadyToInstantiate ()
299+{
300+ namespace cpi = compiz::plugin::internal;
301+
302+ typedef typename T::ClassPluginBaseType ScreenBase;
303+ typedef cpi::LoadedPluginClassBridge <T, ScreenBase, ABI> ScreenBridge;
304+
305+ ScreenBridge::allowInstantiations (*this);
306+}
307+
308+/**
309+ * Allow no further class handler initialization
310+ */
311+template <typename T, int ABI>
312+void
313+CompPlugin::VTableForScreen<T, ABI>::markNoFurtherInstantiation ()
314+{
315+ namespace cpi = compiz::plugin::internal;
316+
317+ typedef typename T::ClassPluginBaseType ScreenBase;
318+ typedef cpi::LoadedPluginClassBridge <T, ScreenBase, ABI> ScreenBridge;
319+
320+ ScreenBridge::disallowInstantiations (*this);
321+}
322+
323+template <typename T, int ABI>
324+bool
325+CompPlugin::VTableForScreen<T, ABI>::initScreen (CompScreen *s)
326 {
327 T * ps = new T (s);
328 if (ps->loadFailed ())
329@@ -277,15 +407,16 @@
330 return true;
331 }
332
333-template <typename T>
334-void CompPlugin::VTableForScreen<T>::finiScreen (CompScreen *s)
335+template <typename T, int ABI>
336+void CompPlugin::VTableForScreen<T, ABI>::finiScreen (CompScreen *s)
337 {
338 T * ps = T::get (s);
339 delete ps;
340 }
341
342-template <typename T>
343-CompOption::Vector & CompPlugin::VTableForScreen<T>::getOptions ()
344+template <typename T, int ABI>
345+CompOption::Vector &
346+CompPlugin::VTableForScreen<T, ABI>::getOptions ()
347 {
348 CompOption::Class *oc = dynamic_cast<CompOption::Class *> (T::get (screen));
349 if (!oc)
350@@ -293,8 +424,9 @@
351 return oc->getOptions ();
352 }
353
354-template <typename T>
355-bool CompPlugin::VTableForScreen<T>::setOption (const CompString &name,
356+template <typename T, int ABI>
357+bool
358+CompPlugin::VTableForScreen<T, ABI>::setOption (const CompString &name,
359 CompOption::Value &value)
360 {
361 CompOption::Class *oc = dynamic_cast<CompOption::Class *> (T::get (screen));
362
363=== modified file 'plugins/animation/src/animation.cpp'
364--- plugins/animation/src/animation.cpp 2013-05-09 13:43:07 +0000
365+++ plugins/animation/src/animation.cpp 2013-05-28 23:39:25 +0000
366@@ -94,7 +94,7 @@
367 using namespace compiz::core;
368
369 class AnimPluginVTable :
370- public CompPlugin::VTableForScreenAndWindow<AnimScreen, AnimWindow>
371+ public CompPlugin::VTableForScreenAndWindow<AnimScreen, AnimWindow, ANIMATION_ABI>
372 {
373 public:
374 bool init ();
375
376=== modified file 'plugins/composite/src/composite.cpp'
377--- plugins/composite/src/composite.cpp 2013-05-09 13:43:07 +0000
378+++ plugins/composite/src/composite.cpp 2013-05-28 23:39:25 +0000
379@@ -33,7 +33,7 @@
380
381
382 class CompositePluginVTable :
383- public CompPlugin::VTableForScreenAndWindow<CompositeScreen, CompositeWindow>
384+ public CompPlugin::VTableForScreenAndWindow<CompositeScreen, CompositeWindow, COMPIZ_COMPOSITE_ABI>
385 {
386 public:
387
388
389=== modified file 'plugins/cube/src/cube.cpp'
390--- plugins/cube/src/cube.cpp 2013-05-19 11:50:08 +0000
391+++ plugins/cube/src/cube.cpp 2013-05-28 23:39:25 +0000
392@@ -33,7 +33,7 @@
393 #include <privates.h>
394
395 class CubePluginVTable :
396- public CompPlugin::VTableForScreenAndWindow<CubeScreen, PrivateCubeWindow>
397+ public CompPlugin::VTableForScreenAndWindow<CubeScreen, PrivateCubeWindow, COMPIZ_CUBE_ABI>
398 {
399 public:
400
401
402=== modified file 'plugins/opengl/src/opengl.cpp'
403--- plugins/opengl/src/opengl.cpp 2013-05-09 13:43:07 +0000
404+++ plugins/opengl/src/opengl.cpp 2013-05-28 23:39:25 +0000
405@@ -79,7 +79,7 @@
406 }
407
408 class OpenglPluginVTable :
409- public CompPlugin::VTableForScreenAndWindow<GLScreen, GLWindow>
410+ public CompPlugin::VTableForScreenAndWindow<GLScreen, GLWindow, COMPIZ_OPENGL_ABI>
411 {
412 public:
413
414
415=== modified file 'plugins/scale/src/scale.cpp'
416--- plugins/scale/src/scale.cpp 2013-05-11 09:30:49 +0000
417+++ plugins/scale/src/scale.cpp 2013-05-28 23:39:25 +0000
418@@ -39,7 +39,7 @@
419 #define EDGE_STATE (CompAction::StateInitEdge)
420
421 class ScalePluginVTable :
422- public CompPlugin::VTableForScreenAndWindow<ScaleScreen, ScaleWindow>
423+ public CompPlugin::VTableForScreenAndWindow<ScaleScreen, ScaleWindow, COMPIZ_SCALE_ABI>
424 {
425 public:
426
427
428=== modified file 'src/plugin.cpp'
429--- src/plugin.cpp 2013-02-14 02:43:51 +0000
430+++ src/plugin.cpp 2013-05-28 23:39:25 +0000
431@@ -54,6 +54,9 @@
432
433 bool init ();
434
435+ void markReadyToInstantiate ();
436+ void markNoFurtherInstantiation ();
437+
438 CompOption::Vector & getOptions ();
439
440 bool setOption (const CompString &name,
441@@ -78,6 +81,16 @@
442 return true;
443 }
444
445+void
446+CorePluginVTable::markReadyToInstantiate ()
447+{
448+}
449+
450+void
451+CorePluginVTable::markNoFurtherInstantiation ()
452+{
453+}
454+
455 CompOption::Vector &
456 CorePluginVTable::getOptions ()
457 {
458@@ -228,6 +241,8 @@
459 return false;
460 }
461
462+ p->vTable->markReadyToInstantiate ();
463+
464 if (screen && screen->displayInitialised())
465 {
466 if (!p->vTable->initScreen (screen))
467@@ -252,6 +267,7 @@
468 void
469 CompManager::finiPlugin (CompPlugin *p)
470 {
471+ p->vTable->markNoFurtherInstantiation ();
472
473 if (screen)
474 {
475
476=== modified file 'src/plugin/tests/test-plugin.cpp'
477--- src/plugin/tests/test-plugin.cpp 2013-02-14 02:43:51 +0000
478+++ src/plugin/tests/test-plugin.cpp 2013-05-28 23:39:25 +0000
479@@ -1,8 +1,9 @@
480+#include <boost/shared_ptr.hpp>
481+#include <boost/foreach.hpp>
482+#define foreach BOOST_FOREACH
483+
484 #include "core/plugin.h"
485
486-// This prevents an instantiation error - not sure why ATM
487-#include "core/screen.h"
488-
489 // Get rid of stupid macro from X.h
490 // Why, oh why, are we including X.h?
491 #undef None
492@@ -10,37 +11,54 @@
493 #include <gtest/gtest.h>
494 #include <gmock/gmock.h>
495 #include <gtest_shared_tmpenv.h>
496-
497-namespace {
498+#include <gtest_shared_autodestroy.h>
499+
500+/* This is a link-seam so that we don't have to include screen.h */
501+class CompAction
502+{
503+};
504+
505+class CompMatch
506+{
507+};
508+
509+namespace
510+{
511
512 class PluginFilesystem
513 {
514-public:
515- virtual bool
516- LoadPlugin(CompPlugin *p, const char *path, const char *name) const = 0;
517-
518- virtual void
519- UnloadPlugin(CompPlugin *p) const = 0;
520-
521- static PluginFilesystem const* instance;
522-
523-protected:
524- PluginFilesystem();
525- virtual ~PluginFilesystem() {}
526+ public:
527+
528+ virtual bool
529+ LoadPlugin(CompPlugin *p, const char *path, const char *name) const = 0;
530+
531+ virtual void
532+ UnloadPlugin(CompPlugin *p) const = 0;
533+
534+ static PluginFilesystem const* instance;
535+
536+ protected:
537+
538+ PluginFilesystem();
539+ virtual ~PluginFilesystem() {}
540 };
541
542 class MockPluginFilesystem : public PluginFilesystem
543 {
544-public:
545- MOCK_CONST_METHOD3(LoadPlugin, bool (CompPlugin *, const char *, const char *));
546-
547- MOCK_CONST_METHOD1(UnloadPlugin, void (CompPlugin *p));
548+ public:
549+
550+ MOCK_CONST_METHOD3(LoadPlugin, bool (CompPlugin *, const char *, const char *));
551+
552+ MOCK_CONST_METHOD1(UnloadPlugin, void (CompPlugin *p));
553 };
554
555-class MockVTable : public CompPlugin::VTable
556+class MockVTable :
557+ public CompPlugin::VTable
558 {
559-public:
560- MOCK_METHOD0(init, bool ());
561+ public:
562+ MOCK_METHOD0(init, bool ());
563+ MOCK_METHOD0(markReadyToInstantiate, void ());
564+ MOCK_METHOD0(markNoFurtherInstantiation, void ());
565 };
566
567
568@@ -59,22 +77,26 @@
569
570 PluginFilesystem::PluginFilesystem()
571 {
572- ::loaderLoadPlugin = ::ThunkLoadPluginProc;
573- ::loaderUnloadPlugin = ::ThunkUnloadPluginProc;
574+ ::loaderLoadPlugin = ::ThunkLoadPluginProc;
575+ ::loaderUnloadPlugin = ::ThunkUnloadPluginProc;
576
577- instance = this;
578+ instance = this;
579 }
580
581 PluginFilesystem const* PluginFilesystem::instance = 0;
582
583 } // (abstract) namespace
584
585-
586-
587-TEST(PluginTest, load_non_existant_plugin_must_fail)
588-{
589- MockPluginFilesystem mockfs;
590-
591+class PluginTest :
592+ public ::testing::Test
593+{
594+ public:
595+
596+ MockPluginFilesystem mockfs;
597+};
598+
599+TEST_F (PluginTest, load_non_existant_plugin_must_fail)
600+{
601 using namespace testing;
602
603 EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("dummy"))).
604@@ -91,10 +113,8 @@
605 ASSERT_EQ(0, CompPlugin::load("dummy"));
606 }
607
608-TEST(PluginTest, load_plugin_from_HOME_PLUGINDIR_succeeds)
609+TEST_F (PluginTest, load_plugin_from_HOME_PLUGINDIR_succeeds)
610 {
611- MockPluginFilesystem mockfs;
612-
613 using namespace testing;
614
615 EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("dummy"))).
616@@ -114,10 +134,8 @@
617 CompPlugin::unload(cp);
618 }
619
620-TEST(PluginTest, load_plugin_from_PLUGINDIR_succeeds)
621+TEST_F (PluginTest, load_plugin_from_PLUGINDIR_succeeds)
622 {
623- MockPluginFilesystem mockfs;
624-
625 using namespace testing;
626
627 EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("dummy"))).
628@@ -137,11 +155,10 @@
629 CompPlugin::unload(cp);
630 }
631
632-TEST(PluginTest, load_plugin_from_COMPIZ_PLUGIN_DIR_env_succeeds)
633+TEST_F (PluginTest, load_plugin_from_COMPIZ_PLUGIN_DIR_env_succeeds)
634 {
635 const char *COMPIZ_PLUGIN_DIR_VALUE = "/path/to/plugin/dir";
636 TmpEnv env ("COMPIZ_PLUGIN_DIR", COMPIZ_PLUGIN_DIR_VALUE);
637- MockPluginFilesystem mockfs;
638
639 using namespace testing;
640
641@@ -165,10 +182,8 @@
642 CompPlugin::unload(cp);
643 }
644
645-TEST(PluginTest, load_plugin_from_void_succeeds)
646+TEST_F (PluginTest, load_plugin_from_void_succeeds)
647 {
648- MockPluginFilesystem mockfs;
649-
650 using namespace testing;
651
652 EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("dummy"))).
653@@ -188,31 +203,429 @@
654 CompPlugin::unload(cp);
655 }
656
657-TEST(PluginTest, when_we_push_plugin_init_is_called)
658-{
659- MockPluginFilesystem mockfs;
660-
661- using namespace testing;
662-
663- EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("dummy"))).
664- WillOnce(Return(true));
665-
666- EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(PLUGINDIR), StrEq("dummy"))).
667- Times(AtMost(0));
668-
669- EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), Eq((void*)0), StrEq("dummy"))).
670- Times(AtMost(0));
671-
672- EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(1);
673-
674- MockVTable mockVtable;
675- EXPECT_CALL(mockVtable, init()).WillOnce(Return(true));
676-
677- CompPlugin* cp = CompPlugin::load("dummy");
678-
679- cp->vTable = &mockVtable;
680-
681- CompPlugin::push(cp);
682- ASSERT_EQ(cp, CompPlugin::pop());
683- CompPlugin::unload(cp);
684+TEST_F (PluginTest, when_we_load_plugin_init_load_is_called_without_null_pointer)
685+{
686+ using namespace testing;
687+
688+ EXPECT_CALL (mockfs, LoadPlugin (NotNull (),
689+ EndsWith(HOME_PLUGINDIR),
690+ StrEq("dummy")))
691+ .Times (1)
692+ .WillOnce (Return (true));
693+
694+ EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(AtLeast (0));
695+
696+ CompPlugin* cp = CompPlugin::load("dummy");
697+ CompPlugin::unload(cp);
698+}
699+
700+TEST_F (PluginTest, when_we_push_plugin_init_is_called)
701+{
702+ using namespace testing;
703+
704+ EXPECT_CALL (mockfs, LoadPlugin (_, _, _)).Times (AtLeast (0));
705+ EXPECT_CALL (mockfs, UnloadPlugin(_)).Times (AtLeast (0));
706+
707+ ON_CALL(mockfs, LoadPlugin (_, _, _)).
708+ WillByDefault (Return (true));
709+
710+ MockVTable mockVtable;
711+ EXPECT_CALL (mockVtable, markReadyToInstantiate ()).Times (AtLeast (0));
712+ EXPECT_CALL (mockVtable, markNoFurtherInstantiation ())
713+ .Times (AtLeast (0));
714+ EXPECT_CALL (mockVtable, init ()).WillOnce (Return (true));
715+
716+ CompPlugin* cp = CompPlugin::load("dummy");
717+
718+ cp->vTable = &mockVtable;
719+
720+ CompPlugin::push(cp);
721+ CompPlugin::pop ();
722+ CompPlugin::unload(cp);
723+}
724+
725+TEST_F (PluginTest, when_we_push_plugin_mark_ready_to_instantiate_is_called)
726+{
727+ using namespace testing;
728+
729+ EXPECT_CALL (mockfs, LoadPlugin (_, _, _)).Times (AtLeast (0));
730+ EXPECT_CALL (mockfs, UnloadPlugin(_)).Times (AtLeast (0));
731+
732+ ON_CALL(mockfs, LoadPlugin (_, _, _)).
733+ WillByDefault (Return (true));
734+
735+ MockVTable mockVtable;
736+ EXPECT_CALL (mockVtable, init ())
737+ .Times (AtLeast (0))
738+ .WillOnce (Return (true));
739+ EXPECT_CALL (mockVtable, markReadyToInstantiate ()).Times (1);
740+ EXPECT_CALL (mockVtable, markNoFurtherInstantiation ())
741+ .Times (AtLeast (0));
742+
743+ CompPlugin* cp = CompPlugin::load("dummy");
744+
745+ cp->vTable = &mockVtable;
746+
747+ CompPlugin::push(cp);
748+ CompPlugin::pop ();
749+ CompPlugin::unload(cp);
750+}
751+
752+TEST_F (PluginTest, when_we_pop_plugin_mark_no_further_instantiation_is_called)
753+{
754+ using namespace testing;
755+
756+ EXPECT_CALL (mockfs, LoadPlugin (_, _, _)).Times (AtLeast (0));
757+ EXPECT_CALL (mockfs, UnloadPlugin(_)).Times (AtLeast (0));
758+
759+ ON_CALL(mockfs, LoadPlugin (_, _, _)).
760+ WillByDefault (Return (true));
761+
762+ MockVTable mockVtable;
763+ EXPECT_CALL (mockVtable, init ())
764+ .Times (AtLeast (0))
765+ .WillOnce (Return (true));
766+ EXPECT_CALL (mockVtable, markReadyToInstantiate ()).Times (AtLeast (0));
767+
768+ CompPlugin* cp = CompPlugin::load("dummy");
769+
770+ cp->vTable = &mockVtable;
771+
772+ CompPlugin::push(cp);
773+
774+ EXPECT_CALL (mockVtable, markNoFurtherInstantiation ())
775+ .Times (1);
776+
777+ CompPlugin::pop ();
778+ CompPlugin::unload(cp);
779+}
780+
781+TEST_F (PluginTest, pop_returns_plugin_pointer)
782+{
783+ using namespace testing;
784+
785+ EXPECT_CALL (mockfs, LoadPlugin (_, _, _)).Times (AtLeast (0));
786+ EXPECT_CALL (mockfs, UnloadPlugin(_)).Times (AtLeast (0));
787+
788+ ON_CALL(mockfs, LoadPlugin (_, _, _)).
789+ WillByDefault (Return (true));
790+
791+ MockVTable mockVtable;
792+ EXPECT_CALL (mockVtable, init ())
793+ .Times (AtLeast (0))
794+ .WillOnce (Return (true));
795+ EXPECT_CALL (mockVtable, markReadyToInstantiate ())
796+ .Times (AtLeast (0));
797+ EXPECT_CALL (mockVtable, markNoFurtherInstantiation ())
798+ .Times (AtLeast (0));
799+
800+ CompPlugin* cp = CompPlugin::load("dummy");
801+
802+ cp->vTable = &mockVtable;
803+
804+ CompPlugin::push(cp);
805+ EXPECT_EQ (cp, CompPlugin::pop ());
806+ CompPlugin::unload(cp);
807+}
808+
809+TEST_F (PluginTest, unload_calls_unload_on_fs)
810+{
811+ using namespace testing;
812+
813+ EXPECT_CALL (mockfs, LoadPlugin (_, _, _)).Times (AtLeast (0));
814+
815+ ON_CALL(mockfs, LoadPlugin (_, _, _)).
816+ WillByDefault (Return (true));
817+
818+ CompPlugin* cp = CompPlugin::load("dummy");
819+
820+ EXPECT_CALL (mockfs, UnloadPlugin (cp)).Times (1);
821+
822+ CompPlugin::unload(cp);
823+}
824+
825+namespace
826+{
827+
828+/* TODO (cleanup): Extract this into a separate library because it
829+ * duplicates what's in test-pluginclasshandler */
830+template <typename BaseType>
831+class Base :
832+ public PluginClassStorage
833+{
834+ public:
835+
836+ typedef BaseType Type;
837+
838+ Base ();
839+ ~Base ();
840+
841+ static unsigned int allocPluginClassIndex ();
842+ static void freePluginClassIndex (unsigned int index);
843+
844+ private:
845+
846+ static PluginClassStorage::Indices indices;
847+ static std::list <Base *> bases;
848+};
849+
850+template <typename BaseType>
851+PluginClassStorage::Indices Base <BaseType>::indices;
852+
853+template <typename BaseType>
854+std::list <Base <BaseType> * > Base <BaseType>::bases;
855+
856+template <typename BaseType>
857+Base <BaseType>::Base () :
858+ PluginClassStorage (indices)
859+{
860+ bases.push_back (this);
861+}
862+
863+template <typename BaseType>
864+Base <BaseType>::~Base ()
865+{
866+ bases.remove (this);
867+}
868+
869+template <typename BaseType>
870+unsigned int
871+Base <BaseType>::allocPluginClassIndex ()
872+{
873+ unsigned int i = PluginClassStorage::allocatePluginClassIndex (indices);
874+
875+ foreach (Base *b, bases)
876+ {
877+ if (indices.size () != b->pluginClasses.size ())
878+ b->pluginClasses.resize (indices.size ());
879+ }
880+
881+ return i;
882+}
883+
884+template <typename BaseType>
885+void
886+Base <BaseType>::freePluginClassIndex (unsigned int index)
887+{
888+ PluginClassStorage::freePluginClassIndex (indices, index);
889+
890+ foreach (Base *b, bases)
891+ {
892+ if (indices.size () != b->pluginClasses.size ())
893+ b->pluginClasses.resize (indices.size ());
894+ }
895+}
896+
897+class BaseScreen :
898+ public Base <BaseScreen>
899+{
900+};
901+
902+class BaseWindow :
903+ public Base <BaseWindow>
904+{
905+};
906+
907+class DestructionVerifier
908+{
909+ public:
910+
911+ DestructionVerifier ();
912+
913+ virtual ~DestructionVerifier ();
914+ MOCK_METHOD0 (destroy, void ());
915+};
916+
917+DestructionVerifier::DestructionVerifier ()
918+{
919+ using namespace testing;
920+
921+ /* By default we don't care */
922+ EXPECT_CALL (*this, destroy ()).Times (AtLeast (0));
923+}
924+
925+DestructionVerifier::~DestructionVerifier ()
926+{
927+ destroy ();
928+}
929+
930+class PluginScreen :
931+ public PluginClassHandler <PluginScreen, BaseScreen>,
932+ public DestructionVerifier
933+{
934+ public:
935+
936+ PluginScreen (BaseScreen *s);
937+};
938+
939+class PluginWindow :
940+ public PluginClassHandler <PluginWindow, BaseWindow>,
941+ public DestructionVerifier
942+{
943+ public:
944+
945+ virtual ~PluginWindow () {}
946+ PluginWindow (BaseWindow *s);
947+};
948+
949+PluginScreen::PluginScreen (BaseScreen *s) :
950+ PluginClassHandler (s)
951+{
952+}
953+
954+PluginWindow::PluginWindow (BaseWindow *w) :
955+ PluginClassHandler (w)
956+{
957+}
958+
959+class MockScreenAndWindowVTable :
960+ public CompPlugin::VTableForScreenAndWindow <PluginScreen, PluginWindow>
961+{
962+ public:
963+
964+ MOCK_METHOD0 (init, bool ());
965+};
966+
967+template <class BasePluginType>
968+class PluginClassIntegrationTest :
969+ public PluginTest
970+{
971+ public:
972+
973+ PluginClassIntegrationTest ();
974+ ~PluginClassIntegrationTest ();
975+
976+ boost::shared_ptr <CompPlugin>
977+ LoadPlugin (MockScreenAndWindowVTable &);
978+
979+ MockPluginFilesystem mockfs;
980+ ValueHolder *valueHolder;
981+};
982+
983+void
984+PopAndUnloadPlugin (CompPlugin *p)
985+{
986+ ASSERT_EQ (p, CompPlugin::pop ());
987+ CompPlugin::unload (p);
988+}
989+
990+template <class BasePluginType>
991+boost::shared_ptr <CompPlugin>
992+PluginClassIntegrationTest <BasePluginType>::LoadPlugin (MockScreenAndWindowVTable &v)
993+{
994+ typedef PluginClassIntegrationTest <BasePluginType> TestParam;
995+
996+ using namespace testing;
997+
998+ EXPECT_CALL (TestParam::mockfs, LoadPlugin (_, _, _))
999+ .Times (AtLeast (0))
1000+ .WillOnce (Return (true));
1001+ EXPECT_CALL (TestParam::mockfs, UnloadPlugin(_))
1002+ .Times (AtLeast (0));
1003+
1004+ /* Load a plugin, we'll assign the vtable later */
1005+ CompPlugin *cp = CompPlugin::load("dummy");
1006+ cp->vTable = &v;
1007+
1008+ EXPECT_CALL (v, init ())
1009+ .Times (AtLeast (0))
1010+ .WillOnce (Return (true));
1011+
1012+ CompPlugin::push(cp);
1013+
1014+ return AutoDestroy (cp,
1015+ PopAndUnloadPlugin);
1016+}
1017+
1018+template <class BasePluginType>
1019+PluginClassIntegrationTest <BasePluginType>::PluginClassIntegrationTest ()
1020+{
1021+ valueHolder = new ValueHolder ();
1022+ ValueHolder::SetDefault (valueHolder);
1023+}
1024+
1025+template <class BasePluginType>
1026+PluginClassIntegrationTest <BasePluginType>::~PluginClassIntegrationTest ()
1027+{
1028+ delete valueHolder;
1029+ ValueHolder::SetDefault (NULL);
1030+}
1031+
1032+template <typename BaseType, typename PluginType>
1033+class BasePluginTemplate
1034+{
1035+ public:
1036+
1037+ typedef BaseType Base;
1038+ typedef PluginType Plugin;
1039+};
1040+
1041+typedef BasePluginTemplate <BaseScreen, PluginScreen> BasePluginScreen;
1042+typedef BasePluginTemplate <BaseWindow, PluginWindow> BasePluginWindow;
1043+
1044+}
1045+
1046+/* TODO: Extract actual interfaces out of CompScreen
1047+ * and CompWindow that can be passed to the vTables without
1048+ * using a link-seam like this one */
1049+class CompScreen :
1050+ public BaseScreen
1051+{
1052+};
1053+
1054+class CompWindow :
1055+ public BaseWindow
1056+{
1057+};
1058+
1059+typedef ::testing::Types <BasePluginScreen, BasePluginWindow> PluginTypes;
1060+TYPED_TEST_CASE (PluginClassIntegrationTest, PluginTypes);
1061+
1062+TYPED_TEST (PluginClassIntegrationTest, get_plugin_structure_null_on_not_loaded)
1063+{
1064+ using namespace testing;
1065+
1066+ /* Can't figure out how to get this out of TestParam::base at the moment */
1067+ typename TypeParam::Base base;
1068+ typename TypeParam::Plugin *p = TypeParam::Plugin::get (&base);
1069+
1070+ EXPECT_THAT (p, IsNull ());
1071+}
1072+
1073+TYPED_TEST (PluginClassIntegrationTest, get_plugin_structure_nonnull_on_loaded)
1074+{
1075+ using namespace testing;
1076+
1077+ typedef PluginClassIntegrationTest <TypeParam> TestParam;
1078+
1079+ MockScreenAndWindowVTable vTable;
1080+ boost::shared_ptr <CompPlugin> cp (TestParam::LoadPlugin (vTable));
1081+
1082+ typename TypeParam::Base base;
1083+ typedef boost::shared_ptr <typename TypeParam::Plugin> PluginPtr;
1084+
1085+ /* Because CompScreen is not available, we just need to delete
1086+ * the plugin structure ourselves */
1087+ PluginPtr p (TypeParam::Plugin::get (&base));
1088+
1089+ EXPECT_THAT (p.get (), NotNull ());
1090+}
1091+
1092+TYPED_TEST (PluginClassIntegrationTest, plugin_class_destroyed_when_vtable_is)
1093+{
1094+ using namespace testing;
1095+
1096+ typedef PluginClassIntegrationTest <TypeParam> TestParam;
1097+
1098+ MockScreenAndWindowVTable vTable;
1099+ boost::shared_ptr <CompPlugin> cp (TestParam::LoadPlugin (vTable));
1100+
1101+ typename TypeParam::Base base;
1102+ typedef boost::shared_ptr <typename TypeParam::Plugin> PluginPtr;
1103+
1104+ /* Because CompScreen is not available, we just need to delete
1105+ * the plugin structure ourselves */
1106+ PluginPtr p (TypeParam::Plugin::get (&base));
1107+
1108+ EXPECT_CALL (*p, destroy ()).Times (1);
1109 }
1110
1111=== modified file 'src/pluginclasshandler/include/core/pluginclasshandler.h'
1112--- src/pluginclasshandler/include/core/pluginclasshandler.h 2013-02-26 11:56:10 +0000
1113+++ src/pluginclasshandler/include/core/pluginclasshandler.h 2013-05-28 23:39:25 +0000
1114@@ -45,9 +45,50 @@
1115 */
1116 extern unsigned int pluginClassHandlerIndex;
1117
1118+namespace compiz
1119+{
1120+namespace plugin
1121+{
1122+namespace internal
1123+{
1124+class PluginKey;
1125+/**
1126+ * LoadedPluginClassBridge
1127+ *
1128+ * This template essentially exists so that we can reduce the
1129+ * scope of functions which are allowed to mark plugin classes
1130+ * as instantiatable as we can't really inject the interface
1131+ * from PluginClassHandler to do that anywhere. We also can't
1132+ * forward declare a nested class declaration, but we can forward
1133+ * declare PluginKey, which users should inherit from and take
1134+ * it by reference. If the class we're depending on can only be
1135+ * defined in one other place along with a private constructor
1136+ * accessible only to a friend it means that we've effectively
1137+ * limited the scope of users of this class.
1138+ */
1139+template <class Tp, class Tb, int ABI = 0>
1140+class LoadedPluginClassBridge
1141+{
1142+ public:
1143+
1144+ static void
1145+ allowInstantiations (const PluginKey &);
1146+
1147+ static void
1148+ disallowInstantiations (const PluginKey &);
1149+};
1150+}
1151+}
1152+}
1153+
1154 template<class Tp, class Tb, int ABI = 0>
1155-class PluginClassHandler {
1156+class PluginClassHandler
1157+{
1158 public:
1159+
1160+ typedef Tp ClassPluginType;
1161+ typedef Tb ClassPluginBaseType;
1162+
1163 PluginClassHandler (Tb *);
1164 ~PluginClassHandler ();
1165
1166@@ -90,16 +131,49 @@
1167 static bool initializeIndex (Tb *base);
1168 static inline Tp * getInstance (Tb *base);
1169
1170+ static void allowInstantiations ();
1171+ static void disallowInstantiations ();
1172+
1173+ template <class Plugin, class Base, int PluginABI>
1174+ friend class compiz::plugin::internal::LoadedPluginClassBridge;
1175+
1176 private:
1177 bool mFailed;
1178 Tb *mBase;
1179
1180 static PluginClassIndex mIndex;
1181+ static bool mPluginLoaded;
1182 };
1183
1184+namespace compiz
1185+{
1186+namespace plugin
1187+{
1188+namespace internal
1189+{
1190+template <class Tp, class Tb, int ABI>
1191+void
1192+LoadedPluginClassBridge <Tp, Tb, ABI>::allowInstantiations (const PluginKey &)
1193+{
1194+ PluginClassHandler <Tp, Tb, ABI>::allowInstantiations ();
1195+}
1196+
1197+template <class Tp, class Tb, int ABI>
1198+void
1199+LoadedPluginClassBridge <Tp, Tb, ABI>::disallowInstantiations (const PluginKey &)
1200+{
1201+ PluginClassHandler <Tp, Tb, ABI>::disallowInstantiations ();
1202+}
1203+}
1204+}
1205+}
1206+
1207 template<class Tp, class Tb, int ABI>
1208 PluginClassIndex PluginClassHandler<Tp,Tb,ABI>::mIndex;
1209
1210+template<class Tp, class Tb, int ABI>
1211+bool PluginClassHandler<Tp,Tb,ABI>::mPluginLoaded = false;
1212+
1213 /**
1214 * Attaches a unique instance of the specified plugin class to a
1215 * unique instance of a specified base class
1216@@ -253,15 +327,23 @@
1217 Tp *
1218 PluginClassHandler<Tp,Tb,ABI>::get (Tb *base)
1219 {
1220+ /* Never instantiate an instance of this class
1221+ * if the relevant plugin has not been loaded
1222+ */
1223+ if (!mPluginLoaded)
1224+ return NULL;
1225+
1226 /* Always ensure that the index is initialized before
1227 * calls to ::get */
1228 if (!mIndex.initiated)
1229 initializeIndex (base);
1230+
1231 /* If pluginClassHandlerIndex == mIndex.pcIndex it means that our
1232 * mIndex.index is fresh and can be used directly without needing
1233 * to fetch it from ValueHolder */
1234 if (mIndex.initiated && pluginClassHandlerIndex == mIndex.pcIndex)
1235 return getInstance (base);
1236+
1237 /* If allocating or getting the updated index failed at any point
1238 * then just return NULL we don't know where our private data is stored */
1239 if (mIndex.failed && pluginClassHandlerIndex == mIndex.pcIndex)
1240@@ -285,4 +367,18 @@
1241 }
1242 }
1243
1244+template<class Tp, class Tb, int ABI>
1245+void
1246+PluginClassHandler<Tp, Tb, ABI>::allowInstantiations ()
1247+{
1248+ mPluginLoaded = true;
1249+}
1250+
1251+template<class Tp, class Tb, int ABI>
1252+void
1253+PluginClassHandler<Tp, Tb, ABI>::disallowInstantiations ()
1254+{
1255+ mPluginLoaded = false;
1256+}
1257+
1258 #endif
1259
1260=== modified file 'src/pluginclasshandler/tests/construct/src/test-pch-construct.cpp'
1261--- src/pluginclasshandler/tests/construct/src/test-pch-construct.cpp 2012-01-12 06:48:58 +0000
1262+++ src/pluginclasshandler/tests/construct/src/test-pch-construct.cpp 2013-05-28 23:39:25 +0000
1263@@ -1,23 +1,46 @@
1264 #include <test-pluginclasshandler.h>
1265
1266-class ConstructPlugin: public Plugin, public PluginClassHandler<ConstructPlugin,
1267- Base>
1268-{
1269-public:
1270- ConstructPlugin (Base * base) :
1271- Plugin(base), PluginClassHandler<ConstructPlugin, Base>(base)
1272- {
1273- }
1274-};
1275-
1276-TEST_F( CompizPCHTest, TestConstruct )
1277+class BuildPlugin:
1278+ public Plugin,
1279+ public PluginClassHandler <BuildPlugin, Base>
1280+{
1281+ public:
1282+ BuildPlugin (Base *base) :
1283+ Plugin(base),
1284+ PluginClassHandler <BuildPlugin, Base> (base)
1285+ {
1286+ }
1287+};
1288+
1289+class PluginClassHandlerConstruction :
1290+ public CompizPCHTest
1291+{
1292+ public:
1293+
1294+ PluginClassHandlerConstruction ();
1295+ ~PluginClassHandlerConstruction ();
1296+};
1297+
1298+PluginClassHandlerConstruction::PluginClassHandlerConstruction ()
1299+{
1300+ namespace cpi = compiz::plugin::internal;
1301+ cpi::LoadedPluginClassBridge <BuildPlugin, Base>::allowInstantiations (key);
1302+}
1303+
1304+PluginClassHandlerConstruction::~PluginClassHandlerConstruction ()
1305+{
1306+ namespace cpi = compiz::plugin::internal;
1307+ cpi::LoadedPluginClassBridge <BuildPlugin, Base>::disallowInstantiations (key);
1308+}
1309+
1310+TEST_F (PluginClassHandlerConstruction, TestConstruction)
1311 {
1312 Plugin *p;
1313
1314 bases.push_back(new Base());
1315- plugins.push_back(static_cast<Plugin *>(new ConstructPlugin(bases.back())));
1316+ plugins.push_back(static_cast<Plugin *>(new BuildPlugin(bases.back())));
1317 bases.push_back(new Base());
1318- plugins.push_back(static_cast<Plugin *>(new ConstructPlugin(bases.back())));
1319+ plugins.push_back(static_cast<Plugin *>(new BuildPlugin(bases.back())));
1320
1321 if (bases.front()->pluginClasses.size() != globalPluginClassIndices.size())
1322 {
1323@@ -26,20 +49,20 @@
1324 }
1325
1326 if (!ValueHolder::Default()->hasValue(
1327- compPrintf("%s_index_%lu", typeid(ConstructPlugin).name(), 0)))
1328+ compPrintf("%s_index_%lu", typeid(BuildPlugin).name(), 0)))
1329 {
1330 FAIL() << "ValueHolder does not have value "
1331- << compPrintf("%s_index_%lu", typeid(ConstructPlugin).name(), 0);
1332+ << compPrintf("%s_index_%lu", typeid(BuildPlugin).name(), 0);
1333 }
1334
1335- p = ConstructPlugin::get(bases.front());
1336+ p = BuildPlugin::get(bases.front());
1337
1338 if (p != plugins.front())
1339 {
1340 FAIL() << "Returned Plugin * is not plugins.front ()";
1341 }
1342
1343- p = ConstructPlugin::get(bases.back());
1344+ p = BuildPlugin::get(bases.back());
1345
1346 if (p != plugins.back())
1347 {
1348
1349=== modified file 'src/pluginclasshandler/tests/get/src/test-pch-get.cpp'
1350--- src/pluginclasshandler/tests/get/src/test-pch-get.cpp 2012-01-12 06:48:58 +0000
1351+++ src/pluginclasshandler/tests/get/src/test-pch-get.cpp 2013-05-28 23:39:25 +0000
1352@@ -1,5 +1,9 @@
1353 #include <test-pluginclasshandler.h>
1354
1355+namespace cpi = compiz::plugin::internal;
1356+
1357+using ::testing::IsNull;
1358+
1359 class GetPlugin :
1360 public Plugin,
1361 public PluginClassHandler <GetPlugin, Base>
1362@@ -14,7 +18,26 @@
1363 {
1364 }
1365
1366-TEST_F( CompizPCHTest, TestGet)
1367+class PluginClassHandlerGet :
1368+ public CompizPCHTest
1369+{
1370+ public:
1371+
1372+ PluginClassHandlerGet ();
1373+ ~PluginClassHandlerGet ();
1374+};
1375+
1376+PluginClassHandlerGet::PluginClassHandlerGet ()
1377+{
1378+ cpi::LoadedPluginClassBridge <GetPlugin, Base>::allowInstantiations (key);
1379+}
1380+
1381+PluginClassHandlerGet::~PluginClassHandlerGet ()
1382+{
1383+ cpi::LoadedPluginClassBridge <GetPlugin, Base>::disallowInstantiations (key);
1384+}
1385+
1386+TEST_F (PluginClassHandlerGet, TestGet)
1387 {
1388 Plugin *p;
1389
1390@@ -49,3 +72,17 @@
1391 FAIL() << "Returned Plugin * is not the plugin for bases.back ()";
1392 }
1393 }
1394+
1395+TEST_F (PluginClassHandlerGet, TestGetNoInstantiationsAllowed)
1396+{
1397+ cpi::LoadedPluginClassBridge <GetPlugin, Base>::disallowInstantiations (key);
1398+
1399+ Plugin *p;
1400+
1401+ bases.push_back (new Base ());
1402+ plugins.push_back (new GetPlugin (bases.back ()));
1403+
1404+ p = GetPlugin::get (bases.front ());
1405+
1406+ EXPECT_THAT (p, IsNull ());
1407+}
1408
1409=== modified file 'src/pluginclasshandler/tests/test-pluginclasshandler.h'
1410--- src/pluginclasshandler/tests/test-pluginclasshandler.h 2012-01-19 18:12:31 +0000
1411+++ src/pluginclasshandler/tests/test-pluginclasshandler.h 2013-05-28 23:39:25 +0000
1412@@ -2,6 +2,7 @@
1413 #include <core/pluginclasses.h>
1414
1415 #include <gtest/gtest.h>
1416+#include <gmock/gmock.h>
1417
1418 #include <list>
1419
1420@@ -44,6 +45,21 @@
1421 Base *b;
1422 };
1423
1424+namespace compiz
1425+{
1426+namespace plugin
1427+{
1428+namespace internal
1429+{
1430+/* The version available in the tests is
1431+ * readily constructed */
1432+class PluginKey
1433+{
1434+};
1435+}
1436+}
1437+}
1438+
1439 class CompizPCHTest : public ::testing::Test
1440 {
1441 public:
1442@@ -54,4 +70,6 @@
1443 Global *global;
1444 std::list <Base *> bases;
1445 std::list <Plugin *> plugins;
1446+
1447+ compiz::plugin::internal::PluginKey key;
1448 };
1449
1450=== modified file 'src/privatescreen/tests/test-privatescreen.cpp'
1451--- src/privatescreen/tests/test-privatescreen.cpp 2012-12-30 11:13:36 +0000
1452+++ src/privatescreen/tests/test-privatescreen.cpp 2013-05-28 23:39:25 +0000
1453@@ -249,23 +249,23 @@
1454
1455 namespace {
1456
1457-class MockVTable: public CompPlugin::VTable {
1458+class MockVTable:
1459+ public CompPlugin::VTable
1460+{
1461 public:
1462 MockVTable (CompString const& name) { initVTable (name); }
1463
1464 MOCK_METHOD0(init, bool ());
1465 MOCK_METHOD0(fini, void ());
1466
1467+ MOCK_METHOD0(markReadyToInstantiate, void ());
1468+ MOCK_METHOD0(markNoFurtherInstantiation, void ());
1469+
1470 MOCK_METHOD1(initScreen, bool (CompScreen *s));
1471-
1472 MOCK_METHOD1(finiScreen, void (CompScreen *s));
1473-
1474 MOCK_METHOD1(initWindow, bool (CompWindow *w));
1475-
1476 MOCK_METHOD1(finiWindow, void (CompWindow *w));
1477-
1478 MOCK_METHOD0(getOptions, CompOption::Vector & ());
1479-
1480 MOCK_METHOD2(setOption, bool (const CompString &name, CompOption::Value &value));
1481 };
1482
1483@@ -285,7 +285,8 @@
1484 virtual ~PluginFilesystem() {}
1485 };
1486
1487-class MockPluginFilesystem : public PluginFilesystem
1488+class MockPluginFilesystem :
1489+ public PluginFilesystem
1490 {
1491 public:
1492 MockVTable mockVtableOne;

Subscribers

People subscribed via source and target branches

to all changes: