test_datasrc_clients_mgr.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright (C) 2012 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. #ifndef TEST_DATASRC_CLIENTS_MGR_H
  15. #define TEST_DATASRC_CLIENTS_MGR_H 1
  16. #include <exceptions/exceptions.h>
  17. #include <auth/datasrc_clients_mgr.h>
  18. #include <datasrc/datasrc_config.h>
  19. #include <boost/function.hpp>
  20. #include <list>
  21. // In this file we provide specialization of thread, mutex, condition variable,
  22. // and DataSrcClientsBuilder for convenience of tests. They don't use
  23. // actual threads or mutex, and allow tests to inspect some internal states
  24. // of the corresponding objects.
  25. //
  26. // In many cases, tests can use TestDataSrcClientsMgr (defined below) where
  27. // DataSrcClientsMgr is needed.
  28. // Below we extend the isc::auth::datasrc_clientmgr_internal namespace to
  29. // specialize the doNoop() method.
  30. namespace isc {
  31. namespace auth {
  32. namespace datasrc_clientmgr_internal {
  33. class TestMutex {
  34. public:
  35. // for throw_from_noop.
  36. // None: no throw from specialized doNoop()
  37. // EXCLASS: throw some exception class object
  38. // INTEGER: throw an integer
  39. enum ExceptionFromNoop { NONE, EXCLASS, INTEGER };
  40. TestMutex() : lock_count(0), unlock_count(0), noop_count(0),
  41. throw_from_noop(NONE)
  42. {}
  43. class Locker {
  44. public:
  45. Locker(TestMutex& mutex) : mutex_(mutex) {
  46. ++mutex.lock_count;
  47. if (mutex.lock_count > 100) { // 100 is an arbitrary choice
  48. isc_throw(Unexpected,
  49. "too many test mutex count, likely a bug in test");
  50. }
  51. }
  52. ~Locker() {
  53. ++mutex_.unlock_count;
  54. }
  55. private:
  56. TestMutex& mutex_;
  57. };
  58. size_t lock_count; // number of lock acquisitions; tests can check this
  59. size_t unlock_count; // number of lock releases; tests can check this
  60. size_t noop_count; // allow doNoop() to modify this
  61. ExceptionFromNoop throw_from_noop; // tests can set this to control doNoop
  62. };
  63. class TestCondVar {
  64. public:
  65. TestCondVar() : wait_count(0), signal_count(0), command_queue_(NULL),
  66. delayed_command_queue_(NULL)
  67. {}
  68. TestCondVar(std::list<Command>& command_queue,
  69. std::list<Command>& delayed_command_queue) :
  70. wait_count(0),
  71. signal_count(0),
  72. command_queue_(&command_queue),
  73. delayed_command_queue_(&delayed_command_queue)
  74. {
  75. }
  76. void wait(TestMutex& mutex) {
  77. // bookkeeping
  78. ++mutex.unlock_count;
  79. ++wait_count;
  80. ++mutex.lock_count;
  81. if (wait_count > 100) { // 100 is an arbitrary choice
  82. isc_throw(Unexpected,
  83. "too many cond wait count, likely a bug in test");
  84. }
  85. // make the delayed commands available
  86. command_queue_->splice(command_queue_->end(), *delayed_command_queue_);
  87. }
  88. void signal() {
  89. ++signal_count;
  90. }
  91. size_t wait_count; // number of calls to wait(); tests can check this
  92. size_t signal_count; // number of calls to signal(); tests can check this
  93. private:
  94. std::list<Command>* command_queue_;
  95. std::list<Command>* delayed_command_queue_;
  96. };
  97. // Convenient shortcut
  98. typedef DataSrcClientsBuilderBase<TestMutex, TestCondVar>
  99. TestDataSrcClientsBuilder;
  100. // We specialize this command handler for the convenience of tests.
  101. // It abuses our specialized Mutex to count the number of calls of this method.
  102. template<>
  103. void
  104. TestDataSrcClientsBuilder::doNoop();
  105. // A specialization of DataSrcClientsBuilder that allows tests to inspect
  106. // its internal states via static class variables. Using static is suboptimal,
  107. // but DataSrcClientsMgr is highly encapsulated, this seems to be the best
  108. // possible compromise.
  109. class FakeDataSrcClientsBuilder {
  110. public:
  111. // true iff a builder has started.
  112. static bool started;
  113. // These three correspond to the resource shared with the manager.
  114. // xxx_copy will be set in the manager's destructor to record the
  115. // final state of the manager.
  116. static std::list<Command>* command_queue;
  117. static TestCondVar* cond;
  118. static TestMutex* queue_mutex;
  119. static isc::datasrc::DataSrcClientListsPtr* clients_map;
  120. static TestMutex* map_mutex;
  121. static std::list<Command> command_queue_copy;
  122. static TestCondVar cond_copy;
  123. static TestMutex queue_mutex_copy;
  124. // true iff the manager waited on the thread running the builder.
  125. static bool thread_waited;
  126. // If set to true by a test, TestThread::wait() throws an exception
  127. // exception.
  128. enum ExceptionFromWait { NOTHROW, THROW_UNCAUGHT_EX, THROW_OTHER };
  129. static ExceptionFromWait thread_throw_on_wait;
  130. FakeDataSrcClientsBuilder(
  131. std::list<Command>* command_queue,
  132. TestCondVar* cond,
  133. TestMutex* queue_mutex,
  134. isc::datasrc::DataSrcClientListsPtr* clients_map,
  135. TestMutex* map_mutex)
  136. {
  137. FakeDataSrcClientsBuilder::started = false;
  138. FakeDataSrcClientsBuilder::command_queue = command_queue;
  139. FakeDataSrcClientsBuilder::cond = cond;
  140. FakeDataSrcClientsBuilder::queue_mutex = queue_mutex;
  141. FakeDataSrcClientsBuilder::clients_map = clients_map;
  142. FakeDataSrcClientsBuilder::map_mutex = map_mutex;
  143. FakeDataSrcClientsBuilder::thread_waited = false;
  144. FakeDataSrcClientsBuilder::thread_throw_on_wait = NOTHROW;
  145. }
  146. void run() {
  147. FakeDataSrcClientsBuilder::started = true;
  148. }
  149. };
  150. // A fake thread class that doesn't really invoke thread but simply calls
  151. // the given main function (synchronously). Tests can tweak the wait()
  152. // behavior via some static variables so it will throw some exceptions.
  153. class TestThread {
  154. public:
  155. TestThread(const boost::function<void()>& main) {
  156. main();
  157. }
  158. void wait() {
  159. FakeDataSrcClientsBuilder::thread_waited = true;
  160. switch (FakeDataSrcClientsBuilder::thread_throw_on_wait) {
  161. case FakeDataSrcClientsBuilder::NOTHROW:
  162. break;
  163. case FakeDataSrcClientsBuilder::THROW_UNCAUGHT_EX:
  164. isc_throw(util::thread::Thread::UncaughtException,
  165. "TestThread wait() saw an exception");
  166. case FakeDataSrcClientsBuilder::THROW_OTHER:
  167. isc_throw(Unexpected,
  168. "General emulated failure in TestThread wait()");
  169. }
  170. }
  171. };
  172. } // namespace datasrc_clientmgr_internal
  173. // Convenient shortcut
  174. typedef DataSrcClientsMgrBase<
  175. datasrc_clientmgr_internal::TestThread,
  176. datasrc_clientmgr_internal::FakeDataSrcClientsBuilder,
  177. datasrc_clientmgr_internal::TestMutex,
  178. datasrc_clientmgr_internal::TestCondVar> TestDataSrcClientsMgr;
  179. // A specialization of manager's "cleanup" called at the end of the
  180. // destructor. We use this to record the final values of some of the class
  181. // member variables.
  182. template<>
  183. void
  184. TestDataSrcClientsMgr::cleanup();
  185. template<>
  186. void
  187. TestDataSrcClientsMgr::reconfigureHook();
  188. } // namespace auth
  189. } // namespace isc
  190. #endif // TEST_DATASRC_CLIENTS_MGR_H
  191. // Local Variables:
  192. // mode: c++
  193. // End: