ctkPluginFrameworkTestSuite.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) 2010 German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #include "ctkPluginFrameworkTestSuite_p.h"
  16. #include <ctkPluginFrameworkTestUtil.h>
  17. #include <ctkPluginContext.h>
  18. #include <ctkPluginConstants.h>
  19. #include <ctkServiceException.h>
  20. #include <QTest>
  21. #include <QDebug>
  22. int ctkPluginFrameworkTestSuite::nRunCount = 0;
  23. ctkPluginFrameworkTestSuite::ctkPluginFrameworkTestSuite(ctkPluginContext* pc)
  24. : eventDelay(500), pc(pc), p(pc->getPlugin())
  25. {
  26. }
  27. void ctkPluginFrameworkTestSuite::initTestCase()
  28. {
  29. qDebug() << "### plugin framework test suite: SETUP start";
  30. if (nRunCount > 0)
  31. {
  32. QFAIL("The ctkPluginFrameworkTestSuite CANNOT be run reliably more than once. Other test results in this suite are/may not be valid. Restart framework to retest: CLEANUP:FAIL");
  33. }
  34. ++nRunCount;
  35. try
  36. {
  37. bool success = pc->connectFrameworkListener(this, SLOT(frameworkListener(ctkPluginFrameworkEvent)));
  38. if (!success)
  39. {
  40. QFAIL("plugin framework test suite: SETUP:FAIL");
  41. }
  42. }
  43. catch (const std::logic_error& e)
  44. {
  45. QString msg = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
  46. QFAIL(msg.toAscii());
  47. }
  48. try
  49. {
  50. bool success = pc->connectPluginListener(this, SLOT(pluginListener(ctkPluginEvent)));
  51. if (!success)
  52. {
  53. QFAIL("plugin framework test suite: SETUP:FAIL");
  54. }
  55. }
  56. catch (const std::logic_error& e)
  57. {
  58. QString msg = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
  59. QFAIL(msg.toAscii());
  60. }
  61. try
  62. {
  63. bool success = pc->connectPluginListener(this, SLOT(syncPluginListener(ctkPluginEvent)), Qt::DirectConnection);
  64. if (!success)
  65. {
  66. QFAIL("plugin framework test suite: SETUP:FAIL");
  67. }
  68. }
  69. catch (const std::logic_error& e)
  70. {
  71. QString msg = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
  72. QFAIL(msg.toAscii());
  73. }
  74. try
  75. {
  76. pc->connectServiceListener(this, "serviceListener");
  77. }
  78. catch (const std::logic_error& e)
  79. {
  80. QString msg = QString("plugin framework test suite ") + e.what() + ": SETUP:FAIL";
  81. QFAIL(msg.toAscii());
  82. }
  83. qDebug() << "### plugin framework test suite: SETUP:PASS";
  84. }
  85. void ctkPluginFrameworkTestSuite::cleanupTestCase()
  86. {
  87. }
  88. // Verify information from the getHeaders() method
  89. void ctkPluginFrameworkTestSuite::frame005a()
  90. {
  91. QHash<QString, QString> headers = p->getHeaders();
  92. // check expected headers
  93. QString k = "Plugin-Name";
  94. QCOMPARE(QString("framework_test"), headers.value(k));
  95. k = "Plugin-Version";
  96. QCOMPARE(QString("1.0.1"), headers.value(k));
  97. k = "Plugin-Description";
  98. QCOMPARE(QString("Test bundle for the CTK plugin framework"), headers.value(k));
  99. k = "Plugin-Vendor";
  100. QCOMPARE(QString("CommonTK"), headers.value(k));
  101. k = "Plugin-DocURL";
  102. QCOMPARE(QString("http://www.commontk.org"), headers.value(k));
  103. k = "Plugin-ContactAddress";
  104. QCOMPARE(QString("http://www.commontk.org"), headers.value(k));
  105. k = "Plugin-Category";
  106. QCOMPARE(QString("test"), headers.value(k));
  107. k = "Plugin-Copyright";
  108. QCOMPARE(QString("German Cancer Research Center, Division of Medical and Biological Informatics"), headers.value(k));
  109. k = "Plugin-License";
  110. QCOMPARE(QString("http://www.apache.org/licenses/LICENSE-2.0.html"), headers.value(k));
  111. }
  112. // Load pluginA_test and check that it exists and that its expected service does not exist,
  113. // also check that the expected events in the framework occur
  114. void ctkPluginFrameworkTestSuite::frame020a()
  115. {
  116. pA.clear();
  117. try
  118. {
  119. pA = ctkPluginFrameworkTestUtil::installPlugin(pc, "pluginA_test");
  120. }
  121. catch (ctkPluginException& e)
  122. {
  123. QFAIL(e.what());
  124. }
  125. const QHash<QString, QString> headers = pA->getHeaders();
  126. QHash<QString, QString>::const_iterator iter =
  127. headers.find(ctkPluginConstants::PLUGIN_SYMBOLICNAME);
  128. QVERIFY(iter != headers.end());
  129. QCOMPARE(iter.value(), QString("pluginA.test"));
  130. // Check that no service reference exist yet.
  131. try
  132. {
  133. pc->getServiceReference("ctkTestPluginAService");
  134. QFAIL("framework test plugin, service from test plugin A unexpectedly found");
  135. }
  136. catch (ctkServiceException& e)
  137. {
  138. }
  139. // check the listeners for events, expect only a plugin event,
  140. // of type installation
  141. bool lStat = checkListenerEvents(false, ctkPluginFrameworkEvent::INFO, true , ctkPluginEvent::INSTALLED,
  142. false, ctkServiceEvent::MODIFIED, pA, 0);
  143. QVERIFY(pA->getState() == ctkPlugin::INSTALLED && lStat == true);
  144. }
  145. // Start pluginA_test and check that it gets state ACTIVE,
  146. // and that the service it registers exist
  147. void ctkPluginFrameworkTestSuite::frame025b()
  148. {
  149. try
  150. {
  151. pA->start();
  152. QVERIFY2(pA->getState() == ctkPlugin::ACTIVE, "pluginA_test should be ACTIVE");
  153. }
  154. catch (const ctkPluginException& pexcA)
  155. {
  156. QString failMsg = QString("Unexpected plugin exception: ") + pexcA.what();
  157. QFAIL(failMsg.toStdString().c_str());
  158. }
  159. catch (const std::logic_error& le)
  160. {
  161. QString failMsg = QString("Start plugin exception: ") + le.what();
  162. QFAIL(failMsg.toStdString().c_str());
  163. }
  164. // Check if pluginA_test registered the expected service
  165. try
  166. {
  167. ctkServiceReference sr1 = pc->getServiceReference("ctkTestPluginAService");
  168. QObject* o1 = pc->getService(sr1);
  169. QVERIFY2(o1 != 0, "no service object found");
  170. try
  171. {
  172. QVERIFY2(pc->ungetService(sr1), "Service unget should return true");
  173. }
  174. catch (const std::logic_error le)
  175. {
  176. QString failMsg = QString("Unget service exception: ") + le.what();
  177. QFAIL(failMsg.toStdString().c_str());
  178. }
  179. // check the listeners for events
  180. QList<ctkPluginEvent> pEvts;
  181. pEvts.push_back(ctkPluginEvent(ctkPluginEvent::RESOLVED, pA.data()));
  182. pEvts.push_back(ctkPluginEvent(ctkPluginEvent::STARTED, pA.data()));
  183. QList<ctkServiceEvent> seEvts;
  184. seEvts.push_back(ctkServiceEvent(ctkServiceEvent::REGISTERED, sr1));
  185. QVERIFY2(checkListenerEvents(QList<ctkPluginFrameworkEvent>(), pEvts, seEvts),
  186. "Unexpected events");
  187. QList<ctkPluginEvent> syncPEvts;
  188. syncPEvts.push_back(ctkPluginEvent(ctkPluginEvent::STARTING, pA.data()));
  189. QVERIFY2(checkSyncListenerEvents(syncPEvts), "Unexpected events");
  190. }
  191. catch (const ctkServiceException& /*se*/)
  192. {
  193. QFAIL("framework test bundle, expected service not found");
  194. }
  195. }
  196. void ctkPluginFrameworkTestSuite::frameworkListener(const ctkPluginFrameworkEvent& fwEvent)
  197. {
  198. frameworkEvents.push_back(fwEvent);
  199. qDebug() << "FrameworkEvent:" << fwEvent;
  200. }
  201. void ctkPluginFrameworkTestSuite::pluginListener(const ctkPluginEvent& event)
  202. {
  203. pluginEvents.push_back(event);
  204. qDebug() << "PluginEvent:" << event;
  205. }
  206. void ctkPluginFrameworkTestSuite::syncPluginListener(const ctkPluginEvent& event)
  207. {
  208. if (event.getType() == ctkPluginEvent::STARTING ||
  209. event.getType() == ctkPluginEvent::STOPPING)
  210. {
  211. syncPluginEvents.push_back(event);
  212. qDebug() << "Synchronous PluginEvent:" << event;
  213. }
  214. }
  215. void ctkPluginFrameworkTestSuite::serviceListener(const ctkServiceEvent& event)
  216. {
  217. serviceEvents.push_back(event);
  218. qDebug() << "ServiceEvent:" << event;
  219. }
  220. ctkPluginEvent ctkPluginFrameworkTestSuite::getPluginEvent() const
  221. {
  222. if (pluginEvents.empty())
  223. {
  224. return ctkPluginEvent();
  225. }
  226. return pluginEvents.last();
  227. }
  228. ctkPluginEvent ctkPluginFrameworkTestSuite::getSyncPluginEvent() const
  229. {
  230. if (syncPluginEvents.empty())
  231. {
  232. return ctkPluginEvent();
  233. }
  234. return syncPluginEvents.last();
  235. }
  236. ctkPluginFrameworkEvent ctkPluginFrameworkTestSuite::getFrameworkEvent() const
  237. {
  238. if (frameworkEvents.empty())
  239. {
  240. return ctkPluginFrameworkEvent();
  241. }
  242. return frameworkEvents.last();
  243. }
  244. ctkServiceEvent ctkPluginFrameworkTestSuite::getServiceEvent() const
  245. {
  246. if (serviceEvents.empty())
  247. {
  248. return ctkServiceEvent();
  249. }
  250. return serviceEvents.last();
  251. }
  252. bool ctkPluginFrameworkTestSuite::checkListenerEvents(
  253. bool fwexp, ctkPluginFrameworkEvent::Type fwtype,
  254. bool pexp, ctkPluginEvent::Type ptype,
  255. bool sexp, ctkServiceEvent::Type stype,
  256. QSharedPointer<ctkPlugin> pluginX, ctkServiceReference* servX)
  257. {
  258. QList<ctkPluginFrameworkEvent> fwEvts;
  259. QList<ctkPluginEvent> pEvts;
  260. QList<ctkServiceEvent> seEvts;
  261. if (fwexp) fwEvts << ctkPluginFrameworkEvent(fwtype, pluginX.data());
  262. if (pexp) pEvts << ctkPluginEvent(ptype, pluginX.data());
  263. if (sexp) seEvts << ctkServiceEvent(stype, *servX);
  264. return checkListenerEvents(fwEvts, pEvts, seEvts);
  265. }
  266. bool ctkPluginFrameworkTestSuite::checkListenerEvents(
  267. const QList<ctkPluginFrameworkEvent>& fwEvts,
  268. const QList<ctkPluginEvent>& pEvts,
  269. const QList<ctkServiceEvent>& seEvts)
  270. {
  271. bool listenState = true; // assume everything will work
  272. // Wait a while to allow events to arrive
  273. QTest::qWait(eventDelay);
  274. //QCoreApplication::sendPostedEvents();
  275. if (fwEvts.size() != frameworkEvents.size())
  276. {
  277. listenState = false;
  278. qDebug() << "*** Plugin Framework event mismatch: expected"
  279. << fwEvts.size() << "event(s), found"
  280. << frameworkEvents.size() << "event(s).";
  281. const int max = fwEvts.size() > frameworkEvents.size()
  282. ? fwEvts.size() : frameworkEvents.size();
  283. for (int i = 0; i < max; ++i)
  284. {
  285. const ctkPluginFrameworkEvent& fwE = i < fwEvts.size() ? fwEvts[i] : ctkPluginFrameworkEvent();
  286. const ctkPluginFrameworkEvent& fwR = i < frameworkEvents.size() ? frameworkEvents[i] : ctkPluginFrameworkEvent();
  287. qDebug() << " " << fwE << " - " << fwR;
  288. }
  289. }
  290. else
  291. {
  292. for (int i = 0; i < fwEvts.size(); ++i)
  293. {
  294. const ctkPluginFrameworkEvent& feE = fwEvts[i];
  295. const ctkPluginFrameworkEvent& feR = frameworkEvents[i];
  296. if (feE.getType() != feR.getType()
  297. || feE.getPlugin() != feR.getPlugin())
  298. {
  299. listenState = false;
  300. qDebug() << "*** Wrong framework event:" << feR
  301. << "expected" << feE;
  302. }
  303. }
  304. }
  305. if (pEvts.size() != pluginEvents.size())
  306. {
  307. listenState = false;
  308. qDebug() << "*** Plugin event mismatch: expected"
  309. << pEvts.size() << "event(s), found "
  310. << pluginEvents.size() << "event(s).";
  311. const int max = pEvts.size() > pluginEvents.size() ? pEvts.size() : pluginEvents.size();
  312. for (int i = 0; i < max; ++i)
  313. {
  314. const ctkPluginEvent& pE = i < pEvts.size() ? pEvts[i] : ctkPluginEvent();
  315. const ctkPluginEvent& pR = i < pluginEvents.size() ? pluginEvents[i] : ctkPluginEvent();
  316. qDebug() << " " << pE << " - " << pR;
  317. }
  318. }
  319. else
  320. {
  321. for (int i = 0; i < pEvts.size(); ++i)
  322. {
  323. const ctkPluginEvent& pE = pEvts[i];
  324. const ctkPluginEvent& pR = pluginEvents[i];
  325. if (pE.getType() != pR.getType()
  326. || pE.getPlugin() != pR.getPlugin())
  327. {
  328. listenState = false;
  329. qDebug() << "*** Wrong plugin event:" << pR << "expected" << pE;
  330. }
  331. }
  332. }
  333. if (seEvts.size() != serviceEvents.size())
  334. {
  335. listenState = false;
  336. qDebug() << "*** Service event mismatch: expected"
  337. << seEvts.size() << "event(s), found"
  338. << serviceEvents.size() << "event(s).";
  339. const int max = seEvts.size() > serviceEvents.size()
  340. ? seEvts.size() : serviceEvents.size();
  341. for (int i = 0; i < max; ++i)
  342. {
  343. const ctkServiceEvent& seE = i < seEvts.size() ? seEvts[i] : ctkServiceEvent();
  344. const ctkServiceEvent& seR = i < serviceEvents.size() ? serviceEvents[i] : ctkServiceEvent();
  345. qDebug() << " " << seE << " - " << seR;
  346. }
  347. }
  348. else
  349. {
  350. for (int i = 0; i < seEvts.size(); ++i)
  351. {
  352. const ctkServiceEvent& seE = seEvts[i];
  353. const ctkServiceEvent& seR = serviceEvents[i];
  354. if (seE.getType() != seR.getType()
  355. || (!(seE.getServiceReference() == seR.getServiceReference())))
  356. {
  357. listenState = false;
  358. qDebug() << "*** Wrong service event:" << seR << "expected" << seE;
  359. }
  360. }
  361. }
  362. frameworkEvents.clear();
  363. pluginEvents.clear();
  364. serviceEvents.clear();
  365. return listenState;
  366. }
  367. // Check that the expected events have reached the listeners and
  368. // reset the events
  369. bool ctkPluginFrameworkTestSuite::checkSyncListenerEvents(
  370. bool pexp, ctkPluginEvent::Type ptype, ctkPlugin* pX,
  371. ctkServiceReference servX)
  372. {
  373. Q_UNUSED(servX)
  374. QList<ctkPluginEvent> pEvts;
  375. if (pexp)
  376. {
  377. pEvts << ctkPluginEvent(ptype, pX);
  378. }
  379. return checkSyncListenerEvents(pEvts);
  380. }
  381. // Check that the expected events have reached the listeners and
  382. // reset the events
  383. bool ctkPluginFrameworkTestSuite::checkSyncListenerEvents(
  384. const QList<ctkPluginEvent>& pEvts)
  385. {
  386. bool listenState = true; // assume everything will work
  387. // Sleep a while to allow events to arrive
  388. QTest::qWait(eventDelay);
  389. if (pEvts.size() != syncPluginEvents.size())
  390. {
  391. listenState = false;
  392. qDebug() << "*** Sync plugin event mismatch: expected"
  393. << pEvts.size() << "event(s), found"
  394. << syncPluginEvents.size() << "event(s).";
  395. const int max = pEvts.size() > syncPluginEvents.size() ? pEvts.size() : syncPluginEvents.size();
  396. for (int i = 0; i < max; ++i)
  397. {
  398. const ctkPluginEvent& pE = i< pEvts.size() ? pEvts[i] : ctkPluginEvent();
  399. const ctkPluginEvent& pR = i < syncPluginEvents.size() ? syncPluginEvents[i] : ctkPluginEvent();
  400. qDebug() << " " << pE << " - " << pR;
  401. }
  402. }
  403. else
  404. {
  405. for (int i = 0; i < pEvts.size(); ++i)
  406. {
  407. const ctkPluginEvent& pE = pEvts[i];
  408. const ctkPluginEvent& pR = syncPluginEvents[i];
  409. if (pE.getType() != pR.getType() || pE.getPlugin() != pR.getPlugin())
  410. {
  411. listenState = false;
  412. qDebug() << "Wrong sync plugin event:" << pR << "expected" << pE;
  413. }
  414. }
  415. }
  416. syncPluginEvents.clear();
  417. return listenState;
  418. }