| #!/usr/bin/env python |
| |
| ##===--- fix_includes_test.py - test for fix_includes.py ------------------===## |
| # |
| # The LLVM Compiler Infrastructure |
| # |
| # This file is distributed under the University of Illinois Open Source |
| # License. See LICENSE.TXT for details. |
| # |
| ##===----------------------------------------------------------------------===## |
| |
| from __future__ import print_function |
| |
| """Test for fix_includes.py |
| |
| Test test test! |
| """ |
| |
| __author__ = 'csilvers@google.com (Craig Silverstein)' |
| |
| try: |
| from cStringIO import StringIO |
| except ImportError: |
| from io import StringIO |
| |
| import re |
| import sys |
| # I use unittest instead of googletest to ease opensourcing. |
| import unittest |
| import fix_includes |
| |
| |
| class FakeFlags(object): |
| def __init__(self): |
| self.blank_lines = False |
| self.comments = True |
| self.dry_run = False |
| self.ignore_re = None |
| self.only_re = None |
| self.safe_headers = False |
| self.separate_project_includes = None |
| self.keep_iwyu_namespace_format = False |
| self.reorder = True |
| self.basedir = None |
| |
| |
| class FixIncludesBase(unittest.TestCase): |
| """Does setup that every test will want.""" |
| |
| def _ReadFile(self, filename, fileinfo): |
| assert filename in self.before_map, filename |
| return self.before_map[filename] |
| |
| def _ParseFileInfo(self, filename): |
| return fix_includes.FileInfo('\n', 'utf-8') |
| |
| def _WriteFile(self, filename, fileinfo, contents): |
| return self.actual_after_contents.extend(contents) |
| |
| def setUp(self): |
| self.flags = FakeFlags() |
| |
| # Map from filename to its contents (a list of lines) before fixing. |
| self.before_map = {} |
| # Map from filename to the 'correct' contents it should have after fixing. |
| self.expected_after_map = {} |
| |
| # INPUT: fix_includes._ReadFile takes a filename |
| # and returns the contents of filename (as a list). |
| # FileInfo controls encoding details of the file, |
| # wire it to return something that agrees with the |
| # tests. |
| fix_includes._ReadFile = self._ReadFile |
| fix_includes.FileInfo.parse = self._ParseFileInfo |
| |
| # OUTPUT: Instead of writing to file, save full output. |
| self.actual_after_contents = [] |
| fix_includes._WriteFile = self._WriteFile |
| |
| # Stub out stdout |
| self.stdout_stub = StringIO() |
| fix_includes.sys.stdout = self.stdout_stub |
| |
| def RegisterFileContents(self, file_contents_map): |
| """Parses and stores the given map from filename to file-contents. |
| |
| The values of the map are file 'contents', written in a simple |
| markup language that allows us to encode both the 'before' and |
| expected 'after' contents of a file. Every line is taken |
| literally to be in both the before and after, with the following |
| exceptions: |
| 1) Lines that look like '///+foo' are removed from 'before', |
| and replaced by 'foo' in 'after'. (This is an 'add' |
| instruction.) |
| 2) Lines that end in '///-' are removed from both 'after' |
| and the '\s*///-' suffix is removed from 'before'. |
| (This is a 'remove' instruction.) |
| |
| This function processes the input map to produce self.before_map |
| and self.expected_after_map. |
| |
| Arguments: |
| file_contents_map: a map from filename to 'contents'. Contents |
| is a string, having the format mentioned above. |
| """ |
| remove_re = re.compile('\s*///-$') |
| for (filename, contents) in file_contents_map.items(): |
| before_contents = [] |
| expected_after_contents = [] |
| for line in contents.splitlines(True): |
| m = remove_re.search(line) |
| if m: |
| # The trailing line separator is stripped, so append a '\n'. |
| before_contents.append(line[:m.start()] + '\n') |
| elif line.startswith('///+'): |
| expected_after_contents.append(line[len('///+'):]) |
| else: |
| before_contents.append(line) |
| expected_after_contents.append(line) |
| self.before_map[filename] = before_contents |
| self.expected_after_map[filename] = expected_after_contents |
| |
| def ProcessAndTest(self, iwyu_output, cmdline_files=None, unedited_files=[], |
| expected_num_modified_files=None, cwd=None): |
| """For all files mentioned in iwyu_output, compare expected and actual. |
| |
| Arguments: |
| iwyu_output: the output the iwyu script gave when run over the |
| set of input files. |
| cmdline_files: files to pass in to ProcessIWYUOutput (that, in |
| an actual fix_includes run, would come from the commandline). |
| These limit what files fix_includes chooses to edit. |
| unedited_files: the list of files that are listed in iwyu_output, |
| but fix_files has chosen not to edit for some reason. |
| expected_num_modified_files: what we expect ProcessIWYUOutput to |
| return. If None, suppress this check. |
| cwd: working directory passed to ProcessIWYUOutput, used to normalize |
| paths in cmdline_files. If None, no normalization occurs. |
| """ |
| filenames = re.findall('^(\S+) should add these lines:', iwyu_output, re.M) |
| if not filenames: # This is the other possible starting-line |
| filenames = re.findall('^\((\S+) has correct #includes/fwd-decls\)', |
| iwyu_output, re.M) |
| |
| expected_after = [] |
| for filename in fix_includes.OrderedSet(filenames): # uniquify |
| filename = fix_includes.NormalizeFilePath(self.flags.basedir, filename) |
| if filename not in unedited_files: |
| expected_after.extend(self.expected_after_map[filename]) |
| |
| iwyu_output_as_file = StringIO(iwyu_output) |
| num_modified_files = fix_includes.ProcessIWYUOutput(iwyu_output_as_file, |
| cmdline_files, |
| self.flags, |
| cwd=cwd) |
| |
| if expected_after != self.actual_after_contents: |
| print("=== Expected:") |
| for line in expected_after: |
| print(line) |
| print("=== Got:") |
| for line in self.actual_after_contents: |
| print(line) |
| print("===") |
| self.assertListEqual(expected_after, self.actual_after_contents) |
| if expected_num_modified_files is not None: |
| self.assertEqual(expected_num_modified_files, num_modified_files) |
| |
| |
| class FixIncludesTest(FixIncludesBase): |
| """End-to-end tests from input file to output file.""" |
| |
| def testSimple(self): |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| simple should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| simple should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for simple: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'simple': infile}) |
| self.ProcessAndTest(iwyu_output, expected_num_modified_files=1) |
| |
| def testUnifiedDiffOutput(self): |
| """Test the unified diff output generated by dry runs.""" |
| infile = """ |
| #include <notused.h> |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| unified_diff.cc should add these lines: |
| |
| unified_diff.cc should remove these lines: |
| - #include <notused.h> // lines 2-2 |
| |
| The full include-list for unified_diff.cc: |
| --- |
| """ |
| diff_expect = """\ |
| >>> Fixing #includes in 'unified_diff.cc' |
| @@ -1,4 +1,2 @@ |
| - |
| -#include <notused.h> |
| |
| int main() { return 0; } |
| IWYU edited 1 files on your behalf. |
| |
| """ |
| |
| self.flags.dry_run = True |
| self.RegisterFileContents({'unified_diff.cc': infile}) |
| self.ProcessAndTest(iwyu_output, unedited_files=['unified_diff.cc']) |
| |
| self.assertEqual(self.stdout_stub.getvalue(), diff_expect) |
| |
| def testNodiffOutput(self): |
| """Tests handling of the '(<file> has correct #includes)' iwyu output.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| #include <ctype.h> // iwyu will not reorder, even though non-alphabetical |
| |
| namespace Foo; |
| |
| namespace Bar; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = "(nodiffs.h has correct #includes/fwd-decls)\n" |
| self.RegisterFileContents({'nodiffs.h': infile}) |
| # fix_includes gives special output when there are no changes, so |
| # we can't use the normal ProcessAndTest. |
| iwyu_output_as_file = StringIO(iwyu_output) |
| num_modified_files = fix_includes.ProcessIWYUOutput(iwyu_output_as_file, |
| None, self.flags, None) |
| self.assertListEqual([], self.actual_after_contents) # 'no diffs' |
| self.assertEqual(0, num_modified_files) |
| |
| def testNodiffOutputWithNoSorting(self): |
| """Tests 'correct #includes' iwyu output, but does not need reordering.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <ctype.h> |
| #include <stdio.h> |
| |
| namespace Foo; |
| |
| namespace Bar; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = "(nodiffs_nosorting.h has correct #includes/fwd-decls)\n" |
| self.RegisterFileContents({'nodiffs_nosorting.h': infile}) |
| # fix_includes gives special output when there are no changes, so |
| # we can't use the normal ProcessAndTest. |
| iwyu_output_as_file = StringIO(iwyu_output) |
| num_modified_files = fix_includes.ProcessIWYUOutput(iwyu_output_as_file, |
| None, self.flags, None) |
| self.assertListEqual([], self.actual_after_contents) # 'no diffs' |
| self.assertEqual(0, num_modified_files) |
| |
| def testRemoveEmptyNamespace(self): |
| """Tests we remove a namespace if we remove all fwd-decls inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| |
| namespace ns { ///- |
| class Foo; ///- |
| namespace ns2 { ///- |
| namespace ns3 { ///- |
| class Bar; ///- |
| } } ///- |
| class Baz; ///- |
| } ///- |
| ///- |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_namespace should add these lines: |
| |
| empty_namespace should remove these lines: |
| - class Foo; // lines 6-6 |
| - namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } // lines 9-9 |
| - namespace ns { class Baz; } } // lines 11-11 |
| |
| The full include-list for empty_namespace: |
| #include <stdio.h> |
| --- |
| """ |
| self.RegisterFileContents({'empty_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveEmptyAllmanNamespace(self): |
| """Tests we remove a namespace with Allman braces if we remove all fwd-decls inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| |
| namespace ns ///- |
| { ///- |
| class Foo; ///- |
| namespace ns2 ///- |
| { ///- |
| namespace ns3 ///- |
| { ///- |
| class Bar; ///- |
| } ///- |
| } ///- |
| class Baz; ///- |
| } ///- |
| ///- |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_namespace should add these lines: |
| |
| empty_namespace should remove these lines: |
| - class Foo; // lines 7-7 |
| - namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } // lines 12-12 |
| - namespace ns { class Baz; } } // lines 15-15 |
| |
| The full include-list for empty_namespace: |
| #include <stdio.h> |
| --- |
| """ |
| self.RegisterFileContents({'empty_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveEmptyMixedNamespace(self): |
| """Tests we remove a namespace with mixed braces if we remove all fwd-decls inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| |
| namespace ns ///- |
| { ///- |
| class Foo; ///- |
| namespace ns2 { namespace ns3 ///- |
| { ///- |
| class Bar; ///- |
| } ///- |
| } ///- |
| class Baz; ///- |
| } ///- |
| ///- |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_namespace should add these lines: |
| |
| empty_namespace should remove these lines: |
| - class Foo; // lines 7-7 |
| - namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } // lines 10-10 |
| - namespace ns { class Baz; } } // lines 13-13 |
| |
| The full include-list for empty_namespace: |
| #include <stdio.h> |
| --- |
| """ |
| self.RegisterFileContents({'empty_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testCXX17NS(self): |
| """Tests handling of output using the --cxx17ns switch.""" |
| infile = """\ |
| #include "cxx17ns-i1.h"///- |
| ///+ |
| ///+namespace a::b::c { |
| ///+struct One; |
| ///+} // namespace a::b::c |
| ///+namespace a::b { |
| ///+struct One2; |
| ///+} // namespace a::b |
| ///+namespace a { |
| ///+struct One4; |
| ///+struct One3; |
| ///+} // namespace a |
| |
| struct Two { |
| Two(a::b::c::One& one); |
| Two(a::b::One2& one); |
| Two(a::One3& one); |
| Two(a::One4& one); |
| }; |
| """ |
| iwyu_output = """\ |
| cxx17ns.cc should add these lines: |
| namespace a { namespace { struct One4; } } |
| namespace a { struct One3; } |
| namespace a::b { struct One2; } |
| namespace a::b::c { struct One; } |
| |
| cxx17ns.cc should remove these lines: |
| - #include "cxx17ns-i1.h" // lines 1-1 |
| |
| The full include-list for cxx17ns.cc: |
| namespace a { namespace { struct One4; } } |
| namespace a { struct One3; } |
| namespace a::b { struct One2; } |
| namespace a::b::c { struct One; } |
| --- |
| """ |
| self.RegisterFileContents({'cxx17ns.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemovePartOfEmptyNamespace(self): |
| """Tests we remove a namespace if empty, but not enclosing namespaces.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| namespace maps_transit_realtime { |
| namespace service_alerts { |
| class StaticServiceAlertStore; |
| namespace trigger { ///- |
| class Trigger; ///- |
| } // namespace trigger ///- |
| namespace ui { ///- |
| class Alert; ///- |
| } // namespace ui ///- |
| } // namespace service_alerts |
| } // namespace maps_transit_realtime |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_internal_namespace should add these lines: |
| |
| empty_internal_namespace should remove these lines: |
| - namespace maps_transit_realtime { namespace service_alerts { namespace trigger { class Trigger; } } } // lines 7-7 |
| - namespace maps_transit_realtime { namespace service_alerts { namespace ui { class Alert; } } } // lines 10-10 |
| |
| The full include-list for empty_internal_namespace: |
| namespace maps_transit_realtime { namespace service_alerts { class StaticServiceAlertStore; } } // lines 5-5 |
| --- |
| """ |
| self.RegisterFileContents({'empty_internal_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemovePartOfEmptyAllmanNamespace(self): |
| """Tests we remove a namespace with Allman braces if empty, but not enclosing namespaces.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| namespace maps_transit_realtime |
| { |
| namespace service_alerts |
| { |
| class StaticServiceAlertStore; |
| namespace trigger ///- |
| { ///- |
| class Trigger; ///- |
| } // namespace trigger ///- |
| namespace ui ///- |
| { ///- |
| class Alert; ///- |
| } // namespace ui ///- |
| } // namespace service_alerts |
| } // namespace maps_transit_realtime |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_internal_namespace should add these lines: |
| |
| empty_internal_namespace should remove these lines: |
| - namespace maps_transit_realtime { namespace service_alerts { namespace trigger { class Trigger; } } } // lines 10-10 |
| - namespace maps_transit_realtime { namespace service_alerts { namespace ui { class Alert; } } } // lines 14-14 |
| |
| The full include-list for empty_internal_namespace: |
| namespace maps_transit_realtime { namespace service_alerts { class StaticServiceAlertStore; } } // lines 7-7 |
| --- |
| """ |
| self.RegisterFileContents({'empty_internal_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemovePartOfEmptyMixedNamespace(self): |
| """Tests we remove a namespace with mixed braces if empty, but not enclosing namespaces.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| namespace maps_transit_realtime |
| { |
| class StaticServiceAlertStore; |
| namespace service_alerts { namespace trigger ///- |
| { ///- |
| class Trigger; ///- |
| } // namespace trigger ///- |
| namespace ui ///- |
| { ///- |
| class Alert; ///- |
| } // namespace ui ///- |
| } // namespace service_alerts ///- |
| } // namespace maps_transit_realtime |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_internal_namespace should add these lines: |
| |
| empty_internal_namespace should remove these lines: |
| - namespace maps_transit_realtime { namespace service_alerts { namespace trigger { class Trigger; } } } // lines 8-8 |
| - namespace maps_transit_realtime { namespace service_alerts { namespace ui { class Alert; } } } // lines 12-12 |
| |
| The full include-list for empty_internal_namespace: |
| namespace maps_transit_realtime { class StaticServiceAlertStore; } // lines 5-5 |
| --- |
| """ |
| self.RegisterFileContents({'empty_internal_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveEmptyIfdef(self): |
| """Tests we remove an #ifdef if we remove all #includes inside it.""" |
| # Also makes sure we reorder properly around the removed ifdef. |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| ///+#include <stdlib.h> |
| // Only on windows. ///- |
| #ifdef OS_WINDOWS ///- |
| #include <notused.h> ///- |
| #include <notused2.h> ///- |
| #endif ///- |
| #include "used.h" |
| #include <stdlib.h> ///- |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_ifdef should add these lines: |
| #include "used2.h" |
| |
| empty_ifdef should remove these lines: |
| - #include <notused.h> // lines 6-6 |
| - #include <notused2.h> // lines 7-7 |
| |
| The full include-list for empty_ifdef: |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'empty_ifdef': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveEmptyNestedIfdef(self): |
| """Tests we remove an empty #ifdef inside a non-empty #ifdef.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| #ifdef NDEBUG |
| // Only on windows. ///- |
| # ifdef OS_WINDOWS ///- |
| # include <notused.h> ///- |
| # include <notused2.h> ///- |
| # endif ///- |
| # undef VERBOSE_LOGGING |
| #endif |
| ///+#include <stdlib.h> |
| #include "used.h" |
| #include <stdlib.h> ///- |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| empty_nested_ifdef should add these lines: |
| #include "used2.h" |
| |
| empty_nested_ifdef should remove these lines: |
| - #include <notused.h> // lines 7-7 |
| - #include <notused2.h> // lines 8-8 |
| |
| The full include-list for empty_nested_ifdef: |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'empty_nested_ifdef': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testNonEmptyIfdef(self): |
| """Tests we keep an #ifdef if we don't remove all #includes inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| #ifdef OS_WINDOWS |
| #include <notused.h> ///- |
| #include <used_win.h> |
| #endif |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| nonempty_ifdef should add these lines: |
| #include "used2.h" |
| |
| nonempty_ifdef should remove these lines: |
| - #include <notused.h> // lines 5-5 |
| |
| The full include-list for nonempty_ifdef: |
| #include <used_win.h> |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'nonempty_ifdef': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testKeepIfdefsWithNonIncludes(self): |
| """Tests we keep an #ifdef if we have a non-#include inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| #ifdef OS_WINDOWS |
| #define IN_WINDOWS |
| #include <notused.h> ///- |
| #endif |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| nonempty_ifdef should add these lines: |
| #include "used2.h" |
| |
| nonempty_ifdef should remove these lines: |
| - #include <notused.h> // lines 6-6 |
| |
| The full include-list for nonempty_ifdef: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'nonempty_ifdef': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveComments(self): |
| """Tests we remove comments above #includes.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| // This file is not used. ///- |
| #include <notused.h> ///- |
| ///- |
| // This file is not used either. ///- |
| // It's not used. ///- |
| // Not used at all. ///- |
| #include <notused2.h> ///- |
| ///- |
| #include "notused3.h" ///- |
| |
| // This comment should stay, it's not before an #include. |
| const int kInt = 5; |
| // This file is used. |
| // It's definitedly used. |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| const int kInt2 = 6; |
| ///- |
| // This forward-declare is in a reorder_span all by itself. ///- |
| class NotUsed; ///- |
| |
| // This comment should stay, it's not before an #include. |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| remove_comments should add these lines: |
| #include "used2.h" |
| |
| remove_comments should remove these lines: |
| - #include <notused.h> // lines 5-5 |
| - #include <notused2.h> // lines 10-10 |
| - #include "notused3.h" // lines 12-12 |
| - class NotUsed; // lines 23-23 |
| |
| The full include-list for remove_comments: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'remove_comments': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testNoBlankLineAfterTopOfFileCxxComments(self): |
| """Tests we don't remove top-of-file c++ comments right before #includes.""" |
| infile = """\ |
| // Copyright 2010 |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| top_of_file_comments.cc should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| top_of_file_comments.cc should remove these lines: |
| - #include <notused.h> // lines 2-2 |
| |
| The full include-list for top_of_file_comments.cc: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'top_of_file_comments.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testNoBlankLineAfterTopOfFileCComments(self): |
| """Tests we don't remove top-of-file c comments right before #includes.""" |
| infile = """\ |
| /* |
| * Copyright 2010 |
| */ |
| #include <notused.h> ///- |
| /* This is a one-line c-style comment. */ ///- |
| #include <notused2.h> /* this is a c-style comment after a line */ ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| top_of_file_comments.c should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| top_of_file_comments.c should remove these lines: |
| - #include <notused.h> // lines 4-4 |
| - #include <notused2.h> // lines 6-6 |
| |
| The full include-list for top_of_file_comments.c: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'top_of_file_comments.c': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testNotFullLineCComments(self): |
| """Tests that we treat lines with c comments then code as code-lines.""" |
| infile = """\ |
| // Copyright 2010 |
| ///+#include <stdio.h> |
| ///+ |
| /* code here */ x = 4; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| not_full_line_c_comments.c should add these lines: |
| #include <stdio.h> |
| |
| not_full_line_c_comments.c should remove these lines: |
| |
| The full include-list for not_full_line_c_comments.c: |
| #include <stdio.h> |
| --- |
| """ |
| self.RegisterFileContents({'not_full_line_c_comments.c': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testUnusualHFileNames(self): |
| """Tests we treat .pb.h files as header files.""" |
| infile = """\ |
| /* |
| * Copyright 2010 |
| */ |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.pb.h" |
| ///+#include "used2.pb.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| pb.h.cc should add these lines: |
| #include <stdio.h> |
| #include "used2.pb.h" |
| |
| pb.h.cc should remove these lines: |
| - #include <notused.h> // lines 4-4 |
| |
| The full include-list for pb.h.cc: |
| #include <stdio.h> |
| #include "used.pb.h" |
| #include "used2.pb.h" |
| --- |
| """ |
| self.RegisterFileContents({'pb.h.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testFwdDeclLines(self): |
| """Tests that we keep or remove forward declares based on iwyu output.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| struct KeepStruct; |
| class NoKeepClass; ///- |
| template<typename Foo> class KeepTplClass; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| fwd_decl should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| fwd_decl should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - class NoKeepClass; // lines 7-7 |
| |
| The full include-list for fwd_decl: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| struct KeepStruct; // lines 6-6 |
| template<typename Foo> class KeepTplClass; // lines 8-8 |
| --- |
| """ |
| self.RegisterFileContents({'fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testMultiLineFwdDecls(self): |
| """Tests we keep forward-decls that span more than one line.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| struct KeepStruct; |
| class NoKeepClass; ///- |
| template<typename Foo, typename Bar = Baz> |
| class Keep2LineTplClass; |
| template<typename Foo, typename Bar = Baz> ///- |
| class NoKeep2LineTplClass; ///- |
| template<typename Foo, |
| typename Bar = Baz> |
| class Keep3LineTplClass; |
| template<typename Foo, ///- |
| typename Bar = Baz> ///- |
| class NoKeep3LineTplClass; ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| multiline_fwd_decl should add these lines: |
| |
| multiline_fwd_decl should remove these lines: |
| - class NoKeepClass; // lines 4-4 |
| - template<typename Foo, typename Bar = Baz> class NoKeep2LineTplClass; // lines 7-8 |
| - template<typename Foo, typename Bar = Baz> class NoKeep3LineTplClass; // lines 12-14 |
| |
| The full include-list for multiline_fwd_decl: |
| struct KeepStruct; // lines 3-3 |
| template<typename Foo, typename Bar=Baz> class Keep2LineTplClass; // lines 5-6 |
| template<typename Foo, typename Bar=Baz> class Keep3LineTplClass; // lines 9-11 |
| --- |
| """ |
| self.RegisterFileContents({'multiline_fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testKeepExplicitSpecializations(self): |
| """Tests we don't interpret an explicit spec. as a forward-declare.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| struct KeepStruct; |
| class NoKeepClass; ///- |
| template<typename Foo> class KeepTplClass; |
| ///+ |
| template<> class KeepTplClass<int>; |
| template<typename T> void TplFn<T>(); |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| explicit_specialization should add these lines: |
| |
| explicit_specialization should remove these lines: |
| - class NoKeepClass; // lines 4-4 |
| |
| The full include-list for explicit_specialization: |
| struct KeepStruct; // lines 3-3 |
| template<typename Foo> class KeepTplClass; // lines 5-5 |
| --- |
| """ |
| self.RegisterFileContents({'explicit_specialization': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testKeepNestedForwardDeclares(self): |
| """Tests that we don't remove forward-declares inside classes/structs.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| class Keep; |
| class NoKeep; ///- |
| ///+ |
| class Nest { |
| class NestedClass; |
| ///+ |
| class NestedClass { |
| }; |
| class NestedClass2 { }; // looks just like a fwd declare, except for the {} |
| template<typename T> |
| class NestedTplClass; // test multi-line nested classes as well |
| ///+ |
| friend class NoKeep; |
| template<typename T> friend class NoKeepTpl; |
| }; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| nested_fwd_decl should add these lines: |
| |
| nested_fwd_decl should remove these lines: |
| - class NoKeep; // lines 4-4 |
| |
| The full include-list for nested_fwd_decl: |
| class Keep; // lines 3-3 |
| class Nest::NestedClass; // lines 6-6 |
| template<typename T> class Nest::NestedTplClass; // lines 11-11 |
| --- |
| """ |
| self.RegisterFileContents({'nested_fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareBeforeUsingStatement(self): |
| """Tests we never add a forward-declare after a contentful line.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| ///+namespace Bar { |
| ///+class Baz; |
| ///+} // namespace Bar |
| ///+ |
| using Bar::baz; |
| |
| namespace Foo { class Bang; } ///- |
| ///+namespace Foo { |
| ///+class Bang; |
| ///+} // namespace Foo |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_before_using should add these lines: |
| namespace Bar { class Baz; } |
| |
| add_fwd_decl_before_using should remove these lines: |
| |
| The full include-list for add_fwd_decl_before_using: |
| #include "foo.h" |
| namespace Bar { class Baz; } |
| namespace Foo { class Bang; } // lines 7-7 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_before_using': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInNamespace(self): |
| """Make sure we normalize namespaces properly.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| ///+namespace ns { |
| ///+class Foo; |
| ///+namespace ns2 { |
| ///+namespace ns3 { |
| ///+class Bar; |
| ///+template <typename T> class Bang; |
| ///+} // namespace ns3 |
| ///+} // namespace ns2 |
| ///+namespace ns4 { |
| ///+class Baz; |
| ///+} // namespace ns4 |
| ///+} // namespace ns |
| ///+ |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_namespace should add these lines: |
| namespace ns { class Foo; } |
| namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| namespace ns { namespace ns4 { class Baz; } } |
| |
| add_fwd_decl_inside_namespace should remove these lines: |
| |
| The full include-list for add_fwd_decl_inside_namespace: |
| #include "foo.h" // lines 3-3 |
| namespace ns { class Foo; } |
| namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| namespace ns { namespace ns4 { class Baz; } } |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNamespaceSometimes(self): |
| """Tests that in special situations, we will put fwd-decls inside a ns.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| class Bar; |
| template <typename T> class Baz; |
| |
| namespace ns { |
| |
| namespace ns2 { // we sure do love nesting our namespaces! |
| |
| class NsFoo; |
| ///+namespace ns3 { |
| ///+class NsBang; |
| ///+template <typename T> class NsBaz; |
| ///+} // namespace ns3 |
| template <typename T> class NsBar; |
| |
| } |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_namespace should add these lines: |
| namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } } |
| |
| add_fwd_decl_inside_namespace should remove these lines: |
| |
| The full include-list for add_fwd_decl_inside_namespace: |
| #include "foo.h" // lines 3-3 |
| class Bar; // lines 5-5 |
| namespace ns { namespace ns2 { class NsFoo; } } // lines 12-12 |
| namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } } |
| namespace ns { namespace ns2 { template <typename T> class NsBar; } } // lines 13-13 |
| template <typename T> class Baz; // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNamespaceWithHeaderGuard(self): |
| """Tests that the header guard doesn't confuse our in-ns algorithm.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #ifndef HDR_GUARD |
| #define HDR_GUARD |
| |
| #include "foo.h" |
| |
| class Bar; |
| template <typename T> class Baz; |
| |
| namespace ns { |
| |
| namespace ns2 { // we sure do love nesting our namespaces! |
| |
| class NsFoo; |
| ///+namespace ns3 { |
| ///+class NsBang; |
| ///+template <typename T> class NsBaz; |
| ///+} // namespace ns3 |
| template <typename T> class NsBar; |
| |
| } |
| } |
| |
| #endif // HDR_GUARD |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_with_hdr_guard should add these lines: |
| namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } } |
| |
| add_fwd_decl_with_hdr_guard should remove these lines: |
| |
| The full include-list for add_fwd_decl_with_hdr_guard: |
| #include "foo.h" // lines 6-6 |
| class Bar; // lines 8-8 |
| namespace ns { namespace ns2 { class NsFoo; } } // lines 15-15 |
| namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } } |
| namespace ns { namespace ns2 { template <typename T> class NsBar; } } // lines 16-16 |
| template <typename T> class Baz; // lines 9-9 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_with_hdr_guard': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNamespaceWithIfDef(self): |
| """Tests that ifdef blocks are ignored when finding namespaces.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| class Bar; |
| template <typename T> class Baz; |
| |
| #ifdef THIS_IS_A_CONTENTFUL_LINE |
| #include "bar.h" |
| #endif |
| |
| namespace ns { |
| |
| namespace ns2 { |
| |
| ///+class NsBang; |
| class NsFoo; |
| template <typename T> class NsBar; |
| ///+template <typename T> class NsBaz; |
| |
| } |
| |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_forward_declares_after_ifdef_code should add these lines: |
| namespace ns { namespace ns2 { class NsBang; } } |
| namespace ns { namespace ns2 { template <typename T> class NsBaz; } } |
| |
| add_forward_declares_after_ifdef_code should remove these lines: |
| |
| The full include-list for add_forward_declares_after_ifdef_code: |
| #include "foo.h" // lines 3-3 |
| class Bar; // lines 5-5 |
| namespace ns { namespace ns2 { class NsBang; } } |
| namespace ns { namespace ns2 { class NsFoo; } } // lines 16-16 |
| namespace ns { namespace ns2 { template <typename T> class NsBar; } } // lines 17-17 |
| namespace ns { namespace ns2 { template <typename T> class NsBaz; } } |
| template <typename T> class Baz; // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'add_forward_declares_after_ifdef_code': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNamespaceWithoutForwardDeclaresAlready(self): |
| """Tests we put fwd-decls inside an ns even if the ns has no fwd-decl.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| class Bar; |
| template <typename T> class Baz; |
| |
| namespace ns { |
| |
| namespace ns2 { // we sure do love nesting our namespaces! |
| ///- |
| ///+namespace ns3 { |
| ///+class NsBang; |
| ///+template <typename T> class NsBaz; |
| ///+} // namespace ns3 |
| ///+ |
| int MyFunction() { } |
| |
| } |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_namespace_without_fwd_decl should add these lines: |
| namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } } |
| |
| add_fwd_decl_inside_namespace_without_fwd_decl should remove these lines: |
| |
| The full include-list for add_fwd_decl_inside_namespace_without_fwd_decl: |
| #include "foo.h" // lines 3-3 |
| class Bar; // lines 5-5 |
| namespace ns { namespace ns2 { namespace ns3 { class NsBang; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBaz; } } } |
| template <typename T> class Baz; // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_namespace_without_fwd_decl': |
| infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNamespaceWithCompactEndings(self): |
| """Tests we put fwd-decls inside an ns when using compact namespace endings.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| namespace ns { namespace ns1 { namespace ns2 { |
| class Ns2Bang; |
| }} // namespace ns2 // namespace ns1 |
| ///+class NsBar; |
| class NsBaz; |
| ///- |
| namespace ns3 { namespace ns4 { ///- |
| class Ns4Bye; ///- |
| }} // namespace ns4 // namespace ns3 ///- |
| } // namespace ns |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_namespace_without_compact_endings should add these lines: |
| namespace ns { class NsBar; } |
| |
| add_fwd_decl_inside_namespace_without_compact_endings should remove these lines: |
| - namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { namespace ns4 { class Ns4Bye; } } } } } // lines 9-9 |
| |
| The full include-list for add_fwd_decl_inside_namespace_without_compact_endings: |
| namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } } // lines 4-4 |
| namespace ns { class NsBaz; } // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_namespace_without_compact_endings': |
| infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNamespaceWithUnnamedNamespace(self): |
| """Tests that unnamed namespaces do not mess up our in-ns calculation.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| class Bar; |
| |
| namespace ns { |
| ///+class NsBang; |
| ///+template <typename T> class NsBaz; |
| |
| namespace { |
| class NsFoo; |
| template <typename T> class NsBar; |
| } |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_namespace_unnamed_ns should add these lines: |
| namespace ns { class NsBang; } |
| namespace ns { template <typename T> class NsBaz; } |
| |
| add_fwd_decl_inside_namespace_unnamed_ns should remove these lines: |
| |
| The full include-list for add_fwd_decl_inside_namespace_unnamed_ns: |
| #include "foo.h" // lines 3-3 |
| class Bar; // lines 5-5 |
| namespace ns { namespace { class NsFoo; } } // lines 10-10 |
| namespace ns { class NsBang; } |
| namespace ns { template <typename T> class NsBaz; } |
| namespace ns { namespace { template <typename T> class NsBar; } } // lines 11-11 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_namespace_unnamed_ns': |
| infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNamespacesWithUnnamedNamespaceAndContent(self): |
| """Tests that nested namespaces with forward declares still get new additions.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| class Bar; |
| ///+class Baz; |
| |
| namespace ns { |
| ///+class NsBang; |
| ///+template <typename T> class NsBaz; |
| |
| namespace { |
| ///+class NsBaz; |
| class NsFoo; |
| template <typename T> class NsBar; |
| } |
| |
| namespace ns1 { |
| ///+class Ns1Bar; |
| ///+class Ns1Baz; |
| class Ns1Foo; |
| |
| int ns_int = 5; // here's my contentful line |
| } |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_namespaces_with_existing_content should add these lines: |
| class Baz; |
| namespace ns { class NsBang; } |
| namespace ns { template <typename T> class NsBaz; } |
| namespace ns { namespace { class NsBaz; } } |
| namespace ns { namespace ns1 { class Ns1Bar; } } |
| namespace ns { namespace ns1 { class Ns1Baz; } } |
| |
| add_fwd_decl_inside_namespaces_with_existing_content should remove these lines: |
| |
| The full include-list for add_fwd_decl_inside_namespaces_with_existing_content: |
| #include "foo.h" // lines 3-3 |
| class Bar; // lines 5-5 |
| class Baz; |
| namespace ns { namespace { class NsFoo; } } // lines 10-10 |
| namespace ns { namespace { class NsBaz; } } |
| namespace ns { class NsBang; } |
| namespace ns { template <typename T> class NsBaz; } |
| namespace ns { namespace { template <typename T> class NsBar; } } // lines 11-11 |
| namespace ns { namespace ns1 { class Ns1Foo; } } // lines 15-15 |
| namespace ns { namespace ns1 { class Ns1Bar; } } |
| namespace ns { namespace ns1 { class Ns1Baz; } } |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_namespaces_with_existing_content': |
| infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideAllmanNamespacesWithUnnamedNamespaceAndContent(self): |
| """Tests that nested Allman namespaces with forward declares still get new additions.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| class Bar; |
| ///+class Baz; |
| |
| namespace ns |
| { |
| ///+class NsBang; |
| ///+template <typename T> class NsBaz; |
| |
| namespace |
| { |
| ///+class NsBaz; |
| class NsFoo; |
| template <typename T> class NsBar; |
| } |
| |
| namespace ns1 |
| { |
| ///+class Ns1Bar; |
| ///+class Ns1Baz; |
| class Ns1Foo; |
| |
| int ns_int = 5; // here's my contentful line |
| } |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_allman_namespaces_with_existing_content should add these lines: |
| class Baz; |
| namespace ns { class NsBang; } |
| namespace ns { template <typename T> class NsBaz; } |
| namespace ns { namespace { class NsBaz; } } |
| namespace ns { namespace ns1 { class Ns1Bar; } } |
| namespace ns { namespace ns1 { class Ns1Baz; } } |
| |
| add_fwd_decl_inside_allman_namespaces_with_existing_content should remove these lines: |
| |
| The full include-list for add_fwd_decl_inside_allman_namespaces_with_existing_content: |
| #include "foo.h" // lines 3-3 |
| class Bar; // lines 5-5 |
| class Baz; |
| namespace ns { namespace { class NsFoo; } } // lines 12-12 |
| namespace ns { namespace { class NsBaz; } } |
| namespace ns { class NsBang; } |
| namespace ns { template <typename T> class NsBaz; } |
| namespace ns { namespace { template <typename T> class NsBar; } } // lines 13-13 |
| namespace ns { namespace ns1 { class Ns1Foo; } } // lines 18-18 |
| namespace ns { namespace ns1 { class Ns1Bar; } } |
| namespace ns { namespace ns1 { class Ns1Baz; } } |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_allman_namespaces_with_existing_content': |
| infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideMixedNamespacesWithUnnamedNamespaceAndContent(self): |
| """Tests that nested mixed namespaces with forward declares still get new additions.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "bar.h" |
| ///+ |
| ///+class Baz; |
| ///+ |
| namespace ns { namespace ns1 { namespace ns2 |
| { |
| ///+class Ns2Bang; |
| ///+template <typename T> class Ns2Baz; |
| ///+ |
| namespace |
| { |
| ///+class NsaBaz; |
| class NsaFoo; |
| template <typename T> class NsaBar; |
| } // namespace |
| namespace ns3 { |
| ///+class Ns3Bar; |
| ///+class Ns3Baz; |
| class Ns3Foo; |
| ///+ |
| int ns3_int = 5; // here's my contentful line |
| } // namespace ns3 |
| } // namespace ns2 |
| } // namespace ns1 |
| } // namespace ns |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_mixed_namespaces_with_existing_content should add these lines: |
| class Baz; |
| namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } } |
| namespace ns { namespace ns1 { namespace ns2 { template <typename T> class Ns2Baz; } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace { class NsaBaz; } } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bar; } } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Baz; } } } } |
| |
| add_fwd_decl_inside_mixed_namespaces_with_existing_content should remove these lines: |
| |
| The full include-list for add_fwd_decl_inside_mixed_namespaces_with_existing_content: |
| #include "bar.h" // lines 3-3 |
| #include "foo.h" |
| class Baz; |
| namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } } |
| namespace ns { namespace ns1 { namespace ns2 { template <typename T> class Ns2Baz; } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace { class NsaFoo; } } } } // lines 8-8 |
| namespace ns { namespace ns1 { namespace ns2 { namespace { template <typename T> class NsaBar; } } } } // lines 9-9 |
| namespace ns { namespace ns1 { namespace ns2 { namespace { class NsaBaz; } } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bar; } } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Baz; } } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Foo; } } } } // lines 12-12 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_mixed_namespaces_with_existing_content': |
| infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInsideNestedNamespacesAndTopLevelForComplexNamespaces(self): |
| """Tests that nested namespaces still get new additions while putting hard to resolve forward declares at the top.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| ///+namespace ns { |
| ///+class NsBang; |
| ///+namespace ns1 { |
| ///+Ns1Bang; |
| ///+} // namespace ns1 |
| ///+} // namespace ns |
| ///+ |
| namespace ns { namespace ns1 { namespace ns2 { |
| class Ns2Bang; |
| class Ns2Bar; ///- |
| ///+class Ns2Baz; |
| ///+ |
| namespace ns3 { |
| ///+class Ns3Bang; |
| class Ns3Baz; |
| } // namespace ns3 |
| } // namespace ns2 |
| } // namespace ns1 |
| } // namespace ns |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces should add these lines: |
| namespace ns { class NsBang; } |
| namespace ns { namespace ns1 { Ns1Bang; } |
| namespace ns { namespace ns1 { namespace ns2 { class Ns2Baz; } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bang; } } } } |
| |
| add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces should remove these lines: |
| - namespace ns { namespace ns1 { namespace ns2 { class Ns2Bar; } } } // lines 5-5 |
| |
| The full include-list for add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces: |
| namespace ns { class NsBang; } |
| namespace ns { namespace ns1 { Ns1Bang; } |
| namespace ns { namespace ns1 { namespace ns2 { class Ns2Bang; } } } // lines 4-4 |
| namespace ns { namespace ns1 { namespace ns2 { class Ns2Baz; } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Bang; } } } } |
| namespace ns { namespace ns1 { namespace ns2 { namespace ns3 { class Ns3Baz; } } } } // lines 7-7 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_inside_nested_namespaces_and_top_level_for_complex_namespaces': |
| infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveNamespaces(self): |
| """Tests that we keep or remove ns's based on fwd decl content.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| namespace ns1 { |
| struct KeepStruct; |
| class NoKeepClass; ///- |
| template<typename Foo> class KeepTplClass; |
| } |
| ///- |
| namespace ns1 { ///- |
| namespace ns2 { ///- |
| // This should all go away. ///- |
| // Even with the multi-line comment here. ///- |
| template<typename Foo> class NoKeepTplClass; ///- |
| } ///- |
| } ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| ns_fwd_decl should add these lines: |
| |
| ns_fwd_decl should remove these lines: |
| - class NoKeepClass; // lines 5-5 |
| - namespace ns1 { namespace ns2 { template<typename Foo> class NoKeepTplClass; } } // lines 13-13 |
| |
| The full include-list for ns_fwd_decl: |
| namespace ns1 { struct KeepStruct; } // lines 4-4 |
| namespace ns1 { template<typename Foo> class KeepTplClass; } // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'ns_fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testKeepNamespacesWithNonForwardDecls(self): |
| """Tests we never remove a ns with 'real' content in it.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| namespace ns1 { |
| int ns_int = 5; |
| class NoKeepClass; ///- |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| keep_ns_fwd_decl should add these lines: |
| |
| keep_ns_fwd_decl should remove these lines: |
| - class NoKeepClass; // lines 5-5 |
| |
| The full include-list for keep_ns_fwd_decl: |
| --- |
| """ |
| self.RegisterFileContents({'keep_ns_fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testICUNamespaces(self): |
| """Tests we treat the icu namespace macros as namespaces.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| U_NAMESPACE_BEGIN // macro from icu |
| struct KeepStruct; |
| class NoKeepClass; ///- |
| template<typename Foo> class KeepTplClass; |
| U_NAMESPACE_END |
| ///- |
| U_NAMESPACE_BEGIN ///- |
| template<typename Foo> class NoKeepTplClass; ///- |
| U_NAMESPACE_END ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| icu_namespace should add these lines: |
| |
| icu_namespace should remove these lines: |
| - class NoKeepClass; // lines 5-5 |
| - template<typename Foo> class NoKeepTplClass; // lines 10-10 |
| |
| The full include-list for icu_namespace: |
| namespace ns1 { struct KeepStruct; } // lines 4-4 |
| namespace ns1 { template<typename Foo> class KeepTplClass; } // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'icu_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testHashNamespaces(self): |
| """Tests we treat the hash namespace macros as namespaces.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| HASH_NAMESPACE_DECLARATION_START // macro from hash.h |
| struct KeepStruct; |
| class NoKeepClass; ///- |
| template<typename Foo> class KeepTplClass; |
| HASH_NAMESPACE_DECLARATION_END |
| ///- |
| HASH_NAMESPACE_DECLARATION_START ///- |
| template<typename Foo> class NoKeepTplClass; ///- |
| HASH_NAMESPACE_DECLARATION_END ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| hash_namespace should add these lines: |
| |
| hash_namespace should remove these lines: |
| - class NoKeepClass; // lines 5-5 |
| - template<typename Foo> class NoKeepTplClass; // lines 10-10 |
| |
| The full include-list for hash_namespace: |
| namespace ns1 { struct KeepStruct; } // lines 4-4 |
| namespace ns1 { template<typename Foo> class KeepTplClass; } // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'hash_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testElaboratedClasses(self): |
| """Tests we don't remove lines like 'class Foo* fooptr'.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| struct KeepStruct; |
| class NoKeepClass; ///- |
| ///+ |
| struct NoKeepStruct* s; |
| struct NoKeepStruct& t; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| elaborated_class should add these lines: |
| |
| elaborated_class should remove these lines: |
| - class NoKeepClass; // lines 4-4 |
| |
| The full include-list for elaborated_class: |
| struct KeepStruct; // lines 3-3 |
| --- |
| """ |
| self.RegisterFileContents({'elaborated_class': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testBFlag(self): |
| """Tests that --b properly separates sections.""" |
| self.flags.blank_lines = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include "subdir/bflag.h" |
| ///+ |
| ///+#include <stdio.h> |
| ///+ |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| subdir/bflag.cc should add these lines: |
| #include "subdir/bflag.h" |
| #include <stdio.h> |
| #include "used2.h" |
| |
| subdir/bflag.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for subdir/bflag.cc: |
| #include "subdir/bflag.h" |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'subdir/bflag.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testSafeHeadersFlag(self): |
| """Tests that --safe_headers causes us to not delete lines.""" |
| self.flags.safe_headers = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> |
| #include <notused2.h> // Hello! |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| class Foo; |
| template<typename T> |
| class Bar; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| safe_flag.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| safe_flag.h should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include <notused.h> // lines 4-4 |
| - class Foo // lines 7-7 |
| - class Bar // lines 8-9 |
| |
| The full include-list for safe_flag.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'safe_flag.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testSafeHeadersFlagTwice(self): |
| """Tests running --safe_headers 2ce in a row doesn't duplicate comments.""" |
| self.flags.safe_headers = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> // iwyu says this can be removed |
| #include <notused2.h> // Hello!; iwyu says this can be removed |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| class Foo; // iwyu says this can be removed |
| template<typename T> // iwyu says this can be removed |
| class Bar; // iwyu says this can be removed |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| safe_flag_twice.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| safe_flag_twice.h should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include <notused.h> // lines 4-4 |
| - class Foo // lines 7-7 |
| - class Bar // lines 8-9 |
| |
| The full include-list for safe_flag_twice.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'safe_flag_twice.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testSafeHeadersFlagOnCcFiles(self): |
| """Tests that we delete even in --safe_headers mode, on .cc files.""" |
| self.flags.safe_headers = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| #include <notused2.h> // Hello! ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| class Foo; ///- |
| template<typename T> ///- |
| class Bar; ///- |
| ///- |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| safe_flag.cc should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| safe_flag.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include <notused.h> // lines 4-4 |
| - class Foo // lines 7-7 |
| - class Bar // lines 8-9 |
| |
| The full include-list for safe_flag.cc: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'safe_flag.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIncludeComments(self): |
| """Tests that we properly include comments on #include lines.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include "subdir/include_comments.h" |
| ///+#include <stdio.h> // for printf(), etc. |
| #include "used.h" ///- |
| ///+#include "used.h" // for Used |
| ///+#include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==() |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| subdir/include_comments.cc should add these lines: |
| #include "subdir/include_comments.h" |
| #include <stdio.h> // for printf(), etc. |
| #include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==() |
| |
| subdir/include_comments.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for subdir/include_comments.cc: |
| #include "subdir/include_comments.h" |
| #include <stdio.h> // for printf(), etc. |
| #include "used.h" // for Used |
| #include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==() |
| --- |
| """ |
| self.RegisterFileContents({'subdir/include_comments.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testNocommentsFlag(self): |
| """Tests we properly don't include/modify comments with --nocomments.""" |
| self.flags.comments = False |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include "subdir/include_comments.h" |
| ///+#include <stdio.h> |
| #include "used.h" // my favorite #include! |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| subdir/include_comments.cc should add these lines: |
| #include "subdir/include_comments.h" |
| #include <stdio.h> // for printf(), etc. |
| #include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==() |
| |
| subdir/include_comments.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for subdir/include_comments.cc: |
| #include "subdir/include_comments.h" |
| #include <stdio.h> // for printf(), etc. |
| #include "used.h" // for Used |
| #include "used2.h" // for Used2, Used2::Used2, Used2::~Used2, Used2::Used_Enum, operator==() |
| --- |
| """ |
| self.RegisterFileContents({'subdir/include_comments.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testFixingTwoFiles(self): |
| """Make sure data for one fix doesn't overlap with a second.""" |
| file_a = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| #include "used_only_in_file_a.h" |
| #include "used_only_in_file_b.h" ///- |
| |
| class FileAClass; // kept for file A, not for file B |
| class FileBClass; // kept for file B, not for file A ///- |
| """ |
| file_b = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| #include "used_only_in_file_a.h" ///- |
| #include "used_only_in_file_b.h" |
| |
| class FileAClass; // kept for file A, not for file B ///- |
| class FileBClass; // kept for file B, not for file A |
| """ |
| iwyu_output = """\ |
| file_a.cc should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| file_a.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include "used_only_in_file_b.h" // lines 6-6 |
| - class FileBClass; // lines 9-9 |
| |
| The full include-list for file_a.cc: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| #include "used_only_in_file_a.h" |
| class FileAClass; // lines 8-8 |
| --- |
| |
| file_b.cc should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| file_b.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include "used_only_in_file_a.h" // lines 5-5 |
| - class FileAClass; // lines 8-8 |
| |
| The full include-list for file_b.cc: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| #include "used_only_in_file_b.h" |
| class FileBClass; // lines 9-9 |
| --- |
| """ |
| self.RegisterFileContents({'file_a.cc': file_a, 'file_b.cc': file_b}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testListingTheSameFileTwice(self): |
| """Test when foo.cc is specified twice. It should fix conservatively.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| ///+#include "include_this_file" // for reason 2 |
| #include "used.h" |
| ///+#include "used2.h" |
| #include "used_only_in_file_a.h" |
| #include "used_only_in_file_b.h" ///- |
| |
| class FileAClass; // kept for file A, not for file B |
| class FileBClass; // kept for file B, not for file A ///- |
| ///+namespace foo { |
| ///+template <typename Arg1> ClassTemplate; |
| ///+} // namespace foo |
| ///+template <typename Arg1> ClassTemplate; |
| """ |
| iwyu_output = """\ |
| twice.cc should add these lines: |
| #include <stdio.h> |
| #include "include_this_file" // for reason 1 |
| namespace foo { template <typename Arg1> ClassTemplate; } |
| template <typename Arg1> ClassTemplate; |
| |
| twice.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include "used_only_in_file_a.h" // lines 5-5 |
| - #include "used_only_in_file_b.h" // lines 6-6 |
| - class FileAClass; // lines 8-8 |
| - class FileBClass; // lines 9-9 |
| |
| The full include-list for twice.cc: |
| #include <stdio.h> |
| #include "include_this_file" // for reason 1 |
| #include "used.h" |
| namespace foo { template <typename Arg1> ClassTemplate; } |
| template <typename Arg1> ClassTemplate; |
| --- |
| |
| twice.cc should add these lines: |
| #include "used2.h" |
| #include "include_this_file" // for reason 2 |
| namespace foo { template <typename Arg2> ClassTemplate; } |
| template <typename Arg2> ClassTemplate; |
| |
| twice.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include "used_only_in_file_b.h" // lines 6-6 |
| - class FileBClass; // lines 9-9 |
| |
| The full include-list for twice.cc: |
| #include "include_this_file" // for reason 2 |
| #include "used.h" |
| #include "used2.h" |
| #include "used_only_in_file_a.h" |
| class FileAClass; // lines 8-8 |
| namespace foo { template <typename Arg2> ClassTemplate; } |
| template <typename Arg2> ClassTemplate; |
| --- |
| """ |
| self.RegisterFileContents({'twice.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testListingTheSameFileTwiceAndOnceIsANoop(self): |
| """Test when foo.cc is specified twice, once with 'all correct'.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> |
| ///+#include <stdio.h> |
| ///+#include "include_this_file" // for reason 1 |
| #include "used.h" |
| #include "used_only_in_file_a.h" |
| |
| class FileAClass; |
| ///+namespace foo { |
| ///+template <typename Arg1> ClassTemplate; |
| ///+} // namespace foo |
| ///+template <typename Arg1> ClassTemplate; |
| """ |
| iwyu_output = """\ |
| twice.cc should add these lines: |
| #include <stdio.h> |
| #include "include_this_file" // for reason 1 |
| namespace foo { template <typename Arg1> ClassTemplate; } |
| template <typename Arg1> ClassTemplate; |
| |
| twice.cc should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include "used_only_in_file_a.h" // lines 5-5 |
| - class FileAClass; // lines 7-7 |
| |
| The full include-list for twice.cc: |
| #include <stdio.h> |
| #include "include_this_file" // for reason 1 |
| #include "used.h" |
| namespace foo { template <typename Arg1> ClassTemplate; } |
| template <typename Arg1> ClassTemplate; |
| --- |
| |
| (twice.cc has correct #includes/fwd-decls) |
| """ |
| self.RegisterFileContents({'twice.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclare(self): |
| """Test adding a forward-declare, rather than keeping one.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| ///+ |
| ///+struct NotUsed; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| new_fwd_decl should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| struct NotUsed; |
| |
| new_fwd_decl should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for new_fwd_decl: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| struct NotUsed; |
| --- |
| """ |
| self.RegisterFileContents({'new_fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddAndKeepForwardDeclare(self): |
| """Test adding a forward-declare in addition to keeping one.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| class ForwardDeclClass; |
| ///+struct NotUsed; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| new_and_keep_fwd_decl should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| struct NotUsed; |
| |
| new_and_keep_fwd_decl should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for new_and_keep_fwd_decl: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| class ForwardDeclareClass; // lines 6-6 |
| struct NotUsed; |
| --- |
| """ |
| self.RegisterFileContents({'new_and_keep_fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeToFileThatHasOnlyForwardDeclarations(self): |
| """Tests we add an #include in an appropriate place if none exist.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| ///+#include <stdio.h> |
| ///+#include "used.h" |
| ///+ |
| const int kFoo = 5; // we should insert before the contentful line. |
| |
| class Foo; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| no_include_fwd_decl should add these lines: |
| #include <stdio.h> |
| #include "used.h" |
| |
| no_include_fwd_decl should remove these lines: |
| |
| The full include-list for no_include_fwd_decl: |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; // lines 5-5 |
| --- |
| """ |
| self.RegisterFileContents({'no_include_fwd_decl': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclarationToFileThatHasOnlyIncludes(self): |
| """Tests we add a forward-declare in an appropriate place if none exist.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| const int kFoo = 5; // make sure we don't just insert at the beginning |
| |
| #include <stdio.h> |
| #include "used.h" |
| ///+ |
| ///+class Foo; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| no_fwd_decl_include should add these lines: |
| class Foo; |
| |
| no_fwd_decl_include should remove these lines: |
| |
| The full include-list for no_fwd_decl_include: |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; |
| --- |
| """ |
| self.RegisterFileContents({'no_fwd_decl_include': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeToContentlessFile(self): |
| """Tests we add an #include ok to a basically empty file..""" |
| infile = """\ |
| // Copyright 2010 |
| ///+#include <stdio.h> |
| ///+#include "used.h" |
| ///+ |
| ///+class Foo; |
| """ |
| iwyu_output = """\ |
| no_include should add these lines: |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; |
| |
| no_include should remove these lines: |
| |
| The full include-list for no_include: |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; |
| --- |
| """ |
| self.RegisterFileContents({'no_include': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeToEmptyFile(self): |
| """Tests we add an #include ok to an empty file..""" |
| infile = '' |
| iwyu_output = """\ |
| empty_file should add these lines: |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; |
| |
| empty_file should remove these lines: |
| |
| The full include-list for empty_file: |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; |
| --- |
| """ |
| self.RegisterFileContents({'empty_file': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeToOnlyOneContentfulLineFile(self): |
| """Prevent regression when the only contentful line was the last.""" |
| infile = """\ |
| // Copyright 2010 |
| ///+ |
| ///+#include <stdio.h> |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| only_one_contentful_line.c should add these lines: |
| #include <stdio.h> |
| |
| only_one_contentful_line.c should remove these lines: |
| |
| The full include-list for only_one_contentful_line.c: |
| #include <stdio.h> |
| --- |
| """ |
| self.RegisterFileContents({'only_one_contentful_line.c': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testCommentsAtEndOfFile(self): |
| """Tests we don't crash if a file ends with #includs and then a comment.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| const int kFoo = 5; // make sure we don't just insert at the beginning |
| |
| #include <stdio.h> |
| #include "used.h" |
| ///+ |
| ///+class Foo; |
| // Comments, and then...nothing |
| """ |
| iwyu_output = """\ |
| comments_at_end_of_file should add these lines: |
| class Foo; |
| |
| comments_at_end_of_file should remove these lines: |
| |
| The full include-list for comments_at_end_of_file: |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; |
| --- |
| """ |
| self.RegisterFileContents({'comments_at_end_of_file': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddSystemIncludeToFileWithoutAny(self): |
| """Tests we add a system #include to a non-sys location when needed.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #ifdef HAVE_TYPE_TRAITS_H |
| #include <type_traits.h> |
| #endif |
| ///+#include <stdio.h> |
| #include "used.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| system_include should add these lines: |
| #include <stdio.h> |
| |
| system_include should remove these lines: |
| |
| The full include-list for system_include: |
| #include <stdio.h> |
| #include "used.h" |
| --- |
| """ |
| self.RegisterFileContents({'system_include': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddNonSystemHeaderUnderMainCUHeader(self): |
| """Tests we distinguish main-cu headers from other non-system headers.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| ///+#include "main_cu.h" |
| #include "main_cu-inl.h" |
| ///- |
| #include <stdio.h> |
| ///+#include <stdlib.h> |
| #ifdef WINDOWS |
| #include <windows.h> |
| #endif |
| |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| main_cu_test.cc should add these lines: |
| #include <stdlib.h> |
| #include "main_cu.h" |
| #include "used2.h" |
| |
| main_cu_test.cc should remove these lines: |
| |
| The full include-list for main_cu_test.cc: |
| #include "main_cu.h" |
| #include "main_cu-inl.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'main_cu_test.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddWithNearestIncludes(self): |
| """Tests we add "includes" with <includes> when there's a choice.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "nearest_include.h" |
| |
| static int x = 6; |
| #include <stdio.h> |
| ///+#include "used.h" |
| |
| static int y = 7; |
| class Foo; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| nearest_include.cc should add these lines: |
| #include "used.h" |
| |
| nearest_include.cc should remove these lines: |
| |
| The full include-list for nearest_include.cc: |
| #include "nearest_include.h" |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; // lines 9-9 |
| --- |
| """ |
| self.RegisterFileContents({'nearest_include.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testFalseAlarmHeaderGuard(self): |
| """Tests we calculate top-level-ness even in face of a fake header-guard.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "nearest_toplevel_include.h" |
| |
| static int x = 6; |
| #include <stdio.h> |
| ///+#include "used.h" |
| |
| #ifndef MAP_ANONYMOUS // This is the fake header guard! |
| # define MAP_ANONYMOUS MAP_ANON |
| #endif |
| |
| #ifdef FOO |
| #include <foo.h> |
| #endif |
| #if defined(BAR) |
| #include <bar.h> |
| #endif |
| |
| static int y = 7; |
| class Foo; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| nearest_toplevel_include.cc should add these lines: |
| #include "used.h" |
| |
| nearest_toplevel_include.cc should remove these lines: |
| |
| The full include-list for nearest_toplevel_include.cc: |
| #include "nearest_toplevel_include.h" |
| #include <bar.h> |
| #include <foo.h> |
| #include <stdio.h> |
| #include "used.h" |
| class Foo; // lines 9-9 |
| --- |
| """ |
| self.RegisterFileContents({'nearest_toplevel_include.cc': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterHeaderGuard(self): |
| """Test that we are willing to insert .h's inside a header guard.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #ifndef SIMPLE_H_ |
| #define SIMPLE_H_ |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| #endif |
| """ |
| iwyu_output = """\ |
| simple.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| simple.h should remove these lines: |
| - #include <notused.h> // lines 6-6 |
| |
| The full include-list for simple.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'simple.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterSoloPragmaOnce(self): |
| """Test that we are willing to insert .h's after #pragma once.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #pragma once |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| """ |
| iwyu_output = """\ |
| pragma_once.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| pragma_once.h should remove these lines: |
| - #include <notused.h> // lines 5-5 |
| |
| The full include-list for pragma_once.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'pragma_once.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterPragmaOnceWithHeaderGuard(self): |
| """Test that we are willing to insert .h's after #pragma once and header |
| guard.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #pragma once |
| #ifndef PRAGMA_ONCE_H_ |
| #define PRAGMA_ONCE_H_ |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| #endif |
| """ |
| iwyu_output = """\ |
| pragma_once_with_guard.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| pragma_once_with_guard.h should remove these lines: |
| - #include <notused.h> // lines 7-7 |
| |
| The full include-list for pragma_once_with_guard.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'pragma_once_with_guard.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterEarlyPragmaOnce(self): |
| """Test that we are willing to insert .h's after early #pragma once.""" |
| infile = """\ |
| #pragma once |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| """ |
| iwyu_output = """\ |
| early_pragma_once.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| early_pragma_once.h should remove these lines: |
| - #include <notused.h> // lines 4-4 |
| |
| The full include-list for early_pragma_once.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'early_pragma_once.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterEarlyPragmaOnceWithHeaderGuard(self): |
| """Test that we are willing to insert .h's after early #pragma once and |
| header guard.""" |
| infile = """\ |
| #pragma once |
| // Copyright 2010 |
| |
| #ifndef PRAGMA_ONCE_H_ |
| #define PRAGMA_ONCE_H_ |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| #endif |
| """ |
| iwyu_output = """\ |
| early_pragma_once_with_guard.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| early_pragma_once_with_guard.h should remove these lines: |
| - #include <notused.h> // lines 7-7 |
| |
| The full include-list for early_pragma_once_with_guard.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'early_pragma_once_with_guard.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterWeirdPragmaOnce(self): |
| """Test that we are willing to insert .h's after creatively formatted |
| #pragma once.""" |
| infile = """\ |
| # pragma once |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| """ |
| iwyu_output = """\ |
| weird_pragma_once.h should add these lines: |
| #include <stdio.h> |
| |
| weird_pragma_once.h should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for weird_pragma_once.h: |
| #include <stdio.h> |
| --- |
| """ |
| self.RegisterFileContents({'weird_pragma_once.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeBeforePragmaMessage(self): |
| """Test that non-once #pragmas are pushed after the #includes.""" |
| infile = """\ |
| ///+#include <stdio.h> |
| ///+ |
| #pragma message "Hello world!" |
| |
| #include <notused.h> ///- |
| """ |
| iwyu_output = """\ |
| weird_pragma_once.h should add these lines: |
| #include <stdio.h> |
| |
| weird_pragma_once.h should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for weird_pragma_once.h: |
| #include <stdio.h> |
| --- |
| """ |
| self.RegisterFileContents({'weird_pragma_once.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterWeirdHeaderGuard(self): |
| """Test that we are willing to insert .h's inside a non-standard h-guard.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #if ! defined (SIMPLE_H_) |
| #define SIMPLE_H_ |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| #endif |
| """ |
| iwyu_output = """\ |
| simple.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| simple.h should remove these lines: |
| - #include <notused.h> // lines 6-6 |
| |
| The full include-list for simple.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'simple.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterHeaderGuardLikeIfdef(self): |
| """Test that we are willing to insert .h's inside a h-guard-*like* line.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #ifdef __linux // serves the same role as a header guard |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| #endif |
| |
| // Comments are allowed after the header guard. |
| """ |
| iwyu_output = """\ |
| os_header_guard.h should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| os_header_guard.h should remove these lines: |
| - #include <notused.h> // lines 5-5 |
| |
| The full include-list for os_header_guard.h: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'os_header_guard.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddIncludeAfterHeaderGuardButBeforeComments(self): |
| """Test that we introduce new #includes right after a header guard.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #ifndef SIMPLE_WITH_COMMENT_H_ |
| #define SIMPLE_WITH_COMMENT_H_ |
| |
| ///+#include <stdio.h> |
| ///+#include "used.h" |
| ///+ |
| // This is a comment |
| void ForThisFunction(); |
| |
| #endif |
| """ |
| iwyu_output = """\ |
| simple_with_comment.h should add these lines: |
| #include <stdio.h> |
| #include "used.h" |
| |
| simple_with_comment.h should remove these lines: |
| |
| The full include-list for simple_with_comment.h: |
| #include <stdio.h> |
| #include "used.h" |
| --- |
| """ |
| self.RegisterFileContents({'simple_with_comment.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIdentifyingHeaderGuardLines(self): |
| """Test that not all #defines look like header guards.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #ifndef IDENTIFYING_HEADER_GUARD_LINES_H_ |
| #define IDENTIFYING_HEADER_GUARD_LINES_H_ |
| |
| namespace foo { |
| ///+namespace bar { |
| ///+class Baz; |
| ///+} // namespace bar |
| ///+ |
| // The namespace decl should come before this #define, not after. |
| // It will, unless we wrongly say the #define is a header-guard define. |
| #define NOT_A_HEADER_GUARD_LINE 1 |
| } |
| |
| #endif |
| """ |
| iwyu_output = """\ |
| identifying_header_guard_lines.h should add these lines: |
| namespace foo { namespace bar { class Baz; } } |
| |
| identifying_header_guard_lines.h should remove these lines: |
| |
| The full include-list for identifying_header_guard_lines.h: |
| namespace foo { namespace bar { class Baz; } } |
| --- |
| """ |
| self.RegisterFileContents({'identifying_header_guard_lines.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIncludeOfCcFile(self): |
| """Test that iwyu leaves .cc #includes alone.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int kFoo = 5; |
| |
| #include "not_mentioned.cc" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| cc_include should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| cc_include should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for cc_include: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'cc_include': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testCommentsBeforeIncludeLines(self): |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+// This is the first include. |
| ///+// Or it will be, after we reorder. |
| ///+#include <stdio.h> |
| // This is the second include. |
| // Or *it* will be, after we reorder. |
| #include "used.h" |
| // This is the first include. ///- |
| // Or it will be, after we reorder. ///- |
| #include <stdio.h> ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| comments_with_includes should add these lines: |
| |
| comments_with_includes should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for comments_with_includes: |
| #include <stdio.h> |
| #include "used.h" |
| --- |
| """ |
| self.RegisterFileContents({'comments_with_includes': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveDuplicateIncludes(self): |
| """Tests we uniquify if an #include is in there twice.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| #include "used.h" // same line even though it has a comment ///- |
| // Even though these two comment-lines are the same, they won't get de-duped. |
| // Even though these two comment-lines are the same, they won't get de-duped. |
| #ifdef _WINDOWS |
| // But keep this one because it's in an #ifdef. |
| #include "used.h" |
| #endif |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| remove_duplicate_includes should add these lines: |
| #include <stdio.h> |
| |
| remove_duplicate_includes should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for remove_duplicate_includes: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'remove_duplicate_includes': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testRemoveDuplicateForwardDeclarations(self): |
| """Tests we uniquify if an #include is in there twice.""" |
| infile = """\ |
| #include <notused.h> ///- |
| class A; |
| template<typename T> // Comment in the middle not a problem |
| class B; |
| class A; ///- |
| template<typename T> ///- |
| class B; ///- |
| template<typename T> class B; ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| remove_duplicate_forward_declarations should add these lines: |
| |
| remove_duplicate_forward_declarations should remove these lines: |
| - #include <notused.h> // lines 1-1 |
| |
| The full include-list for remove_duplicate_forward_declarations: |
| class A; // lines 2-2 |
| template <typename T> class B; // lines 3-4 |
| class A; // lines 5-5 |
| template <typename T> class B; // lines 6-7 |
| template <typename T> class B; // lines 8-8 |
| --- |
| """ |
| self.RegisterFileContents({'remove_duplicate_forward_declarations': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testDontRemoveTemplateLines(self): |
| """Tests we don't accidentally think repeated template lines are dupes.""" |
| infile = """\ |
| #include <notused.h> ///- |
| template<typename T> |
| class A; |
| template<typename T> |
| class B; |
| |
| void f(A&, B&); |
| """ |
| iwyu_output = """\ |
| dont_remove_template_lines should add these lines: |
| |
| dont_remove_template_lines should remove these lines: |
| - #include <notused.h> // lines 1-1 |
| |
| The full include-list for dont_remove_template_lines: |
| template <typename T> class A; // lines 2-3 |
| template <typename T> class B; // lines 4-5 |
| --- |
| """ |
| self.RegisterFileContents({'dont_remove_template_lines': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testDontRemoveSimilarNestedDeclarations(self): |
| """Tests we don't accidentally think repeated nested forward declarations |
| are dupes.""" |
| infile = """\ |
| #include <notused.h> ///- |
| |
| class A { |
| class Inner; |
| }; |
| |
| class B { |
| class Inner; |
| }; |
| """ |
| iwyu_output = """\ |
| dont_remove_similar_nested should add these lines: |
| |
| dont_remove_similar_nested should remove these lines: |
| - #include <notused.h> // lines 1-1 |
| |
| The full include-list for dont_remove_similar_nested: |
| class A::Inner; // lines 4-4 |
| class B::Inner; // lines 8-8 |
| --- |
| """ |
| self.RegisterFileContents({'dont_remove_similar_nested': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testNestedNamespaces(self): |
| infile = """\ |
| // Copyright 2010 |
| |
| ///+#include <stdio.h> |
| ///+ |
| namespace X { |
| class OneA |
| ///+ |
| namespace Y { |
| ///+class TwoA; |
| class TwoB; |
| class TwoA; ///- |
| }} |
| class Toplevel; |
| ///- |
| namespace A { ///- |
| namespace B { namespace C { ///- |
| class Delete1; ///- |
| }}} ///- |
| ///- |
| namespace A { namespace B { class Delete2; } } ///- |
| ///- |
| namespace A { ///- |
| namespace B { ///- |
| class Delete3; ///- |
| } ///- |
| } // namespace A ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| many_namespaces should add these lines: |
| #include <stdio.h> |
| |
| many_namespaces should remove these lines: |
| - class Delete1; // lines 13-13 |
| - class Delete2; // lines 16-16 |
| - class Delete3; // lines 20-20 |
| |
| The full include-list for many_namespaces: |
| #include <stdio.h> |
| class Toplevel; // lines 9-9 |
| class TwoA; // lines 7-7 |
| class TwoB; // lines 6-6 |
| class OneA; // lines 4-4 |
| --- |
| """ |
| self.RegisterFileContents({'many_namespaces': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testDoNotInsertIncludeIntoAClass(self): |
| infile = """\ |
| // Copyright 2010 |
| |
| ///+#include <stdio.h> |
| ///+ |
| class Foo { |
| }; |
| |
| class Bar { |
| class FwdDecl; |
| |
| FwdDecl* f; |
| } |
| """ |
| iwyu_output = """\ |
| include_not_in_class should add these lines: |
| #include <stdio.h> |
| |
| include_not_in_class should remove these lines: |
| |
| The full include-list for include_not_in_class: |
| #include <stdio.h> |
| class FwdDecl; // lines 7-7 |
| --- |
| """ |
| self.RegisterFileContents({'include_not_in_class': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIdenticalForwardDeclaredNamesInDifferentNamespaces(self): |
| infile = """\ |
| // Copyright 2010 |
| |
| ///+namespace ns1 { |
| ///+class ForwardDeclared; |
| ///+} // namespace ns1 |
| ///+namespace ns2 { |
| ///+class ForwardDeclared; |
| ///+} // namespace ns2 |
| """ |
| iwyu_output = """\ |
| identical_names should add these lines: |
| namespace ns1 { class ForwardDeclared; } |
| namespace ns2 { class ForwardDeclared; } |
| |
| identical_names should remove these lines: |
| |
| The full include-list for identical_names: |
| namespace ns1 { class ForwardDeclared; } |
| namespace ns2 { class ForwardDeclared; } |
| --- |
| """ |
| self.RegisterFileContents({'identical_names': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIterativeNamespaceDelete(self): |
| """Tests deleting a namespace with an emptied #ifdef inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| ///- |
| namespace foo { ///- |
| #ifdef FWD_DECL ///- |
| class Bar; ///- |
| #endif ///- |
| } ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| iterative_namespace should add these lines: |
| |
| iterative_namespace should remove these lines: |
| - class Bar; // lines 5-5 |
| |
| The full include-list for iterative_namespace: |
| --- |
| """ |
| self.RegisterFileContents({'iterative_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIterativeAllmanNamespaceDelete(self): |
| """Tests deleting an Allman namespace with an emptied #ifdef inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| ///- |
| namespace foo ///- |
| { ///- |
| #ifdef FWD_DECL ///- |
| class Bar; ///- |
| #endif ///- |
| } ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| iterative_namespace should add these lines: |
| |
| iterative_namespace should remove these lines: |
| - class Bar; // lines 6-6 |
| |
| The full include-list for iterative_namespace: |
| --- |
| """ |
| self.RegisterFileContents({'iterative_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIterativeMixedNamespaceDelete(self): |
| """Tests deleting a namespace with mixed braces with an emptied #ifdef inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| ///- |
| namespace foo { namespace baz ///- |
| { ///- |
| #ifdef FWD_DECL ///- |
| class Bar; ///- |
| #endif ///- |
| } ///- |
| } ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| iterative_namespace should add these lines: |
| |
| iterative_namespace should remove these lines: |
| - class Bar; // lines 6-6 |
| |
| The full include-list for iterative_namespace: |
| --- |
| """ |
| self.RegisterFileContents({'iterative_namespace': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testIterativeIfdefDelete(self): |
| """Tests deleting an ifdef with an emptied namespace inside it.""" |
| infile = """\ |
| // Copyright 2010 |
| ///- |
| #ifdef FWD_DECL ///- |
| namespace foo { ///- |
| class Bar; ///- |
| } ///- |
| #endif ///- |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| iterative_ifdef should add these lines: |
| |
| iterative_ifdef should remove these lines: |
| - class Bar; // lines 5-5 |
| |
| The full include-list for iterative_ifdef: |
| --- |
| """ |
| self.RegisterFileContents({'iterative_ifdef': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testOutOfRangeLineNumber(self): |
| """Test we skip editing completely if iwyu has a really big line number.""" |
| # fix_includes skips the file-editing if it detects a problem, as |
| # in this test case. The way that skipping is evidenced in the |
| # test, is the output is empty. |
| infile = """\ |
| // Copyright 2010 ///- |
| ///- |
| #include <notused.h> ///- |
| #include "used.h" ///- |
| ///- |
| int main() { return 0; } ///- |
| """ |
| iwyu_output = """\ |
| out_of_range should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| out_of_range should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| - #include <bignumber.h> // lines 3000-3000 |
| |
| The full include-list for out_of_range: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'out_of_range': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testDeleteExtraneousBlankLines(self): |
| """Test we delete blank lines around deleted spans correctly.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| class Foo { }; |
| ///- |
| class Bar; ///- |
| |
| |
| class Baz { }; |
| |
| |
| class Bang; ///- |
| ///- |
| class Qux { }; |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| extraneous_blank_lines should add these lines: |
| |
| extraneous_blank_lines should remove these lines: |
| - class Bar; // lines 5-5 |
| - class Bang; // lines 11-11 |
| |
| The full include-list for extraneous_blank_lines: |
| --- |
| """ |
| self.RegisterFileContents({'extraneous_blank_lines': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testKeepNolintComment(self): |
| """Test we keep a nolint comment.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "bar.h" // NOLINT(iwyu) |
| #include "baz.h" // NOLINT(iwyu): blah blah |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| keep_nolint should add these lines: |
| |
| keep_nolint should remove these lines: |
| |
| The full include-list for keep_nolint: |
| #include "bar.h" // lines 3-3 |
| #include "baz.h" // lines 4-4 |
| --- |
| """ |
| |
| self.RegisterFileContents({'keep_nolint': infile}) |
| # No files are written, because there are no changes. |
| self.ProcessAndTest(iwyu_output, unedited_files=['keep_nolint']) |
| |
| def testKeepNolintCommentInNocommentMode(self): |
| """Test we keep a nolint comment even with --nocomments.""" |
| self.flags.comments = False |
| self.testKeepNolintComment() |
| |
| # Test the IWYUOutputParser method _MatchSectionHeading. |
| |
| def testIWYUOutputParserMatchSectionHeadingSuccess(self): |
| parser = fix_includes.IWYUOutputParser() |
| self.assertEqual(None, parser.current_section) |
| self.assertEqual('<unknown file>', parser.filename) |
| |
| self.assertTrue(parser._ProcessOneLine('')) |
| self.assertEqual(None, parser.current_section) |
| self.assertEqual('<unknown file>', parser.filename) |
| |
| self.assertTrue(parser._ProcessOneLine( |
| 'myfile.cc should add these lines:')) |
| self.assertEqual(parser._ADD_SECTION_RE, parser.current_section) |
| self.assertEqual('add', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('myfile.cc', parser.filename) |
| |
| self.assertTrue(parser._ProcessOneLine( |
| 'myfile.cc should remove these lines:')) |
| self.assertEqual(parser._REMOVE_SECTION_RE, parser.current_section) |
| self.assertEqual('remove', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('myfile.cc', parser.filename) |
| |
| self.assertTrue(parser._ProcessOneLine( |
| 'The full include-list for myfile.cc:')) |
| self.assertEqual(parser._TOTAL_SECTION_RE, parser.current_section) |
| self.assertEqual('total', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('myfile.cc', parser.filename) |
| |
| self.assertTrue(not parser._ProcessOneLine('---')) |
| self.assertEqual(parser._SECTION_END_RE, parser.current_section) |
| self.assertEqual('end', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('myfile.cc', parser.filename) |
| |
| def testIWYUOutputParserMatchSectionHeadingWindowsPaths(self): |
| # Windows path names can contain the ':' character, so make sure that parses |
| # correctly. IWYU uses POSIX-style forward slashes consistently, so follow |
| # suit here. |
| parser = fix_includes.IWYUOutputParser() |
| self.assertTrue(parser._ProcessOneLine( |
| 'C:/src/myfile.cc should add these lines:')) |
| self.assertEqual(parser._ADD_SECTION_RE, parser.current_section) |
| self.assertEqual('add', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('C:/src/myfile.cc', parser.filename) |
| |
| self.assertTrue(parser._ProcessOneLine( |
| 'C:/src/myfile.cc should remove these lines:')) |
| self.assertEqual(parser._REMOVE_SECTION_RE, parser.current_section) |
| self.assertEqual('remove', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('C:/src/myfile.cc', parser.filename) |
| |
| self.assertTrue(parser._ProcessOneLine( |
| 'The full include-list for C:/src/myfile.cc:')) |
| self.assertEqual(parser._TOTAL_SECTION_RE, parser.current_section) |
| self.assertEqual('total', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('C:/src/myfile.cc', parser.filename) |
| |
| def testIWYUOutputParserProcessOneLineProcessNoEditsHeader(self): |
| parser = fix_includes.IWYUOutputParser() |
| line = '(myfile.cc has correct #includes/fwd-decls)' |
| self.assertTrue(not parser._ProcessOneLine(line)) |
| self.assertEqual(parser._NO_EDITS_RE, parser.current_section) |
| self.assertEqual('no_edits', parser._RE_TO_NAME[parser.current_section]) |
| self.assertEqual('myfile.cc', parser.filename) |
| |
| def testIWYUOutputParserProcessOneLineAddNotSeenFirst(self): |
| parser = fix_includes.IWYUOutputParser() |
| self.assertRaises(fix_includes.FixIncludesError, |
| parser._ProcessOneLine, |
| 'myfile.cc should remove these lines:') |
| |
| def testIWYUOutputParserProcessOneLineOutOfOrder(self): |
| parser = fix_includes.IWYUOutputParser() |
| self.assertTrue(parser._ProcessOneLine( |
| 'myfile.cc should add these lines:')) |
| self.assertRaises(fix_includes.FixIncludesError, |
| parser._ProcessOneLine, |
| 'The full include-list for myfile.cc:') |
| |
| def testIWYUOutputParserProcessOneLineIncorrectFilename(self): |
| parser = fix_includes.IWYUOutputParser() |
| self.assertTrue(parser._ProcessOneLine( |
| 'myfile.cc should add these lines:')) |
| self.assertRaises(fix_includes.FixIncludesError, |
| parser._ProcessOneLine, |
| 'not_myfile.cc should remove these lines:') |
| |
| def testIWYUOutputParserProcessOneLineNoMatcher(self): |
| parser = fix_includes.IWYUOutputParser() |
| # We successfully process this not-in-any-section line, but update no data. |
| self.assertTrue(parser._ProcessOneLine('#include <foo>')) |
| self.assertEqual(None, parser.current_section) |
| self.assertEqual('<unknown file>', parser.filename) |
| |
| def testIWYUOutputParserSuccess(self): |
| """Tests the IWYUOutputParser method ParseOneRecord.""" |
| iwyu_output = """\ |
| simple should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| namespace ns {class ForwardDeclared;} |
| |
| simple should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for simple: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| namespace ns {class ForwardDeclared;} |
| --- |
| """ |
| parser = fix_includes.IWYUOutputParser() |
| record = parser.ParseOneRecord(iwyu_output.splitlines(), self.flags) |
| |
| self.assertEqual('simple', record.filename) |
| self.assertSetEqual(set([3]), record.lines_to_delete) |
| self.assertSetEqual(set(('#include <stdio.h>', |
| '#include "used2.h"', |
| 'namespace ns {class ForwardDeclared;}')), |
| record.includes_and_forward_declares_to_add) |
| |
| def testIWYUOutputParserRemoveLineNoComment(self): |
| iwyu_output = """\ |
| no_comment should add these lines: |
| |
| no_comment should remove these lines: |
| - #include <notused.h> |
| |
| The full include-list for no_key: |
| --- |
| """ |
| parser = fix_includes.IWYUOutputParser() |
| self.assertRaises(fix_includes.FixIncludesError, |
| parser.ParseOneRecord, |
| iwyu_output.splitlines(), |
| self.flags) |
| |
| def testFileSpecifiedOnCommandline(self): |
| """Test we limit editing to files specified on the commandline.""" |
| changed_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| unchanged_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> |
| #include "used.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| changed should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| changed should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for changed: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| # Have the exact same iwyu output for 'unchanged' as for 'changed'. |
| iwyu_output += iwyu_output.replace('changed', 'unchanged') |
| |
| self.RegisterFileContents({'changed': changed_infile, |
| 'unchanged': unchanged_infile}) |
| # unchanged should not be edited, since it is not listed on the 'cmdline'. |
| self.ProcessAndTest(iwyu_output, cmdline_files=['changed'], |
| unedited_files=['unchanged']) |
| |
| def testIgnoreRe(self): |
| """Test the behavior of the --ignore_re flag.""" |
| changed_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| unchanged_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> |
| #include "used.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| changed should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| changed should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for changed: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| # Have the exact same iwyu output for 'unchanged' as for 'changed'. |
| iwyu_output += iwyu_output.replace('changed', 'unchanged') |
| |
| self.RegisterFileContents({'changed': changed_infile, |
| 'unchanged': unchanged_infile}) |
| # unchanged should not be edited, since it matches ignore_re. |
| self.flags.ignore_re = 'nch' |
| self.ProcessAndTest(iwyu_output, unedited_files=['unchanged']) |
| |
| def testOnlyRe(self): |
| """Test the behavior of the --only_re flag.""" |
| changed_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| unchanged_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> |
| #include "used.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| output should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| output should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for output: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| # Have the exact same iwyu output for 'alice.cpp' as for 'bob.cpp'. |
| iwyu_output = (iwyu_output.replace('output', 'alice.cpp') + |
| iwyu_output.replace('output', 'bob.cpp')) |
| |
| self.RegisterFileContents({'alice.cpp': changed_infile, |
| 'bob.cpp': unchanged_infile}) |
| # only alice.cpp should be edited, since it matches only_re. |
| self.flags.only_re = 'lice' |
| self.ProcessAndTest(iwyu_output, unedited_files=['bob.cpp']) |
| |
| def testIgnoreAndOnlyRe(self): |
| """Test the behavior of both --ignore_re and --only_re flags.""" |
| changed_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> ///- |
| ///+#include <stdio.h> |
| #include "used.h" |
| ///+#include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| unchanged_infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> |
| #include "used.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| output should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| output should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for output: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| # Have the exact same iwyu output for 'alice.cpp' as for 'bob.cpp' and 'charlie.cpp' |
| iwyu_output = (iwyu_output.replace('output', 'alice.cpp') + |
| iwyu_output.replace('output', 'bob.cpp') + |
| iwyu_output.replace('output', 'charlie.cpp')) |
| |
| self.RegisterFileContents({'alice.cpp': changed_infile, |
| 'bob.cpp': unchanged_infile, |
| 'charlie.cpp': changed_infile}) |
| # only alice.cpp should be edited, since it matches only_re and not ignore_re |
| self.flags.only_re = 'li' |
| self.flags.ignore_re = 'char' |
| self.ProcessAndTest(iwyu_output, unedited_files=['bob.cpp', 'charlie.cpp']) |
| |
| def testSortIncludes(self): |
| """Test sorting includes only -- like running fix_includes.py -s.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <stdio.h> |
| // This file is not used. |
| #include <notused.h> |
| |
| // This file is not used either. |
| // It's not used. |
| // Not used at all. |
| #include <notused2.h> |
| |
| #include "notused3.h" |
| |
| // This comment should stay, it's not before an #include. |
| const int kInt = 5; |
| // This file is used. |
| // It's definitedly used. |
| #include "used.h" |
| #include <stdlib.h> |
| |
| const int kInt2 = 6; |
| |
| #include "foo.cc" |
| |
| // This comment should stay, it's not before an #include. |
| int main() { return 0; } |
| """ |
| expected_output = """\ |
| // Copyright 2010 |
| |
| // This file is not used. |
| #include <notused.h> |
| // This file is not used either. |
| // It's not used. |
| // Not used at all. |
| #include <notused2.h> |
| #include <stdio.h> |
| #include "notused3.h" |
| |
| // This comment should stay, it's not before an #include. |
| const int kInt = 5; |
| #include <stdlib.h> |
| // This file is used. |
| // It's definitedly used. |
| #include "used.h" |
| |
| const int kInt2 = 6; |
| |
| #include "foo.cc" |
| |
| // This comment should stay, it's not before an #include. |
| int main() { return 0; } |
| """ |
| self.RegisterFileContents({'sort': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles(['sort'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingMultipleFiles(self): |
| """Tests passing more than one argument to SortIncludesInFiles().""" |
| infile1 = """\ |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <stddef.h> |
| """ |
| infile2 = """\ |
| #include "z.h" |
| #include "y.h" |
| #include "x.y" |
| """ |
| |
| expected_output = """\ |
| #include <stddef.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "x.y" |
| #include "y.h" |
| #include "z.h" |
| """ |
| self.RegisterFileContents({'f1': infile1, 'f2': infile2}) |
| num_files_modified = fix_includes.SortIncludesInFiles(['f1', 'f2'], |
| self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(2, num_files_modified) |
| |
| def testSortingIncludesAlreadySorted(self): |
| """Tests sorting includes only, when includes are already sorted.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <ctype.h> |
| #include <stdio.h> |
| |
| namespace Foo; // fwd-decls are out of order, but sorter ignores them |
| |
| namespace Bar; |
| |
| int main() { return 0; } |
| """ |
| self.RegisterFileContents({'sort_nosorting.h': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles(['sort_nosorting.h'], |
| self.flags) |
| self.assertListEqual([], self.actual_after_contents) |
| self.assertEqual(0, num_files_modified) |
| |
| def testBarrierIncludes(self): |
| """Tests that we correctly sort 'around' _BARRIER_INCLUDES.""" |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <linux/a_stay_top.h> |
| #include <stdlib.h> ///- |
| #include <linux/can_sort_around_this_deleted_include> ///- |
| #include <stdio.h> |
| ///+#include <stdlib.h> |
| #include "user/include.h" |
| ///+#include "user/new_include.h" |
| #include <linux/c_stay_second.h> |
| #include <linux/b_stay_third.h> |
| #include <ctype.h> |
| #include <cpp_include> |
| ///+#include <new_cpp_include> |
| #include <linux/d_stay_fourth.h> |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| barrier_includes.h should add these lines: |
| #include "user/new_include.h" |
| #include <new_cpp_include> |
| |
| barrier_includes.h should remove these lines: |
| - #include <linux/can_sort_around_this_deleted_include> // lines 5-5 |
| |
| The full include-list for barrier_includes.h: |
| #include "user/include.h" |
| #include "user/new_include.h" |
| #include <cpp_include> |
| #include <ctype.h> |
| #include <linux/a_stay_top.h> |
| #include <linux/b_stay_third.h> |
| #include <linux/c_stay_second.h> |
| #include <linux/d_stay_fourth.h> |
| #include <new_cpp_include> |
| #include <stdio.h> |
| #include <stdlib.h> |
| --- |
| """ |
| self.RegisterFileContents({'barrier_includes.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testSortingMainCUIncludeInSameDirectory(self): |
| """Check that we identify when first .h file is a main-cu #include.""" |
| infile = """\ |
| #include <stdio.h> |
| #include "me/subdir0/foo.h" |
| #include "other/baz.h" |
| """ |
| expected_output = """\ |
| #include "me/subdir0/foo.h" |
| #include <stdio.h> |
| #include "other/baz.h" |
| """ |
| self.RegisterFileContents({'me/subdir0/foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['me/subdir0/foo.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingMainCUIncludeViaPragma(self): |
| """Check that we treat (potentially multiple) associated headers as |
| main-cu #includes.""" |
| infile = """\ |
| #include <stdio.h> |
| #include "other/dir/bar.h" // IWYU pragma: associated |
| #include "other/baz.h" // IWYU pragma: associated |
| """ |
| expected_output = """\ |
| #include "other/baz.h" // IWYU pragma: associated |
| #include "other/dir/bar.h" // IWYU pragma: associated |
| #include <stdio.h> |
| """ |
| self.RegisterFileContents({'me/subdir0/foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['me/subdir0/foo.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingMainCUIncludeWithUpperCaseH(self): |
| """Check that we identify when first .H file is a main-cu #include.""" |
| infile = """\ |
| #include <stdio.h> |
| #include "foo.H" |
| """ |
| expected_output = """\ |
| #include "foo.H" |
| #include <stdio.h> |
| """ |
| self.RegisterFileContents({'foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['foo.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingMainCUIncludeWithHpp(self): |
| """Check that we identify when first .hpp file is a main-cu #include.""" |
| infile = """\ |
| #include <stdio.h> |
| #include "foo.hpp" |
| """ |
| expected_output = """\ |
| #include "foo.hpp" |
| #include <stdio.h> |
| """ |
| self.RegisterFileContents({'foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['foo.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingMainCUIncludeWithMixedCaseInl(self): |
| """Check that we identify when first -inl.hpp file with mixed case |
| is a main-cu #include.""" |
| infile = """\ |
| #include <stdio.h> |
| #include "foo-InL.h" |
| """ |
| expected_output = """\ |
| #include "foo-InL.h" |
| #include <stdio.h> |
| """ |
| self.RegisterFileContents({'foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['foo.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingMainCUIncludeInSameDirectoryWithInl(self): |
| """Check that we identify when first -inl.h file is a main-cu #include.""" |
| infile = """\ |
| #include <stdio.h> |
| #include "me/subdir0/foo-inl.h" |
| #include "other/baz.h" |
| """ |
| expected_output = """\ |
| #include "me/subdir0/foo-inl.h" |
| #include <stdio.h> |
| #include "other/baz.h" |
| """ |
| self.RegisterFileContents({'me/subdir0/foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['me/subdir0/foo.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingMainCUIncludeInDifferentDirectory(self): |
| """Check that we identify when first .h file is a main-cu #include.""" |
| infile = """\ |
| #include "me/subdir0/foo.h" |
| #include <stdio.h> |
| #include "other/baz.h" |
| """ |
| self.RegisterFileContents({'me/other_subdir/foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['me/other_subdir/foo.cc'], self.flags) |
| self.assertListEqual([], self.actual_after_contents) |
| self.assertEqual(0, num_files_modified) |
| |
| def testSortingMainCUIncludeInDifferentDirectoryWhenNotFirst(self): |
| """Check that we don't let second .h be a main-cu #include.""" |
| infile = """\ |
| #include <stdio.h> |
| #include "me/subdir0/foo.h" |
| #include "other/baz.h" |
| """ |
| self.RegisterFileContents({'me/other_subdir/foo.cc': infile}) |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['me/other_subdir/foo.cc'], self.flags) |
| self.assertListEqual([], self.actual_after_contents) |
| self.assertEqual(0, num_files_modified) |
| |
| def testSortingProjectIncludesAuto(self): |
| """Check that project includes can be sorted separately.""" |
| infile = """\ |
| #include "me/subdir0/foo.h" |
| #include <stdio.h> |
| #include "me/subdir2/bar.h" |
| #include "me/subdir1/bar.h" |
| #include "me/subdir0/bar.h" |
| #include "other/baz.h" |
| """ |
| expected_output = """\ |
| #include "me/subdir0/foo.h" |
| #include <stdio.h> |
| #include "other/baz.h" |
| #include "me/subdir0/bar.h" |
| #include "me/subdir1/bar.h" |
| #include "me/subdir2/bar.h" |
| """ |
| self.RegisterFileContents({'me/subdir0/foo.cc': infile}) |
| self.flags.separate_project_includes = '<tld>' |
| num_files_modified = fix_includes.SortIncludesInFiles(['me/subdir0/foo.cc'], |
| self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testSortingProjectIncludesUserSpecified(self): |
| """Test user-specified project directory name.""" |
| infile = """\ |
| #include "me/subdir0/foo.h" |
| #include <stdio.h> |
| #include "me/subdir2/bar.h" |
| #include "me/subdir1/bar.h" |
| #include "me/subdir0/bar.h" |
| #include "other/baz.h" |
| """ |
| expected_output = """\ |
| #include "me/subdir0/foo.h" |
| #include <stdio.h> |
| #include "me/subdir1/bar.h" |
| #include "me/subdir2/bar.h" |
| #include "other/baz.h" |
| #include "me/subdir0/bar.h" |
| """ |
| self.RegisterFileContents({'me/subdir0/foo.cc': infile}) |
| self.flags.separate_project_includes = 'me/subdir0' |
| num_files_modified = fix_includes.SortIncludesInFiles(['me/subdir0/foo.cc'], |
| self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testAddingNewIncludesAfterRemovingOldOnes(self): |
| infile = """\ |
| // Copyright 2008 Google Inc. All Rights Reserved. |
| // Author: zhifengc@google.com (Zhifeng Chen) |
| |
| #ifndef STRUCTUREDSEARCH_COMMON_INTERNAL_DFS_H_ |
| #define STRUCTUREDSEARCH_COMMON_INTERNAL_DFS_H_ |
| |
| #include "util/task/status.h" ///- |
| #include "strings/stringpiece.h" ///- |
| ///+#include <string> // for string |
| ///+#include "base/macros.h" // for DISALLOW_COPY_AND_ASSIGN |
| ///+#include "base/scoped_ptr.h" // for scoped_ptr |
| |
| class Query; |
| ///+namespace util { |
| ///+class Status; |
| ///+} // namespace util |
| |
| namespace structuredsearch { |
| |
| ///+class FieldSpecification; |
| class FieldTokenizer; |
| class FieldSpecification; ///- |
| class TokenizationSpec; |
| |
| class QueryXlator { ... }; |
| |
| #endif // #define STRUCTUREDSEARCH_COMMON_INTERNAL_DFS_H_ |
| """ |
| iwyu_output = """\ |
| structuredsearch/common/internal/query_field_xlate.h should add these lines: |
| #include <string> // for string |
| #include "base/macros.h" // for DISALLOW_COPY_AND_ASSIGN |
| #include "base/scoped_ptr.h" // for scoped_ptr |
| namespace util { class Status; } |
| |
| structuredsearch/common/internal/query_field_xlate.h should remove these lines: |
| - #include "strings/stringpiece.h" // lines 8-8 |
| - #include "util/task/status.h" // lines 7-7 |
| |
| The full include-list for structuredsearch/common/internal/query_field_xlate.h: |
| #include <string> // for string |
| #include "base/macros.h" // for DISALLOW_COPY_AND_ASSIGN |
| #include "base/scoped_ptr.h" // for scoped_ptr |
| class Query; // lines 10-10 |
| namespace structuredsearch { class FieldSpecification; } // lines 15-15 |
| namespace structuredsearch { class FieldTokenizer; } // lines 14-14 |
| namespace structuredsearch { class TokenizationSpec; } // lines 16-16 |
| namespace util { class Status; } |
| --- |
| """ |
| self.RegisterFileContents( |
| {'structuredsearch/common/internal/query_field_xlate.h': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testDryRun(self): |
| """Tests that --dry_run mode does not modify files.""" |
| self.flags.dry_run = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include <notused.h> |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| dry_run should add these lines: |
| #include <stdio.h> |
| #include "used2.h" |
| |
| dry_run should remove these lines: |
| - #include <notused.h> // lines 3-3 |
| |
| The full include-list for dry_run: |
| #include <stdio.h> |
| #include "used.h" |
| #include "used2.h" |
| --- |
| """ |
| self.RegisterFileContents({'dry_run': infile}) |
| num_modified_files = fix_includes.ProcessIWYUOutput( |
| StringIO(iwyu_output), ['dry_run'], self.flags, None) |
| self.assertListEqual([], self.actual_after_contents) |
| self.assertEqual(1, num_modified_files) |
| |
| def testAddForwardDeclareAndKeepIwyuNamespaceFormat(self): |
| """Tests that --keep_iwyu_namespace_format writes namespace lines |
| using the IWYU one-line format. |
| Input code similar to case testAddForwardDeclareInNamespace.""" |
| self.flags.keep_iwyu_namespace_format = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| ///+namespace ns { class Foo; } |
| ///+namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| ///+namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| ///+namespace ns { namespace ns4 { class Baz; } } |
| ///+ |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_declare_keep_iwyu_namespace should add these lines: |
| namespace ns { class Foo; } |
| namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| namespace ns { namespace ns4 { class Baz; } } |
| |
| add_fwd_declare_keep_iwyu_namespace should remove these lines: |
| |
| The full include-list for add_fwd_declare_keep_iwyu_namespace: |
| #include "foo.h" // lines 3-3 |
| namespace ns { class Foo; } |
| namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| namespace ns { namespace ns4 { class Baz; } } |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_declare_keep_iwyu_namespace': infile}) |
| self.ProcessAndTest(iwyu_output, expected_num_modified_files=1) |
| |
| def testAddNestedForwardDeclaresWithKeepIwyuNamespaceFormat(self): |
| """Tests that --keep_iwyu_namespace_format writes namespace lines |
| using the IWYU one-line format. |
| Input code similar to case |
| testAddForwardDeclareInsideNamespaceWithoutForwardDeclaresAlready.""" |
| self.flags.keep_iwyu_namespace_format = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| class Bar; |
| ///+class Foo; |
| ///+namespace ns1 { class NsFoo; } |
| ///+namespace ns1 { namespace ns2 { namespace ns3 { class NsBaz; } } } |
| ///+namespace ns1 { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } } |
| template <typename T> class Baz; |
| |
| |
| namespace ns { |
| ///- |
| ///+class NsFoo; |
| ///+namespace ns2 { namespace ns3 { class NsBaz; } } |
| ///+namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } |
| ///+ |
| class NsBar; |
| |
| namespace ns2 { // we sure do love nesting our namespaces! |
| |
| int MyFunction() { } |
| |
| } |
| } |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_decl_with_keep_iwyu_format should add these lines: |
| class Foo; |
| namespace ns { class NsFoo; } |
| namespace ns { namespace ns2 { namespace ns3 { class NsBaz; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } } |
| namespace ns1 { class NsFoo; } |
| namespace ns1 { namespace ns2 { namespace ns3 { class NsBaz; } } } |
| namespace ns1 { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } } |
| |
| add_fwd_decl_with_keep_iwyu_format should remove these lines: |
| |
| The full include-list for add_fwd_decl_with_keep_iwyu_format: |
| #include "foo.h" // lines 3-3 |
| class Bar; // lines 5-5 |
| class Foo; |
| namespace ns { class NsFoo; } |
| namespace ns { namespace ns2 { class NsBar; } } |
| namespace ns { namespace ns2 { namespace ns3 { class NsBaz; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } } |
| namespace ns1 { class NsFoo; } |
| namespace ns1 { namespace ns2 { namespace ns3 { class NsBaz; } } } |
| namespace ns1 { namespace ns2 { namespace ns3 { template <typename T> class NsBang; } } } |
| template <typename T> class Baz; // lines 6-6 |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_decl_with_keep_iwyu_format': infile}) |
| self.ProcessAndTest(iwyu_output) |
| |
| def testAddForwardDeclareInNamespaceWithKeepIwyuNamespaceFormat(self): |
| """Tests that --keep_iwyu_namespace_format writes namespace lines |
| using the IWYU one-line format. |
| Input code similar to case testAddForwardDeclareInNamespace.""" |
| self.flags.keep_iwyu_namespace_format = True |
| infile = """\ |
| // Copyright 2010 |
| |
| #include "foo.h" |
| |
| ///+namespace ns { class Foo; } |
| ///+namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| ///+namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| ///+namespace ns { namespace ns4 { class Baz; } } |
| ///+ |
| |
| int main() { return 0; } |
| """ |
| iwyu_output = """\ |
| add_fwd_declare_keep_iwyu_namespace should add these lines: |
| namespace ns { class Foo; } |
| namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| namespace ns { namespace ns4 { class Baz; } } |
| |
| add_fwd_declare_keep_iwyu_namespace should remove these lines: |
| |
| The full include-list for add_fwd_declare_keep_iwyu_namespace: |
| #include "foo.h" // lines 3-3 |
| namespace ns { class Foo; } |
| namespace ns { namespace ns2 { namespace ns3 { class Bar; } } } |
| namespace ns { namespace ns2 { namespace ns3 { template <typename T> class Bang; } } } |
| namespace ns { namespace ns4 { class Baz; } } |
| --- |
| """ |
| self.RegisterFileContents({'add_fwd_declare_keep_iwyu_namespace': infile}) |
| self.ProcessAndTest(iwyu_output, expected_num_modified_files=1) |
| |
| def testBasedir(self): |
| self.flags.basedir = "/project/build/" |
| iwyu_output = """\ |
| ../src/source.cc should add these lines: |
| |
| ../src/source.cc should remove these lines: |
| - #include <unused.h> // lines 1-1 |
| |
| The full include-list for ../src/source.cc: |
| #include <used.h> |
| --- |
| """ |
| infile = """\ |
| #include <unused.h> ///- |
| #include <used.h> |
| |
| int main() { return 0; } |
| """ |
| self.RegisterFileContents({'/project/src/source.cc': infile}) |
| self.ProcessAndTest(iwyu_output, expected_num_modified_files=1) |
| |
| def testBasedirWithFilesToProcess(self): |
| self.flags.basedir = "/project/build/" |
| iwyu_output = """\ |
| ../src/changed.cc should add these lines: |
| |
| ../src/changed.cc should remove these lines: |
| - #include <unused.h> // lines 1-1 |
| |
| The full include-list for ../src/changed.cc: |
| #include <used.h> |
| --- |
| """ |
| changed_file = """\ |
| #include <unused.h> ///- |
| #include <used.h> |
| |
| int main() { return 0; } |
| """ |
| unchanged_file = """\ |
| #include <unused.h> |
| #include <used.h> |
| |
| int main() { return 0; } |
| """ |
| |
| iwyu_output += iwyu_output.replace('changed.cc', 'unchanged.cc') |
| |
| self.RegisterFileContents({ |
| '/project/src/changed.cc': changed_file, |
| '/project/src/unchanged.cc': unchanged_file |
| }) |
| self.ProcessAndTest(iwyu_output, cmdline_files=['/project/src/changed.cc'], |
| unedited_files=['/project/src/unchanged.cc']) |
| |
| def testBasedirWithRelativeCmdlineFiles(self): |
| self.flags.basedir = "/project/build/" |
| iwyu_output = """\ |
| ../src/changed.cc should add these lines: |
| |
| ../src/changed.cc should remove these lines: |
| - #include <unused.h> // lines 1-1 |
| |
| The full include-list for ../src/changed.cc: |
| #include <used.h> |
| --- |
| """ |
| changed_file = """\ |
| #include <unused.h> ///- |
| #include <used.h> |
| |
| int main() { return 0; } |
| """ |
| |
| self.RegisterFileContents({ |
| # File path is normalized to absolute by ProcessIWYUOutput. |
| '/project/src/changed.cc': changed_file, |
| }) |
| self.ProcessAndTest(iwyu_output, cmdline_files=['changed.cc'], |
| cwd='/project/src') |
| |
| def testMain(self): |
| """Make sure calling main doesn't crash. Inspired by a syntax-error bug.""" |
| # Give an empty stdin so we don't actually try to parse anything. |
| old_stdin = sys.stdin |
| try: |
| sys.stdin = StringIO() |
| fix_includes.main(['fix_includes.py']) # argv[0] doesn't really matter |
| finally: |
| sys.stdin = old_stdin |
| |
| def testFilenamesForSortingInMain(self): |
| """Make sure if we use s, we have a filename specified, in main().""" |
| # -s without any files to sort. |
| self.assertRaises(SystemExit, fix_includes.main, |
| ['fix_includes.py', '-s']) |
| |
| def testReorderingInclusions(self): |
| """Show that the --reorder flag causes #includes to be sorted.""" |
| infile = """\ |
| // namespace B |
| namespace B { class BC; } // B |
| // namespace A |
| namespace A { class AC; } // A |
| // b |
| #include "b" // b |
| // c |
| #include <c> // c |
| // a |
| #include <a> // a |
| // a |
| #include "a" // a |
| // asdf |
| #ifdef asdf |
| // x |
| #include <x> // x |
| // endif |
| #endif |
| """ |
| expected_output = """\ |
| // namespace B |
| namespace B { class BC; } // B |
| // namespace A |
| namespace A { class AC; } // A |
| // a |
| #include <a> // a |
| // c |
| #include <c> // c |
| // a |
| #include "a" // a |
| // b |
| #include "b" // b |
| // asdf |
| #ifdef asdf |
| // x |
| #include <x> // x |
| // endif |
| #endif |
| """ |
| self.RegisterFileContents({'inclusions_reordered.cc': infile}) |
| self.flags.reorder = True |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['inclusions_reordered.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| def testNoReorderingInclusions(self): |
| """Show that the --noreorder flag causes #includes not to be sorted.""" |
| infile = """\ |
| // namespace B |
| namespace B { class BC; } // B |
| // namespace A |
| namespace A { class AC; } // A |
| // b |
| #include "b" // b |
| // c |
| #include <c> // c |
| // a |
| #include <a> // a |
| // a |
| #include "a" // a |
| // asdf |
| #ifdef asdf |
| // x |
| #include <x> // x |
| // endif |
| #endif |
| """ |
| expected_output = """\ |
| // namespace B |
| namespace B { class BC; } // B |
| // namespace A |
| namespace A { class AC; } // A |
| // c |
| #include <c> // c |
| // a |
| #include <a> // a |
| // b |
| #include "b" // b |
| // a |
| #include "a" // a |
| // asdf |
| #ifdef asdf |
| // x |
| #include <x> // x |
| // endif |
| #endif |
| """ |
| self.RegisterFileContents({'inclusions_not_reordered.cc': infile}) |
| self.flags.reorder = False |
| num_files_modified = fix_includes.SortIncludesInFiles( |
| ['inclusions_not_reordered.cc'], self.flags) |
| self.assertListEqual(expected_output.splitlines(True), |
| self.actual_after_contents) |
| self.assertEqual(1, num_files_modified) |
| |
| |
| class FileInfoTest(unittest.TestCase): |
| """ Unit test for file info detection """ |
| |
| def testEndingsWindows(self): |
| buf = b'first\r\nsecond\r\nthird\r\n' |
| self.assertEqual('\r\n', fix_includes.FileInfo.guess_linesep(buf)) |
| |
| def testEndingsUnix(self): |
| buf = b'first\nsecond\nthird\n' |
| self.assertEqual('\n', fix_includes.FileInfo.guess_linesep(buf)) |
| |
| def testEndingsMixedUnixMajority(self): |
| buf = b'first\nsecond\nsecond-and-a-half\r\nthird\nfourth\r\n' |
| self.assertEqual('\n', fix_includes.FileInfo.guess_linesep(buf)) |
| |
| def testEndingsMixedWindowsMajority(self): |
| buf = b'first\nsecond\r\nsecond-and-a-half\r\nthird\nfourth\r\n' |
| self.assertEqual('\r\n', fix_includes.FileInfo.guess_linesep(buf)) |
| |
| def testEndingsMixedTie(self): |
| buf = b'first\nsecond\nthird\r\nfourth\r\n' |
| self.assertEqual(fix_includes.FileInfo.DEFAULT_LINESEP, |
| fix_includes.FileInfo.guess_linesep(buf)) |
| |
| def testEncodingASCII(self): |
| buf = b'abcdefgh' |
| self.assertEqual('ascii', fix_includes.FileInfo.guess_encoding(buf)) |
| |
| def testEncodingUTF8BOM(self): |
| buf = b'\xef\xbb\xbfSomeASCIIButWithTheBOM' |
| self.assertEqual('utf-8-sig', fix_includes.FileInfo.guess_encoding(buf)) |
| |
| def testEncodingUTF8NoBOM(self): |
| # This is a recurring test input in Swedish, translates to "shrimp sandwich" |
| # and contains all three Swedish exotic characters. |
| buf = b'r\xc3\xa4ksm\xc3\xb6rg\xc3\xa5s' |
| self.assertEqual('utf-8', fix_includes.FileInfo.guess_encoding(buf)) |
| |
| def testEncodingISO8859_1(self): |
| # Yours truly |
| buf = b'Kim Gr\xe4sman' |
| self.assertEqual('windows-1250', fix_includes.FileInfo.guess_encoding(buf)) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |