callout_manager_unittest.cc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <exceptions/exceptions.h>
  15. #include <hooks/callout_handle.h>
  16. #include <hooks/callout_manager.h>
  17. #include <hooks/library_handle.h>
  18. #include <hooks/server_hooks.h>
  19. #include <boost/scoped_ptr.hpp>
  20. #include <gtest/gtest.h>
  21. #include <algorithm>
  22. #include <string>
  23. #include <vector>
  24. /// @file
  25. /// @brief CalloutManager and LibraryHandle tests
  26. ///
  27. /// These set of tests check the CalloutManager and LibraryHandle. They are
  28. /// together in the same file because the LibraryHandle is little more than a
  29. /// restricted interface to the CalloutManager, and a lot of the support
  30. /// structure for the tests is common.
  31. using namespace isc;
  32. using namespace isc::hooks;
  33. using namespace std;
  34. namespace {
  35. class CalloutManagerTest : public ::testing::Test {
  36. public:
  37. /// @brief Constructor
  38. ///
  39. /// Sets up a collection of three LibraryHandle objects to use in the test.
  40. CalloutManagerTest() {
  41. // Set up the server hooks. There is sone singleton for all tests,
  42. // so reset it and explicitly set up the hooks for the test.
  43. ServerHooks& hooks = ServerHooks::getServerHooks();
  44. hooks.reset();
  45. alpha_index_ = hooks.registerHook("alpha");
  46. beta_index_ = hooks.registerHook("beta");
  47. gamma_index_ = hooks.registerHook("gamma");
  48. delta_index_ = hooks.registerHook("delta");
  49. // Set up the callout manager with these hooks. Assume a maximum of
  50. // four libraries.
  51. callout_manager_.reset(new CalloutManager(10));
  52. // Set up the callout handle.
  53. callout_handle_.reset(new CalloutHandle(callout_manager_));
  54. // Initialize the static variable.
  55. callout_value_ = 0;
  56. }
  57. /// @brief Return the callout handle
  58. CalloutHandle& getCalloutHandle() {
  59. return (*callout_handle_);
  60. }
  61. /// @brief Return the callout manager
  62. boost::shared_ptr<CalloutManager> getCalloutManager() {
  63. return (callout_manager_);
  64. }
  65. /// Static variable used for accumulating information
  66. static int callout_value_;
  67. /// Hook indexes. These are somewhat ubiquitous, so are made public for
  68. /// ease of reference instead of being accessible by a function.
  69. int alpha_index_;
  70. int beta_index_;
  71. int gamma_index_;
  72. int delta_index_;
  73. private:
  74. /// Callout handle used in calls
  75. boost::shared_ptr<CalloutHandle> callout_handle_;
  76. /// Callout manager used for the test
  77. boost::shared_ptr<CalloutManager> callout_manager_;
  78. };
  79. // Definition of the static variable.
  80. int CalloutManagerTest::callout_value_ = 0;
  81. // Callout definitions
  82. //
  83. // The callouts defined here are structured in such a way that it is possible
  84. // to determine the order in which they are called and whether they are called
  85. // at all. The method used is simple - after a sequence of callouts, the digits
  86. // in the value, reading left to right, determines the order of the callouts
  87. // called. For example, callout one followed by two followed by three followed
  88. // by two followed by one results in a value of 12321.
  89. //
  90. // Functions return a zero to indicate success.
  91. extern "C" {
  92. int callout_general(int number) {
  93. CalloutManagerTest::callout_value_ =
  94. 10 * CalloutManagerTest::callout_value_ + number;
  95. return (0);
  96. }
  97. int callout_one(CalloutHandle&) {
  98. return (callout_general(1));
  99. }
  100. int callout_two(CalloutHandle&) {
  101. return (callout_general(2));
  102. }
  103. int callout_three(CalloutHandle&) {
  104. return (callout_general(3));
  105. }
  106. int callout_four(CalloutHandle&) {
  107. return (callout_general(4));
  108. }
  109. int callout_five(CalloutHandle&) {
  110. return (callout_general(5));
  111. }
  112. int callout_six(CalloutHandle&) {
  113. return (callout_general(6));
  114. }
  115. int callout_seven(CalloutHandle&) {
  116. return (callout_general(7));
  117. }
  118. // The next functions are duplicates of some of the above, but return an error.
  119. int callout_one_error(CalloutHandle& handle) {
  120. (void) callout_one(handle);
  121. return (1);
  122. }
  123. int callout_two_error(CalloutHandle& handle) {
  124. (void) callout_two(handle);
  125. return (1);
  126. }
  127. int callout_three_error(CalloutHandle& handle) {
  128. (void) callout_three(handle);
  129. return (1);
  130. }
  131. int callout_four_error(CalloutHandle& handle) {
  132. (void) callout_four(handle);
  133. return (1);
  134. }
  135. }; // extern "C"
  136. // *** Callout Tests ***
  137. //
  138. // The next set of tests check that callouts can be called.
  139. // Constructor - check that we trap bad parameters.
  140. TEST_F(CalloutManagerTest, BadConstructorParameters) {
  141. boost::scoped_ptr<CalloutManager> cm;
  142. // Invalid number of libraries
  143. EXPECT_THROW(cm.reset(new CalloutManager(-1)), BadValue);
  144. }
  145. // Check the number of libraries is reported successfully.
  146. TEST_F(CalloutManagerTest, NumberOfLibraries) {
  147. boost::scoped_ptr<CalloutManager> cm;
  148. // Check two valid values of number of libraries to ensure that the
  149. // GetNumLibraries() returns the value set.
  150. EXPECT_NO_THROW(cm.reset(new CalloutManager()));
  151. EXPECT_EQ(0, cm->getNumLibraries());
  152. EXPECT_NO_THROW(cm.reset(new CalloutManager(0)));
  153. EXPECT_EQ(0, cm->getNumLibraries());
  154. EXPECT_NO_THROW(cm.reset(new CalloutManager(4)));
  155. EXPECT_EQ(4, cm->getNumLibraries());
  156. EXPECT_NO_THROW(cm.reset(new CalloutManager(42)));
  157. EXPECT_EQ(42, cm->getNumLibraries());
  158. // Check that setting the number of libraries alterns the number reported.
  159. EXPECT_NO_THROW(cm->setNumLibraries(27));
  160. EXPECT_EQ(27, cm->getNumLibraries());
  161. }
  162. // Check that we can only set the current library index to the correct values.
  163. TEST_F(CalloutManagerTest, CheckLibraryIndex) {
  164. // Check valid indexes
  165. for (int i = 0; i < 4; ++i) {
  166. EXPECT_NO_THROW(getCalloutManager()->setLibraryIndex(i));
  167. }
  168. // Check invalid ones
  169. EXPECT_THROW(getCalloutManager()->setLibraryIndex(-1), NoSuchLibrary);
  170. EXPECT_THROW(getCalloutManager()->setLibraryIndex(15), NoSuchLibrary);
  171. }
  172. // Check that we can only register callouts on valid hook names.
  173. TEST_F(CalloutManagerTest, ValidHookNames) {
  174. getCalloutManager()->setLibraryIndex(0);
  175. EXPECT_NO_THROW(getCalloutManager()->registerCallout("alpha", callout_one));
  176. EXPECT_THROW(getCalloutManager()->registerCallout("unknown", callout_one),
  177. NoSuchHook);
  178. }
  179. // Check we can register callouts appropriately.
  180. TEST_F(CalloutManagerTest, RegisterCallout) {
  181. // Ensure that no callouts are attached to any of the hooks.
  182. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  183. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  184. // Set up so that hooks "alpha" and "beta" have callouts attached from a
  185. // different libraries.
  186. getCalloutManager()->setLibraryIndex(0);
  187. getCalloutManager()->registerCallout("alpha", callout_one);
  188. getCalloutManager()->setLibraryIndex(1);
  189. getCalloutManager()->registerCallout("beta", callout_two);
  190. // Check all is as expected.
  191. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  192. EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_));
  193. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  194. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  195. // Check that calling the callouts returns as expected. (This is also a
  196. // test of the callCallouts method.)
  197. callout_value_ = 0;
  198. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  199. EXPECT_EQ(1, callout_value_);
  200. callout_value_ = 0;
  201. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  202. EXPECT_EQ(2, callout_value_);
  203. // Register some more callouts from different libraries on hook "alpha".
  204. getCalloutManager()->setLibraryIndex(2);
  205. getCalloutManager()->registerCallout("alpha", callout_three);
  206. getCalloutManager()->registerCallout("alpha", callout_four);
  207. getCalloutManager()->setLibraryIndex(3);
  208. getCalloutManager()->registerCallout("alpha", callout_five);
  209. // Check it is as expected.
  210. callout_value_ = 0;
  211. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  212. EXPECT_EQ(1345, callout_value_);
  213. // ... and check the additional callouts were not registered on the "beta"
  214. // hook.
  215. callout_value_ = 0;
  216. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  217. EXPECT_EQ(2, callout_value_);
  218. // Add another callout to hook "alpha" from library index 2 - this should
  219. // appear at the end of the callout list for that library.
  220. getCalloutManager()->setLibraryIndex(2);
  221. getCalloutManager()->registerCallout("alpha", callout_six);
  222. callout_value_ = 0;
  223. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  224. EXPECT_EQ(13465, callout_value_);
  225. // Add a callout from library index 1 - this should appear between the
  226. // callouts from library index 0 and linrary index 2.
  227. getCalloutManager()->setLibraryIndex(1);
  228. getCalloutManager()->registerCallout("alpha", callout_seven);
  229. callout_value_ = 0;
  230. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  231. EXPECT_EQ(173465, callout_value_);
  232. }
  233. // Check the "calloutsPresent()" method.
  234. TEST_F(CalloutManagerTest, CalloutsPresent) {
  235. // Ensure that no callouts are attached to any of the hooks.
  236. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  237. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  238. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  239. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  240. // Set up so that hooks "alpha", "beta" and "delta" have callouts attached
  241. // to them, and callout "gamma" does not. (In the statements below, the
  242. // exact callouts attached to a hook are not relevant - only the fact
  243. // that some callouts are). Chose the libraries for which the callouts
  244. // are registered randomly.
  245. getCalloutManager()->setLibraryIndex(0);
  246. getCalloutManager()->registerCallout("alpha", callout_one);
  247. getCalloutManager()->setLibraryIndex(1);
  248. getCalloutManager()->registerCallout("alpha", callout_two);
  249. getCalloutManager()->registerCallout("beta", callout_two);
  250. getCalloutManager()->setLibraryIndex(3);
  251. getCalloutManager()->registerCallout("alpha", callout_three);
  252. getCalloutManager()->registerCallout("delta", callout_four);
  253. // Check all is as expected.
  254. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  255. EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_));
  256. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  257. EXPECT_TRUE(getCalloutManager()->calloutsPresent(delta_index_));
  258. // Check we fail on an invalid hook index.
  259. EXPECT_THROW(getCalloutManager()->calloutsPresent(42), NoSuchHook);
  260. EXPECT_THROW(getCalloutManager()->calloutsPresent(-1), NoSuchHook);
  261. }
  262. // Test that calling a hook with no callouts on it returns success.
  263. TEST_F(CalloutManagerTest, CallNoCallouts) {
  264. // Ensure that no callouts are attached to any of the hooks.
  265. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  266. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  267. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  268. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  269. // Call the callouts on an arbitrary hook and ensure that nothing happens.
  270. callout_value_ = 475;
  271. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  272. EXPECT_EQ(475, callout_value_); // Unchanged
  273. }
  274. // Test that the callouts are called in the correct order (i.e. the callouts
  275. // from the first library in the order they were registered, then the callouts
  276. // from the second library in the order they were registered etc.)
  277. TEST_F(CalloutManagerTest, CallCalloutsSuccess) {
  278. // Ensure that no callouts are attached to any of the hooks.
  279. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  280. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  281. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  282. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  283. // Each library contributes one callout on hook "alpha".
  284. callout_value_ = 0;
  285. getCalloutManager()->setLibraryIndex(1);
  286. getCalloutManager()->registerCallout("alpha", callout_one);
  287. getCalloutManager()->setLibraryIndex(1);
  288. getCalloutManager()->registerCallout("alpha", callout_two);
  289. getCalloutManager()->setLibraryIndex(2);
  290. getCalloutManager()->registerCallout("alpha", callout_three);
  291. getCalloutManager()->setLibraryIndex(3);
  292. getCalloutManager()->registerCallout("alpha", callout_four);
  293. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  294. EXPECT_EQ(1234, callout_value_);
  295. // Do a random selection of callouts on hook "beta".
  296. callout_value_ = 0;
  297. getCalloutManager()->setLibraryIndex(0);
  298. getCalloutManager()->registerCallout("beta", callout_one);
  299. getCalloutManager()->registerCallout("beta", callout_three);
  300. getCalloutManager()->setLibraryIndex(1);
  301. getCalloutManager()->registerCallout("beta", callout_two);
  302. getCalloutManager()->setLibraryIndex(3);
  303. getCalloutManager()->registerCallout("beta", callout_four);
  304. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  305. EXPECT_EQ(1324, callout_value_);
  306. // Ensure that calling the callouts on a hook with no callouts works.
  307. callout_value_ = 0;
  308. getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle());
  309. EXPECT_EQ(0, callout_value_);
  310. }
  311. // Test that the callouts are called in order, but that callouts occurring
  312. // after a callout that returns an error are not called.
  313. //
  314. // (Note: in this test, the callouts that return an error set the value of
  315. // callout_value_ before they return the error code.)
  316. TEST_F(CalloutManagerTest, CallCalloutsError) {
  317. // Ensure that no callouts are attached to any of the hooks.
  318. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  319. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  320. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  321. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  322. // Each library contributing one callout on hook "alpha". The first callout
  323. // returns an error (after adding its value to the result).
  324. callout_value_ = 0;
  325. getCalloutManager()->setLibraryIndex(0);
  326. getCalloutManager()->registerCallout("alpha", callout_one_error);
  327. getCalloutManager()->setLibraryIndex(1);
  328. getCalloutManager()->registerCallout("alpha", callout_two);
  329. getCalloutManager()->setLibraryIndex(2);
  330. getCalloutManager()->registerCallout("alpha", callout_three);
  331. getCalloutManager()->setLibraryIndex(3);
  332. getCalloutManager()->registerCallout("alpha", callout_four);
  333. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  334. EXPECT_EQ(1234, callout_value_);
  335. // Each library contributing multiple callouts on hook "beta". The last
  336. // callout on the first library returns an error.
  337. callout_value_ = 0;
  338. getCalloutManager()->setLibraryIndex(0);
  339. getCalloutManager()->registerCallout("beta", callout_one);
  340. getCalloutManager()->registerCallout("beta", callout_one_error);
  341. getCalloutManager()->setLibraryIndex(1);
  342. getCalloutManager()->registerCallout("beta", callout_two);
  343. getCalloutManager()->registerCallout("beta", callout_two);
  344. getCalloutManager()->registerCallout("beta", callout_three);
  345. getCalloutManager()->registerCallout("beta", callout_three);
  346. getCalloutManager()->setLibraryIndex(3);
  347. getCalloutManager()->registerCallout("beta", callout_four);
  348. getCalloutManager()->registerCallout("beta", callout_four);
  349. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  350. EXPECT_EQ(11223344, callout_value_);
  351. // A callout in a random position in the callout list returns an error.
  352. callout_value_ = 0;
  353. getCalloutManager()->setLibraryIndex(0);
  354. getCalloutManager()->registerCallout("gamma", callout_one);
  355. getCalloutManager()->registerCallout("gamma", callout_one);
  356. getCalloutManager()->setLibraryIndex(1);
  357. getCalloutManager()->registerCallout("gamma", callout_two);
  358. getCalloutManager()->registerCallout("gamma", callout_two);
  359. getCalloutManager()->setLibraryIndex(3);
  360. getCalloutManager()->registerCallout("gamma", callout_four_error);
  361. getCalloutManager()->registerCallout("gamma", callout_four);
  362. getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle());
  363. EXPECT_EQ(112244, callout_value_);
  364. // The last callout on a hook returns an error.
  365. callout_value_ = 0;
  366. getCalloutManager()->setLibraryIndex(0);
  367. getCalloutManager()->registerCallout("delta", callout_one);
  368. getCalloutManager()->registerCallout("delta", callout_one);
  369. getCalloutManager()->setLibraryIndex(1);
  370. getCalloutManager()->registerCallout("delta", callout_two);
  371. getCalloutManager()->registerCallout("delta", callout_two);
  372. getCalloutManager()->setLibraryIndex(2);
  373. getCalloutManager()->registerCallout("delta", callout_three);
  374. getCalloutManager()->registerCallout("delta", callout_three);
  375. getCalloutManager()->setLibraryIndex(3);
  376. getCalloutManager()->registerCallout("delta", callout_four);
  377. getCalloutManager()->registerCallout("delta", callout_four_error);
  378. getCalloutManager()->callCallouts(delta_index_, getCalloutHandle());
  379. EXPECT_EQ(11223344, callout_value_);
  380. }
  381. // Now test that we can deregister a single callout on a hook.
  382. TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
  383. // Ensure that no callouts are attached to any of the hooks.
  384. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  385. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  386. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  387. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  388. // Add a callout to hook "alpha" and check it is added correctly.
  389. callout_value_ = 0;
  390. getCalloutManager()->setLibraryIndex(0);
  391. getCalloutManager()->registerCallout("alpha", callout_two);
  392. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  393. EXPECT_EQ(2, callout_value_);
  394. // Remove it and check that the no callouts are present. We have to reset
  395. // the current library index here as it was invalidated by the call
  396. // to callCallouts().
  397. getCalloutManager()->setLibraryIndex(0);
  398. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  399. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  400. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  401. }
  402. // Now test that we can deregister a single callout on a hook that has multiple
  403. // callouts from the same library.
  404. TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) {
  405. // Ensure that no callouts are attached to any of the hooks.
  406. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  407. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  408. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  409. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  410. // Add multiple callouts to hook "alpha".
  411. callout_value_ = 0;
  412. getCalloutManager()->setLibraryIndex(0);
  413. getCalloutManager()->registerCallout("alpha", callout_one);
  414. getCalloutManager()->registerCallout("alpha", callout_two);
  415. getCalloutManager()->registerCallout("alpha", callout_three);
  416. getCalloutManager()->registerCallout("alpha", callout_four);
  417. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  418. EXPECT_EQ(1234, callout_value_);
  419. // Remove the callout_two callout. We have to reset the current library
  420. // index here as it was invalidated by the call to callCallouts().
  421. getCalloutManager()->setLibraryIndex(0);
  422. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  423. callout_value_ = 0;
  424. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  425. EXPECT_EQ(134, callout_value_);
  426. // Try removing it again.
  427. getCalloutManager()->setLibraryIndex(0);
  428. EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  429. callout_value_ = 0;
  430. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  431. EXPECT_EQ(134, callout_value_);
  432. }
  433. // Check we can deregister multiple callouts from the same library.
  434. TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
  435. // Ensure that no callouts are attached to any of the hooks.
  436. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  437. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  438. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  439. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  440. // Each library contributes one callout on hook "alpha".
  441. callout_value_ = 0;
  442. getCalloutManager()->setLibraryIndex(0);
  443. getCalloutManager()->registerCallout("alpha", callout_one);
  444. getCalloutManager()->registerCallout("alpha", callout_two);
  445. getCalloutManager()->registerCallout("alpha", callout_one);
  446. getCalloutManager()->registerCallout("alpha", callout_two);
  447. getCalloutManager()->registerCallout("alpha", callout_three);
  448. getCalloutManager()->registerCallout("alpha", callout_four);
  449. getCalloutManager()->registerCallout("alpha", callout_three);
  450. getCalloutManager()->registerCallout("alpha", callout_four);
  451. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  452. EXPECT_EQ(12123434, callout_value_);
  453. // Remove the callout_two callouts. We have to reset the current library
  454. // index here as it was invalidated by the call to callCallouts().
  455. getCalloutManager()->setLibraryIndex(0);
  456. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  457. callout_value_ = 0;
  458. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  459. EXPECT_EQ(113434, callout_value_);
  460. // Try removing multiple callouts that includes one at the end of the
  461. // list of callouts.
  462. getCalloutManager()->setLibraryIndex(0);
  463. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_four));
  464. callout_value_ = 0;
  465. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  466. EXPECT_EQ(1133, callout_value_);
  467. // ... and from the start.
  468. getCalloutManager()->setLibraryIndex(0);
  469. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_one));
  470. callout_value_ = 0;
  471. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  472. EXPECT_EQ(33, callout_value_);
  473. // ... and the remaining callouts.
  474. getCalloutManager()->setLibraryIndex(0);
  475. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_three));
  476. callout_value_ = 0;
  477. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  478. EXPECT_EQ(0, callout_value_);
  479. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  480. }
  481. // Check we can deregister multiple callouts from multiple libraries.
  482. TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) {
  483. // Ensure that no callouts are attached to any of the hooks.
  484. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  485. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  486. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  487. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  488. // Each library contributes two callouts to hook "alpha".
  489. callout_value_ = 0;
  490. getCalloutManager()->setLibraryIndex(0);
  491. getCalloutManager()->registerCallout("alpha", callout_one);
  492. getCalloutManager()->registerCallout("alpha", callout_two);
  493. getCalloutManager()->setLibraryIndex(1);
  494. getCalloutManager()->registerCallout("alpha", callout_three);
  495. getCalloutManager()->registerCallout("alpha", callout_four);
  496. getCalloutManager()->setLibraryIndex(2);
  497. getCalloutManager()->registerCallout("alpha", callout_five);
  498. getCalloutManager()->registerCallout("alpha", callout_two);
  499. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  500. EXPECT_EQ(123452, callout_value_);
  501. // Remove the callout_two callout from library 0. It should not affect
  502. // the second callout_two callout registered by library 2.
  503. getCalloutManager()->setLibraryIndex(0);
  504. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  505. callout_value_ = 0;
  506. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  507. EXPECT_EQ(13452, callout_value_);
  508. }
  509. // Check we can deregister all callouts from a single library.
  510. TEST_F(CalloutManagerTest, DeregisterAllCallouts) {
  511. // Ensure that no callouts are attached to hook one.
  512. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  513. // Each library contributes two callouts to hook "alpha".
  514. callout_value_ = 0;
  515. getCalloutManager()->setLibraryIndex(0);
  516. getCalloutManager()->registerCallout("alpha", callout_one);
  517. getCalloutManager()->registerCallout("alpha", callout_two);
  518. getCalloutManager()->setLibraryIndex(1);
  519. getCalloutManager()->registerCallout("alpha", callout_three);
  520. getCalloutManager()->registerCallout("alpha", callout_four);
  521. getCalloutManager()->setLibraryIndex(2);
  522. getCalloutManager()->registerCallout("alpha", callout_five);
  523. getCalloutManager()->registerCallout("alpha", callout_six);
  524. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  525. EXPECT_EQ(123456, callout_value_);
  526. // Remove all callouts from library index 1.
  527. getCalloutManager()->setLibraryIndex(1);
  528. EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
  529. callout_value_ = 0;
  530. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  531. EXPECT_EQ(1256, callout_value_);
  532. // Remove all callouts from library index 2.
  533. getCalloutManager()->setLibraryIndex(2);
  534. EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
  535. callout_value_ = 0;
  536. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  537. EXPECT_EQ(12, callout_value_);
  538. }
  539. // Check that we can register/deregister callouts on different libraries
  540. // and different hooks, and that the callout instances are regarded as
  541. // unique and do not affect one another.
  542. TEST_F(CalloutManagerTest, MultipleCalloutsLibrariesHooks) {
  543. // Ensure that no callouts are attached to any of the hooks.
  544. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  545. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  546. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  547. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  548. // Register callouts on the alpha hook.
  549. callout_value_ = 0;
  550. getCalloutManager()->setLibraryIndex(0);
  551. getCalloutManager()->registerCallout("alpha", callout_one);
  552. getCalloutManager()->registerCallout("alpha", callout_two);
  553. getCalloutManager()->setLibraryIndex(1);
  554. getCalloutManager()->registerCallout("alpha", callout_three);
  555. getCalloutManager()->registerCallout("alpha", callout_four);
  556. getCalloutManager()->setLibraryIndex(2);
  557. getCalloutManager()->registerCallout("alpha", callout_five);
  558. getCalloutManager()->registerCallout("alpha", callout_two);
  559. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  560. EXPECT_EQ(123452, callout_value_);
  561. // Register the same callouts on the beta hook, and check that those
  562. // on the alpha hook are not affected.
  563. callout_value_ = 0;
  564. getCalloutManager()->setLibraryIndex(0);
  565. getCalloutManager()->registerCallout("beta", callout_five);
  566. getCalloutManager()->registerCallout("beta", callout_one);
  567. getCalloutManager()->setLibraryIndex(2);
  568. getCalloutManager()->registerCallout("beta", callout_four);
  569. getCalloutManager()->registerCallout("beta", callout_three);
  570. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  571. EXPECT_EQ(5143, callout_value_);
  572. // Check that the order of callouts on the alpha hook has not been affected.
  573. callout_value_ = 0;
  574. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  575. EXPECT_EQ(123452, callout_value_);
  576. // Remove callout four from beta and check that alpha is not affected.
  577. getCalloutManager()->setLibraryIndex(2);
  578. EXPECT_TRUE(getCalloutManager()->deregisterCallout("beta", callout_four));
  579. callout_value_ = 0;
  580. getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
  581. EXPECT_EQ(513, callout_value_);
  582. callout_value_ = 0;
  583. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  584. EXPECT_EQ(123452, callout_value_);
  585. }
  586. // Library handle tests. As by inspection the LibraryHandle can be seen to be
  587. // little more than shell around CalloutManager, only a basic set of tests
  588. // is done concerning registration and deregistration of functions.
  589. //
  590. // More extensive tests (i.e. checking that when a callout is called it can
  591. // only register and deregister callouts within its library) require that
  592. // the CalloutHandle object pass the appropriate LibraryHandle to the
  593. // callout. These tests are done in the handles_unittest tests.
  594. TEST_F(CalloutManagerTest, LibraryHandleRegistration) {
  595. // Ensure that no callouts are attached to any of the hooks.
  596. EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
  597. // Set up so that hooks "alpha" and "beta" have callouts attached from a
  598. // different libraries.
  599. getCalloutManager()->setLibraryIndex(0);
  600. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  601. callout_one);
  602. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  603. callout_two);
  604. getCalloutManager()->setLibraryIndex(1);
  605. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  606. callout_three);
  607. getCalloutManager()->getLibraryHandle().registerCallout("alpha",
  608. callout_four);
  609. // Check all is as expected.
  610. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
  611. EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
  612. EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
  613. EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
  614. // Check that calling the callouts returns as expected. (This is also a
  615. // test of the callCallouts method.)
  616. callout_value_ = 0;
  617. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  618. EXPECT_EQ(1234, callout_value_);
  619. // Deregister a callout on library index 0 (after we check we can't
  620. // deregister it through library index 1).
  621. getCalloutManager()->setLibraryIndex(1);
  622. EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  623. callout_value_ = 0;
  624. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  625. EXPECT_EQ(1234, callout_value_);
  626. getCalloutManager()->setLibraryIndex(0);
  627. EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
  628. callout_value_ = 0;
  629. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  630. EXPECT_EQ(134, callout_value_);
  631. // Deregister all callouts on library index 1.
  632. getCalloutManager()->setLibraryIndex(1);
  633. EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
  634. callout_value_ = 0;
  635. getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
  636. EXPECT_EQ(1, callout_value_);
  637. }
  638. // The setting of the hook index is checked in the handles_unittest
  639. // set of tests, as access restrictions mean it is not easily tested
  640. // on its own.
  641. } // Anonymous namespace