lru_list_unittest.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright (C) 2010 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. // $Id$
  15. #include <iostream>
  16. #include <algorithm>
  17. #include <string>
  18. #include <vector>
  19. #include <gtest/gtest.h>
  20. #include <boost/lexical_cast.hpp>
  21. #include "../nsas_entry.h"
  22. #include "../lru_list.h"
  23. #include "nsas_test.h"
  24. using namespace std;
  25. namespace isc {
  26. namespace nsas {
  27. /// \brief Dropped Functor Class
  28. ///
  29. /// Functor object is called when an object is dropped from the LRU list.
  30. /// To prove that it has run, this function does nothing more than set the
  31. /// MS bit on the 16-bit class value.
  32. class Dropped : public LruList<TestEntry>::Dropped {
  33. public:
  34. virtual void operator()(TestEntry* entry) const {
  35. entry->setClass(RRClass(entry->getClass().getCode() | 0x8000));
  36. }
  37. };
  38. /// \brief Text Fixture Class
  39. class LruListTest : public ::testing::Test {
  40. protected:
  41. LruListTest() :
  42. entry1_(new TestEntry("alpha", RRClass::IN())),
  43. entry2_(new TestEntry("beta", RRClass::CH())),
  44. entry3_(new TestEntry("gamma", RRClass::HS())),
  45. entry4_(new TestEntry("delta", RRClass::IN())),
  46. entry5_(new TestEntry("epsilon", RRClass::HS())),
  47. entry6_(new TestEntry("zeta", RRClass::CH())),
  48. entry7_(new TestEntry("eta", RRClass::IN()))
  49. {}
  50. virtual ~LruListTest()
  51. {}
  52. boost::shared_ptr<TestEntry> entry1_;
  53. boost::shared_ptr<TestEntry> entry2_;
  54. boost::shared_ptr<TestEntry> entry3_;
  55. boost::shared_ptr<TestEntry> entry4_;
  56. boost::shared_ptr<TestEntry> entry5_;
  57. boost::shared_ptr<TestEntry> entry6_;
  58. boost::shared_ptr<TestEntry> entry7_;
  59. };
  60. // Test of the constructor
  61. TEST_F(LruListTest, Constructor) {
  62. LruList<TestEntry> lru(100);
  63. EXPECT_EQ(100, lru.getMaxSize());
  64. EXPECT_EQ(0, lru.size());
  65. }
  66. // Test of Get/Set the maximum number of entrys
  67. TEST_F(LruListTest, GetSet) {
  68. LruList<TestEntry> lru(100);
  69. EXPECT_EQ(100, lru.getMaxSize());
  70. lru.setMaxSize(42);
  71. EXPECT_EQ(42, lru.getMaxSize());
  72. }
  73. // Test that adding an entry really does add an entry
  74. TEST_F(LruListTest, Add) {
  75. LruList<TestEntry> lru(100);
  76. EXPECT_EQ(0, lru.size());
  77. lru.add(entry1_);
  78. EXPECT_EQ(1, lru.size());
  79. lru.add(entry2_);
  80. EXPECT_EQ(2, lru.size());
  81. }
  82. // Test that removing an entry really does remove it.
  83. TEST_F(LruListTest, Remove) {
  84. LruList<TestEntry> lru(100);
  85. EXPECT_EQ(0, lru.size());
  86. EXPECT_FALSE(entry1_->iteratorValid());
  87. lru.add(entry1_);
  88. EXPECT_TRUE(entry1_->iteratorValid());
  89. EXPECT_EQ(1, lru.size());
  90. EXPECT_FALSE(entry2_->iteratorValid());
  91. lru.add(entry2_);
  92. EXPECT_TRUE(entry2_->iteratorValid());
  93. EXPECT_EQ(2, lru.size());
  94. lru.remove(entry1_);
  95. EXPECT_FALSE(entry1_->iteratorValid());
  96. EXPECT_EQ(1, lru.size());
  97. }
  98. // Check that adding a new entry to a limited size list does delete the
  99. // oldest entry from the list.
  100. TEST_F(LruListTest, SizeLimit) {
  101. LruList<TestEntry> lru(3);
  102. EXPECT_EQ(0, lru.size());
  103. // Add first entry and check that the shared pointer's reference count
  104. // has increased. There will be two references: one from the "entry1_"
  105. // member in the test fixture class, and one from the list.
  106. EXPECT_EQ(1, entry1_.use_count());
  107. lru.add(entry1_);
  108. EXPECT_EQ(2, entry1_.use_count());
  109. EXPECT_EQ(1, lru.size());
  110. // Same for entry 2.
  111. EXPECT_EQ(1, entry2_.use_count());
  112. lru.add(entry2_);
  113. EXPECT_EQ(2, entry2_.use_count());
  114. EXPECT_EQ(2, lru.size());
  115. // Same for entry 3.
  116. EXPECT_EQ(1, entry3_.use_count());
  117. lru.add(entry3_);
  118. EXPECT_EQ(2, entry3_.use_count());
  119. EXPECT_EQ(3, lru.size());
  120. // Adding entry 4 should remove entry 1 from the list. This will
  121. // delete the list's shared pointer to the entry and will therefore
  122. // drop the reference count back to one (from the "entry1_" member in
  123. // the text fixture class).
  124. EXPECT_EQ(2, entry1_.use_count());
  125. EXPECT_EQ(1, entry4_.use_count());
  126. lru.add(entry4_);
  127. EXPECT_EQ(1, entry1_.use_count());
  128. EXPECT_EQ(2, entry4_.use_count());
  129. EXPECT_EQ(3, lru.size());
  130. // Adding entry 5 should remove entry 2 from the list.
  131. EXPECT_EQ(2, entry2_.use_count());
  132. EXPECT_EQ(1, entry5_.use_count());
  133. lru.add(entry5_);
  134. EXPECT_EQ(1, entry2_.use_count());
  135. EXPECT_EQ(2, entry5_.use_count());
  136. EXPECT_EQ(3, lru.size());
  137. }
  138. // Check that "touching" an entry adds it to the back of the list.
  139. TEST_F(LruListTest, Touch) {
  140. // Create the list
  141. LruList<TestEntry> lru(3);
  142. EXPECT_EQ(0, lru.size());
  143. lru.add(entry1_);
  144. lru.add(entry2_);
  145. lru.add(entry3_);
  146. // Check the reference counts of the entrys and the list size
  147. EXPECT_EQ(2, entry1_.use_count());
  148. EXPECT_EQ(2, entry2_.use_count());
  149. EXPECT_EQ(2, entry3_.use_count());
  150. EXPECT_EQ(1, entry4_.use_count());
  151. EXPECT_EQ(1, entry5_.use_count());
  152. EXPECT_EQ(1, entry6_.use_count());
  153. EXPECT_EQ(1, entry7_.use_count());
  154. EXPECT_EQ(3, lru.size());
  155. // "Touch" the first entry
  156. lru.touch(entry1_);
  157. // Adding two more entries should not remove the touched entry.
  158. lru.add(entry4_);
  159. lru.add(entry5_);
  160. // Check the status of the entrys and the list.
  161. EXPECT_EQ(2, entry1_.use_count());
  162. EXPECT_EQ(1, entry2_.use_count());
  163. EXPECT_EQ(1, entry3_.use_count());
  164. EXPECT_EQ(2, entry4_.use_count());
  165. EXPECT_EQ(2, entry5_.use_count());
  166. EXPECT_EQ(1, entry6_.use_count());
  167. EXPECT_EQ(1, entry7_.use_count());
  168. EXPECT_EQ(3, lru.size());
  169. // Now touch the entry agin to move it to the back of the list.
  170. // This checks that the iterator stored in the entry as a result of the
  171. // last touch operation is valid.
  172. lru.touch(entry1_);
  173. // Check this by adding two more entrys and checking reference counts
  174. // to see what is stored.
  175. lru.add(entry6_);
  176. lru.add(entry7_);
  177. EXPECT_EQ(2, entry1_.use_count());
  178. EXPECT_EQ(1, entry2_.use_count());
  179. EXPECT_EQ(1, entry3_.use_count());
  180. EXPECT_EQ(1, entry4_.use_count());
  181. EXPECT_EQ(1, entry5_.use_count());
  182. EXPECT_EQ(2, entry6_.use_count());
  183. EXPECT_EQ(2, entry7_.use_count());
  184. EXPECT_EQ(3, lru.size());
  185. }
  186. // Dropped functor tests: tests that the function object is called when an
  187. // object expires from the list.
  188. TEST_F(LruListTest, Dropped) {
  189. // Create an object with an expiration handler.
  190. LruList<TestEntry> lru(3, new Dropped());
  191. // Fill the list
  192. lru.add(entry1_);
  193. lru.add(entry2_);
  194. lru.add(entry3_);
  195. EXPECT_EQ(RRClass::IN(), entry1_->getClass());
  196. EXPECT_EQ(RRClass::CH(), entry2_->getClass());
  197. // Add another entry and check that the handler runs.
  198. EXPECT_EQ(0, (entry1_->getClass().getCode() & 0x8000));
  199. lru.add(entry4_);
  200. EXPECT_NE(0, (entry1_->getClass().getCode() & 0x8000));
  201. EXPECT_EQ(0, (entry2_->getClass().getCode() & 0x8000));
  202. lru.add(entry5_);
  203. EXPECT_NE(0, (entry2_->getClass().getCode() & 0x8000));
  204. // Delete an entry and check that the handler does not run.
  205. EXPECT_EQ(0, (entry3_->getClass().getCode() & 0x8000));
  206. lru.remove(entry3_);
  207. EXPECT_EQ(0, (entry3_->getClass().getCode() & 0x8000));
  208. }
  209. // Miscellaneous tests - pathological conditions
  210. TEST_F(LruListTest, Miscellaneous) {
  211. // Zero size list should not allow entrys to be added
  212. LruList<TestEntry> lru_1(0);
  213. lru_1.add(entry1_);
  214. EXPECT_EQ(0, lru_1.size());
  215. EXPECT_EQ(1, entry1_.use_count());
  216. // Removing an uninserted entry should not affect the list.
  217. LruList<TestEntry> lru_2(100);
  218. lru_2.add(entry1_);
  219. lru_2.add(entry2_);
  220. lru_2.add(entry3_);
  221. EXPECT_EQ(3, lru_2.size());
  222. lru_2.remove(entry4_);
  223. EXPECT_EQ(2, entry1_.use_count());
  224. EXPECT_EQ(2, entry2_.use_count());
  225. EXPECT_EQ(2, entry3_.use_count());
  226. EXPECT_EQ(1, entry4_.use_count());
  227. EXPECT_EQ(1, entry5_.use_count());
  228. EXPECT_EQ(3, lru_2.size());
  229. // Touching an uninserted entry should not affect the list.
  230. lru_2.touch(entry5_);
  231. EXPECT_EQ(2, entry1_.use_count());
  232. EXPECT_EQ(2, entry2_.use_count());
  233. EXPECT_EQ(2, entry3_.use_count());
  234. EXPECT_EQ(1, entry4_.use_count());
  235. EXPECT_EQ(1, entry5_.use_count());
  236. EXPECT_EQ(3, lru_2.size());
  237. }
  238. } // namespace nsas
  239. } // namespace isc