Home | History | Annotate | Download | only in gn
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "testing/gtest/include/gtest/gtest.h"
      6 #include "tools/gn/c_include_iterator.h"
      7 #include "tools/gn/input_file.h"
      8 #include "tools/gn/location.h"
      9 
     10 namespace {
     11 
     12 bool RangeIs(const LocationRange& range,
     13              int line, int begin_char, int end_char) {
     14   return range.begin().line_number() == line &&
     15          range.end().line_number() == line &&
     16          range.begin().char_offset() == begin_char &&
     17          range.end().char_offset() == end_char;
     18 }
     19 
     20 }  // namespace
     21 
     22 TEST(CIncludeIterator, Basic) {
     23   std::string buffer;
     24   buffer.append("// Some comment\n");
     25   buffer.append("\n");
     26   buffer.append("#include \"foo/bar.h\"\n");
     27   buffer.append("\n");
     28   buffer.append("#include <stdio.h>\n");
     29   buffer.append("\n");
     30   buffer.append(" #include \"foo/baz.h\"\n");  // Leading whitespace
     31   buffer.append("#include \"la/deda.h\"\n");
     32   buffer.append("#import \"weird_mac_import.h\"\n");
     33   buffer.append("\n");
     34   buffer.append("void SomeCode() {\n");
     35 
     36   InputFile file(SourceFile("//foo.cc"));
     37   file.SetContents(buffer);
     38 
     39   CIncludeIterator iter(&file);
     40 
     41   base::StringPiece contents;
     42   LocationRange range;
     43   EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
     44   EXPECT_EQ("foo/bar.h", contents);
     45   EXPECT_TRUE(RangeIs(range, 3, 11, 20)) << range.begin().Describe(true);
     46 
     47   EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
     48   EXPECT_EQ("foo/baz.h", contents);
     49   EXPECT_TRUE(RangeIs(range, 7, 12, 21)) << range.begin().Describe(true);
     50 
     51   EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
     52   EXPECT_EQ("la/deda.h", contents);
     53   EXPECT_TRUE(RangeIs(range, 8, 11, 20)) << range.begin().Describe(true);
     54 
     55   EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
     56   EXPECT_EQ("weird_mac_import.h", contents);
     57   EXPECT_TRUE(RangeIs(range, 9, 10, 28)) << range.begin().Describe(true);
     58 
     59   EXPECT_FALSE(iter.GetNextIncludeString(&contents, &range));
     60 }
     61 
     62 // Tests that we don't search for includes indefinitely.
     63 TEST(CIncludeIterator, GiveUp) {
     64   std::string buffer;
     65   for (size_t i = 0; i < 1000; i++)
     66     buffer.append("x\n");
     67   buffer.append("#include \"foo/bar.h\"\n");
     68 
     69   InputFile file(SourceFile("//foo.cc"));
     70   file.SetContents(buffer);
     71 
     72   base::StringPiece contents;
     73   LocationRange range;
     74 
     75   CIncludeIterator iter(&file);
     76   EXPECT_FALSE(iter.GetNextIncludeString(&contents, &range));
     77   EXPECT_TRUE(contents.empty());
     78 }
     79 
     80 // Don't count blank lines, comments, and preprocessor when giving up.
     81 TEST(CIncludeIterator, DontGiveUp) {
     82   std::string buffer;
     83   for (size_t i = 0; i < 1000; i++)
     84     buffer.push_back('\n');
     85   for (size_t i = 0; i < 1000; i++)
     86     buffer.append("// comment\n");
     87   for (size_t i = 0; i < 1000; i++)
     88     buffer.append("#preproc\n");
     89   buffer.append("#include \"foo/bar.h\"\n");
     90 
     91   InputFile file(SourceFile("//foo.cc"));
     92   file.SetContents(buffer);
     93 
     94   base::StringPiece contents;
     95   LocationRange range;
     96 
     97   CIncludeIterator iter(&file);
     98   EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
     99   EXPECT_EQ("foo/bar.h", contents);
    100 }
    101 
    102 // Tests that we'll tolerate some small numbers of non-includes interspersed
    103 // with real includes.
    104 TEST(CIncludeIterator, TolerateNonIncludes) {
    105   const size_t kSkip = CIncludeIterator::kMaxNonIncludeLines - 2;
    106   const size_t kGroupCount = 100;
    107 
    108   std::string include("foo/bar.h");
    109 
    110   // Allow a series of includes with blanks in between.
    111   std::string buffer;
    112   for (size_t group = 0; group < kGroupCount; group++) {
    113     for (size_t i = 0; i < kSkip; i++)
    114       buffer.append("foo\n");
    115     buffer.append("#include \"" + include + "\"\n");
    116   }
    117 
    118   InputFile file(SourceFile("//foo.cc"));
    119   file.SetContents(buffer);
    120 
    121   base::StringPiece contents;
    122   LocationRange range;
    123 
    124   CIncludeIterator iter(&file);
    125   for (size_t group = 0; group < kGroupCount; group++) {
    126     EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
    127     EXPECT_EQ(include, contents.as_string());
    128   }
    129   EXPECT_FALSE(iter.GetNextIncludeString(&contents, &range));
    130 }
    131