loadquery_unittest.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 <algorithm>
  16. #include <utility>
  17. #include <vector>
  18. #include <sstream>
  19. #include <dns/buffer.h>
  20. #include <dns/message.h>
  21. #include <dns/name.h>
  22. #include <dns/rrclass.h>
  23. #include <dns/rrtype.h>
  24. #include <bench/benchmark_util.h>
  25. #include <gtest/gtest.h>
  26. using namespace std;
  27. using namespace isc::bench;
  28. using namespace isc::dns;
  29. namespace {
  30. typedef pair<string, string> QueryParam;
  31. class LoadQueryTest : public ::testing::Test {
  32. protected:
  33. LoadQueryTest() : query_rrclass(RRClass::IN()) {
  34. queries.push_back(QueryParam("www.example.org", "AAAA"));
  35. queries.push_back(QueryParam("www.example.com", "A"));
  36. queries.push_back(QueryParam("test.example", "NS"));
  37. }
  38. RRClass query_rrclass;
  39. BenchQueries result_queries;
  40. vector<QueryParam> queries;
  41. stringstream query_stream;
  42. static const char* const DATA_DIR;
  43. };
  44. const char* const LoadQueryTest::DATA_DIR = TEST_DATA_DIR;
  45. class QueryInserter {
  46. public:
  47. QueryInserter(stringstream& stream) : stream_(stream) {}
  48. void operator()(const QueryParam& query) {
  49. stream_ << query.first << " " << query.second << endl;
  50. }
  51. private:
  52. stringstream& stream_;
  53. };
  54. class QueryChecker {
  55. public:
  56. QueryChecker(const vector<QueryParam>* expected, const RRClass& rrclass) :
  57. expected_(expected), rrclass_(rrclass)
  58. {
  59. if (expected != NULL) {
  60. iter_ = expected_->begin();
  61. }
  62. }
  63. void operator()(const vector<unsigned char>& actual_data) {
  64. InputBuffer buffer(&actual_data[0], actual_data.size());
  65. Message message(Message::PARSE);
  66. message.fromWire(buffer);
  67. // Check if the header part indicates an expected standard query.
  68. EXPECT_EQ(0, message.getQid());
  69. EXPECT_EQ(Opcode::QUERY(), message.getOpcode());
  70. EXPECT_EQ(Rcode::NOERROR(), message.getRcode());
  71. EXPECT_EQ(Rcode::NOERROR(), message.getRcode());
  72. EXPECT_FALSE(message.getHeaderFlag(MessageFlag::QR()));
  73. EXPECT_FALSE(message.getHeaderFlag(MessageFlag::AA()));
  74. EXPECT_EQ(1, message.getRRCount(Section::QUESTION()));
  75. EXPECT_EQ(0, message.getRRCount(Section::ANSWER()));
  76. EXPECT_EQ(0, message.getRRCount(Section::AUTHORITY()));
  77. EXPECT_EQ(0, message.getRRCount(Section::ADDITIONAL()));
  78. // Check if the question matches our original data, if the expected
  79. // data is given.
  80. if (expected_ != NULL) {
  81. ConstQuestionPtr question = *message.beginQuestion();;
  82. EXPECT_EQ(Name((*iter_).first), question->getName());
  83. EXPECT_EQ(RRType((*iter_).second), question->getType());
  84. EXPECT_EQ(rrclass_, question->getClass());
  85. ++iter_;
  86. }
  87. }
  88. private:
  89. const vector<QueryParam>* expected_;
  90. vector<QueryParam>::const_iterator iter_;
  91. const RRClass rrclass_;
  92. };
  93. TEST_F(LoadQueryTest, load) {
  94. for_each(queries.begin(), queries.end(), QueryInserter(query_stream));
  95. loadQueryData(query_stream, result_queries, query_rrclass);
  96. EXPECT_EQ(queries.size(), result_queries.size());
  97. for_each(result_queries.begin(), result_queries.end(),
  98. QueryChecker(&queries, query_rrclass));
  99. }
  100. TEST_F(LoadQueryTest, loadForCHClass) {
  101. for_each(queries.begin(), queries.end(), QueryInserter(query_stream));
  102. query_rrclass = RRClass::CH();
  103. loadQueryData(query_stream, result_queries, query_rrclass);
  104. EXPECT_EQ(queries.size(), result_queries.size());
  105. for_each(result_queries.begin(), result_queries.end(),
  106. QueryChecker(&queries, query_rrclass));
  107. }
  108. TEST_F(LoadQueryTest, loadWithComment) {
  109. for_each(queries.begin(), queries.end(), QueryInserter(query_stream));
  110. // add a comment line. this shouldn't change the result.
  111. query_stream << "# this is a comment" << endl;
  112. query_stream << endl; // empty line. should be ignored, too.
  113. loadQueryData(query_stream, result_queries, query_rrclass);
  114. EXPECT_EQ(queries.size(), result_queries.size());
  115. for_each(result_queries.begin(), result_queries.end(),
  116. QueryChecker(&queries, query_rrclass));
  117. }
  118. TEST_F(LoadQueryTest, loadWithIncompleteData) {
  119. for_each(queries.begin(), queries.end(), QueryInserter(query_stream));
  120. // RRType is missing. It should be ignored by default.
  121. query_stream << "type-is-missing" << endl;
  122. loadQueryData(query_stream, result_queries, query_rrclass);
  123. EXPECT_EQ(queries.size(), result_queries.size());
  124. for_each(result_queries.begin(), result_queries.end(),
  125. QueryChecker(&queries, query_rrclass));
  126. }
  127. TEST_F(LoadQueryTest, loadWithIncompleteDataToBeRejected) {
  128. for_each(queries.begin(), queries.end(), QueryInserter(query_stream));
  129. // RRType is missing. We're going to specify the "strict" check, so
  130. // we should receive an exception.
  131. query_stream << "type-is-missing" << endl;
  132. EXPECT_THROW(loadQueryData(query_stream, result_queries, query_rrclass,
  133. true), BenchMarkError);
  134. }
  135. TEST_F(LoadQueryTest, loadWithBadData) {
  136. for_each(queries.begin(), queries.end(), QueryInserter(query_stream));
  137. // invalid RRType. It should be ignored by default.
  138. query_stream << "www.example.com NOSUCHRRTYPE" << endl;
  139. loadQueryData(query_stream, result_queries, query_rrclass);
  140. EXPECT_EQ(queries.size(), result_queries.size());
  141. for_each(result_queries.begin(), result_queries.end(),
  142. QueryChecker(&queries, query_rrclass));
  143. }
  144. TEST_F(LoadQueryTest, loadWithBadDataToBeRejected) {
  145. for_each(queries.begin(), queries.end(), QueryInserter(query_stream));
  146. // invalid RRType, which should trigger an exception.
  147. query_stream << "www.example.com NOSUCHRRTYPE" << endl;
  148. EXPECT_THROW(loadQueryData(query_stream, result_queries, query_rrclass,
  149. true), BenchMarkError);
  150. }
  151. TEST_F(LoadQueryTest, loadFromFile) {
  152. const string data_file = string(DATA_DIR) + string("/query.txt");
  153. loadQueryData(data_file.c_str(), result_queries, query_rrclass);
  154. EXPECT_LT(0, result_queries.size());
  155. // We are going to skip matching the query data; we only check the header.
  156. // We could check the data, too, but to do so we need to populate the
  157. // expected data from the file (or prepare a consistent copy locally).
  158. // Since the implementation is shared with the stringstream case, the
  159. // additional setup wouldn't be worthwhile.
  160. for_each(result_queries.begin(), result_queries.end(),
  161. QueryChecker(NULL, query_rrclass));
  162. }
  163. TEST_F(LoadQueryTest, loadFromFileNotExist) {
  164. EXPECT_THROW(loadQueryData("notexistent/query.data", result_queries,
  165. query_rrclass), BenchMarkError);
  166. }
  167. }