master_lexer_inputsource_unittest.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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 <dns/master_lexer_inputsource.h>
  15. #include <exceptions/exceptions.h>
  16. #include <gtest/gtest.h>
  17. #include <iostream>
  18. #include <sstream>
  19. #include <string>
  20. #include <string.h>
  21. using namespace std;
  22. using namespace isc::dns;
  23. using namespace isc::dns::master_lexer_internal;
  24. namespace {
  25. class InputSourceTest : public ::testing::Test {
  26. protected:
  27. InputSourceTest() :
  28. str_("Line1 to scan.\nLine2 to scan.\nLine3 to scan.\n"),
  29. str_length_(strlen(str_)),
  30. iss_(str_),
  31. source_(iss_)
  32. {}
  33. const char* str_;
  34. const size_t str_length_;
  35. stringstream iss_;
  36. InputSource source_;
  37. };
  38. // Test the default return values set during InputSource construction.
  39. TEST_F(InputSourceTest, defaults) {
  40. EXPECT_EQ(1, source_.getCurrentLine());
  41. EXPECT_FALSE(source_.atEOF());
  42. }
  43. // getName() on file and stream sources
  44. TEST_F(InputSourceTest, getName) {
  45. EXPECT_EQ(0, source_.getName().find("stream-"));
  46. // Use some file; doesn't really matter what.
  47. InputSource source2(TEST_DATA_SRCDIR "/masterload.txt");
  48. EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", source2.getName());
  49. }
  50. TEST_F(InputSourceTest, nonExistentFile) {
  51. EXPECT_THROW({
  52. InputSource source(TEST_DATA_SRCDIR "/does-not-exist");
  53. }, InputSource::OpenError);
  54. }
  55. // getChar() should return characters from the input stream in
  56. // sequence. ungetChar() should skip backwards.
  57. void
  58. checkGetAndUngetChar(InputSource& source,
  59. const char* str, const size_t str_length)
  60. {
  61. for (size_t i = 0; i < str_length; ++i) {
  62. EXPECT_EQ(str[i], source.getChar());
  63. EXPECT_FALSE(source.atEOF());
  64. }
  65. // At this point, we still have not reached EOF.
  66. EXPECT_FALSE(source.atEOF());
  67. // This should cause EOF to be set.
  68. EXPECT_EQ(InputSource::END_OF_STREAM, source.getChar());
  69. // Now, EOF should be set.
  70. EXPECT_TRUE(source.atEOF());
  71. // Now, let's go backwards. This should cause the EOF to be set to
  72. // false.
  73. source.ungetChar();
  74. // Now, EOF should be false.
  75. EXPECT_FALSE(source.atEOF());
  76. // This should cause EOF to be set again.
  77. EXPECT_EQ(InputSource::END_OF_STREAM, source.getChar());
  78. // Now, EOF should be set.
  79. EXPECT_TRUE(source.atEOF());
  80. // Now, let's go backwards in a loop. Start by skipping the EOF.
  81. source.ungetChar();
  82. for (size_t i = 0; i < str_length; ++i) {
  83. const size_t index = str_length - 1 - i;
  84. // Skip one character.
  85. source.ungetChar();
  86. EXPECT_EQ(str[index], source.getChar());
  87. // Skip the character we received again.
  88. source.ungetChar();
  89. }
  90. // Skipping past the start of buffer should throw.
  91. EXPECT_THROW(source.ungetChar(), InputSource::UngetBeforeBeginning);
  92. }
  93. TEST_F(InputSourceTest, stream) {
  94. checkGetAndUngetChar(source_, str_, str_length_);
  95. }
  96. TEST_F(InputSourceTest, file) {
  97. std::ifstream fs(TEST_DATA_SRCDIR "/masterload.txt");
  98. const std::string str((std::istreambuf_iterator<char>(fs)),
  99. std::istreambuf_iterator<char>());
  100. fs.close();
  101. InputSource source(TEST_DATA_SRCDIR "/masterload.txt");
  102. checkGetAndUngetChar(source, str.c_str(), str.size());
  103. }
  104. // ungetAll() should skip back to the place where the InputSource
  105. // started at construction, or the last saved start of line.
  106. TEST_F(InputSourceTest, ungetAll) {
  107. while (!source_.atEOF()) {
  108. source_.getChar();
  109. }
  110. // Now, we are at EOF.
  111. EXPECT_TRUE(source_.atEOF());
  112. EXPECT_EQ(4, source_.getCurrentLine());
  113. source_.ungetAll();
  114. // Now we are back to where we started.
  115. EXPECT_EQ(1, source_.getCurrentLine());
  116. EXPECT_FALSE(source_.atEOF());
  117. }
  118. TEST_F(InputSourceTest, compact) {
  119. // Compact at the start
  120. source_.compact();
  121. // Ungetting here must throw.
  122. EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
  123. for (size_t i = 0; i < str_length_; ++i) {
  124. EXPECT_EQ(str_[i], source_.getChar());
  125. EXPECT_FALSE(source_.atEOF());
  126. }
  127. // At this point, we still have not reached EOF.
  128. EXPECT_FALSE(source_.atEOF());
  129. // This should cause EOF to be set.
  130. EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
  131. // Now, EOF should be set.
  132. EXPECT_TRUE(source_.atEOF());
  133. EXPECT_EQ(4, source_.getCurrentLine());
  134. // Compact again
  135. source_.compact();
  136. // We are still at EOF.
  137. EXPECT_TRUE(source_.atEOF());
  138. EXPECT_EQ(4, source_.getCurrentLine());
  139. // Skip the EOF.
  140. source_.ungetChar();
  141. // Ungetting here must throw.
  142. EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
  143. EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
  144. EXPECT_TRUE(source_.atEOF());
  145. }
  146. TEST_F(InputSourceTest, markDuring) {
  147. // First, skip to line 2.
  148. while (!source_.atEOF() &&
  149. (source_.getCurrentLine() != 2)) {
  150. source_.getChar();
  151. }
  152. EXPECT_FALSE(source_.atEOF());
  153. EXPECT_EQ(2, source_.getCurrentLine());
  154. // Now, unget a couple of characters. This should cause the
  155. // buffer_pos_ to be not equal to the size of the buffer.
  156. source_.ungetChar();
  157. source_.ungetChar();
  158. // Now "mark" the source, meaning that we save line number and also
  159. // compact the internal buffer at this stage.
  160. source_.mark();
  161. // Ungetting here must throw.
  162. EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
  163. for (size_t i = 13; i < str_length_; ++i) {
  164. EXPECT_EQ(str_[i], source_.getChar());
  165. EXPECT_FALSE(source_.atEOF());
  166. }
  167. // At this point, we still have not reached EOF.
  168. EXPECT_FALSE(source_.atEOF());
  169. // This should cause EOF to be set.
  170. EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
  171. // Now, EOF should be set.
  172. EXPECT_TRUE(source_.atEOF());
  173. // Now, ungetAll() and check where it goes back.
  174. source_.ungetAll();
  175. // Ungetting here must throw.
  176. EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning);
  177. for (size_t i = 13; i < str_length_; ++i) {
  178. EXPECT_EQ(str_[i], source_.getChar());
  179. EXPECT_FALSE(source_.atEOF());
  180. }
  181. // At this point, we still have not reached EOF.
  182. EXPECT_FALSE(source_.atEOF());
  183. // This should cause EOF to be set.
  184. EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar());
  185. // Now, EOF should be set.
  186. EXPECT_TRUE(source_.atEOF());
  187. }
  188. // Test line counters.
  189. TEST_F(InputSourceTest, lines) {
  190. size_t line = 1;
  191. while (!source_.atEOF()) {
  192. if (source_.getChar() == '\n') {
  193. ++line;
  194. }
  195. EXPECT_EQ(line, source_.getCurrentLine());
  196. }
  197. // Now, we are at EOF.
  198. EXPECT_TRUE(source_.atEOF());
  199. EXPECT_EQ(4, source_.getCurrentLine());
  200. // Go backwards 2 characters, skipping the last EOF and '\n'.
  201. source_.ungetChar();
  202. source_.ungetChar();
  203. EXPECT_FALSE(source_.atEOF());
  204. EXPECT_EQ(3, source_.getCurrentLine());
  205. source_.ungetAll();
  206. // Now we are back to where we started.
  207. EXPECT_EQ(1, source_.getCurrentLine());
  208. EXPECT_FALSE(source_.atEOF());
  209. // Now check that line numbers are decremented properly (as much as
  210. // possible using the available API).
  211. while (!source_.atEOF()) {
  212. source_.getChar();
  213. }
  214. line = source_.getCurrentLine();
  215. // Now, we are at EOF.
  216. EXPECT_TRUE(source_.atEOF());
  217. EXPECT_EQ(4, line);
  218. EXPECT_THROW({
  219. while (true) {
  220. source_.ungetChar();
  221. EXPECT_TRUE(((line == source_.getCurrentLine()) ||
  222. ((line - 1) == source_.getCurrentLine())));
  223. line = source_.getCurrentLine();
  224. }
  225. }, InputSource::UngetBeforeBeginning);
  226. // Now we are back to where we started.
  227. EXPECT_EQ(1, source_.getCurrentLine());
  228. }
  229. // ungetAll() after saveLine() should skip back to the last-saved place.
  230. TEST_F(InputSourceTest, saveLine) {
  231. // First, skip to line 2.
  232. while (!source_.atEOF() &&
  233. (source_.getCurrentLine() != 2)) {
  234. source_.getChar();
  235. }
  236. EXPECT_FALSE(source_.atEOF());
  237. EXPECT_EQ(2, source_.getCurrentLine());
  238. // Now, save the line.
  239. source_.saveLine();
  240. // Now, go to EOF
  241. while (!source_.atEOF()) {
  242. source_.getChar();
  243. }
  244. // Now, we are at EOF.
  245. EXPECT_TRUE(source_.atEOF());
  246. EXPECT_EQ(4, source_.getCurrentLine());
  247. // Now, ungetAll() and check where it goes back.
  248. source_.ungetAll();
  249. // Now we are back to where we last-saved.
  250. EXPECT_EQ(2, source_.getCurrentLine());
  251. EXPECT_FALSE(source_.atEOF());
  252. }
  253. } // end namespace