123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- #!/usr/bin/env python3
- # Copyright 2021 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- import random
- import unittest
- import add_header
- class DecoratedFilenameTest(unittest.TestCase):
- def testCHeaderClassification(self):
- self.assertTrue(add_header.IsCSystemHeader('<stdlib.h>'))
- self.assertFalse(add_header.IsCSystemHeader('<type_traits>'))
- self.assertFalse(add_header.IsCSystemHeader('"moo.h"'))
- def testCXXHeaderClassification(self):
- self.assertFalse(add_header.IsCXXSystemHeader('<stdlib.h>'))
- self.assertTrue(add_header.IsCXXSystemHeader('<type_traits>'))
- self.assertFalse(add_header.IsCXXSystemHeader('"moo.h"'))
- def testUserHeaderClassification(self):
- self.assertFalse(add_header.IsUserHeader('<stdlib.h>'))
- self.assertFalse(add_header.IsUserHeader('<type_traits>'))
- self.assertTrue(add_header.IsUserHeader('"moo.h"'))
- def testClassifyHeader(self):
- self.assertEqual(add_header.ClassifyHeader('<stdlib.h>'),
- add_header._HEADER_TYPE_C_SYSTEM)
- self.assertEqual(add_header.ClassifyHeader('<type_traits>'),
- add_header._HEADER_TYPE_CXX_SYSTEM)
- self.assertEqual(add_header.ClassifyHeader('"moo.h"'),
- add_header._HEADER_TYPE_USER)
- self.assertEqual(add_header.ClassifyHeader('invalid'),
- add_header._HEADER_TYPE_INVALID)
- class FindIncludesTest(unittest.TestCase):
- def testEmpty(self):
- begin, end = add_header.FindIncludes([])
- self.assertEqual(begin, -1)
- self.assertEqual(end, -1)
- def testNoIncludes(self):
- begin, end = add_header.FindIncludes(['a'])
- self.assertEqual(begin, -1)
- self.assertEqual(end, -1)
- def testOneInclude(self):
- begin, end = add_header.FindIncludes(['#include <algorithm>'])
- self.assertEqual(begin, 0)
- self.assertEqual(end, 1)
- def testIncludeWithInlineComment(self):
- begin, end = add_header.FindIncludes(
- ['#include "moo.h" // TODO: Add more sounds.'])
- self.assertEqual(begin, 0)
- self.assertEqual(end, 1)
- def testNewlinesBetweenIncludes(self):
- begin, end = add_header.FindIncludes(
- ['#include <utility>', '', '#include "moo.h"'])
- self.assertEqual(begin, 0)
- self.assertEqual(end, 3)
- def testCommentsBetweenIncludes(self):
- begin, end = add_header.FindIncludes([
- '#include <utility>', '// TODO: Add goat support.', '#include "moo.h"'
- ])
- self.assertEqual(begin, 0)
- self.assertEqual(end, 3)
- def testEmptyLinesNotIncluded(self):
- begin, end = add_header.FindIncludes(
- ['', '#include <utility>', '', '#include "moo.h"', ''])
- self.assertEqual(begin, 1)
- self.assertEqual(end, 4)
- def testCommentsNotIncluded(self):
- begin, end = add_header.FindIncludes([
- '// Cow module.', '#include <utility>', '// For cow speech synthesis.',
- '#include "moo.h"', '// TODO: Add Linux audio support.'
- ])
- self.assertEqual(begin, 1)
- self.assertEqual(end, 4)
- def testNonIncludesLinesBeforeIncludesIgnored(self):
- begin, end = add_header.FindIncludes(
- ['#ifndef COW_H_', '#define COW_H_', '#include "moo.h"'])
- self.assertEqual(begin, 2)
- self.assertEqual(end, 3)
- def testNonIncludesLinesAfterIncludesTerminates(self):
- begin, end = add_header.FindIncludes([
- '#include "moo.h"', '#ifndef COW_MESSAGES_H_', '#define COW_MESSAGE_H_'
- ])
- self.assertEqual(begin, 0)
- self.assertEqual(end, 1)
- class IncludeTest(unittest.TestCase):
- def testToSource(self):
- self.assertEqual(
- add_header.Include('<moo.h>', 'include', [], None).ToSource(),
- ['#include <moo.h>'])
- def testIncludeWithPreambleToSource(self):
- self.assertEqual(
- add_header.Include('"moo.h"', 'include', ['// preamble'],
- None).ToSource(),
- ['// preamble', '#include "moo.h"'])
- def testIncludeWithInlineCommentToSource(self):
- self.assertEqual(
- add_header.Include('"moo.h"', 'include', [],
- ' inline comment').ToSource(),
- ['#include "moo.h" // inline comment'])
- def testIncludeWithPreambleAndInlineCommentToSource(self):
- # Make sure whitespace is vaguely normalized too.
- self.assertEqual(
- add_header.Include('"moo.h"', 'include', [
- '// preamble with trailing space ',
- ], ' inline comment with trailing space ').ToSource(), [
- '// preamble with trailing space',
- '#include "moo.h" // inline comment with trailing space'
- ])
- def testImportToSource(self):
- self.assertEqual(
- add_header.Include('"moo.h"', 'import', [], None).ToSource(),
- ['#import "moo.h"'])
- class ParseIncludesTest(unittest.TestCase):
- def testInvalid(self):
- self.assertIsNone(add_header.ParseIncludes(['invalid']))
- def testInclude(self):
- includes = add_header.ParseIncludes(['#include "moo.h"'])
- self.assertEqual(len(includes), 1)
- self.assertEqual(includes[0].decorated_name, '"moo.h"')
- self.assertEqual(includes[0].directive, 'include')
- self.assertEqual(includes[0].preamble, [])
- self.assertIsNone(includes[0].inline_comment)
- self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[0].is_primary_header)
- def testIncludeSurroundedByWhitespace(self):
- includes = add_header.ParseIncludes([' #include "moo.h" '])
- self.assertEqual(len(includes), 1)
- self.assertEqual(includes[0].decorated_name, '"moo.h"')
- self.assertEqual(includes[0].directive, 'include')
- self.assertEqual(includes[0].preamble, [])
- self.assertIsNone(includes[0].inline_comment)
- self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[0].is_primary_header)
- def testImport(self):
- includes = add_header.ParseIncludes(['#import "moo.h"'])
- self.assertEqual(len(includes), 1)
- self.assertEqual(includes[0].decorated_name, '"moo.h"')
- self.assertEqual(includes[0].directive, 'import')
- self.assertEqual(includes[0].preamble, [])
- self.assertIsNone(includes[0].inline_comment)
- self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[0].is_primary_header)
- def testIncludeWithPreamble(self):
- includes = add_header.ParseIncludes(
- ['// preamble comment ', '#include "moo.h"'])
- self.assertEqual(len(includes), 1)
- self.assertEqual(includes[0].decorated_name, '"moo.h"')
- self.assertEqual(includes[0].directive, 'include')
- self.assertEqual(includes[0].preamble, ['// preamble comment '])
- self.assertIsNone(includes[0].inline_comment)
- self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[0].is_primary_header)
- def testIncludeWithInvalidPreamble(self):
- self.assertIsNone(
- add_header.ParseIncludes(['// orphan comment', '', '#include "moo.h"']))
- def testIncludeWIthInlineComment(self):
- includes = add_header.ParseIncludes(['#include "moo.h"// For SFX '])
- self.assertEqual(len(includes), 1)
- self.assertEqual(includes[0].decorated_name, '"moo.h"')
- self.assertEqual(includes[0].directive, 'include')
- self.assertEqual(includes[0].preamble, [])
- self.assertEqual(includes[0].inline_comment, ' For SFX ')
- self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[0].is_primary_header)
- def testIncludeWithInlineCommentAndPreamble(self):
- includes = add_header.ParseIncludes(
- ['// preamble comment ', '#include "moo.h" // For SFX '])
- self.assertEqual(len(includes), 1)
- self.assertEqual(includes[0].decorated_name, '"moo.h"')
- self.assertEqual(includes[0].directive, 'include')
- self.assertEqual(includes[0].preamble, ['// preamble comment '])
- self.assertEqual(includes[0].inline_comment, ' For SFX ')
- self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[0].is_primary_header)
- def testMultipleIncludes(self):
- includes = add_header.ParseIncludes([
- '#include <time.h>', '', '#include "moo.h" // For SFX ',
- '// TODO: Implement death ray.', '#import "goat.h"'
- ])
- self.assertEqual(len(includes), 3)
- self.assertEqual(includes[0].decorated_name, '<time.h>')
- self.assertEqual(includes[0].directive, 'include')
- self.assertEqual(includes[0].preamble, [])
- self.assertIsNone(includes[0].inline_comment)
- self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_C_SYSTEM)
- self.assertFalse(includes[0].is_primary_header)
- self.assertEqual(includes[1].decorated_name, '"moo.h"')
- self.assertEqual(includes[1].directive, 'include')
- self.assertEqual(includes[1].preamble, [])
- self.assertEqual(includes[1].inline_comment, ' For SFX ')
- self.assertEqual(includes[1].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[1].is_primary_header)
- self.assertEqual(includes[2].decorated_name, '"goat.h"')
- self.assertEqual(includes[2].directive, 'import')
- self.assertEqual(includes[2].preamble, ['// TODO: Implement death ray.'])
- self.assertIsNone(includes[2].inline_comment)
- self.assertEqual(includes[2].header_type, add_header._HEADER_TYPE_USER)
- self.assertFalse(includes[2].is_primary_header)
- class MarkPrimaryIncludeTest(unittest.TestCase):
- def _extract_primary_name(self, includes):
- for include in includes:
- if include.is_primary_header:
- return include.decorated_name
- def testNoOpOnHeader(self):
- includes = [add_header.Include('"cow.h"', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'cow.h')
- self.assertIsNone(self._extract_primary_name(includes))
- def testSystemHeaderNotMatched(self):
- includes = [add_header.Include('<cow.h>', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'cow.cc')
- self.assertIsNone(self._extract_primary_name(includes))
- def testExactMatch(self):
- includes = [
- add_header.Include('"cow.h"', 'include', [], None),
- add_header.Include('"cow_posix.h"', 'include', [], None),
- ]
- add_header.MarkPrimaryInclude(includes, 'cow.cc')
- self.assertEqual(self._extract_primary_name(includes), '"cow.h"')
- def testFuzzyMatch(self):
- includes = [add_header.Include('"cow.h"', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'cow_linux_unittest.cc')
- self.assertEqual(self._extract_primary_name(includes), '"cow.h"')
- def testFuzzymatchInReverse(self):
- includes = [add_header.Include('"cow.h"', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'cow_uitest_aura.cc')
- self.assertEqual(self._extract_primary_name(includes), '"cow.h"')
- def testFuzzyMatchDoesntMatchDifferentSuffixes(self):
- includes = [add_header.Include('"cow_posix.h"', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'cow_windows.cc')
- self.assertIsNone(self._extract_primary_name(includes))
- def testMarksMostSpecific(self):
- includes = [
- add_header.Include('"cow.h"', 'include', [], None),
- add_header.Include('"cow_posix.h"', 'include', [], None),
- ]
- add_header.MarkPrimaryInclude(includes, 'cow_posix.cc')
- self.assertEqual(self._extract_primary_name(includes), '"cow_posix.h"')
- def testFullPathMatch(self):
- includes = [add_header.Include('"zfs/impl/cow.h"', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'zfs/impl/cow.cc')
- self.assertEqual(self._extract_primary_name(includes), '"zfs/impl/cow.h"')
- def testTopmostDirectoryDoesNotMatch(self):
- includes = [add_header.Include('"animal/impl/cow.h"', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'zfs/impl/cow.cc')
- self.assertIsNone(self._extract_primary_name(includes))
- def testSubstantiallySimilarPaths(self):
- includes = [
- add_header.Include('"farm/public/animal/cow.h"', 'include', [], None)
- ]
- add_header.MarkPrimaryInclude(includes, 'farm/animal/cow.cc')
- self.assertEqual(self._extract_primary_name(includes),
- '"farm/public/animal/cow.h"')
- def testSubstantiallySimilarPathsAndExactMatch(self):
- includes = [
- add_header.Include('"ui/gfx/ipc/geometry/gfx_param_traits.h"',
- 'include', [], None),
- add_header.Include('"ui/gfx/ipc/gfx_param_traits.h"', 'include', [],
- None),
- ]
- add_header.MarkPrimaryInclude(includes, 'ui/gfx/ipc/gfx_param_traits.cc')
- self.assertEqual(self._extract_primary_name(includes),
- '"ui/gfx/ipc/gfx_param_traits.h"')
- def testNoMatchingSubdirectories(self):
- includes = [add_header.Include('"base/zfs/cow.h"', 'include', [], None)]
- add_header.MarkPrimaryInclude(includes, 'base/animal/cow.cc')
- self.assertIsNone(self._extract_primary_name(includes))
- class SerializeIncludesTest(unittest.TestCase):
- def testSystemHeaders(self):
- source = add_header.SerializeIncludes([
- add_header.Include('<stdlib.h>', 'include', [], None),
- add_header.Include('<map>', 'include', [], None),
- ])
- self.assertEqual(source, ['#include <stdlib.h>', '', '#include <map>'])
- def testUserHeaders(self):
- source = add_header.SerializeIncludes([
- add_header.Include('"goat.h"', 'include', [], None),
- add_header.Include('"moo.h"', 'include', [], None),
- ])
- self.assertEqual(source, ['#include "goat.h"', '#include "moo.h"'])
- def testSystemAndUserHeaders(self):
- source = add_header.SerializeIncludes([
- add_header.Include('<stdlib.h>', 'include', [], None),
- add_header.Include('<map>', 'include', [], None),
- add_header.Include('"moo.h"', 'include', [], None),
- ])
- self.assertEqual(
- source,
- ['#include <stdlib.h>', '', '#include <map>', '', '#include "moo.h"'])
- def testPrimaryAndSystemHeaders(self):
- primary_header = add_header.Include('"cow.h"', 'include', [], None)
- primary_header.is_primary_header = True
- source = add_header.SerializeIncludes([
- primary_header,
- add_header.Include('<stdlib.h>', 'include', [], None),
- add_header.Include('<map>', 'include', [], None),
- ])
- self.assertEqual(
- source,
- ['#include "cow.h"', '', '#include <stdlib.h>', '', '#include <map>'])
- def testPrimaryAndUserHeaders(self):
- primary_header = add_header.Include('"cow.h"', 'include', [], None)
- primary_header.is_primary_header = True
- source = add_header.SerializeIncludes([
- primary_header,
- add_header.Include('"moo.h"', 'include', [], None),
- ])
- self.assertEqual(source, ['#include "cow.h"', '', '#include "moo.h"'])
- def testPrimarySystemAndUserHeaders(self):
- primary_header = add_header.Include('"cow.h"', 'include', [], None)
- primary_header.is_primary_header = True
- source = add_header.SerializeIncludes([
- primary_header,
- add_header.Include('<stdlib.h>', 'include', [], None),
- add_header.Include('<map>', 'include', [], None),
- add_header.Include('"moo.h"', 'include', [], None),
- ])
- self.assertEqual(source, [
- '#include "cow.h"', '', '#include <stdlib.h>', '', '#include <map>', '',
- '#include "moo.h"'
- ])
- def testSpecialHeaders(self):
- includes = []
- primary_header = add_header.Include('"cow.h"', 'include', [], None)
- primary_header.is_primary_header = True
- includes.append(primary_header)
- includes.append(add_header.Include('<winsock2.h>', 'include', [], None))
- includes.append(add_header.Include('<windows.h>', 'include', [], None))
- includes.append(add_header.Include('<ws2tcpip.h>', 'include', [], None))
- includes.append(add_header.Include('<shobjidl.h>', 'include', [], None))
- includes.append(add_header.Include('<atlbase.h>', 'include', [], None))
- includes.append(add_header.Include('<ole2.h>', 'include', [], None))
- includes.append(add_header.Include('<unknwn.h>', 'include', [], None))
- includes.append(add_header.Include('<objbase.h>', 'include', [], None))
- includes.append(add_header.Include('<tchar.h>', 'include', [], None))
- includes.append(add_header.Include('<string.h>', 'include', [], None))
- includes.append(add_header.Include('<stddef.h>', 'include', [], None))
- includes.append(add_header.Include('<stdio.h>', 'include', [], None))
- includes.append(add_header.Include('"moo.h"', 'include', [], None))
- random.shuffle(includes)
- source = add_header.SerializeIncludes(includes)
- self.assertEqual(source, [
- '#include "cow.h"', '', '#include <winsock2.h>', '#include <windows.h>',
- '#include <ws2tcpip.h>', '#include <shobjidl.h>',
- '#include <atlbase.h>', '#include <ole2.h>', '#include <unknwn.h>',
- '#include <objbase.h>', '#include <tchar.h>', '#include <stddef.h>',
- '#include <stdio.h>', '#include <string.h>', '', '#include "moo.h"'
- ])
- class AddHeaderToSourceTest(unittest.TestCase):
- def testAddInclude(self):
- source = add_header.AddHeaderToSource(
- 'cow.cc', '\n'.join([
- '// Copyright info here.', '', '#include <utility>',
- '// For cow speech synthesis.',
- '#include "moo.h" // TODO: Add Linux audio support.',
- '#include <time.h>', '#include "cow.h"', 'namespace bovine {', '',
- '// TODO: Implement.', '} // namespace bovine'
- ]), '<memory>')
- self.assertEqual(
- source, '\n'.join([
- '// Copyright info here.', '', '#include "cow.h"', '',
- '#include <time.h>', '', '#include <memory>', '#include <utility>',
- '', '// For cow speech synthesis.',
- '#include "moo.h" // TODO: Add Linux audio support.',
- 'namespace bovine {', '', '// TODO: Implement.',
- '} // namespace bovine', ''
- ]))
- def testAlreadyIncluded(self):
- # To make sure the original source is returned unmodified, the input source
- # intentionally scrambles the #include order.
- source = '\n'.join([
- '// Copyright info here.', '', '#include "moo.h"', '#include <utility>',
- '#include <memory>', '#include "cow.h"', 'namespace bovine {', '',
- '// TODO: Implement.', '} // namespace bovine'
- ])
- self.assertEqual(add_header.AddHeaderToSource('cow.cc', source, '<memory>'),
- None)
- def testConditionalIncludesLeftALone(self):
- # TODO(dcheng): Conditional header handling could probably be more clever.
- # But for the moment, this is probably Good Enough.
- source = add_header.AddHeaderToSource(
- 'cow.cc', '\n'.join([
- '// Copyright info here.', '', '#include "cow.h"',
- '#include <utility>', '// For cow speech synthesis.',
- '#include "moo.h" // TODO: Add Linux audio support.',
- '#if defined(USE_AURA)', '#include <memory>',
- '#endif // defined(USE_AURA)'
- ]), '<memory>')
- self.assertEqual(
- source, '\n'.join([
- '// Copyright info here.', '', '#include "cow.h"', '',
- '#include <memory>', '#include <utility>', '',
- '// For cow speech synthesis.',
- '#include "moo.h" // TODO: Add Linux audio support.',
- '#if defined(USE_AURA)', '#include <memory>',
- '#endif // defined(USE_AURA)', ''
- ]))
- def testRemoveInclude(self):
- source = add_header.AddHeaderToSource(
- 'cow.cc',
- '\n'.join([
- '// Copyright info here.', '', '#include <memory>',
- '#include <utility>', '// For cow speech synthesis.',
- '#include "moo.h" // TODO: Add Linux audio support.',
- '#include <time.h>', '#include "cow.h"', 'namespace bovine {', '',
- '// TODO: Implement.', '} // namespace bovine'
- ]),
- '<utility>',
- remove=True)
- self.assertEqual(
- source, '\n'.join([
- '// Copyright info here.', '', '#include "cow.h"', '',
- '#include <time.h>', '', '#include <memory>', '',
- '// For cow speech synthesis.',
- '#include "moo.h" // TODO: Add Linux audio support.',
- 'namespace bovine {', '', '// TODO: Implement.',
- '} // namespace bovine', ''
- ]))
- if __name__ == '__main__':
- unittest.main()
|