| #!/usr/bin/env python3 |
| # Copyright 2021 The Chromium Authors |
| # 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 |
| |
| |
| classDecoratedFilenameTest(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) |
| |
| |
| classFindIncludesTest(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) |
| |
| |
| classIncludeTest(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"']) |
| |
| |
| classParseIncludesTest(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) |
| |
| |
| classMarkPrimaryIncludeTest(unittest.TestCase): |
| def _extract_primary_name(self, includes): |
| for includein 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)) |
| |
| |
| classSerializeIncludesTest(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('<objbase.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('<shobjidl.h>','include',[],None)) |
| includes.append(add_header.Include('<tchar.h>','include',[],None)) |
| includes.append(add_header.Include('<unknwn.h>','include',[],None)) |
| 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('<stddef.h>','include',[],None)) |
| includes.append(add_header.Include('<stdio.h>','include',[],None)) |
| includes.append(add_header.Include('<string.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 <objbase.h>','#include <atlbase.h>', |
| '#include <ole2.h>','#include <shobjidl.h>','#include <tchar.h>', |
| '#include <unknwn.h>','#include <windows.h>','#include <winsock2.h>', |
| '#include <ws2tcpip.h>','#include <stddef.h>','#include <stdio.h>', |
| '#include <string.h>','','#include "moo.h"' |
| ]) |
| |
| |
| classAddHeaderToSourceTest(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() |