handles_unittest.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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/callout_handle.h>
  15. #include <util/hooks/library_handle.h>
  16. #include <util/hooks/server_hooks.h>
  17. #include <boost/lexical_cast.hpp>
  18. #include <gtest/gtest.h>
  19. #include <algorithm>
  20. #include <string>
  21. /// @file
  22. /// CalloutHandle/LibraryCalloutHandle interaction tests
  23. ///
  24. /// This file holds unit tests checking the interaction between the
  25. /// CalloutHandle and LibraryCalloutHandle[Collection] classes. In particular,
  26. /// they check that:
  27. ///
  28. /// - A CalloutHandle's context is shared between callouts from the same
  29. /// library, but there is a separate context for each library.
  30. ///
  31. /// - The LibraryHandle retrieved by the CalloutHandle is the same for each
  32. /// callout in the library, but different for different libraries.
  33. ///
  34. /// - The various methods manipulating the items in the CalloutHandle's context
  35. /// work correctly.
  36. ///
  37. /// Some minor interactions between the two classes are checked in the unit
  38. /// tests for each class (mainly the use of the "skip" flag).
  39. using namespace isc::util;
  40. using namespace std;
  41. namespace {
  42. // The next set of functions define the callouts used by the tests. They
  43. // manipulate the data in such a way that callouts called - and the order in
  44. // which they were called - can be determined. The functions also check that
  45. // the "callout context" and "library context" data areas are separate.
  46. //
  47. // Three libraries are assumed, and each supplies four callouts. All callouts
  48. // manipulate four context elements - two in the CalloutHandle and two in the
  49. // LibraryHandle, the elements being called "string" and "int" (which describe
  50. // the type of data manipulated).
  51. //
  52. // For the string item, each callout shifts data to the left and inserts its own
  53. // data. The aata is a string of the form "nmwc", where "n" is the number of
  54. // the library, "m" is the callout number and "w" is an indication of what is
  55. // being altered (library context ["x"] or callout context ["c"]) and "y" is the
  56. // indication of what callout was passed as an argument ("x" or "b"). ("x" is
  57. // used instead of "l" to indicate that library context is being altered since
  58. // in the results, these single characters will be mixed with digits and "l"
  59. // " looks too much like "1".) Hence we have:
  60. //
  61. // - "xa" if library context is being altered from a callout made with the
  62. // first callout handle passed as argument.
  63. // - "xb" if library context is being altered from a callout made with the
  64. // second callout handle passed as argument.
  65. // - "ca" if the first callout handle's context is being manipulated.
  66. // - "cb" if the second callout handle's context is being manipulated.
  67. //
  68. // For simplicity, and to cut down the number of functions actually written,
  69. // the callout indicator ("a" or "b") ) used in the in the CalloutHandle
  70. // functions is passed via a CalloutArgument. The argument is named "string":
  71. // use of a name the same as that of one of the context elements serves as a
  72. // check that the argument name space and argument context space are separate.
  73. //
  74. // For integer data, the value starts at zero and an increment is added on each
  75. // call. This increment is equal to:
  76. //
  77. // 1000 * library number + 100 * callout_number + 10 * lib/callout + indicator
  78. //
  79. // where "lib/callout" is 1 if a library context is updated and 2 if a
  80. // a callout context is changed. "indicator" is 1 for callout a and 2 for
  81. // callout b. This scheme gives a direct correspondence between the characters
  82. // appended to the string context item and the amount by which the integers
  83. // context item is incremented. For example, the string "21cb" corresponds to
  84. // a value of 2122.
  85. //
  86. // Although this gives less information than the string value, the reasons for
  87. // using it are:
  88. //
  89. // - It is a separate item in the context, so checks that the context can
  90. // handle multiple items.
  91. // - It provides an item that can be deleted by the context deletion
  92. // methods.
  93. // Values set in the LibraryHandle context. There are three libraries, so
  94. // there are three sets of library context. To avoid a static initialization
  95. // fiasco, encapsulate these in a function.
  96. std::string& resultLibraryString(int index) {
  97. static std::string result_library_string[3];
  98. return (result_library_string[index]);
  99. }
  100. int& resultLibraryInt(int index) {
  101. static int result_library_int[3];
  102. return (result_library_int[index]);
  103. }
  104. // Values set in the CalloutHandle context. There are three libraries, so
  105. // there are three contexts for the callout, one for each library.
  106. std::string& resultCalloutString(int index) {
  107. static std::string result_callout_string[3];
  108. return (result_callout_string[index]);
  109. }
  110. int& resultCalloutInt(int index) {
  111. static int result_callout_int[3];
  112. return (result_callout_int[index]);
  113. }
  114. // A simple function to zero the results.
  115. static void zero_results() {
  116. for (int i = 0; i < 3; ++i) {
  117. resultLibraryString(i) = "";
  118. resultLibraryInt(i) = 0;
  119. resultCalloutString(i) = "";
  120. resultCalloutInt(i) = 0;
  121. }
  122. }
  123. // Library callouts.
  124. // Common code for setting the callout and library context values.
  125. int
  126. execute(CalloutHandle& callout_handle, int library_num, int callout_num) {
  127. // Obtain the callout handle indicator.
  128. string indicator;
  129. callout_handle.getArgument("string", indicator);
  130. // Create the basic data to be appended to the context value.
  131. int idata = 1000 * library_num + 100 * callout_num;
  132. string sdata = boost::lexical_cast<string>(10 * library_num + callout_num);
  133. // Get the library context data. As the context will not exist on the
  134. // first call, catch the exception and create it. (In real life, the context
  135. // should have been created by the libraries' "load()" function.)
  136. string string_value = "";
  137. try {
  138. callout_handle.getLibraryHandle().getContext("string", string_value);
  139. } catch (const NoSuchLibraryContext&) {
  140. string_value = "";
  141. }
  142. int int_value = 0;
  143. try {
  144. callout_handle.getLibraryHandle().getContext("int", int_value);
  145. } catch (const NoSuchLibraryContext&) {
  146. int_value = 0;
  147. }
  148. // Update the context value with the library/callout indication (and the
  149. // suffix "x" to denote library) and set it.
  150. string_value += (sdata + string("x") + indicator);
  151. callout_handle.getLibraryHandle().setContext("string", string_value);
  152. int_value += (idata + 10 + (indicator == "a" ? 1 : 2));
  153. callout_handle.getLibraryHandle().setContext("int", int_value);
  154. // Get the context data. As before, this will not exist for the first
  155. // callout called. (In real life, the library should create it when the
  156. // "context_create" hook gets called before any packet processing takes
  157. // place.)
  158. string_value = "";
  159. try {
  160. callout_handle.getContext("string", string_value);
  161. } catch (const NoSuchCalloutContext&) {
  162. string_value = "";
  163. }
  164. int_value = 0;
  165. try {
  166. callout_handle.getContext("int", int_value);
  167. } catch (const NoSuchCalloutContext&) {
  168. int_value = 0;
  169. }
  170. // Update the values and set them.
  171. string_value += (sdata + string("c") + indicator);
  172. callout_handle.setContext("string", string_value);
  173. int_value += (idata + 20 + (indicator == "a" ? 1 : 2));
  174. callout_handle.setContext("int", int_value);
  175. return (0);
  176. }
  177. // The following functions are the actual callouts - ther name is of the
  178. // form "callout_<library number>_<callout number>"
  179. int
  180. callout11(CalloutHandle& callout_handle) {
  181. return (execute(callout_handle, 1, 1));
  182. }
  183. int
  184. callout12(CalloutHandle& callout_handle) {
  185. return (execute(callout_handle, 1, 2));
  186. }
  187. int
  188. callout13(CalloutHandle& callout_handle) {
  189. return (execute(callout_handle, 1, 3));
  190. }
  191. int
  192. callout21(CalloutHandle& callout_handle) {
  193. return (execute(callout_handle, 2, 1));
  194. }
  195. int
  196. callout22(CalloutHandle& callout_handle) {
  197. return (execute(callout_handle, 2, 2));
  198. }
  199. int
  200. callout23(CalloutHandle& callout_handle) {
  201. return (execute(callout_handle, 2, 3));
  202. }
  203. int
  204. callout31(CalloutHandle& callout_handle) {
  205. return (execute(callout_handle, 3, 1));
  206. }
  207. int
  208. callout32(CalloutHandle& callout_handle) {
  209. return (execute(callout_handle, 3, 2));
  210. }
  211. int
  212. callout33(CalloutHandle& callout_handle) {
  213. return (execute(callout_handle, 3, 3));
  214. }
  215. // Common callout code for the fourth hook (which makes the data available for
  216. // checking). It copies the library and callout context data to the global
  217. // variables.
  218. int printExecute(CalloutHandle& callout_handle, int library_num) {
  219. // Print per-library context values.
  220. callout_handle.getLibraryHandle()
  221. .getContext("string", resultLibraryString(library_num - 1));
  222. callout_handle.getLibraryHandle()
  223. .getContext("int", resultLibraryInt(library_num - 1));
  224. // Print callout context.
  225. callout_handle.getContext("string", resultCalloutString(library_num - 1));
  226. callout_handle.getContext("int", resultCalloutInt(library_num - 1));
  227. return (0);
  228. }
  229. // These are the actual callouts.
  230. int
  231. print1(CalloutHandle& callout_handle) {
  232. return (printExecute(callout_handle, 1));
  233. }
  234. int
  235. print2(CalloutHandle& callout_handle) {
  236. return (printExecute(callout_handle, 2));
  237. }
  238. int
  239. print3(CalloutHandle& callout_handle) {
  240. return (printExecute(callout_handle, 3));
  241. }
  242. // This test checks the many-faced nature of the context for both the
  243. // CalloutContext and the LibraryContext.
  244. TEST(HandlesTest, ContextAccessCheck) {
  245. // Create the LibraryHandleCollection with a set of four callouts
  246. // (the test does not use the ContextCreate and ContextDestroy callouts.)
  247. boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
  248. const int one_index = server_hooks->registerHook("one");
  249. const int two_index = server_hooks->registerHook("two");
  250. const int three_index = server_hooks->registerHook("three");
  251. const int four_index = server_hooks->registerHook("four");
  252. // Create the library handle collection and the library handles.
  253. boost::shared_ptr<LibraryHandleCollection>
  254. collection(new LibraryHandleCollection());
  255. boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
  256. handle->registerCallout("one", callout11);
  257. handle->registerCallout("two", callout12);
  258. handle->registerCallout("three", callout13);
  259. handle->registerCallout("four", print1);
  260. collection->addLibraryHandle(handle);
  261. handle.reset(new LibraryHandle(server_hooks));
  262. handle->registerCallout("one", callout21);
  263. handle->registerCallout("two", callout22);
  264. handle->registerCallout("three", callout23);
  265. handle->registerCallout("four", print2);
  266. collection->addLibraryHandle(handle);
  267. handle.reset(new LibraryHandle(server_hooks));
  268. handle->registerCallout("one", callout31);
  269. handle->registerCallout("two", callout32);
  270. handle->registerCallout("three", callout33);
  271. handle->registerCallout("four", print3);
  272. collection->addLibraryHandle(handle);
  273. // Create the callout handles and distinguish them by setting the "long"
  274. // argument.
  275. CalloutHandle callout_handle_a(collection);
  276. callout_handle_a.setArgument("string", string("a"));
  277. CalloutHandle callout_handle_b(collection);
  278. callout_handle_b.setArgument("string", string("b"));
  279. // Now call the callouts attached to the first three hooks. Each hook is
  280. // called twice (once for each callout handle) before the next hook is
  281. // called.
  282. collection->callCallouts(one_index, callout_handle_a);
  283. collection->callCallouts(one_index, callout_handle_b);
  284. collection->callCallouts(two_index, callout_handle_a);
  285. collection->callCallouts(two_index, callout_handle_b);
  286. collection->callCallouts(three_index, callout_handle_a);
  287. collection->callCallouts(three_index, callout_handle_b);
  288. // Get the results for each callout. Explicitly zero the variables before
  289. // getting the results so we are certain that the values are the results
  290. // of the callouts.
  291. zero_results();
  292. collection->callCallouts(four_index, callout_handle_a);
  293. // To explain the expected library context results:
  294. //
  295. // The first callCallouts() call above calls the callouts for hook "one"
  296. // with callout handle "a". This calls the callout attached to hook "one"
  297. // from library 1, then that attached to hook "one" from library 2, then
  298. // from library 3. The callout in library 1 appends "11xa" to the first
  299. // library's context. The callout in library 2 appends "21xa" to its
  300. // library's context. Finally, the third library's context gets "31xa"
  301. // appended to it.
  302. //
  303. // The next callCallouts() call repeats the calls to the callouts attached
  304. // to hook "one", which result in "11xb", "21xb", "31xb" being appended to
  305. // the context of libraries 1, 2, and 3 respectively.
  306. //
  307. // The process is then repeated for hooks "two" and "three", leading to
  308. // the expected context values listed below.
  309. //
  310. // The expected integer values can be found by summing up the values
  311. // corresponding to the elements of the strings.
  312. EXPECT_EQ("11xa11xb12xa12xb13xa13xb", resultLibraryString(0));
  313. EXPECT_EQ("21xa21xb22xa22xb23xa23xb", resultLibraryString(1));
  314. EXPECT_EQ("31xa31xb32xa32xb33xa33xb", resultLibraryString(2));
  315. EXPECT_EQ((1111 + 1112 + 1211 + 1212 + 1311 + 1312), resultLibraryInt(0));
  316. EXPECT_EQ((2111 + 2112 + 2211 + 2212 + 2311 + 2312), resultLibraryInt(1));
  317. EXPECT_EQ((3111 + 3112 + 3211 + 3212 + 3311 + 3312), resultLibraryInt(2));
  318. // To explain the expected callout context results.
  319. //
  320. // The callout handle maintains a separate context for each library. When
  321. // the first call to callCallouts() is made, "11ca" gets appended to
  322. // the context for library 1 maintained by by the callout handle, "21ca"
  323. // gets appended to the context maintained for library 2, and "31ca" to
  324. // the context maintained for library 3.
  325. //
  326. // The next call to callCallouts() calls the same callouts but for a
  327. // different callout handle. It also maintains three contexts (one for
  328. // each library) and they will get "11cb", "21cb", "31cb" appended to
  329. // them. These don't affect the contexts maintained by callout handle a.
  330. //
  331. // The process is then repeated for hooks "two" and "three", which append
  332. // "12ca", "22ca" and "32ca" for hook "two" and "31ca", "32ca" and "33ca"
  333. // for hook "three".
  334. //
  335. // The expected integer values can be found by summing up the values
  336. // corresponding to the elements of the strings.
  337. // At this point, we have only called the "print" function for callout
  338. // handle "a", so the following results are checking the context values
  339. // maintained in that callout handle.
  340. EXPECT_EQ("11ca12ca13ca", resultCalloutString(0));
  341. EXPECT_EQ("21ca22ca23ca", resultCalloutString(1));
  342. EXPECT_EQ("31ca32ca33ca", resultCalloutString(2));
  343. EXPECT_EQ((1121 + 1221 + 1321), resultCalloutInt(0));
  344. EXPECT_EQ((2121 + 2221 + 2321), resultCalloutInt(1));
  345. EXPECT_EQ((3121 + 3221 + 3321), resultCalloutInt(2));
  346. // Repeat the checks for callout b. The library handle context values
  347. // should not change, but the context maintained by the callout handle
  348. // should.
  349. zero_results();
  350. collection->callCallouts(four_index, callout_handle_b);
  351. EXPECT_EQ("11xa11xb12xa12xb13xa13xb", resultLibraryString(0));
  352. EXPECT_EQ("21xa21xb22xa22xb23xa23xb", resultLibraryString(1));
  353. EXPECT_EQ("31xa31xb32xa32xb33xa33xb", resultLibraryString(2));
  354. EXPECT_EQ((1111 + 1112 + 1211 + 1212 + 1311 + 1312), resultLibraryInt(0));
  355. EXPECT_EQ((2111 + 2112 + 2211 + 2212 + 2311 + 2312), resultLibraryInt(1));
  356. EXPECT_EQ((3111 + 3112 + 3211 + 3212 + 3311 + 3312), resultLibraryInt(2));
  357. EXPECT_EQ("11cb12cb13cb", resultCalloutString(0));
  358. EXPECT_EQ("21cb22cb23cb", resultCalloutString(1));
  359. EXPECT_EQ("31cb32cb33cb", resultCalloutString(2));
  360. EXPECT_EQ((1122 + 1222 + 1322), resultCalloutInt(0));
  361. EXPECT_EQ((2122 + 2222 + 2322), resultCalloutInt(1));
  362. EXPECT_EQ((3122 + 3222 + 3322), resultCalloutInt(2));
  363. }
  364. // Now repeat the test, but add a deletion callout to the list. The "two"
  365. // hook of library 2 will have an additional callout to delete the "int"
  366. // element: the same hook for library 3 will delete both elements. In
  367. // addition, the names of context elements for the libraries at this point
  368. // will be printed.
  369. // List of context item names.
  370. vector<string>&
  371. getItemNames(int index) {
  372. static vector<string> context_items[3];
  373. return (context_items[index]);
  374. }
  375. // Context item deletion functions.
  376. int
  377. deleteIntContextItem(CalloutHandle& handle) {
  378. handle.deleteContext("int");
  379. return (0);
  380. }
  381. int
  382. deleteAllContextItems(CalloutHandle& handle) {
  383. handle.deleteAllContext();
  384. return (0);
  385. }
  386. // Generic print function - copy names in sorted order.
  387. int
  388. printContextNamesExecute(CalloutHandle& handle, int library_num) {
  389. const int index = library_num - 1;
  390. getItemNames(index) = handle.getContextNames();
  391. sort(getItemNames(index).begin(), getItemNames(index).end());
  392. return (0);
  393. }
  394. int
  395. printContextNames1(CalloutHandle& handle) {
  396. return (printContextNamesExecute(handle, 1));
  397. }
  398. int
  399. printContextNames2(CalloutHandle& handle) {
  400. return (printContextNamesExecute(handle, 2));
  401. }
  402. int
  403. printContextNames3(CalloutHandle& handle) {
  404. return (printContextNamesExecute(handle, 3));
  405. }
  406. // Perform the test including deletion of context items.
  407. TEST(HandlesTest, ContextDeletionCheck) {
  408. // Create the LibraryHandleCollection with a set of four callouts
  409. // (the test does not use the ContextCreate and ContextDestroy callouts.)
  410. boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
  411. const int one_index = server_hooks->registerHook("one");
  412. const int two_index = server_hooks->registerHook("two");
  413. const int three_index = server_hooks->registerHook("three");
  414. const int four_index = server_hooks->registerHook("four");
  415. // Create the library handle collection and the library handles.
  416. boost::shared_ptr<LibraryHandleCollection>
  417. collection(new LibraryHandleCollection());
  418. boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
  419. handle->registerCallout("one", callout11);
  420. handle->registerCallout("two", callout12);
  421. handle->registerCallout("two", printContextNames1);
  422. handle->registerCallout("three", callout13);
  423. handle->registerCallout("four", print1);
  424. collection->addLibraryHandle(handle);
  425. handle.reset(new LibraryHandle(server_hooks));
  426. handle->registerCallout("one", callout21);
  427. handle->registerCallout("two", callout22);
  428. handle->registerCallout("two", deleteIntContextItem);
  429. handle->registerCallout("two", printContextNames2);
  430. handle->registerCallout("three", callout23);
  431. handle->registerCallout("four", print2);
  432. collection->addLibraryHandle(handle);
  433. handle.reset(new LibraryHandle(server_hooks));
  434. handle->registerCallout("one", callout31);
  435. handle->registerCallout("two", callout32);
  436. handle->registerCallout("two", deleteAllContextItems);
  437. handle->registerCallout("two", printContextNames3);
  438. handle->registerCallout("three", callout33);
  439. handle->registerCallout("four", print3);
  440. collection->addLibraryHandle(handle);
  441. // Create the callout handles and distinguish them by setting the "long"
  442. // argument.
  443. CalloutHandle callout_handle_a(collection);
  444. callout_handle_a.setArgument("string", string("a"));
  445. CalloutHandle callout_handle_b(collection);
  446. callout_handle_b.setArgument("string", string("b"));
  447. // Now call the callouts attached to the first three hooks. Each hook is
  448. // called twice (once for each callout handle) before the next hook is
  449. // called.
  450. collection->callCallouts(one_index, callout_handle_a);
  451. collection->callCallouts(one_index, callout_handle_b);
  452. collection->callCallouts(two_index, callout_handle_a);
  453. collection->callCallouts(two_index, callout_handle_b);
  454. collection->callCallouts(three_index, callout_handle_a);
  455. collection->callCallouts(three_index, callout_handle_b);
  456. // Get the results for each callout. Explicitly zero the variables before
  457. // getting the results so we are certain that the values are the results
  458. // of the callouts.
  459. zero_results();
  460. collection->callCallouts(four_index, callout_handle_a);
  461. // The logic by which the expected results are arrived at is described
  462. // in the ContextAccessCheck test. The results here are different
  463. // because context items have been modified along the way.
  464. //
  465. // As only the ContextHandle context is modified, the LibraryHandle
  466. // context is unaltered from the values obtained in the previous test.
  467. EXPECT_EQ("11xa11xb12xa12xb13xa13xb", resultLibraryString(0));
  468. EXPECT_EQ("21xa21xb22xa22xb23xa23xb", resultLibraryString(1));
  469. EXPECT_EQ("31xa31xb32xa32xb33xa33xb", resultLibraryString(2));
  470. EXPECT_EQ((1111 + 1112 + 1211 + 1212 + 1311 + 1312), resultLibraryInt(0));
  471. EXPECT_EQ((2111 + 2112 + 2211 + 2212 + 2311 + 2312), resultLibraryInt(1));
  472. EXPECT_EQ((3111 + 3112 + 3211 + 3212 + 3311 + 3312), resultLibraryInt(2));
  473. // ContextHandle context results.
  474. EXPECT_EQ("11ca12ca13ca", resultCalloutString(0));
  475. EXPECT_EQ("21ca22ca23ca", resultCalloutString(1));
  476. EXPECT_EQ( "33ca", resultCalloutString(2));
  477. EXPECT_EQ((1121 + 1221 + 1321), resultCalloutInt(0));
  478. EXPECT_EQ(( 2321), resultCalloutInt(1));
  479. EXPECT_EQ(( 3321), resultCalloutInt(2));
  480. // Repeat the checks for callout b. The library handle context values
  481. // should not change, but the context maintained by the callout handle
  482. // should.
  483. zero_results();
  484. collection->callCallouts(four_index, callout_handle_b);
  485. EXPECT_EQ("11xa11xb12xa12xb13xa13xb", resultLibraryString(0));
  486. EXPECT_EQ("21xa21xb22xa22xb23xa23xb", resultLibraryString(1));
  487. EXPECT_EQ("31xa31xb32xa32xb33xa33xb", resultLibraryString(2));
  488. EXPECT_EQ((1111 + 1112 + 1211 + 1212 + 1311 + 1312), resultLibraryInt(0));
  489. EXPECT_EQ((2111 + 2112 + 2211 + 2212 + 2311 + 2312), resultLibraryInt(1));
  490. EXPECT_EQ((3111 + 3112 + 3211 + 3212 + 3311 + 3312), resultLibraryInt(2));
  491. EXPECT_EQ("11cb12cb13cb", resultCalloutString(0));
  492. EXPECT_EQ("21cb22cb23cb", resultCalloutString(1));
  493. EXPECT_EQ( "33cb", resultCalloutString(2));
  494. EXPECT_EQ((1122 + 1222 + 1322), resultCalloutInt(0));
  495. EXPECT_EQ(( 2322), resultCalloutInt(1));
  496. EXPECT_EQ(( 3322), resultCalloutInt(2));
  497. // ... and check what the names of the context items are after the callouts
  498. // for hook "two". We know they are in sorted order.
  499. EXPECT_EQ(2, getItemNames(0).size());
  500. EXPECT_EQ(string("int"), getItemNames(0)[0]);
  501. EXPECT_EQ(string("string"), getItemNames(0)[1]);
  502. EXPECT_EQ(1, getItemNames(1).size());
  503. EXPECT_EQ(string("string"), getItemNames(1)[0]);
  504. EXPECT_EQ(0, getItemNames(2).size());
  505. }
  506. } // Anonymous namespace