callout_manager_unittest.cc 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. // Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <exceptions/exceptions.h>
  7. #include <hooks/callout_handle.h>
  8. #include <hooks/callout_manager.h>
  9. #include <hooks/library_handle.h>
  10. #include <hooks/server_hooks.h>
  11. #include <boost/scoped_ptr.hpp>
  12. #include <gtest/gtest.h>
  13. #include <algorithm>
  14. #include <climits>
  15. #include <string>
  16. #include <vector>
  17. /// @file
  18. /// @brief CalloutManager and LibraryHandle tests
  19. ///
  20. /// These set of tests check the CalloutManager and LibraryHandle. They are
  21. /// together in the same file because the LibraryHandle is little more than a
  22. /// restricted interface to the CalloutManager, and a lot of the support
  23. /// structure for the tests is common.
  24. using namespace isc;
  25. using namespace isc::hooks;
  26. using namespace std;
  27. namespace {
  28. class CalloutManagerTest : public ::testing::Test {
  29. public:
  30. /// @brief Constructor
  31. ///
  32. /// Sets up a collection of three LibraryHandle objects to use in the test.
  33. CalloutManagerTest() {
  34. // Set up the server hooks. There is one singleton for all tests,
  35. // so reset it and explicitly set up the hooks for the test.
  36. ServerHooks& hooks = ServerHooks::getServerHooks();
  37. hooks.reset();
  38. alpha_index_ = hooks.registerHook("alpha");
  39. beta_index_ = hooks.registerHook("beta");
  40. gamma_index_ = hooks.registerHook("gamma");
  41. delta_index_ = hooks.registerHook("delta");
  42. // Set up the callout manager with these hooks. Assume a maximum of
  43. // four libraries.
  44. callout_manager_.reset(new CalloutManager(10));
  45. // Set up the callout handle.
  46. callout_handle_.reset(new CalloutHandle(callout_manager_));
  47. // Initialize the static variable.
  48. callout_value_ = 0;
  49. }
  50. /// @brief Return the callout handle
  51. CalloutHandle& getCalloutHandle() {
  52. return (*callout_handle_);
  53. }
  54. /// @brief Return the callout manager
  55. boost::shared_ptr<CalloutManager> getCalloutManager() {
  56. return (callout_manager_);
  57. }
  58. /// Static variable used for accumulating information
  59. static int callout_value_;
  60. /// Hook indexes. These are somewhat ubiquitous, so are made public for
  61. /// ease of reference instead of being accessible by a function.
  62. int alpha_index_;
  63. int beta_index_;
  64. int gamma_index_;
  65. int delta_index_;
  66. private:
  67. /// Callout handle used in calls
  68. boost::shared_ptr<CalloutHandle> callout_handle_;
  69. /// Callout manager used for the test
  70. boost::shared_ptr<CalloutManager> callout_manager_;
  71. };
  72. // Definition of the static variable.
  73. int CalloutManagerTest::callout_value_ = 0;
  74. // Callout definitions
  75. //
  76. // The callouts defined here are structured in such a way that it is possible
  77. // to determine the order in which they are called and whether they are called
  78. // at all. The method used is simple - after a sequence of callouts, the digits
  79. // in the value, reading left to right, determines the order of the callouts
  80. // called. For example, callout one followed by two followed by three followed
  81. // by two followed by one results in a value of 12321.
  82. //
  83. // Functions return a zero to indicate success.
  84. extern "C" {
  85. int callout_general(int number) {
  86. CalloutManagerTest::callout_value_ =
  87. 10 * CalloutManagerTest::callout_value_ + number;
  88. return (0);
  89. }
  90. int callout_one(CalloutHandle&) {
  91. return (callout_general(1));
  92. }
  93. int callout_two(CalloutHandle&) {
  94. return (callout_general(2));
  95. }
  96. int callout_three(CalloutHandle&) {
  97. return (callout_general(3));
  98. }
  99. int callout_four(CalloutHandle&) {
  100. return (callout_general(4));
  101. }
  102. int callout_five(CalloutHandle&) {
  103. return (callout_general(5));
  104. }
  105. int callout_six(CalloutHandle&) {
  106. return (callout_general(6));
  107. }
  108. int callout_seven(CalloutHandle&) {
  109. return (callout_general(7));
  110. }
  111. // The next functions are duplicates of some of the above, but return an error.
  112. int callout_one_error(CalloutHandle& handle) {
  113. (void) callout_one(handle);
  114. return (1);
  115. }
  116. int callout_two_error(CalloutHandle& handle) {
  117. (void) callout_two(handle);
  118. return (1);
  119. }
  120. int callout_three_error(CalloutHandle& handle) {
  121. (void) callout_three(handle);
  122. return (1);
  123. }
  124. int callout_four_error(CalloutHandle& handle) {
  125. (void) callout_four(handle);
  126. return (1);
  127. }
  128. }; // extern "C"
  129. // *** Callout Tests ***
  130. //
  131. // The next set of tests check that callouts can be called.
  132. // Constructor - check that we trap bad parameters.
  133. TEST_F(CalloutManagerTest, BadConstructorParameters) {
  134. boost::scoped_ptr<CalloutManager> cm;
  135. // Invalid number of libraries
  136. EXPECT_THROW(cm.reset(new CalloutManager(-1)), BadValue);
  137. }
  138. // Check the number of libraries is reported successfully.
  139. TEST_F(CalloutManagerTest, NumberOfLibraries) {
  140. boost::scoped_ptr<CalloutManager> cm;
  141. // Check two valid values of number of libraries to ensure that the
  142. // GetNumLibraries() returns the value set.
  143. EXPECT_NO_THROW(cm.reset(new CalloutManager()));
  144. EXPECT_EQ(0, cm->getNumLibraries());
  145. EXPECT_NO_THROW(cm.reset(new CalloutManager(0)));
  146. EXPECT_EQ(0, cm->getNumLibraries());
  147. EXPECT_NO_THROW(cm.reset(new CalloutManager(4)));
  148. EXPECT_EQ(4, cm->getNumLibraries());
  149. EXPECT_NO_THROW(cm.reset(new CalloutManager(42)));
  150. EXPECT_EQ(42, cm->getNumLibraries());
  151. }
  152. // Check that we can only set the current library index to the correct values.
  153. TEST_F(CalloutManagerTest, CheckLibraryIndex) {
  154. // Check valid indexes. As the callout manager is sized for 10 libraries,
  155. // we expect:
  156. //
  157. // -1 to be valid as it is the standard "invalid" value.
  158. // 0 to be valid for the pre-user library callouts
  159. // 1-10 to be valid for the user-library callouts
  160. // INT_MAX to be valid for the post-user library callouts
  161. //
  162. // All other values to be invalid.
  163. for (int i = -1; i < 11; ++i) {
  164. EXPECT_NO_THROW(getCalloutManager()->setLibraryIndex(i));
  165. EXPECT_EQ(i, getCalloutManager()->getLibraryIndex());
  166. }
  167. EXPECT_NO_THROW(getCalloutManager()->setLibraryIndex(INT_MAX));
  168. EXPECT_EQ(INT_MAX, getCalloutManager()->getLibraryIndex());
  169. // Check invalid ones
  170. EXPECT_THROW(getCalloutManager()->setLibraryIndex(-2), NoSuchLibrary);
  171. EXPECT_THROW(getCalloutManager()->setLibraryIndex(11), NoSuchLibrary);
  172. }
  173. // Check that we can only register callouts on valid hook names.
  174. TEST_F(CalloutManagerTest, ValidHookNames) {
  175. getCalloutManager()->setLibraryIndex(0);
  176. EXPECT_NO_THROW(getCalloutManager()->registerCallout("alpha", callout_one));
  177. EXPECT_THROW(getCalloutManager()->registerCallout("unknown", callout_one),
  178. NoSuchHook);
  179. }
  180. // Check we can register callouts appropriately.
  181. TEST_F(CalloutManagerTest, RegisterCallout) {
  182. // Ensure that no callouts are attached to any of the hooks.
  183. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  184. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  185. // Set up so that hooks "alpha" and "beta" have callouts attached from a
  186. // different libraries.
  187. getCalloutManager()->setLibraryIndex(0);
  188. getCalloutManager()->registerCallout("alpha", callout_one);
  189. getCalloutManager()->setLibraryIndex(1);
  190. getCalloutManager()->registerCallout("beta", callout_two);
  191. // Check all is as expected.
  192. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  193. EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_));
  194. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  195. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  196. // Check that calling the callouts returns as expected. (This is also a
  197. // test of the callCallouts method.)
  198. callout_value_ = 0;
  199. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  200. EXPECT_EQ(1, callout_value_);
  201. callout_value_ = 0;
  202. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  203. EXPECT_EQ(2, callout_value_);
  204. // Register some more callouts from different libraries on hook "alpha".
  205. getCalloutManager()->setLibraryIndex(2);
  206. getCalloutManager()->registerCallout("alpha", callout_three);
  207. getCalloutManager()->registerCallout("alpha", callout_four);
  208. getCalloutManager()->setLibraryIndex(3);
  209. getCalloutManager()->registerCallout("alpha", callout_five);
  210. // Check it is as expected.
  211. callout_value_ = 0;
  212. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  213. EXPECT_EQ(1345, callout_value_);
  214. // ... and check the additional callouts were not registered on the "beta"
  215. // hook.
  216. callout_value_ = 0;
  217. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  218. EXPECT_EQ(2, callout_value_);
  219. // Add another callout to hook "alpha" from library index 2 - this should
  220. // appear at the end of the callout list for that library.
  221. getCalloutManager()->setLibraryIndex(2);
  222. getCalloutManager()->registerCallout("alpha", callout_six);
  223. callout_value_ = 0;
  224. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  225. EXPECT_EQ(13465, callout_value_);
  226. // Add a callout from library index 1 - this should appear between the
  227. // callouts from library index 0 and library index 2.
  228. getCalloutManager()->setLibraryIndex(1);
  229. getCalloutManager()->registerCallout("alpha", callout_seven);
  230. callout_value_ = 0;
  231. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  232. EXPECT_EQ(173465, callout_value_);
  233. }
  234. // Check the "calloutsPresent()" method.
  235. TEST_F(CalloutManagerTest, CalloutsPresent) {
  236. // Ensure that no callouts are attached to any of the hooks.
  237. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  238. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  239. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  240. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  241. // Set up so that hooks "alpha", "beta" and "delta" have callouts attached
  242. // to them, and callout "gamma" does not. (In the statements below, the
  243. // exact callouts attached to a hook are not relevant - only the fact
  244. // that some callouts are). Chose the libraries for which the callouts
  245. // are registered randomly.
  246. getCalloutManager()->setLibraryIndex(0);
  247. getCalloutManager()->registerCallout("alpha", callout_one);
  248. getCalloutManager()->setLibraryIndex(1);
  249. getCalloutManager()->registerCallout("alpha", callout_two);
  250. getCalloutManager()->registerCallout("beta", callout_two);
  251. getCalloutManager()->setLibraryIndex(3);
  252. getCalloutManager()->registerCallout("alpha", callout_three);
  253. getCalloutManager()->registerCallout("delta", callout_four);
  254. // Check all is as expected.
  255. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  256. EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_));
  257. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  258. EXPECT_TRUE(getCalloutManager()->calloutsPresent(delta_index_));
  259. // Check we fail on an invalid hook index.
  260. EXPECT_THROW(getCalloutManager()->calloutsPresent(42), NoSuchHook);
  261. EXPECT_THROW(getCalloutManager()->calloutsPresent(-1), NoSuchHook);
  262. }
  263. // Test that calling a hook with no callouts on it returns success.
  264. TEST_F(CalloutManagerTest, CallNoCallouts) {
  265. // Ensure that no callouts are attached to any of the hooks.
  266. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  267. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  268. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  269. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  270. // Call the callouts on an arbitrary hook and ensure that nothing happens.
  271. callout_value_ = 475;
  272. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  273. EXPECT_EQ(475, callout_value_); // Unchanged
  274. }
  275. // Test that the callouts are called in the correct order (i.e. the callouts
  276. // from the first library in the order they were registered, then the callouts
  277. // from the second library in the order they were registered etc.)
  278. TEST_F(CalloutManagerTest, CallCalloutsSuccess) {
  279. // Ensure that no callouts are attached to any of the hooks.
  280. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  281. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  282. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  283. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  284. // Each library contributes one callout on hook "alpha".
  285. callout_value_ = 0;
  286. getCalloutManager()->setLibraryIndex(1);
  287. getCalloutManager()->registerCallout("alpha", callout_one);
  288. getCalloutManager()->setLibraryIndex(1);
  289. getCalloutManager()->registerCallout("alpha", callout_two);
  290. getCalloutManager()->setLibraryIndex(2);
  291. getCalloutManager()->registerCallout("alpha", callout_three);
  292. getCalloutManager()->setLibraryIndex(3);
  293. getCalloutManager()->registerCallout("alpha", callout_four);
  294. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  295. EXPECT_EQ(1234, callout_value_);
  296. // Do a random selection of callouts on hook "beta".
  297. callout_value_ = 0;
  298. getCalloutManager()->setLibraryIndex(0);
  299. getCalloutManager()->registerCallout("beta", callout_one);
  300. getCalloutManager()->registerCallout("beta", callout_three);
  301. getCalloutManager()->setLibraryIndex(1);
  302. getCalloutManager()->registerCallout("beta", callout_two);
  303. getCalloutManager()->setLibraryIndex(3);
  304. getCalloutManager()->registerCallout("beta", callout_four);
  305. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  306. EXPECT_EQ(1324, callout_value_);
  307. // Ensure that calling the callouts on a hook with no callouts works.
  308. callout_value_ = 0;
  309. getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle());
  310. EXPECT_EQ(0, callout_value_);
  311. }
  312. // Test that the callouts are called in order, but that callouts occurring
  313. // after a callout that returns an error are not called.
  314. //
  315. // (Note: in this test, the callouts that return an error set the value of
  316. // callout_value_ before they return the error code.)
  317. TEST_F(CalloutManagerTest, CallCalloutsError) {
  318. // Ensure that no callouts are attached to any of the hooks.
  319. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  320. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  321. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  322. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  323. // Each library contributing one callout on hook "alpha". The first callout
  324. // returns an error (after adding its value to the result).
  325. callout_value_ = 0;
  326. getCalloutManager()->setLibraryIndex(0);
  327. getCalloutManager()->registerCallout("alpha", callout_one_error);
  328. getCalloutManager()->setLibraryIndex(1);
  329. getCalloutManager()->registerCallout("alpha", callout_two);
  330. getCalloutManager()->setLibraryIndex(2);
  331. getCalloutManager()->registerCallout("alpha", callout_three);
  332. getCalloutManager()->setLibraryIndex(3);
  333. getCalloutManager()->registerCallout("alpha", callout_four);
  334. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  335. EXPECT_EQ(1234, callout_value_);
  336. // Each library contributing multiple callouts on hook "beta". The last
  337. // callout on the first library returns an error.
  338. callout_value_ = 0;
  339. getCalloutManager()->setLibraryIndex(0);
  340. getCalloutManager()->registerCallout("beta", callout_one);
  341. getCalloutManager()->registerCallout("beta", callout_one_error);
  342. getCalloutManager()->setLibraryIndex(1);
  343. getCalloutManager()->registerCallout("beta", callout_two);
  344. getCalloutManager()->registerCallout("beta", callout_two);
  345. getCalloutManager()->registerCallout("beta", callout_three);
  346. getCalloutManager()->registerCallout("beta", callout_three);
  347. getCalloutManager()->setLibraryIndex(3);
  348. getCalloutManager()->registerCallout("beta", callout_four);
  349. getCalloutManager()->registerCallout("beta", callout_four);
  350. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  351. EXPECT_EQ(11223344, callout_value_);
  352. // A callout in a random position in the callout list returns an error.
  353. callout_value_ = 0;
  354. getCalloutManager()->setLibraryIndex(0);
  355. getCalloutManager()->registerCallout("gamma", callout_one);
  356. getCalloutManager()->registerCallout("gamma", callout_one);
  357. getCalloutManager()->setLibraryIndex(1);
  358. getCalloutManager()->registerCallout("gamma", callout_two);
  359. getCalloutManager()->registerCallout("gamma", callout_two);
  360. getCalloutManager()->setLibraryIndex(3);
  361. getCalloutManager()->registerCallout("gamma", callout_four_error);
  362. getCalloutManager()->registerCallout("gamma", callout_four);
  363. getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle());
  364. EXPECT_EQ(112244, callout_value_);
  365. // The last callout on a hook returns an error.
  366. callout_value_ = 0;
  367. getCalloutManager()->setLibraryIndex(0);
  368. getCalloutManager()->registerCallout("delta", callout_one);
  369. getCalloutManager()->registerCallout("delta", callout_one);
  370. getCalloutManager()->setLibraryIndex(1);
  371. getCalloutManager()->registerCallout("delta", callout_two);
  372. getCalloutManager()->registerCallout("delta", callout_two);
  373. getCalloutManager()->setLibraryIndex(2);
  374. getCalloutManager()->registerCallout("delta", callout_three);
  375. getCalloutManager()->registerCallout("delta", callout_three);
  376. getCalloutManager()->setLibraryIndex(3);
  377. getCalloutManager()->registerCallout("delta", callout_four);
  378. getCalloutManager()->registerCallout("delta", callout_four_error);
  379. getCalloutManager()->callCallouts(delta_index_, getCalloutHandle());
  380. EXPECT_EQ(11223344, callout_value_);
  381. }
  382. // Now test that we can deregister a single callout on a hook.
  383. TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
  384. // Ensure that no callouts are attached to any of the hooks.
  385. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  386. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  387. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  388. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  389. // Add a callout to hook "alpha" and check it is added correctly.
  390. callout_value_ = 0;
  391. getCalloutManager()->setLibraryIndex(0);
  392. getCalloutManager()->registerCallout("alpha", callout_two);
  393. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  394. EXPECT_EQ(2, callout_value_);
  395. // Remove it and check that the no callouts are present. We have to reset
  396. // the current library index here as it was invalidated by the call
  397. // to callCallouts().
  398. getCalloutManager()->setLibraryIndex(0);
  399. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  400. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  401. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  402. }
  403. // Now test that we can deregister a single callout on a hook that has multiple
  404. // callouts from the same library.
  405. TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) {
  406. // Ensure that no callouts are attached to any of the hooks.
  407. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  408. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  409. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  410. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  411. // Add multiple callouts to hook "alpha".
  412. callout_value_ = 0;
  413. getCalloutManager()->setLibraryIndex(0);
  414. getCalloutManager()->registerCallout("alpha", callout_one);
  415. getCalloutManager()->registerCallout("alpha", callout_two);
  416. getCalloutManager()->registerCallout("alpha", callout_three);
  417. getCalloutManager()->registerCallout("alpha", callout_four);
  418. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  419. EXPECT_EQ(1234, callout_value_);
  420. // Remove the callout_two callout. We have to reset the current library
  421. // index here as it was invalidated by the call to callCallouts().
  422. getCalloutManager()->setLibraryIndex(0);
  423. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  424. callout_value_ = 0;
  425. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  426. EXPECT_EQ(134, callout_value_);
  427. // Try removing it again.
  428. getCalloutManager()->setLibraryIndex(0);
  429. EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  430. callout_value_ = 0;
  431. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  432. EXPECT_EQ(134, callout_value_);
  433. }
  434. // Check we can deregister multiple callouts from the same library.
  435. TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
  436. // Ensure that no callouts are attached to any of the hooks.
  437. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  438. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  439. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  440. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  441. // Each library contributes one callout on hook "alpha".
  442. callout_value_ = 0;
  443. getCalloutManager()->setLibraryIndex(0);
  444. getCalloutManager()->registerCallout("alpha", callout_one);
  445. getCalloutManager()->registerCallout("alpha", callout_two);
  446. getCalloutManager()->registerCallout("alpha", callout_one);
  447. getCalloutManager()->registerCallout("alpha", callout_two);
  448. getCalloutManager()->registerCallout("alpha", callout_three);
  449. getCalloutManager()->registerCallout("alpha", callout_four);
  450. getCalloutManager()->registerCallout("alpha", callout_three);
  451. getCalloutManager()->registerCallout("alpha", callout_four);
  452. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  453. EXPECT_EQ(12123434, callout_value_);
  454. // Remove the callout_two callouts. We have to reset the current library
  455. // index here as it was invalidated by the call to callCallouts().
  456. getCalloutManager()->setLibraryIndex(0);
  457. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  458. callout_value_ = 0;
  459. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  460. EXPECT_EQ(113434, callout_value_);
  461. // Try removing multiple callouts that includes one at the end of the
  462. // list of callouts.
  463. getCalloutManager()->setLibraryIndex(0);
  464. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_four));
  465. callout_value_ = 0;
  466. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  467. EXPECT_EQ(1133, callout_value_);
  468. // ... and from the start.
  469. getCalloutManager()->setLibraryIndex(0);
  470. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_one));
  471. callout_value_ = 0;
  472. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  473. EXPECT_EQ(33, callout_value_);
  474. // ... and the remaining callouts.
  475. getCalloutManager()->setLibraryIndex(0);
  476. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_three));
  477. callout_value_ = 0;
  478. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  479. EXPECT_EQ(0, callout_value_);
  480. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  481. }
  482. // Check we can deregister multiple callouts from multiple libraries.
  483. TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) {
  484. // Ensure that no callouts are attached to any of the hooks.
  485. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  486. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  487. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  488. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  489. // Each library contributes two callouts to hook "alpha".
  490. callout_value_ = 0;
  491. getCalloutManager()->setLibraryIndex(0);
  492. getCalloutManager()->registerCallout("alpha", callout_one);
  493. getCalloutManager()->registerCallout("alpha", callout_two);
  494. getCalloutManager()->setLibraryIndex(1);
  495. getCalloutManager()->registerCallout("alpha", callout_three);
  496. getCalloutManager()->registerCallout("alpha", callout_four);
  497. getCalloutManager()->setLibraryIndex(2);
  498. getCalloutManager()->registerCallout("alpha", callout_five);
  499. getCalloutManager()->registerCallout("alpha", callout_two);
  500. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  501. EXPECT_EQ(123452, callout_value_);
  502. // Remove the callout_two callout from library 0. It should not affect
  503. // the second callout_two callout registered by library 2.
  504. getCalloutManager()->setLibraryIndex(0);
  505. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  506. callout_value_ = 0;
  507. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  508. EXPECT_EQ(13452, callout_value_);
  509. }
  510. // Check we can deregister all callouts from a single library.
  511. TEST_F(CalloutManagerTest, DeregisterAllCallouts) {
  512. // Ensure that no callouts are attached to hook one.
  513. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  514. // Each library contributes two callouts to hook "alpha".
  515. callout_value_ = 0;
  516. getCalloutManager()->setLibraryIndex(0);
  517. getCalloutManager()->registerCallout("alpha", callout_one);
  518. getCalloutManager()->registerCallout("alpha", callout_two);
  519. getCalloutManager()->setLibraryIndex(1);
  520. getCalloutManager()->registerCallout("alpha", callout_three);
  521. getCalloutManager()->registerCallout("alpha", callout_four);
  522. getCalloutManager()->setLibraryIndex(2);
  523. getCalloutManager()->registerCallout("alpha", callout_five);
  524. getCalloutManager()->registerCallout("alpha", callout_six);
  525. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  526. EXPECT_EQ(123456, callout_value_);
  527. // Remove all callouts from library index 1.
  528. getCalloutManager()->setLibraryIndex(1);
  529. EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
  530. callout_value_ = 0;
  531. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  532. EXPECT_EQ(1256, callout_value_);
  533. // Remove all callouts from library index 2.
  534. getCalloutManager()->setLibraryIndex(2);
  535. EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
  536. callout_value_ = 0;
  537. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  538. EXPECT_EQ(12, callout_value_);
  539. }
  540. // Check that we can register/deregister callouts on different libraries
  541. // and different hooks, and that the callout instances are regarded as
  542. // unique and do not affect one another.
  543. TEST_F(CalloutManagerTest, MultipleCalloutsLibrariesHooks) {
  544. // Ensure that no callouts are attached to any of the hooks.
  545. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  546. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  547. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  548. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  549. // Register callouts on the alpha hook.
  550. callout_value_ = 0;
  551. getCalloutManager()->setLibraryIndex(0);
  552. getCalloutManager()->registerCallout("alpha", callout_one);
  553. getCalloutManager()->registerCallout("alpha", callout_two);
  554. getCalloutManager()->setLibraryIndex(1);
  555. getCalloutManager()->registerCallout("alpha", callout_three);
  556. getCalloutManager()->registerCallout("alpha", callout_four);
  557. getCalloutManager()->setLibraryIndex(2);
  558. getCalloutManager()->registerCallout("alpha", callout_five);
  559. getCalloutManager()->registerCallout("alpha", callout_two);
  560. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  561. EXPECT_EQ(123452, callout_value_);
  562. // Register the same callouts on the beta hook, and check that those
  563. // on the alpha hook are not affected.
  564. callout_value_ = 0;
  565. getCalloutManager()->setLibraryIndex(0);
  566. getCalloutManager()->registerCallout("beta", callout_five);
  567. getCalloutManager()->registerCallout("beta", callout_one);
  568. getCalloutManager()->setLibraryIndex(2);
  569. getCalloutManager()->registerCallout("beta", callout_four);
  570. getCalloutManager()->registerCallout("beta", callout_three);
  571. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  572. EXPECT_EQ(5143, callout_value_);
  573. // Check that the order of callouts on the alpha hook has not been affected.
  574. callout_value_ = 0;
  575. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  576. EXPECT_EQ(123452, callout_value_);
  577. // Remove callout four from beta and check that alpha is not affected.
  578. getCalloutManager()->setLibraryIndex(2);
  579. EXPECT_TRUE(getCalloutManager()->deregisterCallout("beta", callout_four));
  580. callout_value_ = 0;
  581. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  582. EXPECT_EQ(513, callout_value_);
  583. callout_value_ = 0;
  584. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  585. EXPECT_EQ(123452, callout_value_);
  586. }
  587. // Library handle tests. As by inspection the LibraryHandle can be seen to be
  588. // little more than shell around CalloutManager, only a basic set of tests
  589. // is done concerning registration and deregistration of functions.
  590. //
  591. // More extensive tests (i.e. checking that when a callout is called it can
  592. // only register and deregister callouts within its library) require that
  593. // the CalloutHandle object pass the appropriate LibraryHandle to the
  594. // callout. These tests are done in the handles_unittest tests.
  595. TEST_F(CalloutManagerTest, LibraryHandleRegistration) {
  596. // Ensure that no callouts are attached to any of the hooks.
  597. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  598. // Set up so that hooks "alpha" and "beta" have callouts attached from a
  599. // different libraries.
  600. getCalloutManager()->setLibraryIndex(0);
  601. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  602. callout_one);
  603. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  604. callout_two);
  605. getCalloutManager()->setLibraryIndex(1);
  606. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  607. callout_three);
  608. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  609. callout_four);
  610. // Check all is as expected.
  611. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  612. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  613. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  614. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  615. // Check that calling the callouts returns as expected. (This is also a
  616. // test of the callCallouts method.)
  617. callout_value_ = 0;
  618. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  619. EXPECT_EQ(1234, callout_value_);
  620. // Deregister a callout on library index 0 (after we check we can't
  621. // deregister it through library index 1).
  622. getCalloutManager()->setLibraryIndex(1);
  623. EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  624. callout_value_ = 0;
  625. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  626. EXPECT_EQ(1234, callout_value_);
  627. getCalloutManager()->setLibraryIndex(0);
  628. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  629. callout_value_ = 0;
  630. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  631. EXPECT_EQ(134, callout_value_);
  632. // Deregister all callouts on library index 1.
  633. getCalloutManager()->setLibraryIndex(1);
  634. EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
  635. callout_value_ = 0;
  636. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  637. EXPECT_EQ(1, callout_value_);
  638. }
  639. // A repeat of the test above, but using the alternate constructor for the
  640. // LibraryHandle.
  641. TEST_F(CalloutManagerTest, LibraryHandleAlternateConstructor) {
  642. // Ensure that no callouts are attached to any of the hooks.
  643. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  644. // Set up so that hooks "alpha" and "beta" have callouts attached from a
  645. // different libraries.
  646. LibraryHandle lh0(getCalloutManager().get(), 0);
  647. lh0.registerCallout("alpha", callout_one);
  648. lh0.registerCallout("alpha", callout_two);
  649. LibraryHandle lh1(getCalloutManager().get(), 1);
  650. lh1.registerCallout("alpha", callout_three);
  651. lh1.registerCallout("alpha", callout_four);
  652. // Check all is as expected.
  653. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  654. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  655. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  656. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  657. // Check that calling the callouts returns as expected. (This is also a
  658. // test of the callCallouts method.)
  659. callout_value_ = 0;
  660. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  661. EXPECT_EQ(1234, callout_value_);
  662. // Deregister a callout on library index 0 (after we check we can't
  663. // deregister it through library index 1).
  664. EXPECT_FALSE(lh1.deregisterCallout("alpha", callout_two));
  665. callout_value_ = 0;
  666. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  667. EXPECT_EQ(1234, callout_value_);
  668. EXPECT_TRUE(lh0.deregisterCallout("alpha", callout_two));
  669. callout_value_ = 0;
  670. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  671. EXPECT_EQ(134, callout_value_);
  672. // Deregister all callouts on library index 1.
  673. EXPECT_TRUE(lh1.deregisterAllCallouts("alpha"));
  674. callout_value_ = 0;
  675. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  676. EXPECT_EQ(1, callout_value_);
  677. }
  678. // Check that the pre- and post- user callout library handles work
  679. // appropriately with no user libraries.
  680. TEST_F(CalloutManagerTest, LibraryHandlePrePostNoLibraries) {
  681. // Create a local callout manager and callout handle to reflect no libraries
  682. // being loaded.
  683. boost::shared_ptr<CalloutManager> manager(new CalloutManager(0));
  684. CalloutHandle handle(manager);
  685. // Ensure that no callouts are attached to any of the hooks.
  686. EXPECT_FALSE(manager->calloutsPresent(alpha_index_));
  687. // Setup the pre-and post callouts.
  688. manager->getPostLibraryHandle().registerCallout("alpha", callout_four);
  689. manager->getPreLibraryHandle().registerCallout("alpha", callout_one);
  690. // Check all is as expected.
  691. EXPECT_TRUE(manager->calloutsPresent(alpha_index_));
  692. EXPECT_FALSE(manager->calloutsPresent(beta_index_));
  693. EXPECT_FALSE(manager->calloutsPresent(gamma_index_));
  694. EXPECT_FALSE(manager->calloutsPresent(delta_index_));
  695. // Check that calling the callouts returns as expected.
  696. callout_value_ = 0;
  697. manager->callCallouts(alpha_index_, handle);
  698. EXPECT_EQ(14, callout_value_);
  699. // Deregister the pre- library callout.
  700. EXPECT_TRUE(manager->getPreLibraryHandle().deregisterAllCallouts("alpha"));
  701. callout_value_ = 0;
  702. manager->callCallouts(alpha_index_, handle);
  703. EXPECT_EQ(4, callout_value_);
  704. }
  705. // Repeat the tests with one user library.
  706. TEST_F(CalloutManagerTest, LibraryHandlePrePostUserLibrary) {
  707. // Setup the pre-, library and post callouts.
  708. getCalloutManager()->getPostLibraryHandle().registerCallout("alpha",
  709. callout_four);
  710. getCalloutManager()->getPreLibraryHandle().registerCallout("alpha",
  711. callout_one);
  712. // ... and set up a callout in between, on library number 2.
  713. LibraryHandle lh1(getCalloutManager().get(), 2);
  714. lh1.registerCallout("alpha", callout_five);
  715. // Check all is as expected.
  716. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  717. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  718. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  719. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  720. // Check that calling the callouts returns as expected.
  721. callout_value_ = 0;
  722. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  723. EXPECT_EQ(154, callout_value_);
  724. }
  725. // Test that control command handlers can be installed as callouts.
  726. TEST_F(CalloutManagerTest, LibraryHandleRegisterCommandHandler) {
  727. CalloutHandle handle(getCalloutManager());
  728. // Simulate creation of the two hook libraries. Fist library implements two
  729. // handlers for the control command 'command-one'. Second library implements
  730. // two control command handlers: one for the 'command-one', another one for
  731. // 'command-two'. Each of the handlers for the 'command-one' must be called
  732. // and they must be called in the appropriate order. Command handler for
  733. // 'command-two' should also be called.
  734. getCalloutManager()->setLibraryIndex(0);
  735. getCalloutManager()->getLibraryHandle().registerCommandCallout("command-one",
  736. callout_one);
  737. getCalloutManager()->getLibraryHandle().registerCommandCallout("command-one",
  738. callout_four);
  739. getCalloutManager()->setLibraryIndex(1);
  740. getCalloutManager()->getLibraryHandle().registerCommandCallout("command-one",
  741. callout_two);
  742. getCalloutManager()->getLibraryHandle().registerCommandCallout("command-two",
  743. callout_three);
  744. // Command handlers are installed for commands: 'command-one' and 'command-two'.
  745. EXPECT_TRUE(getCalloutManager()->commandHandlersPresent("command-one"));
  746. EXPECT_TRUE(getCalloutManager()->commandHandlersPresent("command-two"));
  747. // There should be no handlers installed for 'command-three' and 'command-four'.
  748. EXPECT_FALSE(getCalloutManager()->commandHandlersPresent("command-three"));
  749. EXPECT_FALSE(getCalloutManager()->commandHandlersPresent("command-four"));
  750. // Call handlers for 'command-one'. There should be three handlers called in
  751. // the following order: 1, 4, 2.
  752. callout_value_ = 0;
  753. ASSERT_NO_THROW(getCalloutManager()->callCommandHandlers("command-one", handle));
  754. EXPECT_EQ(142, callout_value_);
  755. // There should be one handler invoked for the 'command-two'. This handler has
  756. // index of 3.
  757. callout_value_ = 0;
  758. ASSERT_NO_THROW(getCalloutManager()->callCommandHandlers("command-two", handle));
  759. EXPECT_EQ(3, callout_value_);
  760. // An attempt to call handlers for the commands for which no hook points
  761. // were created should result in exception.
  762. EXPECT_THROW(getCalloutManager()->callCommandHandlers("command-three", handle),
  763. NoSuchHook);
  764. EXPECT_THROW(getCalloutManager()->callCommandHandlers("command-four", handle),
  765. NoSuchHook);
  766. }
  767. // The setting of the hook index is checked in the handles_unittest
  768. // set of tests, as access restrictions mean it is not easily tested
  769. // on its own.
  770. } // Anonymous namespace