loadquery_unittest.cc 7.3 KB

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