Merge lp:~compiz-team/compiz/compiz.fix_1101026.1 into lp:compiz/0.9.10
- compiz.fix_1101026.1
- Merge into 0.9.10
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 | ||||||||
Related bugs: |
|
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.
PluginClassHand
class for the core structure, but it did this without checking if the plugin was
loaded.
Added some new methods to PluginClassHandler exposed by LoadedPluginCla
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
Description of the change
Added some new hooks to PluginClassHandler to allow a VTable to specify if loaded.
PluginClassHand
class for the core structure, but it did this without checking if the plugin was
loaded.
Added some new methods to PluginClassHandler exposed by LoadedPluginCla
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
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3658
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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(
523 +
524 + virtual void
525 + UnloadPlugin(
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.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3659
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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...
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3726
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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.
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... ;)
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal | # |
Hmm strange:
/home/bschaefer
/home/bschaefer
typedef PluginClassInte
At global scope:
cc1plus: error: unrecognized command line option "-Wno-unused-
cc1plus: error: unrecognized command line option "-Wno-unused-
cc1plus: error: unrecognized command line option "-Wno-unused-
cc1plus: error: unrecognized command line option "-Wno-unused-
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 :)
Sam Spilsbury (smspillaz) wrote : | # |
Saucy's compiler added a new warning. CI isn't yet running on saucy. All fixed, tests passing.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3727
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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 - GWDMockSettings
Errors while running CTest
Still not this branches problem :).
Overall looks good to me.
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!
PS Jenkins bot (ps-jenkins) : | # |
MC Return (mc-return) wrote : | # |
On a side note, this breaks Unity, see bug #1185778.
7 === modified file 'include/
8 --- include/
9 +++ include/
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
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; |
FAILED: Continuous integration, rev:3658 jenkins. qa.ubuntu. com/job/ compiz- ci/135/ jenkins. qa.ubuntu. com/job/ compiz- gles-ci/ ./build= pbuilder, distribution= raring, flavor= amd64/172/ console jenkins. qa.ubuntu. com/job/ compiz- pbuilder/ ./build= pbuilder, distribution= raring, flavor= amd64/524/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ compiz- ci/135/ rebuild
http://