1 #include "privatescreen.h"
   2 #include "privateaction.h"
   3 #include "eventmanagement.h"
   4 
   5 // Get rid of stupid macro from X.h
   6 // Why, oh why, are we including X.h?
   7 #undef None
   8 
   9 #include <gtest/gtest.h>
  10 #include <gmock/gmock.h>
  11 
  12 #include <stdlib.h>
  13 
  14 using ::testing::Return;
  15 using ::testing::ReturnRef;
  16 using ::testing::_;
  17 
  18 namespace {
  19 
  20 const unsigned long None = 0;
  21 
  22 class MockCompScreen : public CompScreen
  23 {
  24 public:
  25     MockCompScreen()
  26     {
  27 	// The PluginManager ctor uses screen->... (indirectly via CoreOptions)
  28 	// We should kill this dependency
  29 	screen = this;
  30     }
  31 
  32     ~MockCompScreen()
  33     {
  34 	// Because of another indirect use of screen in PluginManager dtor
  35 	// via option.cpp:finiOptionValue()
  36 	screen = 0;
  37     }
  38 
  39     // Interface hoisted from CompScreen
  40     MOCK_METHOD0(updateDefaultIcon, bool ());
  41     MOCK_METHOD0(dpy, Display * ());
  42     MOCK_METHOD0(root, Window ());
  43     MOCK_CONST_METHOD0(vpSize, const CompSize  & () );
  44     MOCK_METHOD1(forEachWindow, void (CompWindow::ForEach));
  45     MOCK_METHOD0(windows, CompWindowList & ());
  46     MOCK_METHOD3(moveViewport, void (int tx, int ty, bool sync));
  47     MOCK_CONST_METHOD0(vp,const CompPoint & ());
  48     MOCK_METHOD0(updateWorkarea, void ());
  49     MOCK_METHOD1(addAction, bool (CompAction *action));
  50     MOCK_METHOD1(findWindow, CompWindow * (Window id));
  51 
  52     MOCK_METHOD2(findTopLevelWindow, CompWindow * (
  53 	    Window id, bool   override_redirect));
  54     MOCK_METHOD6(toolkitAction, void (
  55 	    Atom   toolkitAction,
  56 	    Time   eventTime,
  57 	    Window window,
  58 	    long   data0,
  59 	    long   data1,
  60 	    long   data2));
  61     MOCK_CONST_METHOD0(showingDesktopMask, unsigned int ());
  62     MOCK_CONST_METHOD0(grabsEmpty, bool ());
  63     MOCK_METHOD1(sizePluginClasses, void (unsigned int size));
  64 
  65     MOCK_METHOD1(_initPluginForScreen, bool (CompPlugin *));
  66     MOCK_METHOD1(_finiPluginForScreen, void (CompPlugin *));
  67     MOCK_METHOD3(_setOptionForPlugin, bool (const char *, const char *, CompOption::Value &));
  68     MOCK_METHOD1(_handleEvent, void (XEvent *event));
  69     MOCK_METHOD3(_logMessage, void (const char *, CompLogLevel, const char*));
  70     MOCK_METHOD0(_enterShowDesktopMode, void ());
  71     MOCK_METHOD1(_leaveShowDesktopMode, void (CompWindow *));
  72     MOCK_METHOD1(_addSupportedAtoms, void (std::vector<Atom>& atoms));
  73 
  74     MOCK_METHOD1(_fileWatchAdded, void (CompFileWatch *));
  75     MOCK_METHOD1(_fileWatchRemoved, void (CompFileWatch *));
  76     MOCK_METHOD2(_sessionEvent, void (CompSession::Event, CompOption::Vector &));
  77     MOCK_METHOD3(_handleCompizEvent, void (const char *, const char *, CompOption::Vector &));
  78     MOCK_METHOD4(_fileToImage, bool (CompString &, CompSize &, int &, void *&));
  79     MOCK_METHOD5(_imageToFile, bool (CompString &, CompString &, CompSize &, int, void *));
  80     MOCK_METHOD1(_matchInitExp, CompMatch::Expression * (const CompString&));
  81     MOCK_METHOD0(_matchExpHandlerChanged, void ());
  82     MOCK_METHOD1(_matchPropertyChanged, void (CompWindow *));
  83     MOCK_METHOD0(_outputChangeNotify, void ());
  84 
  85     MOCK_METHOD0(outputDevs, CompOutput::vector & ());
  86     MOCK_METHOD2(setWindowState, void (unsigned int state, Window id));
  87     MOCK_METHOD0(XShape, bool ());
  88     MOCK_METHOD0(screenInfo, std::vector<XineramaScreenInfo> & ());
  89     MOCK_METHOD0(serverWindows, CompWindowList & ());
  90     MOCK_METHOD3(setWindowProp, void (Window       id,
  91 			    Atom         property,
  92 			    unsigned int value));
  93     MOCK_METHOD0(activeWindow, Window ());
  94     MOCK_METHOD0(currentDesktop, unsigned int ());
  95     MOCK_METHOD0(currentHistory, CompActiveWindowHistory *());
  96     MOCK_METHOD0(focusDefaultWindow, void ());
  97     MOCK_METHOD0(getCurrentTime, Time ());
  98     MOCK_METHOD3(getWindowProp, unsigned int (Window       id,
  99 				    Atom         property,
 100 				    unsigned int defaultValue));
 101     MOCK_METHOD2(insertServerWindow, void (CompWindow *w, Window aboveId));
 102     MOCK_METHOD2(insertWindow, void (CompWindow *w, Window aboveId));
 103     MOCK_METHOD0(nDesktop, unsigned int ());
 104     MOCK_METHOD1(outputDeviceForGeometry, int (const CompWindow::Geometry& gm));
 105     MOCK_METHOD0(screenNum, int ());
 106     MOCK_METHOD1(unhookServerWindow, void (CompWindow *w));
 107     MOCK_METHOD1(unhookWindow, void (CompWindow *w));
 108     MOCK_METHOD2(viewportForGeometry, void (const CompWindow::Geometry &gm,
 109 				  CompPoint                   &viewport));
 110 
 111     MOCK_METHOD1(addToDestroyedWindows, void (CompWindow * cw));
 112 
 113     MOCK_CONST_METHOD0(workArea, CompRect const& ());
 114     MOCK_METHOD1(removeAction, void (CompAction *action));
 115     MOCK_METHOD0(getOptions, CompOption::Vector & ());
 116     MOCK_METHOD2(setOption, bool (const CompString &name, CompOption::Value &value));
 117     MOCK_METHOD2(storeValue, void (CompString key, CompPrivate value));
 118     MOCK_METHOD1(hasValue, bool (CompString key));
 119     MOCK_METHOD1(getValue, CompPrivate (CompString key));
 120     MOCK_METHOD1(eraseValue, void (CompString key));
 121     MOCK_METHOD3(addWatchFd, CompWatchFdHandle (int             fd,
 122 				      short int       events,
 123 				      FdWatchCallBack callBack));
 124     MOCK_METHOD1(removeWatchFd, void (CompWatchFdHandle handle));
 125     MOCK_METHOD0(eventLoop, void ());
 126     MOCK_METHOD3(addFileWatch, CompFileWatchHandle (const char        *path,
 127 					  int               mask,
 128 					  FileWatchCallBack callBack));
 129     MOCK_METHOD1(removeFileWatch, void (CompFileWatchHandle handle));
 130     MOCK_CONST_METHOD0(getFileWatches, const CompFileWatchList& ());
 131     MOCK_METHOD0(updateSupportedWmHints, void ());
 132     MOCK_METHOD0(destroyedWindows, CompWindowList & ());
 133     MOCK_CONST_METHOD0(region, const CompRegion & ());
 134     MOCK_METHOD0(hasOverlappingOutputs, bool ());
 135     MOCK_METHOD0(fullscreenOutput, CompOutput & ());
 136     MOCK_METHOD3(setWindowProp32, void (Window         id,
 137 			      Atom           property,
 138 			      unsigned short value));
 139     MOCK_METHOD3(getWindowProp32, unsigned short (Window         id,
 140     					Atom           property,
 141     					unsigned short defaultValue));
 142     MOCK_METHOD4(readImageFromFile, bool (CompString &name,
 143 				CompString &pname,
 144 				CompSize   &size,
 145 				void       *&data));
 146     MOCK_METHOD0(desktopWindowCount, int ());
 147     MOCK_METHOD0(attrib, XWindowAttributes ());
 148     MOCK_CONST_METHOD0(defaultIcon, CompIcon *());
 149     virtual bool otherGrabExist (const char *, ...) { return false; }  // TODO How to mock?
 150     MOCK_METHOD2(pushGrab, GrabHandle (Cursor cursor, const char *name));
 151     MOCK_METHOD2(removeGrab, void (GrabHandle handle, CompPoint *restorePointer));
 152     MOCK_METHOD4(writeImageToFile, bool (CompString &path,
 153 			       const char *format,
 154 			       CompSize   &size,
 155 			       void       *data));
 156     MOCK_METHOD1(runCommand, void (CompString command));
 157     MOCK_METHOD0(shouldSerializePlugins, bool ());
 158     MOCK_CONST_METHOD1(getWorkareaForOutput, const CompRect & (unsigned int outputNum));
 159     MOCK_CONST_METHOD0(currentOutputDev, CompOutput & ());
 160     MOCK_METHOD1(grabExist, bool (const char *));
 161     MOCK_METHOD0(invisibleCursor, Cursor ());
 162     MOCK_CONST_METHOD0(activeNum, unsigned int ());
 163     MOCK_METHOD1(sendWindowActivationRequest, void (Window id));
 164     MOCK_METHOD1(clientList, const CompWindowVector & (bool stackingOrder));
 165     MOCK_METHOD1(outputDeviceForPoint, int (const CompPoint &point));
 166     MOCK_METHOD2(outputDeviceForPoint, int (int x, int y));
 167     MOCK_METHOD0(xkbEvent, int ());
 168     MOCK_METHOD2(warpPointer, void (int dx, int dy));
 169     MOCK_METHOD2(updateGrab, void (GrabHandle handle, Cursor cursor));
 170     MOCK_METHOD0(shapeEvent, int ());
 171     MOCK_METHOD0(syncEvent, int ());
 172     MOCK_METHOD0(autoRaiseWindow, Window  ());
 173     MOCK_METHOD0(processEvents, void ());
 174     MOCK_METHOD1(alwaysHandleEvent, void (XEvent *event));
 175     MOCK_METHOD0(displayString, const char * ());
 176     MOCK_METHOD0(getCurrentOutputExtents, CompRect ());
 177     MOCK_METHOD0(normalCursor, Cursor ());
 178     MOCK_METHOD0(grabbed, bool ());
 179     MOCK_METHOD0(snDisplay, SnDisplay * ());
 180     MOCK_CONST_METHOD0(createFailed, bool ());
 181     MOCK_METHOD0(incrementDesktopWindowCount, void ());
 182     MOCK_METHOD0(decrementDesktopWindowCount, void ());
 183     MOCK_METHOD0(nextMapNum, unsigned int ());
 184     MOCK_CONST_METHOD0(updatePassiveKeyGrabs, void ());
 185     MOCK_METHOD1(updatePassiveButtonGrabs, void (Window serverFrame));
 186     MOCK_CONST_METHOD0(lastPing, unsigned int  ());
 187 
 188     MOCK_CONST_METHOD0(displayInitialised, bool ());
 189     MOCK_METHOD1(applyStartupProperties, void (CompWindow *window));
 190     MOCK_METHOD0(updateClientList, void ());
 191     MOCK_CONST_METHOD0(getTopWindow, CompWindow * ());
 192     MOCK_CONST_METHOD0(getTopServerWindow, CompWindow * ());
 193     MOCK_METHOD0(getCoreOptions, CoreOptions& ());
 194     MOCK_CONST_METHOD0(colormap, Colormap ());
 195     MOCK_METHOD1(setCurrentDesktop, void (unsigned int desktop));
 196     MOCK_CONST_METHOD0(activeWindow, Window ());
 197     MOCK_CONST_METHOD1(grabWindowIsNot, bool (Window w));
 198     MOCK_METHOD0(incrementPendingDestroys, void ());
 199     MOCK_METHOD1(setNextActiveWindow, void (Window id));
 200     MOCK_CONST_METHOD0(getNextActiveWindow, Window ());
 201     MOCK_METHOD0(focusTopMostWindow, CompWindow* ());
 202 
 203     MOCK_METHOD1(getWmState, int (Window id));
 204     MOCK_CONST_METHOD2(setWmState, void (int state, Window id));
 205     MOCK_CONST_METHOD3(getMwmHints, void (Window id,
 206 			  unsigned int *func,
 207 			  unsigned int *decor));
 208     MOCK_METHOD1(getProtocols, unsigned int (Window id));
 209     MOCK_METHOD1(getWindowType, unsigned int (Window id));
 210     MOCK_METHOD1(getWindowState, unsigned int (Window id));
 211 
 212     MOCK_METHOD0(grabServer, void ());
 213     MOCK_METHOD0(ungrabServer, void ());
 214     MOCK_METHOD0(syncServer, void ());
 215     MOCK_METHOD0(serverGrabInterface, ServerGrabInterface * ());
 216 };
 217 
 218 class MockViewportRetreival :
 219     public compiz::private_screen::ViewportRetrievalInterface
 220 {
 221     public:
 222 
 223 	MOCK_CONST_METHOD0(getCurrentViewport, const CompPoint & ());
 224 	MOCK_CONST_METHOD0(viewportDimensions, const CompSize & ());
 225 };
 226 
 227 class StubActivePluginsOption : public CoreOptions
 228 {
 229 public:
 230     StubActivePluginsOption() : CoreOptions(false)
 231     {
 232 	CompOption::Vector& mOptions = getOptions ();
 233 	CompOption::Value::Vector list;
 234 	CompOption::Value value;
 235 
 236 	// active_plugins
 237 	mOptions[CoreOptions::ActivePlugins].setName ("active_plugins", CompOption::TypeList);
 238 	list.clear ();
 239 	value.set(CompString ("core"));
 240 	list.push_back (value);
 241     }
 242 
 243     bool setActivePlugins(const char*, const char* key, CompOption::Value & value)
 244     {
 245 	return setOption(key, value);
 246     }
 247 };
 248 } // (anon) namespace
 249 
 250 namespace {
 251 
 252 class MockVTable: public CompPlugin::VTable {
 253 public:
 254     MockVTable (CompString const& name) { initVTable (name); }
 255 
 256     MOCK_METHOD0(init, bool ());
 257     MOCK_METHOD0(fini, void ());
 258 
 259     MOCK_METHOD1(initScreen, bool (CompScreen *s));
 260 
 261     MOCK_METHOD1(finiScreen, void (CompScreen *s));
 262 
 263     MOCK_METHOD1(initWindow, bool (CompWindow *w));
 264 
 265     MOCK_METHOD1(finiWindow, void (CompWindow *w));
 266 
 267     MOCK_METHOD0(getOptions, CompOption::Vector & ());
 268 
 269     MOCK_METHOD2(setOption, bool (const CompString  &name, CompOption::Value &value));
 270 };
 271 
 272 class PluginFilesystem
 273 {
 274 public:
 275     virtual bool
 276     LoadPlugin(CompPlugin *p, const char *path, const char *name) const = 0;
 277 
 278     virtual void
 279     UnloadPlugin(CompPlugin *p) const = 0;
 280 
 281     static PluginFilesystem const* instance;
 282 
 283 protected:
 284     PluginFilesystem();
 285     virtual ~PluginFilesystem() {}
 286 };
 287 
 288 class MockPluginFilesystem : public PluginFilesystem
 289 {
 290 public:
 291     MockVTable mockVtableOne;
 292     MockVTable mockVtableTwo;
 293     MockVTable mockVtableThree;
 294     MockVTable mockVtableFour;
 295 
 296     MockPluginFilesystem() :
 297 	mockVtableOne("one"),
 298     	mockVtableTwo("two"),
 299     	mockVtableThree("three"),
 300     	mockVtableFour("four")
 301     {}
 302 
 303     MOCK_CONST_METHOD3(LoadPlugin, bool (CompPlugin *, const char *, const char *));
 304 
 305     MOCK_CONST_METHOD1(UnloadPlugin, void (CompPlugin *p));
 306 
 307     bool DummyLoader(CompPlugin *p, const char * path, const char * name)
 308     {
 309 	using namespace testing;
 310 	if (strcmp(name, "one") == 0)
 311 	{
 312 	    p->vTable = &mockVtableOne;
 313 	}
 314 	else if (strcmp(name, "two") == 0)
 315 	{
 316 	    p->vTable = &mockVtableTwo;
 317 	}
 318 	else if (strcmp(name, "three") == 0)
 319 	{
 320 	    p->vTable = &mockVtableThree;
 321 	}
 322 	else
 323 	{
 324 	    p->vTable = &mockVtableFour;
 325 	}
 326 	return true;
 327     }
 328 };
 329 
 330 
 331 bool
 332 ThunkLoadPluginProc(CompPlugin *p, const char *path_, const char *name)
 333 {
 334     return PluginFilesystem::instance->LoadPlugin(p, path_, name);
 335 }
 336 
 337 void
 338 ThunkUnloadPluginProc(CompPlugin *p)
 339 {
 340     PluginFilesystem::instance->UnloadPlugin(p);
 341 }
 342 
 343 PluginFilesystem::PluginFilesystem()
 344 {
 345 	::loaderLoadPlugin = ::ThunkLoadPluginProc;
 346 	::loaderUnloadPlugin = ::ThunkUnloadPluginProc;
 347 
 348 	instance = this;
 349 }
 350 
 351 // tell GLib not to use the slice-allocator implementation
 352 // and avoid spurious valgrind reporting
 353 void glib_nice_for_valgrind() { setenv("G_SLICE", "always-malloc", true); }
 354 int const init = (glib_nice_for_valgrind(), 0);
 355 
 356 PluginFilesystem const* PluginFilesystem::instance = 0;
 357 
 358 } // (abstract) namespace
 359 
 360 namespace cps = compiz::private_screen;
 361 namespace ce = compiz::events;
 362 namespace ca = compiz::actions;
 363 
 364 TEST(privatescreen_PluginManagerTest, create_and_destroy)
 365 {
 366     using namespace testing;
 367 
 368     MockCompScreen comp_screen;
 369 
 370     cps::PluginManager ps;
 371 }
 372 
 373 TEST(privatescreen_PluginManagerTest, calling_updatePlugins_does_not_error)
 374 {
 375     using namespace testing;
 376 
 377     MockCompScreen comp_screen;
 378 
 379     cps::PluginManager ps;
 380 
 381     // Stuff that has to be done before calling updatePlugins()
 382     CompOption::Value::Vector values;
 383     values.push_back ("core");
 384     ps.setPlugins (values);
 385     ps.setDirtyPluginList ();
 386 
 387     // Now we can call updatePlugins() without a segfault.  Hoorah!
 388     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 389 	WillOnce(Return(false));
 390     ps.updatePlugins(&comp_screen, StubActivePluginsOption().optionGetActivePlugins());
 391 }
 392 
 393 TEST(privatescreen_PluginManagerTest, calling_updatePlugins_after_setting_initialPlugins)
 394 {
 395     using namespace testing;
 396 
 397     MockCompScreen comp_screen;
 398 
 399     cps::PluginManager ps;
 400 
 401     // Stuff that has to be done before calling updatePlugins()
 402     CompOption::Value::Vector values;
 403     values.push_back ("core");
 404     ps.setPlugins (values);
 405     ps.setDirtyPluginList ();
 406 
 407     std::list <CompString> plugins;
 408     plugins.push_back ("one");
 409     plugins.push_back ("two");
 410     plugins.push_back ("three");
 411     initialPlugins = plugins;
 412 
 413     MockPluginFilesystem mockfs;
 414 
 415     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("one"))).
 416 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 417     EXPECT_CALL(mockfs.mockVtableOne, init()).WillOnce(Return(true));
 418 
 419     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("two"))).
 420 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 421     EXPECT_CALL(mockfs.mockVtableTwo, init()).WillOnce(Return(true));
 422 
 423     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("three"))).
 424 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 425     EXPECT_CALL(mockfs.mockVtableThree, init()).WillOnce(Return(false));
 426 
 427     EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(1);  // Once for "three" which doesn't load
 428 
 429     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 430 	    WillOnce(Return(false));
 431 
 432     ps.updatePlugins(&comp_screen, StubActivePluginsOption().optionGetActivePlugins());
 433 
 434     Mock::VerifyAndClearExpectations(&mockfs);
 435     Mock::VerifyAndClearExpectations(&mockfs.mockVtableOne);
 436     Mock::VerifyAndClearExpectations(&mockfs.mockVtableTwo);
 437     Mock::VerifyAndClearExpectations(&mockfs.mockVtableThree);
 438     Mock::VerifyAndClearExpectations(&mockfs.mockVtableFour);
 439 
 440     // TODO Some cleanup that probably ought to be automatic.
 441     EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(2);
 442     EXPECT_CALL(comp_screen, _finiPluginForScreen(Ne((void*)0))).Times(2);
 443     EXPECT_CALL(mockfs.mockVtableOne, finiScreen(Ne((void*)0))).Times(1);
 444     EXPECT_CALL(mockfs.mockVtableOne, fini()).Times(1);
 445     EXPECT_CALL(mockfs.mockVtableTwo, finiScreen(Ne((void*)0))).Times(1);
 446     EXPECT_CALL(mockfs.mockVtableTwo, fini()).Times(1);
 447 
 448     for (CompPlugin* p; (p = CompPlugin::pop ()) != 0; CompPlugin::unload (p));
 449 }
 450 
 451 TEST(privatescreen_PluginManagerTest, updating_when_failing_to_load_plugin_in_middle_of_list)
 452 {
 453     using namespace testing;
 454 
 455     MockCompScreen comp_screen;
 456 
 457     cps::PluginManager ps;
 458     StubActivePluginsOption sapo;
 459 
 460     CompOption::Value::Vector values;
 461     values.push_back ("core");
 462     ps.setPlugins (values);
 463     ps.setDirtyPluginList ();
 464 
 465     std::list <CompString> plugins;
 466     plugins.push_back ("one");
 467     plugins.push_back ("three");
 468     plugins.push_back ("four");
 469     initialPlugins = plugins;
 470 
 471     MockPluginFilesystem mockfs;
 472 
 473     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("one"))).
 474 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 475     EXPECT_CALL(mockfs.mockVtableOne, init()).WillOnce(Return(true));
 476 
 477     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("three"))).
 478 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 479     EXPECT_CALL(mockfs.mockVtableThree, init()).WillOnce(Return(false));
 480 
 481     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("four"))).
 482 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 483     EXPECT_CALL(mockfs.mockVtableFour, init()).Times(1).WillRepeatedly(Return(true));
 484 
 485     EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(1);  // Once for "three" which doesn't load
 486 
 487     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 488 	    WillOnce(Return(true));
 489 
 490     ps.updatePlugins(&comp_screen, sapo.optionGetActivePlugins());
 491 
 492     Mock::VerifyAndClearExpectations(&mockfs);
 493     Mock::VerifyAndClearExpectations(&mockfs.mockVtableOne);
 494     Mock::VerifyAndClearExpectations(&mockfs.mockVtableTwo);
 495     Mock::VerifyAndClearExpectations(&mockfs.mockVtableThree);
 496     Mock::VerifyAndClearExpectations(&mockfs.mockVtableFour);
 497 
 498     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 499 	    WillOnce(Invoke(&sapo, &StubActivePluginsOption::setActivePlugins));
 500 
 501     ps.updatePlugins(&comp_screen, sapo.optionGetActivePlugins());
 502 
 503     Mock::VerifyAndClearExpectations(&mockfs);
 504     Mock::VerifyAndClearExpectations(&mockfs.mockVtableOne);
 505     Mock::VerifyAndClearExpectations(&mockfs.mockVtableTwo);
 506     Mock::VerifyAndClearExpectations(&mockfs.mockVtableThree);
 507     Mock::VerifyAndClearExpectations(&mockfs.mockVtableFour);
 508 
 509     // TODO Some cleanup that probably ought to be automatic.
 510     EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(2);
 511     EXPECT_CALL(comp_screen, _finiPluginForScreen(Ne((void*)0))).Times(2);
 512     EXPECT_CALL(mockfs.mockVtableOne, finiScreen(Ne((void*)0))).Times(1);
 513     EXPECT_CALL(mockfs.mockVtableOne, fini()).Times(1);
 514     EXPECT_CALL(mockfs.mockVtableFour, finiScreen(Ne((void*)0))).Times(1);
 515     EXPECT_CALL(mockfs.mockVtableFour, fini()).Times(1);
 516     for (CompPlugin* p; (p = CompPlugin::pop ()) != 0; CompPlugin::unload (p));
 517 }
 518 
 519 TEST(privatescreen_PluginManagerTest, calling_updatePlugins_with_fewer_plugins)
 520 {
 521     using namespace testing;
 522 
 523     MockCompScreen comp_screen;
 524 
 525     cps::PluginManager ps;
 526 
 527     StubActivePluginsOption sapo;
 528 
 529     // Stuff that has to be done before calling updatePlugins()
 530     initialPlugins = std::list <CompString>();
 531     CompOption::Value::Vector values;
 532     values.push_back ("core");
 533     ps.setPlugins (values);
 534     ps.setDirtyPluginList ();
 535 
 536     {
 537 	CompOption::Value::Vector plugins;
 538 	plugins.push_back ("one");
 539 	plugins.push_back ("two");
 540 	plugins.push_back ("three");
 541 	CompOption::Value v(plugins);
 542 	sapo.setActivePlugins("core", "active_plugins", v);
 543     }
 544 
 545     MockPluginFilesystem mockfs;
 546 
 547     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("one"))).
 548 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 549     EXPECT_CALL(mockfs.mockVtableOne, init()).WillOnce(Return(true));
 550 
 551     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("two"))).
 552 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 553     EXPECT_CALL(mockfs.mockVtableTwo, init()).WillOnce(Return(true));
 554 
 555     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("three"))).
 556 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 557     EXPECT_CALL(mockfs.mockVtableThree, init()).WillOnce(Return(true));
 558 
 559     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 560 	    WillOnce(Invoke(&sapo, &StubActivePluginsOption::setActivePlugins));
 561 
 562     ps.updatePlugins(&comp_screen, sapo.optionGetActivePlugins());
 563 
 564     Mock::VerifyAndClearExpectations(&mockfs);
 565     Mock::VerifyAndClearExpectations(&mockfs.mockVtableOne);
 566     Mock::VerifyAndClearExpectations(&mockfs.mockVtableTwo);
 567     Mock::VerifyAndClearExpectations(&mockfs.mockVtableThree);
 568     Mock::VerifyAndClearExpectations(&mockfs.mockVtableFour);
 569 
 570     EXPECT_CALL(comp_screen, _finiPluginForScreen(Ne((void*)0))).Times(2);
 571     EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(1);
 572     EXPECT_CALL(mockfs.mockVtableTwo, finiScreen(Ne((void*)0))).Times(1);
 573     EXPECT_CALL(mockfs.mockVtableTwo, fini()).Times(1);
 574     EXPECT_CALL(mockfs.mockVtableThree, fini()).Times(1);
 575     EXPECT_CALL(mockfs.mockVtableThree, finiScreen(Ne((void*)0))).Times(1);
 576     EXPECT_CALL(mockfs.mockVtableThree, init()).WillOnce(Return(true));
 577     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 578 	    WillOnce(Invoke(&sapo, &StubActivePluginsOption::setActivePlugins));
 579 
 580     {
 581 	CompOption::Value::Vector plugins;
 582 	plugins.push_back ("one");
 583 	plugins.push_back ("three");
 584 	CompOption::Value v(plugins);
 585 	sapo.setActivePlugins("core", "active_plugins", v);
 586     }
 587 
 588     ps.updatePlugins(&comp_screen, sapo.optionGetActivePlugins());
 589 
 590     Mock::VerifyAndClearExpectations(&mockfs);
 591     Mock::VerifyAndClearExpectations(&mockfs.mockVtableOne);
 592     Mock::VerifyAndClearExpectations(&mockfs.mockVtableTwo);
 593     Mock::VerifyAndClearExpectations(&mockfs.mockVtableThree);
 594     Mock::VerifyAndClearExpectations(&mockfs.mockVtableFour);
 595 
 596     // TODO Some cleanup that probably ought to be automatic.
 597     EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(2);
 598     EXPECT_CALL(comp_screen, _finiPluginForScreen(Ne((void*)0))).Times(2);
 599     EXPECT_CALL(mockfs.mockVtableOne, finiScreen(Ne((void*)0))).Times(1);
 600     EXPECT_CALL(mockfs.mockVtableOne, fini()).Times(1);
 601     EXPECT_CALL(mockfs.mockVtableThree, finiScreen(Ne((void*)0))).Times(1);
 602     EXPECT_CALL(mockfs.mockVtableThree, fini()).Times(1);
 603 
 604     for (CompPlugin* p; (p = CompPlugin::pop ()) != 0; CompPlugin::unload (p));
 605 }
 606 
 607 // Verify plugin ordering, and verify that plugins not in availablePlugins
 608 // don't get dropped. Because availablePlugins is NOT a definitive list
 609 // of what the dynamic loader might be able to find in its path.
 610 TEST(privatescreen_PluginManagerTest, verify_plugin_ordering)
 611 {
 612     using namespace testing;
 613 
 614     cps::PluginManager ps;
 615 
 616     initialPlugins.clear();
 617     initialPlugins.push_back("alice");
 618     initialPlugins.push_back("bob");
 619     initialPlugins.push_back("charlie");
 620 
 621     CompOption::Value::Vector extra;
 622     extra.push_back("charlie");
 623     extra.push_back("david");
 624     extra.push_back("alice");
 625     extra.push_back("eric");
 626     
 627     CompOption::Value::Vector merged = ps.mergedPluginList(extra);
 628 
 629     ASSERT_EQ(merged.size(), 6);
 630     ASSERT_EQ(merged[0].s(), "core");
 631     ASSERT_EQ(merged[1].s(), "alice");
 632     ASSERT_EQ(merged[2].s(), "bob");
 633     ASSERT_EQ(merged[3].s(), "charlie");
 634     ASSERT_EQ(merged[4].s(), "david");
 635     ASSERT_EQ(merged[5].s(), "eric");
 636 }
 637 
 638 TEST(privatescreen_PluginManagerTest, calling_updatePlugins_with_additional_plugins)
 639 {
 640     using namespace testing;
 641 
 642     MockCompScreen comp_screen;
 643 
 644     cps::PluginManager ps;
 645 
 646     StubActivePluginsOption sapo;
 647 
 648     // Stuff that has to be done before calling updatePlugins()
 649     initialPlugins = std::list <CompString>();
 650     CompOption::Value::Vector values;
 651     values.push_back ("core");
 652     ps.setPlugins (values);
 653     ps.setDirtyPluginList ();
 654 
 655     {
 656 	CompOption::Value::Vector plugins;
 657 	plugins.push_back ("one");
 658 	plugins.push_back ("two");
 659 	plugins.push_back ("four");
 660 	CompOption::Value v(plugins);
 661 	sapo.setActivePlugins("core", "active_plugins", v);
 662     }
 663 
 664     MockPluginFilesystem mockfs;
 665 
 666     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("one"))).
 667 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 668     EXPECT_CALL(mockfs.mockVtableOne, init()).WillOnce(Return(true));
 669 
 670     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("two"))).
 671 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 672     EXPECT_CALL(mockfs.mockVtableTwo, init()).WillOnce(Return(true));
 673 
 674     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("four"))).
 675 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 676     EXPECT_CALL(mockfs.mockVtableFour, init()).WillOnce(Return(true));
 677 
 678     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 679 	    WillOnce(Invoke(&sapo, &StubActivePluginsOption::setActivePlugins));
 680 
 681     ps.updatePlugins(&comp_screen, sapo.optionGetActivePlugins());
 682 
 683     Mock::VerifyAndClearExpectations(&mockfs);
 684     Mock::VerifyAndClearExpectations(&mockfs.mockVtableOne);
 685     Mock::VerifyAndClearExpectations(&mockfs.mockVtableTwo);
 686     Mock::VerifyAndClearExpectations(&mockfs.mockVtableThree);
 687     Mock::VerifyAndClearExpectations(&mockfs.mockVtableFour);
 688 
 689     EXPECT_CALL(comp_screen, _finiPluginForScreen(Ne((void*)0))).Times(1);
 690     EXPECT_CALL(mockfs.mockVtableFour, fini()).Times(1);
 691     EXPECT_CALL(mockfs.mockVtableFour, finiScreen(Ne((void*)0))).Times(1);
 692     EXPECT_CALL(mockfs, LoadPlugin(Ne((void*)0), EndsWith(HOME_PLUGINDIR), StrEq("three"))).
 693 	WillOnce(Invoke(&mockfs, &MockPluginFilesystem::DummyLoader));
 694     EXPECT_CALL(mockfs.mockVtableThree, init()).WillOnce(Return(true));
 695     EXPECT_CALL(mockfs.mockVtableFour, init()).WillOnce(Return(true));
 696     EXPECT_CALL(comp_screen, _setOptionForPlugin(StrEq("core"), StrEq("active_plugins"), _)).
 697 	    WillOnce(Invoke(&sapo, &StubActivePluginsOption::setActivePlugins));
 698 
 699     {
 700 	CompOption::Value::Vector plugins;
 701 	plugins.push_back ("one");
 702 	plugins.push_back ("two");
 703 	plugins.push_back ("three");
 704 	plugins.push_back ("four");
 705 	CompOption::Value v(plugins);
 706 	sapo.setActivePlugins("core", "active_plugins", v);
 707     }
 708 
 709     ps.updatePlugins(&comp_screen, sapo.optionGetActivePlugins());
 710 
 711     Mock::VerifyAndClearExpectations(&mockfs);
 712     Mock::VerifyAndClearExpectations(&mockfs.mockVtableOne);
 713     Mock::VerifyAndClearExpectations(&mockfs.mockVtableTwo);
 714     Mock::VerifyAndClearExpectations(&mockfs.mockVtableThree);
 715     Mock::VerifyAndClearExpectations(&mockfs.mockVtableFour);
 716 
 717     // TODO Some cleanup that probably ought to be automatic.
 718     EXPECT_CALL(mockfs, UnloadPlugin(_)).Times(4);
 719     EXPECT_CALL(comp_screen, _finiPluginForScreen(Ne((void*)0))).Times(4);
 720     EXPECT_CALL(mockfs.mockVtableFour, finiScreen(Ne((void*)0))).Times(1);
 721     EXPECT_CALL(mockfs.mockVtableFour, fini()).Times(1);
 722     EXPECT_CALL(mockfs.mockVtableThree, finiScreen(Ne((void*)0))).Times(1);
 723     EXPECT_CALL(mockfs.mockVtableThree, fini()).Times(1);
 724     EXPECT_CALL(mockfs.mockVtableTwo, finiScreen(Ne((void*)0))).Times(1);
 725     EXPECT_CALL(mockfs.mockVtableTwo, fini()).Times(1);
 726     EXPECT_CALL(mockfs.mockVtableOne, finiScreen(Ne((void*)0))).Times(1);
 727     EXPECT_CALL(mockfs.mockVtableOne, fini()).Times(1);
 728 
 729     for (CompPlugin* p; (p = CompPlugin::pop ()) != 0; CompPlugin::unload (p));
 730 }
 731 
 732 TEST(privatescreen_EventManagerTest, create_and_destroy)
 733 {
 734     using namespace testing;
 735 
 736     MockCompScreen comp_screen;
 737 
 738     cps::EventManager em;
 739 }
 740 
 741 TEST(privatescreen_EventManagerTest, init)
 742 {
 743     using namespace testing;
 744 
 745     MockCompScreen comp_screen;
 746 
 747     CompOption::Value::Vector values;
 748     values.push_back ("core");
 749     initialPlugins = std::list <CompString>();
 750 
 751     EXPECT_CALL(comp_screen, addAction(_)).WillRepeatedly(Return(false));
 752     EXPECT_CALL(comp_screen, removeAction(_)).WillRepeatedly(Return());
 753     EXPECT_CALL(comp_screen, _matchInitExp(StrEq("any"))).WillRepeatedly(Return((CompMatch::Expression*)0));
 754 
 755     // The PrivateScreen ctor indirectly calls screen->dpy().
 756     // We should kill this dependency
 757     EXPECT_CALL(comp_screen, dpy()).WillRepeatedly(Return((Display*)(0)));
 758 
 759     cps::EventManager em;
 760 
 761     CoreOptions coreOptions(false);
 762     em.init();
 763 }
 764 
 765 TEST(privatescreen_ViewportGeometryTest, PickCurrent)
 766 {
 767     CompPoint vp;
 768     compiz::window::Geometry g (250, 250, 500, 500, 0);
 769     MockViewportRetreival mvp;
 770 
 771     CompPoint current (0, 0);
 772     CompSize  dimensions (1, 1);
 773 
 774     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 775     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 776 
 777     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 778 
 779     EXPECT_EQ (vp, CompPoint (0, 0));
 780 }
 781 
 782 TEST(privatescreen_ViewportGeometryTest, PickRight)
 783 {
 784     CompPoint vp;
 785     compiz::window::Geometry g (1250, 0, 500, 500, 0);
 786     MockViewportRetreival mvp;
 787 
 788     CompPoint current (0, 0);
 789     CompSize  dimensions (2, 1);
 790 
 791     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 792     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 793 
 794     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 795 
 796     EXPECT_EQ (vp, CompPoint (1, 0));
 797 }
 798 
 799 TEST(privatescreen_ViewportGeometryTest, PickLeft)
 800 {
 801     CompPoint vp;
 802     compiz::window::Geometry g (-750, 0, 500, 500, 0);
 803     MockViewportRetreival mvp;
 804 
 805     CompPoint current (1, 0);
 806     CompSize  dimensions (2, 1);
 807 
 808     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 809     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 810 
 811     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 812 
 813     EXPECT_EQ (vp, CompPoint (0, 0));
 814 }
 815 
 816 TEST(privatescreen_ViewportGeometryTest, PickBottom)
 817 {
 818     CompPoint vp;
 819     compiz::window::Geometry g (0, 1250, 500, 500, 0);
 820     MockViewportRetreival mvp;
 821 
 822     CompPoint current (0, 0);
 823     CompSize  dimensions (1, 2);
 824 
 825     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 826     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 827 
 828     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 829 
 830     EXPECT_EQ (vp, CompPoint (0, 1));
 831 }
 832 
 833 TEST(privatescreen_ViewportGeometryTest, PickTop)
 834 {
 835     CompPoint vp;
 836     compiz::window::Geometry g (0, -750, 500, 500, 0);
 837     MockViewportRetreival mvp;
 838 
 839     CompPoint current (0, 1);
 840     CompSize  dimensions (1, 2);
 841 
 842     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 843     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 844 
 845     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 846 
 847     EXPECT_EQ (vp, CompPoint (0, 0));
 848 }
 849 
 850 TEST(privatescreen_ViewportGeometryTest, PickTopWhenJustAbove)
 851 {
 852     CompPoint vp;
 853     compiz::window::Geometry g (0, -251, 500, 500, 0);
 854     MockViewportRetreival mvp;
 855 
 856     CompPoint current (0, 1);
 857     CompSize  dimensions (1, 2);
 858 
 859     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 860     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 861 
 862     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 863 
 864     EXPECT_EQ (vp, CompPoint (0, 0));
 865 }
 866 
 867 TEST(privatescreen_ViewportGeometryTest, PickRightWhenJustRight)
 868 {
 869     CompPoint vp;
 870     compiz::window::Geometry g (751, 0, 500, 500, 0);
 871     MockViewportRetreival mvp;
 872 
 873     CompPoint current (0, 0);
 874     CompSize  dimensions (2, 1);
 875 
 876     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 877     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 878 
 879     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 880 
 881     EXPECT_EQ (vp, CompPoint (1, 0));
 882 }
 883 
 884 TEST(privatescreen_ViewportGeometryTest, PickLeftWhenJustLeft)
 885 {
 886     CompPoint vp;
 887     compiz::window::Geometry g (-251, 0, 500, 500, 0);
 888     MockViewportRetreival mvp;
 889 
 890     CompPoint current (1, 0);
 891     CompSize  dimensions (2, 1);
 892 
 893     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 894     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 895 
 896     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 897 
 898     EXPECT_EQ (vp, CompPoint (0, 0));
 899 }
 900 
 901 TEST(privatescreen_ViewportGeometryTest, PickBottomWhenJustBelow)
 902 {
 903     CompPoint vp;
 904     compiz::window::Geometry g (0, 751, 500, 500, 0);
 905     MockViewportRetreival mvp;
 906 
 907     CompPoint current (0, 0);
 908     CompSize  dimensions (1, 2);
 909 
 910     EXPECT_CALL (mvp, getCurrentViewport ()).WillOnce (ReturnRef (current));
 911     EXPECT_CALL (mvp, viewportDimensions ()).WillOnce (ReturnRef (dimensions));
 912 
 913     compiz::private_screen::viewports::viewportForGeometry (g, vp, &mvp, CompSize (1000, 1000));
 914 
 915     EXPECT_EQ (vp, CompPoint (0, 1));
 916 }
 917 
 918 namespace
 919 {
 920 const Window topLeftScreenEdge = 1;
 921 const Window topScreenEdge = 2;
 922 const Window topRightScreenEdge = 3;
 923 const Window rightScreenEdge = 4;
 924 const Window bottomRightScreenEdge = 5;
 925 const Window bottomScreenEdge = 6;
 926 const Window bottomLeftScreenEdge = 7;
 927 const Window leftScreenEdge = 8;
 928 
 929 const CompScreenEdge screenEdges[SCREEN_EDGE_NUM] =
 930 {
 931     { leftScreenEdge, SCREEN_EDGE_LEFT },
 932     { rightScreenEdge, SCREEN_EDGE_RIGHT },
 933     { topScreenEdge, SCREEN_EDGE_TOP },
 934     { bottomScreenEdge , SCREEN_EDGE_BOTTOM },
 935     { topLeftScreenEdge, SCREEN_EDGE_TOPLEFT },
 936     { topRightScreenEdge, SCREEN_EDGE_TOPRIGHT },
 937     { bottomLeftScreenEdge, SCREEN_EDGE_BOTTOMLEFT },
 938     { bottomRightScreenEdge, SCREEN_EDGE_BOTTOMRIGHT}
 939 };
 940 }
 941 
 942 TEST (privatescreen_ButtonPressEdgeEventManagementTest, IgnoreWhenEventAndRootWindowMismatch)
 943 {
 944     const Window rootWindow = 1;
 945     const Window edgeWindow = topScreenEdge;
 946 
 947     cps::OrphanData orphanData;
 948     cps::GrabList grabList;
 949 
 950     EXPECT_EQ (ce::processButtonPressOnEdgeWindow (edgeWindow,
 951 						   rootWindow,
 952 						   0,
 953 						   0,
 954 						   grabList,
 955 						   screenEdges), -1);
 956 }
 957 
 958 TEST (privatescreen_ButtonPressEdgeEventManagementTest, IgnoreWhenEventMismatchAndNoGrabs)
 959 {
 960     const Window rootWindow = 1;
 961     const Window edgeWindow = topScreenEdge;
 962 
 963     cps::OrphanData orphanData;
 964     cps::GrabList grabList;
 965 
 966     EXPECT_EQ (ce::processButtonPressOnEdgeWindow (edgeWindow,
 967 						   rootWindow,
 968 						   0,
 969 						   rootWindow,
 970 						   grabList,
 971 						   screenEdges), -1);
 972 }
 973 
 974 TEST (privatescreen_ButtonPressEdgeEventManagementTest, AllowWhenEventButNotRootWindowMismatchWhileGrabbed)
 975 {
 976     const Window rootWindow = 1;
 977     const Window edgeWindow = topScreenEdge;
 978     unsigned int topEdgeMask = 1 << SCREEN_EDGE_TOP;
 979 
 980     cps::OrphanData orphanData;
 981     cps::GrabList grabList;
 982 
 983     grabList.grabsPush (new cps::Grab (None, "Nil"));
 984 
 985     EXPECT_EQ (ce::processButtonPressOnEdgeWindow (edgeWindow,
 986 						   rootWindow,
 987 						   0,
 988 						   rootWindow,
 989 						   grabList,
 990 						   screenEdges), topEdgeMask);
 991 
 992     grabList.grabsRemove (grabList.grabsBack ());
 993 }
 994 
 995 TEST (privatescreen_ButtonPressEventManagementTest, SetEventWindowArgument)
 996 {
 997     const Window activeWindow = 1;
 998 
 999     ce::EventArguments arguments (2);
1000     ce::setEventWindowInButtonPressArguments (arguments, activeWindow);
1001     EXPECT_EQ (arguments[1].value ().i (), activeWindow);
1002 }
1003 
1004 namespace
1005 {
1006 class MockTriggerableAction
1007 {
1008     public:
1009 
1010 	MOCK_METHOD2 (matchEventState, bool (unsigned int,
1011 					     unsigned int));
1012 	MOCK_METHOD3 (initiate, bool (CompAction         *,
1013 				      CompAction::State   ,
1014 				      CompOption::Vector &));
1015 	MOCK_METHOD3 (terminate, bool (CompAction         *,
1016 				       CompAction::State   ,
1017 				       CompOption::Vector &));
1018 };
1019 
1020 const unsigned int testingButtonNumber = 1;
1021 const unsigned int testingButtonState = (1 << 1);
1022 
1023 ce::ActionModsMatchesEventStateFunc
1024 GetMatchEventStateFuncForMock (MockTriggerableAction &triggerableAction)
1025 {
1026     return boost::bind (&MockTriggerableAction::matchEventState,
1027 			&triggerableAction,
1028 			_1, _2);
1029 }
1030 
1031 CompAction::CallBack
1032 GetInitiateForMock (MockTriggerableAction &triggerableAction)
1033 {
1034     return boost::bind (&MockTriggerableAction::initiate,
1035 			&triggerableAction,
1036 			_1, _2, _3);
1037 }
1038 
1039 }
1040 
1041 bool operator== (const CompOption &lhs,
1042 		 const CompOption &rhs)
1043 {
1044     if (lhs.type () != rhs.type ())
1045 	return false;
1046 
1047     return lhs.value () == rhs.value ();
1048 }
1049 
1050 TEST (privatescreen_ButtonPressEventManagementTest, NoTriggerOnUnboundAction)
1051 {
1052     CompAction            action;
1053     CompOption            option ("button", CompOption::TypeButton);
1054     CompOption::Value     value (action);
1055     cps::EventManager     eventManager;
1056     MockTriggerableAction triggerableAction;
1057     ce::EventArguments    arguments;
1058 
1059     option.set (value);
1060 
1061     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1062 	    GetMatchEventStateFuncForMock (triggerableAction);
1063 
1064     EXPECT_FALSE (ce::activateButtonPressOnWindowBindingOption (option,
1065 								testingButtonNumber,
1066 								testingButtonState,
1067 								eventManager,
1068 								matchEventState,
1069 								arguments));
1070 }
1071 
1072 TEST (privatescreen_ButtonPressEventManagementTest, NoTriggerOnUnboundInactiveAction)
1073 {
1074     CompAction            action;
1075     MockTriggerableAction triggerableAction;
1076     int                   edgeMask = 1 << SCREEN_EDGE_TOP;
1077 
1078     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1079 	    GetMatchEventStateFuncForMock (triggerableAction);
1080     const CompAction::CallBack                &initiate =
1081 	    GetInitiateForMock (triggerableAction);
1082 
1083     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1084 						 testingButtonState));
1085     action.setEdgeMask (edgeMask);
1086 
1087 
1088     CompOption            option ("button", CompOption::TypeButton);
1089     CompOption::Value     value (action);
1090     cps::EventManager     eventManager;
1091     ce::EventArguments    arguments;
1092 
1093     option.set (value);
1094     option.value ().action ().setInitiate (initiate);
1095     option.value ().action ().setState (CompAction::StateInitButton);
1096     ca::setActionActiveState (option.value ().action (), false);
1097 
1098     EXPECT_FALSE (ce::activateButtonPressOnEdgeBindingOption (option,
1099 							      testingButtonNumber,
1100 							      testingButtonState,
1101 							      edgeMask,
1102 							      eventManager,
1103 							      matchEventState,
1104 							      arguments));
1105 }
1106 
1107 TEST (privatescreen_ButtonPressEventManagementTest, NoTriggerOnMismatchedButtonNumber)
1108 {
1109     CompAction            action;
1110     MockTriggerableAction triggerableAction;
1111 
1112     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1113 	    GetMatchEventStateFuncForMock (triggerableAction);
1114     const CompAction::CallBack                &initiate =
1115 	    GetInitiateForMock (triggerableAction);
1116 
1117     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1118 						 testingButtonState));
1119 
1120     CompOption            option ("button", CompOption::TypeButton);
1121     CompOption::Value     value (action);
1122     cps::EventManager     eventManager;
1123     ce::EventArguments    arguments;
1124 
1125     option.set (value);
1126     option.value ().action ().setInitiate (initiate);
1127     option.value ().action ().setState (CompAction::StateInitButton);
1128     ca::setActionActiveState (option.value ().action (), true);
1129 
1130     EXPECT_CALL (triggerableAction, initiate (_, _, _)).Times (0);
1131     EXPECT_FALSE (ce::activateButtonPressOnWindowBindingOption (option,
1132 								0,
1133 								testingButtonState,
1134 								eventManager,
1135 								matchEventState,
1136 								arguments));
1137 }
1138 
1139 TEST (privatescreen_ButtonPressEventManagementTest, NoTriggerOnMismatchedButtonState)
1140 {
1141     CompAction            action;
1142     MockTriggerableAction triggerableAction;
1143 
1144     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1145 	    GetMatchEventStateFuncForMock (triggerableAction);
1146     const CompAction::CallBack                &initiate =
1147 	    GetInitiateForMock (triggerableAction);
1148 
1149     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1150 						 testingButtonState));
1151 
1152     CompOption            option ("button", CompOption::TypeButton);
1153     CompOption::Value     value (action);
1154     cps::EventManager     eventManager;
1155     ce::EventArguments    arguments;
1156 
1157     option.set (value);
1158     option.value ().action ().setInitiate (initiate);
1159     option.value ().action ().setState (CompAction::StateInitButton);
1160     ca::setActionActiveState (option.value ().action (), true);
1161 
1162     EXPECT_CALL (triggerableAction, matchEventState (testingButtonState, 0))
1163 	    .WillOnce (Return (false));
1164     EXPECT_CALL (triggerableAction, initiate (_, _, _)).Times (0);
1165     EXPECT_FALSE (ce::activateButtonPressOnWindowBindingOption (option,
1166 								testingButtonNumber,
1167 								0,
1168 								eventManager,
1169 								matchEventState,
1170 								arguments));
1171 }
1172 
1173 TEST (privatescreen_ButtonPressEventManagementTest, TriggerWhenStateAndButtonMatch)
1174 {
1175     CompAction            action;
1176     MockTriggerableAction triggerableAction;
1177 
1178     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1179 	    GetMatchEventStateFuncForMock (triggerableAction);
1180     const CompAction::CallBack                &initiate =
1181 	    GetInitiateForMock (triggerableAction);
1182 
1183     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1184 						 testingButtonState));
1185 
1186     CompOption            option ("button", CompOption::TypeButton);
1187     CompOption::Value     value (action);
1188     cps::EventManager     eventManager;
1189     ce::EventArguments    arguments;
1190 
1191     option.set (value);
1192     option.value ().action ().setInitiate (initiate);
1193     option.value ().action ().setState (CompAction::StateInitButton);
1194     ca::setActionActiveState (option.value ().action (), true);
1195 
1196     EXPECT_CALL (triggerableAction, matchEventState (testingButtonState, testingButtonState))
1197 	    .WillOnce (Return (true));
1198     EXPECT_CALL (triggerableAction, initiate (&option.value ().action (),
1199 					      CompAction::StateInitButton,
1200 					      arguments)).WillOnce (Return (true));
1201     EXPECT_TRUE (ce::activateButtonPressOnWindowBindingOption (option,
1202 							       testingButtonNumber,
1203 							       testingButtonState,
1204 							       eventManager,
1205 							       matchEventState,
1206 							       arguments));
1207 }
1208 
1209 TEST (privatescreen_ButtonPressEdgeEventManagementTest, NoTriggerOnInvalidEdge)
1210 {
1211     CompAction            action;
1212     CompOption            option ("button", CompOption::TypeButton);
1213     CompOption::Value     value (action);
1214     cps::EventManager     eventManager;
1215     MockTriggerableAction triggerableAction;
1216     ce::EventArguments    arguments;
1217     int                   edgeMask = -1;
1218 
1219     option.set (value);
1220 
1221     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1222 	    GetMatchEventStateFuncForMock (triggerableAction);
1223 
1224     EXPECT_FALSE (ce::activateButtonPressOnEdgeBindingOption (option,
1225 							      testingButtonNumber,
1226 							      testingButtonState,
1227 							      edgeMask,
1228 							      eventManager,
1229 							      matchEventState,
1230 							      arguments));
1231 }
1232 
1233 TEST (privatescreen_ButtonPressEdgeEventManagementTest, NoTriggerOnUnboundAction)
1234 {
1235     CompAction            action;
1236     CompOption            option ("button", CompOption::TypeButton);
1237     CompOption::Value     value (action);
1238     cps::EventManager     eventManager;
1239     MockTriggerableAction triggerableAction;
1240     ce::EventArguments    arguments;
1241     int                   edgeMask = 1 << SCREEN_EDGE_TOP;
1242 
1243     option.set (value);
1244 
1245     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1246 	    GetMatchEventStateFuncForMock (triggerableAction);
1247 
1248     EXPECT_FALSE (ce::activateButtonPressOnEdgeBindingOption (option,
1249 							      testingButtonNumber,
1250 							      testingButtonState,
1251 							      edgeMask,
1252 							      eventManager,
1253 							      matchEventState,
1254 							      arguments));
1255 }
1256 
1257 TEST (privatescreen_ButtonPressEdgeEventManagementTest, NoTriggerOnMismatchedEdgeMask)
1258 {
1259     CompAction            action;
1260     MockTriggerableAction triggerableAction;
1261     int                   edgeMask = 1 << SCREEN_EDGE_TOP;
1262 
1263     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1264 	    GetMatchEventStateFuncForMock (triggerableAction);
1265     const CompAction::CallBack                &initiate =
1266 	    GetInitiateForMock (triggerableAction);
1267 
1268     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1269 						 testingButtonState));
1270     action.setEdgeMask (edgeMask);
1271 
1272     CompOption            option ("button", CompOption::TypeButton);
1273     CompOption::Value     value (action);
1274     cps::EventManager     eventManager;
1275     ce::EventArguments    arguments;
1276 
1277 
1278     option.set (value);
1279     option.value ().action ().setInitiate (initiate);
1280     option.value ().action ().setState (CompAction::StateInitButton);
1281     ca::setActionActiveState (option.value ().action (), true);
1282 
1283     EXPECT_CALL (triggerableAction, initiate (_, _, _)).Times (0);
1284     EXPECT_FALSE (ce::activateButtonPressOnEdgeBindingOption (option,
1285 							      testingButtonNumber,
1286 							      testingButtonState,
1287 							      0,
1288 							      eventManager,
1289 							      matchEventState,
1290 							      arguments));
1291 }
1292 
1293 TEST (privatescreen_ButtonPressEdgeEventManagementTest, NoTriggerOnMismatchedButtonNumber)
1294 {
1295     CompAction            action;
1296     MockTriggerableAction triggerableAction;
1297     int                   edgeMask = 1 << SCREEN_EDGE_TOP;
1298 
1299     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1300 	    GetMatchEventStateFuncForMock (triggerableAction);
1301     const CompAction::CallBack                &initiate =
1302 	    GetInitiateForMock (triggerableAction);
1303 
1304     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1305 						 testingButtonState));
1306     action.setEdgeMask (edgeMask);
1307 
1308     CompOption            option ("button", CompOption::TypeButton);
1309     CompOption::Value     value (action);
1310     cps::EventManager     eventManager;
1311     ce::EventArguments    arguments;
1312 
1313 
CID 12413 - CHECKED_RETURN
Calling function "CompOption::set(CompOption::Value &)" without checking return value (as is done elsewhere 1171 out of 1219 times).
No check of the return value of "option.set(value)".
1314     option.set (value);
1315     option.value ().action ().setInitiate (initiate);
1316     option.value ().action ().setState (CompAction::StateInitButton);
1317     ca::setActionActiveState (option.value ().action (), true);
1318 
1319     EXPECT_CALL (triggerableAction, initiate (_, _, _)).Times (0);
1320     EXPECT_FALSE (ce::activateButtonPressOnEdgeBindingOption (option,
1321 							      0,
1322 							      testingButtonState,
1323 							      edgeMask,
1324 							      eventManager,
1325 							      matchEventState,
1326 							      arguments));
1327 }
1328 
1329 TEST (privatescreen_ButtonPressEdgeEventManagementTest, NoTriggerOnMismatchedButtonState)
1330 {
1331     CompAction            action;
1332     MockTriggerableAction triggerableAction;
1333     int                   edgeMask = 1 << SCREEN_EDGE_TOP;
1334 
1335     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1336 	    GetMatchEventStateFuncForMock (triggerableAction);
1337     const CompAction::CallBack                &initiate =
1338 	    GetInitiateForMock (triggerableAction);
1339 
1340     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1341 						 testingButtonState));
1342     action.setEdgeMask (edgeMask);
1343 
1344 
1345     CompOption            option ("button", CompOption::TypeButton);
1346     CompOption::Value     value (action);
1347     cps::EventManager     eventManager;
1348     ce::EventArguments    arguments;
1349 
1350     option.set (value);
1351     option.value ().action ().setInitiate (initiate);
1352     option.value ().action ().setState (CompAction::StateInitButton);
1353     ca::setActionActiveState (option.value ().action (), true);
1354 
1355     EXPECT_CALL (triggerableAction, matchEventState (testingButtonState, 0))
1356 	    .WillOnce (Return (false));
1357     EXPECT_CALL (triggerableAction, initiate (_, _, _)).Times (0);
1358     EXPECT_FALSE (ce::activateButtonPressOnEdgeBindingOption (option,
1359 							      testingButtonNumber,
1360 							      0,
1361 							      edgeMask,
1362 							      eventManager,
1363 							      matchEventState,
1364 							      arguments));
1365 }
1366 
1367 TEST (privatescreen_ButtonPressEdgeEventManagementTest, TriggerWhenStateButtonAndEdgeMaskMatch)
1368 {
1369     CompAction            action;
1370     MockTriggerableAction triggerableAction;
1371     int                   edgeMask = 1 << SCREEN_EDGE_TOP;
1372 
1373     const ce::ActionModsMatchesEventStateFunc &matchEventState =
1374 	    GetMatchEventStateFuncForMock (triggerableAction);
1375     const CompAction::CallBack                &initiate =
1376 	    GetInitiateForMock (triggerableAction);
1377 
1378     action.setButton (CompAction::ButtonBinding (testingButtonNumber,
1379 						 testingButtonState));
1380     action.setEdgeMask (edgeMask);
1381 
1382     CompOption            option ("button", CompOption::TypeButton);
1383     CompOption::Value     value (action);
1384     cps::EventManager     eventManager;
1385     ce::EventArguments    arguments;
1386 
1387     option.set (value);
1388     option.value ().action ().setInitiate (initiate);
1389     option.value ().action ().setState (CompAction::StateInitButton |
1390 					CompAction::StateInitEdge);
1391     ca::setActionActiveState (option.value ().action (), true);
1392 
1393     EXPECT_CALL (triggerableAction, matchEventState (testingButtonState, testingButtonState))
1394 	    .WillOnce (Return (true));
1395     EXPECT_CALL (triggerableAction, initiate (&option.value ().action (),
1396 					      CompAction::StateInitButton |
1397 					      CompAction::StateInitEdge,
1398 					      arguments)).WillOnce (Return (true));
1399     EXPECT_TRUE (ce::activateButtonPressOnEdgeBindingOption (option,
1400 							     testingButtonNumber,
1401 							     testingButtonState,
1402 							     edgeMask,
1403 							     eventManager,
1404 							     matchEventState,
1405 							     arguments));
1406 }
1407 
1408 TEST (privatescreen_ActionActiveTest, TestMakeActionActive)
1409 {
1410     CompAction action;
1411 
1412     ASSERT_EQ (action.active (), false);
1413     ca::setActionActiveState (action, true);
1414     ASSERT_EQ (action.active (), true);
1415     ca::setActionActiveState (action, false);
1416     ASSERT_EQ (action.active (), false);
1417 }