callout_handle_unittest.cc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // Copyright (C) 2013,2015 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 <hooks/callout_handle.h>
  15. #include <hooks/callout_manager.h>
  16. #include <hooks/library_handle.h>
  17. #include <hooks/server_hooks.h>
  18. #include <boost/shared_ptr.hpp>
  19. #include <gtest/gtest.h>
  20. using namespace isc::hooks;
  21. using namespace std;
  22. namespace {
  23. /// @file
  24. /// @brief Holds the CalloutHandle argument tests
  25. ///
  26. /// Additional testing of the CalloutHandle - together with the interaction
  27. /// of the LibraryHandle - is done in the handles_unittests set of tests.
  28. class CalloutHandleTest : public ::testing::Test {
  29. public:
  30. /// @brief Constructor
  31. ///
  32. /// Sets up a callout manager to be referenced by the CalloutHandle in
  33. /// these tests. (The "4" for the number of libraries in the
  34. /// CalloutManager is arbitrary - it is not used in these tests.)
  35. CalloutHandleTest() : manager_(new CalloutManager(4))
  36. {}
  37. /// Obtain hook manager
  38. boost::shared_ptr<CalloutManager>& getCalloutManager() {
  39. return (manager_);
  40. }
  41. private:
  42. /// Callout manager accessed by this CalloutHandle.
  43. boost::shared_ptr<CalloutManager> manager_;
  44. };
  45. // *** Argument Tests ***
  46. //
  47. // The first set of tests check that the CalloutHandle can store and retrieve
  48. // arguments. These are very similar to the LibraryHandle context tests.
  49. // Test that we can store multiple values of the same type and that they
  50. // are distinct.
  51. TEST_F(CalloutHandleTest, ArgumentDistinctSimpleType) {
  52. CalloutHandle handle(getCalloutManager());
  53. // Store and retrieve an int (random value).
  54. int a = 42;
  55. handle.setArgument("integer1", a);
  56. EXPECT_EQ(42, a);
  57. int b = 0;
  58. handle.getArgument("integer1", b);
  59. EXPECT_EQ(42, b);
  60. // Add another integer (another random value).
  61. int c = 142;
  62. handle.setArgument("integer2", c);
  63. EXPECT_EQ(142, c);
  64. int d = 0;
  65. handle.getArgument("integer2", d);
  66. EXPECT_EQ(142, d);
  67. // Add a short (random value).
  68. short e = -81;
  69. handle.setArgument("short", e);
  70. EXPECT_EQ(-81, e);
  71. short f = 0;
  72. handle.getArgument("short", f);
  73. EXPECT_EQ(-81, f);
  74. }
  75. // Test that trying to get an unknown argument throws an exception.
  76. TEST_F(CalloutHandleTest, ArgumentUnknownName) {
  77. CalloutHandle handle(getCalloutManager());
  78. // Set an integer
  79. int a = 42;
  80. handle.setArgument("integer1", a);
  81. EXPECT_EQ(42, a);
  82. // Check we can retrieve it
  83. int b = 0;
  84. handle.getArgument("integer1", b);
  85. EXPECT_EQ(42, b);
  86. // Check that getting an unknown name throws an exception.
  87. int c = 0;
  88. EXPECT_THROW(handle.getArgument("unknown", c), NoSuchArgument);
  89. }
  90. // Test that trying to get an argument with an incorrect type throws an
  91. // exception.
  92. TEST_F(CalloutHandleTest, ArgumentIncorrectType) {
  93. CalloutHandle handle(getCalloutManager());
  94. // Set an integer
  95. int a = 42;
  96. handle.setArgument("integer1", a);
  97. EXPECT_EQ(42, a);
  98. // Check we can retrieve it
  99. long b = 0;
  100. EXPECT_THROW(handle.getArgument("integer1", b), boost::bad_any_cast);
  101. }
  102. // Now try with some very complex types. The types cannot be defined within
  103. // the function and they should contain a copy constructor. For this reason,
  104. // a simple "struct" is used.
  105. struct Alpha {
  106. int a;
  107. int b;
  108. Alpha(int first = 0, int second = 0) : a(first), b(second) {}
  109. };
  110. struct Beta {
  111. int c;
  112. int d;
  113. Beta(int first = 0, int second = 0) : c(first), d(second) {}
  114. };
  115. TEST_F(CalloutHandleTest, ComplexTypes) {
  116. CalloutHandle handle(getCalloutManager());
  117. // Declare two variables of different (complex) types. (Note as to the
  118. // variable names: aleph and beth are the first two letters of the Hebrew
  119. // alphabet.)
  120. Alpha aleph(1, 2);
  121. EXPECT_EQ(1, aleph.a);
  122. EXPECT_EQ(2, aleph.b);
  123. handle.setArgument("aleph", aleph);
  124. Beta beth(11, 22);
  125. EXPECT_EQ(11, beth.c);
  126. EXPECT_EQ(22, beth.d);
  127. handle.setArgument("beth", beth);
  128. // Ensure we can extract the data correctly.
  129. Alpha aleph2;
  130. EXPECT_EQ(0, aleph2.a);
  131. EXPECT_EQ(0, aleph2.b);
  132. handle.getArgument("aleph", aleph2);
  133. EXPECT_EQ(1, aleph2.a);
  134. EXPECT_EQ(2, aleph2.b);
  135. Beta beth2;
  136. EXPECT_EQ(0, beth2.c);
  137. EXPECT_EQ(0, beth2.d);
  138. handle.getArgument("beth", beth2);
  139. EXPECT_EQ(11, beth2.c);
  140. EXPECT_EQ(22, beth2.d);
  141. // Ensure that complex types also thrown an exception if we attempt to
  142. // get a context element of the wrong type.
  143. EXPECT_THROW(handle.getArgument("aleph", beth), boost::bad_any_cast);
  144. }
  145. // Check that the context can store pointers. And also check that it respects
  146. // that a "pointer to X" is not the same as a "pointer to const X".
  147. TEST_F(CalloutHandleTest, PointerTypes) {
  148. CalloutHandle handle(getCalloutManager());
  149. // Declare a couple of variables, const and non-const.
  150. Alpha aleph(5, 10);
  151. const Beta beth(15, 20);
  152. Alpha* pa = &aleph;
  153. const Beta* pcb = &beth;
  154. // Check pointers can be set and retrieved OK.
  155. handle.setArgument("non_const_pointer", pa);
  156. handle.setArgument("const_pointer", pcb);
  157. Alpha* pa2 = 0;
  158. handle.getArgument("non_const_pointer", pa2);
  159. EXPECT_TRUE(pa == pa2);
  160. const Beta* pcb2 = 0;
  161. handle.getArgument("const_pointer", pcb2);
  162. EXPECT_TRUE(pcb == pcb2);
  163. // Check that the "const" is protected in the context.
  164. const Alpha* pca3;
  165. EXPECT_THROW(handle.getArgument("non_const_pointer", pca3),
  166. boost::bad_any_cast);
  167. Beta* pb3;
  168. EXPECT_THROW(handle.getArgument("const_pointer", pb3),
  169. boost::bad_any_cast);
  170. }
  171. // Check that we can get the names of the arguments.
  172. TEST_F(CalloutHandleTest, ContextItemNames) {
  173. CalloutHandle handle(getCalloutManager());
  174. vector<string> expected_names;
  175. expected_names.push_back("faith");
  176. handle.setArgument("faith", 42);
  177. expected_names.push_back("hope");
  178. handle.setArgument("hope", 43);
  179. expected_names.push_back("charity");
  180. handle.setArgument("charity", 44);
  181. // Get the names and check against the expected names. We'll sort
  182. // both arrays to simplify the checking.
  183. vector<string> actual_names = handle.getArgumentNames();
  184. sort(actual_names.begin(), actual_names.end());
  185. sort(expected_names.begin(), expected_names.end());
  186. EXPECT_TRUE(expected_names == actual_names);
  187. }
  188. // Test that we can delete an argument.
  189. TEST_F(CalloutHandleTest, DeleteArgument) {
  190. CalloutHandle handle(getCalloutManager());
  191. int one = 1;
  192. int two = 2;
  193. int three = 3;
  194. int four = 4;
  195. int value; // Return value
  196. handle.setArgument("one", one);
  197. handle.setArgument("two", two);
  198. handle.setArgument("three", three);
  199. handle.setArgument("four", four);
  200. // Delete "one".
  201. handle.getArgument("one", value);
  202. EXPECT_EQ(1, value);
  203. handle.deleteArgument("one");
  204. EXPECT_THROW(handle.getArgument("one", value), NoSuchArgument);
  205. handle.getArgument("two", value);
  206. EXPECT_EQ(2, value);
  207. handle.getArgument("three", value);
  208. EXPECT_EQ(3, value);
  209. handle.getArgument("four", value);
  210. EXPECT_EQ(4, value);
  211. // Delete "three".
  212. handle.getArgument("three", value);
  213. EXPECT_EQ(3, value);
  214. handle.deleteArgument("three");
  215. EXPECT_THROW(handle.getArgument("one", value), NoSuchArgument);
  216. handle.getArgument("two", value);
  217. EXPECT_EQ(2, value);
  218. EXPECT_THROW(handle.getArgument("three", value), NoSuchArgument);
  219. handle.getArgument("four", value);
  220. EXPECT_EQ(4, value);
  221. }
  222. // Test that we can delete all arguments.
  223. TEST_F(CalloutHandleTest, DeleteAllArguments) {
  224. CalloutHandle handle(getCalloutManager());
  225. int one = 1;
  226. int two = 2;
  227. int three = 3;
  228. int four = 4;
  229. int value; // Return value
  230. // Set the arguments. The previous test verifies that this works.
  231. handle.setArgument("one", one);
  232. handle.setArgument("two", two);
  233. handle.setArgument("three", three);
  234. handle.setArgument("four", four);
  235. // Delete all arguments...
  236. handle.deleteAllArguments();
  237. // ... and check that none are left.
  238. EXPECT_THROW(handle.getArgument("one", value), NoSuchArgument);
  239. EXPECT_THROW(handle.getArgument("two", value), NoSuchArgument);
  240. EXPECT_THROW(handle.getArgument("three", value), NoSuchArgument);
  241. EXPECT_THROW(handle.getArgument("four", value), NoSuchArgument);
  242. }
  243. // Test the "status" field.
  244. TEST_F(CalloutHandleTest, StatusField) {
  245. CalloutHandle handle(getCalloutManager());
  246. // Should be false on construction.
  247. EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, handle.getStatus());
  248. handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  249. EXPECT_EQ(CalloutHandle::NEXT_STEP_SKIP, handle.getStatus());
  250. handle.setStatus(CalloutHandle::NEXT_STEP_DROP);
  251. EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, handle.getStatus());
  252. handle.setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
  253. EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, handle.getStatus());
  254. }
  255. // Further tests of the "skip" flag and tests of getting the name of the
  256. // hook to which the current callout is attached is in the "handles_unittest"
  257. // module.
  258. } // Anonymous namespace