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