library_handle_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  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 <util/hooks/library_handle.h>
  15. #include <util/hooks/server_hooks.h>
  16. #include <gtest/gtest.h>
  17. using namespace isc::util;
  18. using namespace std;
  19. // Dummy class for testing
  20. namespace isc {
  21. namespace util {
  22. class CalloutHandle {};
  23. }
  24. }
  25. namespace {
  26. class LibraryHandleTest : public ::testing::Test {
  27. public:
  28. /// @brief Constructor
  29. ///
  30. /// Sets up an appropriate number of server hooks to pass to the
  31. /// constructed callout handle objects.
  32. LibraryHandleTest() : hooks_(new ServerHooks()) {
  33. hooks_->registerHook("alpha");
  34. hooks_->registerHook("beta");
  35. hooks_->registerHook("gamma");
  36. // Also initialize the callout variables.
  37. one_count = 0;
  38. two_count = 0;
  39. callout_value = 0;
  40. }
  41. /// Obtain constructed server hooks
  42. boost::shared_ptr<ServerHooks> getServerHooks() {
  43. return (hooks_);
  44. }
  45. /// Variables for callouts test. These are public and static to allow non-
  46. /// member functions to access them, but declared as class variables to
  47. /// allow initialization every time the test starts.
  48. static int one_count;
  49. static int two_count;
  50. static int callout_value;
  51. private:
  52. boost::shared_ptr<ServerHooks> hooks_;
  53. };
  54. // Definition of the static variables.
  55. int LibraryHandleTest::one_count = 0;
  56. int LibraryHandleTest::two_count = 0;
  57. int LibraryHandleTest::callout_value = 0;
  58. // *** Context Tests ***
  59. //
  60. // The first set of tests check that the LibraryHandle can store and retrieve
  61. // context.
  62. // Test that we can store multiple values of the same type and that they
  63. // are distinct.
  64. TEST_F(LibraryHandleTest, ContextDistinctSimpleType) {
  65. LibraryHandle handle(getServerHooks(), 1);
  66. // Store and retrieve an int (random value).
  67. int a = 42;
  68. handle.setContext("integer1", a);
  69. EXPECT_EQ(42, a);
  70. int b = 0;
  71. handle.getContext("integer1", b);
  72. EXPECT_EQ(42, b);
  73. // Add another integer (another random value).
  74. int c = 142;
  75. handle.setContext("integer2", c);
  76. EXPECT_EQ(142, c);
  77. int d = -1;
  78. handle.getContext("integer2", d);
  79. EXPECT_EQ(142, d);
  80. // Add a short (random value).
  81. short e = 81;
  82. handle.setContext("short", e);
  83. EXPECT_EQ(81, e);
  84. short f = -1;
  85. handle.getContext("short", f);
  86. EXPECT_EQ(81, f);
  87. }
  88. // Test that trying to get something with an incorrect name throws an
  89. // exception.
  90. TEST_F(LibraryHandleTest, ContextUnknownName) {
  91. LibraryHandle handle(getServerHooks(), 1);
  92. // Set an integer
  93. int a = 42;
  94. handle.setContext("integer1", a);
  95. EXPECT_EQ(42, a);
  96. // Check we can retrieve it
  97. int b = 0;
  98. handle.getContext("integer1", b);
  99. EXPECT_EQ(42, b);
  100. // Check that getting an unknown name throws an exception.
  101. int c = -1;
  102. EXPECT_THROW(handle.getContext("unknown", c), NoSuchContext);
  103. }
  104. // Test that trying to get something with an incorrect type throws an exception.
  105. TEST_F(LibraryHandleTest, ContextIncorrectType) {
  106. LibraryHandle handle(getServerHooks(), 1);
  107. // Set an integer
  108. int a = 42;
  109. handle.setContext("integer1", a);
  110. EXPECT_EQ(42, a);
  111. // Check we can retrieve it
  112. long b = 0;
  113. EXPECT_THROW(handle.getContext("integer1", b), boost::bad_any_cast);
  114. }
  115. // Now try with some very complex types. The types cannot be defined within
  116. // the function and they should contain a copy constructor. For this reason,
  117. // a simple "struct" is used.
  118. struct Alpha {
  119. int a;
  120. int b;
  121. Alpha(int first = 0, int second = 0) : a(first), b(second) {}
  122. };
  123. struct Beta {
  124. int c;
  125. int d;
  126. Beta(int first = 0, int second = 0) : c(first), d(second) {}
  127. };
  128. TEST_F(LibraryHandleTest, ComplexTypes) {
  129. LibraryHandle handle(getServerHooks(), 1);
  130. // Declare two variables of different (complex) types. (Note as to the
  131. // variable names: aleph and beth are the first two letters of the Hebrew
  132. // alphabet.)
  133. Alpha aleph(1, 2);
  134. EXPECT_EQ(1, aleph.a);
  135. EXPECT_EQ(2, aleph.b);
  136. handle.setContext("aleph", aleph);
  137. Beta beth(11, 22);
  138. EXPECT_EQ(11, beth.c);
  139. EXPECT_EQ(22, beth.d);
  140. handle.setContext("beth", beth);
  141. // Ensure we can extract the data correctly
  142. Alpha aleph2;
  143. EXPECT_EQ(0, aleph2.a);
  144. EXPECT_EQ(0, aleph2.b);
  145. handle.getContext("aleph", aleph2);
  146. EXPECT_EQ(1, aleph2.a);
  147. EXPECT_EQ(2, aleph2.b);
  148. Beta beth2;
  149. EXPECT_EQ(0, beth2.c);
  150. EXPECT_EQ(0, beth2.d);
  151. handle.getContext("beth", beth2);
  152. EXPECT_EQ(11, beth2.c);
  153. EXPECT_EQ(22, beth2.d);
  154. // Ensure that complex types also thrown an exception if we attempt to
  155. // get a context element of the wrong type.
  156. EXPECT_THROW(handle.getContext("aleph", beth), boost::bad_any_cast);
  157. }
  158. // Check that the context can store pointers. And also check that it respects
  159. // that a "pointer to X" is not the same as a "pointer to const X".
  160. TEST_F(LibraryHandleTest, PointerTypes) {
  161. LibraryHandle handle(getServerHooks(), 1);
  162. // Declare a couple of variables, const and non-const.
  163. Alpha aleph(5, 10);
  164. const Beta beth(15, 20);
  165. Alpha* pa = &aleph;
  166. const Beta* pcb = &beth;
  167. // Check pointers can be set and retrieved OK
  168. handle.setContext("non_const_pointer", pa);
  169. handle.setContext("const_pointer", pcb);
  170. Alpha* pa2 = 0;
  171. handle.getContext("non_const_pointer", pa2);
  172. EXPECT_TRUE(pa == pa2);
  173. const Beta* pcb2 = 0;
  174. handle.getContext("const_pointer", pcb2);
  175. EXPECT_TRUE(pcb == pcb2);
  176. // Check that the "const" is protected in the context.
  177. const Alpha* pca3;
  178. EXPECT_THROW(handle.getContext("non_const_pointer", pca3),
  179. boost::bad_any_cast);
  180. Beta* pb3;
  181. EXPECT_THROW(handle.getContext("const_pointer", pb3),
  182. boost::bad_any_cast);
  183. }
  184. // *** Callout Tests ***
  185. //
  186. // The next set of tests check that callouts can be registered.
  187. // Supply callouts structured in such a way that we can determine the order
  188. // that they are called and whether they are called at all. In particular
  189. // if the callout order is:
  190. //
  191. // * one followed by two, the resulting value is 20
  192. // * two followed by one, the resuling value is -10
  193. // * one and two is not called, the resulting value is 10
  194. // * two and one is not called, the resulting value is -20
  195. // * neither called, the resulting value is 0
  196. //
  197. // The variable xxx_count is the number of times the function has been called
  198. // in the current test.
  199. extern "C" {
  200. int one(CalloutHandle&) {
  201. ++LibraryHandleTest::one_count;
  202. if (LibraryHandleTest::callout_value == 0) {
  203. LibraryHandleTest::callout_value = 10;
  204. } else {
  205. LibraryHandleTest::callout_value = -10;
  206. }
  207. return (0);
  208. }
  209. int two(CalloutHandle&) {
  210. ++LibraryHandleTest::two_count;
  211. if (LibraryHandleTest::callout_value == 10) {
  212. LibraryHandleTest::callout_value = 20;
  213. } else {
  214. LibraryHandleTest::callout_value = -20;
  215. }
  216. return (0);
  217. }
  218. // The next function is a duplicate of "one", but returns an error status.
  219. int one_error(CalloutHandle& handle) {
  220. (void) one(handle);
  221. return (1);
  222. }
  223. }; // extern "C"
  224. // Check that we can register callouts on a particular hook.
  225. TEST_F(LibraryHandleTest, RegisterSingleCallout) {
  226. LibraryHandle handle(getServerHooks(), 1);
  227. // Register callouts for hooks alpha and see that it is registered.
  228. EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
  229. handle.registerCallout("alpha", one);
  230. EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
  231. // Do the same for beta (which checks that the hooks are independent).
  232. EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("beta")));
  233. handle.registerCallout("beta", one);
  234. EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("beta")));
  235. }
  236. // Check that we can call a single callout on a particular hook. Refer
  237. // to the above definition of the callouts "one" and "two" to understand
  238. // the expected return values.
  239. TEST_F(LibraryHandleTest, CallSingleCallout) {
  240. LibraryHandle handle(getServerHooks(), 1);
  241. // Register callout for hook alpha...
  242. EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
  243. handle.registerCallout("alpha", one);
  244. EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
  245. // Call it.
  246. EXPECT_EQ(0, LibraryHandleTest::one_count);
  247. EXPECT_EQ(0, LibraryHandleTest::two_count);
  248. EXPECT_EQ(0, LibraryHandleTest::callout_value);
  249. int index = getServerHooks()->getIndex("alpha");
  250. CalloutHandle dummy;
  251. int status = handle.callCallouts(index, dummy);
  252. EXPECT_EQ(0, status);
  253. EXPECT_EQ(1, LibraryHandleTest::one_count);
  254. EXPECT_EQ(0, LibraryHandleTest::two_count);
  255. EXPECT_EQ(10, LibraryHandleTest::callout_value);
  256. }
  257. // Check that we can register two callouts for a hook and that they are called
  258. // in order.
  259. TEST_F(LibraryHandleTest, TwoCallouts) {
  260. LibraryHandle handle(getServerHooks(), 1);
  261. // Register two callouts for hook alpha...
  262. handle.registerCallout("alpha", one);
  263. handle.registerCallout("alpha", two);
  264. // ... and call them.
  265. EXPECT_EQ(0, LibraryHandleTest::one_count);
  266. EXPECT_EQ(0, LibraryHandleTest::two_count);
  267. EXPECT_EQ(0, LibraryHandleTest::callout_value);
  268. int index = getServerHooks()->getIndex("alpha");
  269. CalloutHandle dummy;
  270. int status = handle.callCallouts(index, dummy);
  271. EXPECT_EQ(0, status);
  272. EXPECT_EQ(1, LibraryHandleTest::one_count);
  273. EXPECT_EQ(1, LibraryHandleTest::two_count);
  274. EXPECT_EQ(20, LibraryHandleTest::callout_value);
  275. }
  276. // Check that we can register two callouts for a hook and that the second is not
  277. // called if the first returns a non-zero status.
  278. TEST_F(LibraryHandleTest, TwoCalloutsWithError) {
  279. LibraryHandle handle(getServerHooks(), 1);
  280. // Register callout for hook alpha...
  281. handle.registerCallout("alpha", one_error);
  282. handle.registerCallout("alpha", two);
  283. // Call them.
  284. EXPECT_EQ(0, LibraryHandleTest::one_count);
  285. EXPECT_EQ(0, LibraryHandleTest::two_count);
  286. EXPECT_EQ(0, LibraryHandleTest::callout_value);
  287. int index = getServerHooks()->getIndex("alpha");
  288. CalloutHandle dummy;
  289. int status = handle.callCallouts(index, dummy);
  290. EXPECT_EQ(1, status);
  291. EXPECT_EQ(1, LibraryHandleTest::one_count);
  292. EXPECT_EQ(0, LibraryHandleTest::two_count);
  293. EXPECT_EQ(10, LibraryHandleTest::callout_value);
  294. }
  295. // Check that a callout can be registered more than once.
  296. TEST_F(LibraryHandleTest, MultipleRegistration) {
  297. LibraryHandle handle(getServerHooks(), 1);
  298. // Register callouts for hook alpha...
  299. handle.registerCallout("alpha", one);
  300. handle.registerCallout("alpha", two);
  301. handle.registerCallout("alpha", one);
  302. // Call them.
  303. EXPECT_EQ(0, LibraryHandleTest::one_count);
  304. EXPECT_EQ(0, LibraryHandleTest::two_count);
  305. EXPECT_EQ(0, LibraryHandleTest::callout_value);
  306. int index = getServerHooks()->getIndex("alpha");
  307. CalloutHandle dummy;
  308. int status = handle.callCallouts(index, dummy);
  309. EXPECT_EQ(0, status);
  310. EXPECT_EQ(2, LibraryHandleTest::one_count);
  311. EXPECT_EQ(1, LibraryHandleTest::two_count);
  312. EXPECT_EQ(-10, LibraryHandleTest::callout_value);
  313. }
  314. // Check that a callout can be deregistered.
  315. TEST_F(LibraryHandleTest, Degreister) {
  316. LibraryHandle handle(getServerHooks(), 1);
  317. // Register callouts for hook alpha...
  318. handle.registerCallout("alpha", one);
  319. handle.registerCallout("alpha", two);
  320. handle.registerCallout("alpha", one);
  321. // Get rid of all the "one" callbacks.
  322. handle.deregisterCallout("alpha", one);
  323. // Call it.
  324. EXPECT_EQ(0, LibraryHandleTest::one_count);
  325. EXPECT_EQ(0, LibraryHandleTest::two_count);
  326. EXPECT_EQ(0, LibraryHandleTest::callout_value);
  327. int index = getServerHooks()->getIndex("alpha");
  328. CalloutHandle dummy;
  329. int status = handle.callCallouts(index, dummy);
  330. EXPECT_EQ(0, status);
  331. EXPECT_EQ(0, LibraryHandleTest::one_count);
  332. EXPECT_EQ(1, LibraryHandleTest::two_count);
  333. EXPECT_EQ(-20, LibraryHandleTest::callout_value);
  334. }
  335. // Check that all callouts can be deregistered.
  336. TEST_F(LibraryHandleTest, DeregisterAll) {
  337. LibraryHandle handle(getServerHooks(), 1);
  338. // Register callouts for hook alpha...
  339. EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
  340. handle.registerCallout("alpha", one);
  341. handle.registerCallout("alpha", two);
  342. EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
  343. // ... and remove them.
  344. handle.deregisterAll("alpha");
  345. EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
  346. }
  347. } // Anonymous namespace