zone_table_unittest.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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 <exceptions/exceptions.h>
  15. #include <util/memory_segment_local.h>
  16. #include <dns/name.h>
  17. #include <dns/rrclass.h>
  18. #include <datasrc/result.h>
  19. #include <datasrc/memory/zone_data.h>
  20. #include <datasrc/memory/zone_table.h>
  21. #include <gtest/gtest.h>
  22. #include <new> // for bad_alloc
  23. using namespace isc::dns;
  24. using namespace isc::datasrc;
  25. using namespace isc::datasrc::memory;
  26. namespace {
  27. // Memory segment specified for tests. It normally behaves like a "local"
  28. // memory segment. If "throw count" is set to non 0 via setThrowCount(),
  29. // it continues the normal behavior up to the specified number of calls to
  30. // allocate(), and throws an exception at the next call.
  31. class TestMemorySegment : public isc::util::MemorySegmentLocal {
  32. public:
  33. TestMemorySegment() : throw_count_(0) {}
  34. virtual void* allocate(size_t size) {
  35. if (throw_count_ > 0) {
  36. if (--throw_count_ == 0) {
  37. throw std::bad_alloc();
  38. }
  39. }
  40. return (isc::util::MemorySegmentLocal::allocate(size));
  41. }
  42. void setThrowCount(size_t count) { throw_count_ = count; }
  43. private:
  44. size_t throw_count_;
  45. };
  46. class ZoneTableTest : public ::testing::Test {
  47. protected:
  48. ZoneTableTest() : zclass_(RRClass::IN()),
  49. zname1(Name("example.com")),
  50. zname2(Name("example.net")),
  51. zname3(Name("example")),
  52. zone_table(ZoneTable::create(mem_sgmt_, zclass_))
  53. {}
  54. ~ZoneTableTest() {
  55. if (zone_table != NULL) {
  56. ZoneTable::destroy(mem_sgmt_, zone_table, zclass_);
  57. }
  58. }
  59. void TearDown() {
  60. ZoneTable::destroy(mem_sgmt_, zone_table, zclass_);
  61. zone_table = NULL;
  62. EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated()); // catch any leak here.
  63. }
  64. const RRClass zclass_;
  65. const Name zname1, zname2, zname3;
  66. TestMemorySegment mem_sgmt_;
  67. ZoneTable* zone_table;
  68. };
  69. TEST_F(ZoneTableTest, create) {
  70. // Test about creating a zone table. Normal case covers through other
  71. // tests. We only check exception safety by letting the test memory
  72. // segment throw.
  73. mem_sgmt_.setThrowCount(2);
  74. EXPECT_THROW(ZoneTable::create(mem_sgmt_, zclass_), std::bad_alloc);
  75. // This shouldn't cause memory leak (that would be caught in TearDown()).
  76. }
  77. TEST_F(ZoneTableTest, addZone) {
  78. // Normal successful case.
  79. const ZoneTable::AddResult result1 =
  80. zone_table->addZone(mem_sgmt_, zclass_, zname1);
  81. EXPECT_EQ(result::SUCCESS, result1.code);
  82. // Duplicate add doesn't replace the existing data.
  83. EXPECT_EQ(result::EXIST, zone_table->addZone(mem_sgmt_, zclass_,
  84. zname1).code);
  85. EXPECT_EQ(result1.zone_data,
  86. zone_table->addZone(mem_sgmt_, zclass_, zname1).zone_data);
  87. // names are compared in a case insensitive manner.
  88. EXPECT_EQ(result::EXIST, zone_table->addZone(mem_sgmt_, zclass_,
  89. Name("EXAMPLE.COM")).code);
  90. // Add some more different ones. Should just succeed.
  91. EXPECT_EQ(result::SUCCESS,
  92. zone_table->addZone(mem_sgmt_, zclass_, zname2).code);
  93. EXPECT_EQ(result::SUCCESS,
  94. zone_table->addZone(mem_sgmt_, zclass_, zname3).code);
  95. // Have the memory segment throw an exception in extending the internal
  96. // tree. It still shouldn't cause memory leak (which would be detected
  97. // in TearDown()).
  98. mem_sgmt_.setThrowCount(2);
  99. EXPECT_THROW(zone_table->addZone(mem_sgmt_, zclass_, Name("example.org")),
  100. std::bad_alloc);
  101. }
  102. TEST_F(ZoneTableTest, findZone) {
  103. const ZoneTable::AddResult add_result1 =
  104. zone_table->addZone(mem_sgmt_, zclass_, zname1);
  105. EXPECT_EQ(result::SUCCESS, add_result1.code);
  106. EXPECT_EQ(result::SUCCESS,
  107. zone_table->addZone(mem_sgmt_, zclass_, zname2).code);
  108. EXPECT_EQ(result::SUCCESS,
  109. zone_table->addZone(mem_sgmt_, zclass_, zname3).code);
  110. const ZoneTable::FindResult find_result1 =
  111. zone_table->findZone(Name("example.com"));
  112. EXPECT_EQ(result::SUCCESS, find_result1.code);
  113. EXPECT_EQ(add_result1.zone_data, find_result1.zone_data);
  114. EXPECT_EQ(result::NOTFOUND,
  115. zone_table->findZone(Name("example.org")).code);
  116. EXPECT_EQ(static_cast<ZoneData*>(NULL),
  117. zone_table->findZone(Name("example.org")).zone_data);
  118. // there's no exact match. the result should be the longest match,
  119. // and the code should be PARTIALMATCH.
  120. EXPECT_EQ(result::PARTIALMATCH,
  121. zone_table->findZone(Name("www.example.com")).code);
  122. EXPECT_EQ(add_result1.zone_data,
  123. zone_table->findZone(Name("www.example.com")).zone_data);
  124. // make sure the partial match is indeed the longest match by adding
  125. // a zone with a shorter origin and query again.
  126. EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zclass_,
  127. Name("com")).code);
  128. EXPECT_EQ(add_result1.zone_data,
  129. zone_table->findZone(Name("www.example.com")).zone_data);
  130. }
  131. }