zone_table_unittest.cc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. #include "memory_segment_test.h"
  15. #include <exceptions/exceptions.h>
  16. #include <util/memory_segment_local.h>
  17. #include <dns/name.h>
  18. #include <dns/rrclass.h>
  19. #include <datasrc/result.h>
  20. #include <datasrc/memory/zone_data.h>
  21. #include <datasrc/memory/zone_table.h>
  22. #include <datasrc/memory/segment_object_holder.h>
  23. #include <gtest/gtest.h>
  24. #include <new> // for bad_alloc
  25. using namespace isc::dns;
  26. using namespace isc::datasrc;
  27. using namespace isc::datasrc::memory;
  28. using namespace isc::datasrc::memory::detail;
  29. namespace {
  30. class ZoneTableTest : public ::testing::Test {
  31. protected:
  32. ZoneTableTest() : zclass_(RRClass::IN()),
  33. zname1(Name("example.com")),
  34. zname2(Name("example.net")),
  35. zname3(Name("example")),
  36. zone_table(ZoneTable::create(mem_sgmt_, zclass_))
  37. {}
  38. ~ZoneTableTest() {
  39. if (zone_table != NULL) {
  40. ZoneTable::destroy(mem_sgmt_, zone_table);
  41. }
  42. }
  43. void TearDown() {
  44. ZoneTable::destroy(mem_sgmt_, zone_table);
  45. zone_table = NULL;
  46. EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated()); // catch any leak here.
  47. }
  48. const RRClass zclass_;
  49. const Name zname1, zname2, zname3;
  50. test::MemorySegmentTest mem_sgmt_;
  51. ZoneTable* zone_table;
  52. };
  53. TEST_F(ZoneTableTest, create) {
  54. // Test about creating a zone table. Normal case covers through other
  55. // tests. We only check exception safety by letting the test memory
  56. // segment throw.
  57. mem_sgmt_.setThrowCount(2);
  58. EXPECT_THROW(ZoneTable::create(mem_sgmt_, zclass_), std::bad_alloc);
  59. // This shouldn't cause memory leak (that would be caught in TearDown()).
  60. }
  61. TEST_F(ZoneTableTest, addZone) {
  62. // It doesn't accept empty (NULL) zones
  63. EXPECT_THROW(zone_table->addZone(mem_sgmt_, zclass_, zname1, NULL),
  64. isc::BadValue);
  65. SegmentObjectHolder<ZoneData, RRClass> holder1(
  66. mem_sgmt_, ZoneData::create(mem_sgmt_, zname1), zclass_);
  67. const ZoneData* data1(holder1.get());
  68. // Normal successful case.
  69. const ZoneTable::AddResult result1(zone_table->addZone(mem_sgmt_, zclass_,
  70. zname1,
  71. holder1.release()));
  72. EXPECT_EQ(result::SUCCESS, result1.code);
  73. EXPECT_EQ(static_cast<const ZoneData*>(NULL), result1.zone_data);
  74. // It got released by it
  75. EXPECT_EQ(static_cast<const ZoneData*>(NULL), holder1.get());
  76. // Duplicate add doesn't replace the existing data.
  77. SegmentObjectHolder<ZoneData, RRClass> holder2(
  78. mem_sgmt_, ZoneData::create(mem_sgmt_, zname1), zclass_);
  79. const ZoneTable::AddResult result2(zone_table->addZone(mem_sgmt_, zclass_,
  80. zname1,
  81. holder2.release()));
  82. EXPECT_EQ(result::EXIST, result2.code);
  83. // The old one gets out
  84. EXPECT_EQ(data1, result2.zone_data);
  85. // It releases this one even when we replace the old zone
  86. EXPECT_EQ(static_cast<const ZoneData*>(NULL), holder2.get());
  87. // We need to release the old one manually
  88. ZoneData::destroy(mem_sgmt_, result2.zone_data, zclass_);
  89. SegmentObjectHolder<ZoneData, RRClass> holder3(
  90. mem_sgmt_, ZoneData::create(mem_sgmt_, Name("EXAMPLE.COM")),
  91. zclass_);
  92. // names are compared in a case insensitive manner.
  93. const ZoneTable::AddResult result3(zone_table->addZone(mem_sgmt_, zclass_,
  94. Name("EXAMPLE.COM"),
  95. holder3.release()));
  96. EXPECT_EQ(result::EXIST, result3.code);
  97. ZoneData::destroy(mem_sgmt_, result3.zone_data, zclass_);
  98. // Add some more different ones. Should just succeed.
  99. SegmentObjectHolder<ZoneData, RRClass> holder4(
  100. mem_sgmt_, ZoneData::create(mem_sgmt_, zname2), zclass_);
  101. EXPECT_EQ(result::SUCCESS,
  102. zone_table->addZone(mem_sgmt_, zclass_, zname2,
  103. holder4.release()).code);
  104. SegmentObjectHolder<ZoneData, RRClass> holder5(
  105. mem_sgmt_, ZoneData::create(mem_sgmt_, zname3), zclass_);
  106. EXPECT_EQ(result::SUCCESS,
  107. zone_table->addZone(mem_sgmt_, zclass_, zname3,
  108. holder5.release()).code);
  109. // Have the memory segment throw an exception in extending the internal
  110. // tree. It still shouldn't cause memory leak (which would be detected
  111. // in TearDown()).
  112. SegmentObjectHolder<ZoneData, RRClass> holder6(
  113. mem_sgmt_, ZoneData::create(mem_sgmt_, Name("example.org")), zclass_);
  114. mem_sgmt_.setThrowCount(1);
  115. EXPECT_THROW(zone_table->addZone(mem_sgmt_, zclass_, Name("example.org"),
  116. holder6.release()),
  117. std::bad_alloc);
  118. }
  119. TEST_F(ZoneTableTest, findZone) {
  120. SegmentObjectHolder<ZoneData, RRClass> holder1(
  121. mem_sgmt_, ZoneData::create(mem_sgmt_, zname1), zclass_);
  122. ZoneData* zone_data = holder1.get();
  123. EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zclass_, zname1,
  124. holder1.release()).code);
  125. SegmentObjectHolder<ZoneData, RRClass> holder2(
  126. mem_sgmt_, ZoneData::create(mem_sgmt_, zname2), zclass_);
  127. EXPECT_EQ(result::SUCCESS,
  128. zone_table->addZone(mem_sgmt_, zclass_, zname2,
  129. holder2.release()).code);
  130. SegmentObjectHolder<ZoneData, RRClass> holder3(
  131. mem_sgmt_, ZoneData::create(mem_sgmt_, zname3), zclass_);
  132. EXPECT_EQ(result::SUCCESS,
  133. zone_table->addZone(mem_sgmt_, zclass_, zname3,
  134. holder3.release()).code);
  135. const ZoneTable::FindResult find_result1 =
  136. zone_table->findZone(Name("example.com"));
  137. EXPECT_EQ(result::SUCCESS, find_result1.code);
  138. EXPECT_EQ(zone_data, find_result1.zone_data);
  139. EXPECT_EQ(result::NOTFOUND,
  140. zone_table->findZone(Name("example.org")).code);
  141. EXPECT_EQ(static_cast<ZoneData*>(NULL),
  142. zone_table->findZone(Name("example.org")).zone_data);
  143. // there's no exact match. the result should be the longest match,
  144. // and the code should be PARTIALMATCH.
  145. EXPECT_EQ(result::PARTIALMATCH,
  146. zone_table->findZone(Name("www.example.com")).code);
  147. EXPECT_EQ(zone_data,
  148. zone_table->findZone(Name("www.example.com")).zone_data);
  149. // make sure the partial match is indeed the longest match by adding
  150. // a zone with a shorter origin and query again.
  151. SegmentObjectHolder<ZoneData, RRClass> holder4(
  152. mem_sgmt_, ZoneData::create(mem_sgmt_, Name("com")), zclass_);
  153. EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zclass_,
  154. Name("com"),
  155. holder4.release()).code);
  156. EXPECT_EQ(zone_data,
  157. zone_table->findZone(Name("www.example.com")).zone_data);
  158. }
  159. }