OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 import unittest |
| 7 |
| 8 import add_header |
| 9 |
| 10 |
| 11 class DecoratedFilenameTest(unittest.TestCase): |
| 12 |
| 13 def testCHeaderClassification(self): |
| 14 self.assertTrue(add_header.IsCSystemHeader('<stdlib.h>')) |
| 15 self.assertFalse(add_header.IsCSystemHeader('<type_traits>')) |
| 16 self.assertFalse(add_header.IsCSystemHeader('"moo.h"')) |
| 17 |
| 18 def testCXXHeaderClassification(self): |
| 19 self.assertFalse(add_header.IsCXXSystemHeader('<stdlib.h>')) |
| 20 self.assertTrue(add_header.IsCXXSystemHeader('<type_traits>')) |
| 21 self.assertFalse(add_header.IsCXXSystemHeader('"moo.h"')) |
| 22 |
| 23 def testUserHeaderClassification(self): |
| 24 self.assertFalse(add_header.IsUserHeader('<stdlib.h>')) |
| 25 self.assertFalse(add_header.IsUserHeader('<type_traits>')) |
| 26 self.assertTrue(add_header.IsUserHeader('"moo.h"')) |
| 27 |
| 28 def testClassifyHeader(self): |
| 29 self.assertEqual( |
| 30 add_header.ClassifyHeader('<stdlib.h>'), |
| 31 add_header._HEADER_TYPE_C_SYSTEM) |
| 32 self.assertEqual( |
| 33 add_header.ClassifyHeader('<type_traits>'), |
| 34 add_header._HEADER_TYPE_CXX_SYSTEM) |
| 35 self.assertEqual( |
| 36 add_header.ClassifyHeader('"moo.h"'), add_header._HEADER_TYPE_USER) |
| 37 self.assertEqual( |
| 38 add_header.ClassifyHeader('invalid'), add_header._HEADER_TYPE_INVALID) |
| 39 |
| 40 |
| 41 class FindIncludesTest(unittest.TestCase): |
| 42 |
| 43 def testEmpty(self): |
| 44 begin, end = add_header.FindIncludes([]) |
| 45 self.assertEqual(begin, -1) |
| 46 self.assertEqual(end, -1) |
| 47 |
| 48 def testNoIncludes(self): |
| 49 begin, end = add_header.FindIncludes(['a']) |
| 50 self.assertEqual(begin, -1) |
| 51 self.assertEqual(end, -1) |
| 52 |
| 53 def testOneInclude(self): |
| 54 begin, end = add_header.FindIncludes(['#include <algorithm>']) |
| 55 self.assertEqual(begin, 0) |
| 56 self.assertEqual(end, 1) |
| 57 |
| 58 def testIncludeWithInlineComment(self): |
| 59 begin, end = add_header.FindIncludes( |
| 60 ['#include "moo.h" // TODO: Add more sounds.']) |
| 61 self.assertEqual(begin, 0) |
| 62 self.assertEqual(end, 1) |
| 63 |
| 64 def testNewlinesBetweenIncludes(self): |
| 65 begin, end = add_header.FindIncludes(['#include <utility>', '', |
| 66 '#include "moo.h"']) |
| 67 self.assertEqual(begin, 0) |
| 68 self.assertEqual(end, 3) |
| 69 |
| 70 def testCommentsBetweenIncludes(self): |
| 71 begin, end = add_header.FindIncludes( |
| 72 ['#include <utility>', '// TODO: Add goat support.', '#include "moo.h"' |
| 73 ]) |
| 74 self.assertEqual(begin, 0) |
| 75 self.assertEqual(end, 3) |
| 76 |
| 77 def testEmptyLinesNotIncluded(self): |
| 78 begin, end = add_header.FindIncludes(['', '#include <utility>', '', |
| 79 '#include "moo.h"', '']) |
| 80 self.assertEqual(begin, 1) |
| 81 self.assertEqual(end, 4) |
| 82 |
| 83 def testCommentsNotIncluded(self): |
| 84 begin, end = add_header.FindIncludes( |
| 85 ['// Cow module.', '#include <utility>', '// For cow speech synthesis.', |
| 86 '#include "moo.h"', '// TODO: Add Linux audio support.']) |
| 87 self.assertEqual(begin, 1) |
| 88 self.assertEqual(end, 4) |
| 89 |
| 90 def testNonIncludesLinesBeforeIncludesIgnored(self): |
| 91 begin, end = add_header.FindIncludes(['#ifndef COW_H_', '#define COW_H_', |
| 92 '#include "moo.h"']) |
| 93 self.assertEqual(begin, 2) |
| 94 self.assertEqual(end, 3) |
| 95 |
| 96 def testNonIncludesLinesAfterIncludesTerminates(self): |
| 97 begin, end = add_header.FindIncludes( |
| 98 ['#include "moo.h"', '#ifndef COW_MESSAGES_H_', '#define COW_MESSAGE_H_' |
| 99 ]) |
| 100 self.assertEqual(begin, 0) |
| 101 self.assertEqual(end, 1) |
| 102 |
| 103 |
| 104 class IncludeTest(unittest.TestCase): |
| 105 |
| 106 def testToSource(self): |
| 107 self.assertEqual( |
| 108 add_header.Include('<moo.h>', 'include', [], None).ToSource(), |
| 109 ['#include <moo.h>']) |
| 110 |
| 111 def testIncludeWithPreambleToSource(self): |
| 112 self.assertEqual( |
| 113 add_header.Include('"moo.h"', 'include', ['//preamble'], |
| 114 None).ToSource(), ['// preamble' |
| 115 '#include "moo.h"']) |
| 116 |
| 117 def testIncludeWithPreambleToSource(self): |
| 118 self.assertEqual( |
| 119 add_header.Include('"moo.h"', 'include', [], |
| 120 ' inline comment').ToSource(), |
| 121 ['#include "moo.h" // inline comment']) |
| 122 |
| 123 def testIncludeWithPreambleAndInlineCommentToSource(self): |
| 124 # Make sure whitespace is vaguely normalized too. |
| 125 self.assertEqual( |
| 126 add_header.Include('"moo.h"', 'include', |
| 127 ['// preamble with trailing space ',], |
| 128 ' inline comment with trailing space ').ToSource(), |
| 129 ['// preamble with trailing space', |
| 130 '#include "moo.h" // inline comment with trailing space']) |
| 131 |
| 132 def testImportToSource(self): |
| 133 self.assertEqual( |
| 134 add_header.Include('"moo.h"', 'import', [], None).ToSource(), |
| 135 ['#import "moo.h"']) |
| 136 |
| 137 |
| 138 class ParseIncludesTest(unittest.TestCase): |
| 139 |
| 140 def testInvalid(self): |
| 141 self.assertIsNone(add_header.ParseIncludes(['invalid'])) |
| 142 |
| 143 def testInclude(self): |
| 144 includes = add_header.ParseIncludes(['#include "moo.h"']) |
| 145 self.assertEqual(len(includes), 1) |
| 146 self.assertEqual(includes[0].decorated_name, '"moo.h"') |
| 147 self.assertEqual(includes[0].directive, 'include') |
| 148 self.assertEqual(includes[0].preamble, []) |
| 149 self.assertIsNone(includes[0].inline_comment) |
| 150 self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER) |
| 151 self.assertFalse(includes[0].is_primary_header) |
| 152 |
| 153 def testIncludeSurroundedByWhitespace(self): |
| 154 includes = add_header.ParseIncludes([' #include "moo.h" ']) |
| 155 self.assertEqual(len(includes), 1) |
| 156 self.assertEqual(includes[0].decorated_name, '"moo.h"') |
| 157 self.assertEqual(includes[0].directive, 'include') |
| 158 self.assertEqual(includes[0].preamble, []) |
| 159 self.assertIsNone(includes[0].inline_comment) |
| 160 self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER) |
| 161 self.assertFalse(includes[0].is_primary_header) |
| 162 |
| 163 def testImport(self): |
| 164 includes = add_header.ParseIncludes(['#import "moo.h"']) |
| 165 self.assertEqual(len(includes), 1) |
| 166 self.assertEqual(includes[0].decorated_name, '"moo.h"') |
| 167 self.assertEqual(includes[0].directive, 'import') |
| 168 self.assertEqual(includes[0].preamble, []) |
| 169 self.assertIsNone(includes[0].inline_comment) |
| 170 self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER) |
| 171 self.assertFalse(includes[0].is_primary_header) |
| 172 |
| 173 def testIncludeWithPreamble(self): |
| 174 includes = add_header.ParseIncludes(['// preamble comment ', |
| 175 '#include "moo.h"']) |
| 176 self.assertEqual(len(includes), 1) |
| 177 self.assertEqual(includes[0].decorated_name, '"moo.h"') |
| 178 self.assertEqual(includes[0].directive, 'include') |
| 179 self.assertEqual(includes[0].preamble, ['// preamble comment ']) |
| 180 self.assertIsNone(includes[0].inline_comment) |
| 181 self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER) |
| 182 self.assertFalse(includes[0].is_primary_header) |
| 183 |
| 184 def testIncludeWithInvalidPreamble(self): |
| 185 self.assertIsNone(add_header.ParseIncludes(['// orphan comment', '', |
| 186 '#include "moo.h"'])) |
| 187 |
| 188 def testIncludeWIthInlineComment(self): |
| 189 includes = add_header.ParseIncludes(['#include "moo.h"// For SFX ']) |
| 190 self.assertEqual(len(includes), 1) |
| 191 self.assertEqual(includes[0].decorated_name, '"moo.h"') |
| 192 self.assertEqual(includes[0].directive, 'include') |
| 193 self.assertEqual(includes[0].preamble, []) |
| 194 self.assertEqual(includes[0].inline_comment, ' For SFX ') |
| 195 self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER) |
| 196 self.assertFalse(includes[0].is_primary_header) |
| 197 |
| 198 def testIncludeWithInlineCommentAndPreamble(self): |
| 199 includes = add_header.ParseIncludes(['// preamble comment ', |
| 200 '#include "moo.h" // For SFX ']) |
| 201 self.assertEqual(len(includes), 1) |
| 202 self.assertEqual(includes[0].decorated_name, '"moo.h"') |
| 203 self.assertEqual(includes[0].directive, 'include') |
| 204 self.assertEqual(includes[0].preamble, ['// preamble comment ']) |
| 205 self.assertEqual(includes[0].inline_comment, ' For SFX ') |
| 206 self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_USER) |
| 207 self.assertFalse(includes[0].is_primary_header) |
| 208 |
| 209 def testMultipleIncludes(self): |
| 210 includes = add_header.ParseIncludes( |
| 211 ['#include <time.h>', '', '#include "moo.h" // For SFX ', |
| 212 '// TODO: Implement death ray.', '#import "goat.h"']) |
| 213 self.assertEqual(len(includes), 3) |
| 214 self.assertEqual(includes[0].decorated_name, '<time.h>') |
| 215 self.assertEqual(includes[0].directive, 'include') |
| 216 self.assertEqual(includes[0].preamble, []) |
| 217 self.assertIsNone(includes[0].inline_comment) |
| 218 self.assertEqual(includes[0].header_type, add_header._HEADER_TYPE_C_SYSTEM) |
| 219 self.assertFalse(includes[0].is_primary_header) |
| 220 self.assertEqual(includes[1].decorated_name, '"moo.h"') |
| 221 self.assertEqual(includes[1].directive, 'include') |
| 222 self.assertEqual(includes[1].preamble, []) |
| 223 self.assertEqual(includes[1].inline_comment, ' For SFX ') |
| 224 self.assertEqual(includes[1].header_type, add_header._HEADER_TYPE_USER) |
| 225 self.assertFalse(includes[1].is_primary_header) |
| 226 self.assertEqual(includes[2].decorated_name, '"goat.h"') |
| 227 self.assertEqual(includes[2].directive, 'import') |
| 228 self.assertEqual(includes[2].preamble, ['// TODO: Implement death ray.']) |
| 229 self.assertIsNone(includes[2].inline_comment) |
| 230 self.assertEqual(includes[2].header_type, add_header._HEADER_TYPE_USER) |
| 231 self.assertFalse(includes[2].is_primary_header) |
| 232 |
| 233 |
| 234 class MarkPrimaryIncludeTest(unittest.TestCase): |
| 235 |
| 236 def extractPrimaryName(self, includes): |
| 237 for include in includes: |
| 238 if include.is_primary_header: |
| 239 return include.decorated_name |
| 240 |
| 241 def testNoOpOnHeader(self): |
| 242 includes = [add_header.Include('"cow.h"', 'include', [], None)] |
| 243 add_header.MarkPrimaryInclude(includes, 'cow.h') |
| 244 self.assertIsNone(self.extractPrimaryName(includes)) |
| 245 |
| 246 def testSystemHeaderNotMatched(self): |
| 247 includes = [add_header.Include('<cow.h>', 'include', [], None)] |
| 248 add_header.MarkPrimaryInclude(includes, 'cow.cc') |
| 249 self.assertIsNone(self.extractPrimaryName(includes)) |
| 250 |
| 251 def testExactMatch(self): |
| 252 includes = [ |
| 253 add_header.Include('"cow.h"', 'include', [], None), |
| 254 add_header.Include('"cow_posix.h"', 'include', [], None), |
| 255 ] |
| 256 add_header.MarkPrimaryInclude(includes, 'cow.cc') |
| 257 self.assertEqual(self.extractPrimaryName(includes), '"cow.h"') |
| 258 |
| 259 def testFuzzyMatch(self): |
| 260 includes = [add_header.Include('"cow.h"', 'include', [], None)] |
| 261 add_header.MarkPrimaryInclude(includes, 'cow_linux_unittest.cc') |
| 262 self.assertEqual(self.extractPrimaryName(includes), '"cow.h"') |
| 263 |
| 264 def testFuzzymatchInReverse(self): |
| 265 includes = [add_header.Include('"cow.h"', 'include', [], None)] |
| 266 add_header.MarkPrimaryInclude(includes, 'cow_uitest_aura.cc') |
| 267 self.assertEqual(self.extractPrimaryName(includes), '"cow.h"') |
| 268 |
| 269 def testFuzzyMatchDoesntMatchDifferentSuffixes(self): |
| 270 includes = [add_header.Include('"cow_posix.h"', 'include', [], None)] |
| 271 add_header.MarkPrimaryInclude(includes, 'cow_windows.cc') |
| 272 self.assertIsNone(self.extractPrimaryName(includes)) |
| 273 |
| 274 def testMarksMostSpecific(self): |
| 275 includes = [ |
| 276 add_header.Include('"cow.h"', 'include', [], None), |
| 277 add_header.Include('"cow_posix.h"', 'include', [], None), |
| 278 ] |
| 279 add_header.MarkPrimaryInclude(includes, 'cow_posix.cc') |
| 280 self.assertEqual(self.extractPrimaryName(includes), '"cow_posix.h"') |
| 281 |
| 282 def testFullPathMatch(self): |
| 283 includes = [add_header.Include('"zfs/impl/cow.h"', 'include', [], None)] |
| 284 add_header.MarkPrimaryInclude(includes, 'zfs/impl/cow.cc') |
| 285 self.assertEqual(self.extractPrimaryName(includes), '"zfs/impl/cow.h"') |
| 286 |
| 287 def testTopmostDirectoryDoesNotMatch(self): |
| 288 includes = [add_header.Include('"animal/impl/cow.h"', 'include', [], None)] |
| 289 add_header.MarkPrimaryInclude(includes, 'zfs/impl/cow.cc') |
| 290 self.assertIsNone(self.extractPrimaryName(includes)) |
| 291 |
| 292 def testSubstantiallySimilarPaths(self): |
| 293 includes = [add_header.Include('"farm/public/animal/cow.h"', 'include', [], |
| 294 None)] |
| 295 add_header.MarkPrimaryInclude(includes, 'farm/animal/cow.cc') |
| 296 self.assertEqual( |
| 297 self.extractPrimaryName(includes), '"farm/public/animal/cow.h"') |
| 298 |
| 299 def testNoMatchingSubdirectories(self): |
| 300 includes = [add_header.Include('"base/zfs/cow.h"', 'include', [], None)] |
| 301 add_header.MarkPrimaryInclude(includes, 'base/animal/cow.cc') |
| 302 self.assertIsNone(self.extractPrimaryName(includes)) |
| 303 |
| 304 |
| 305 class SerializeIncludesTest(unittest.TestCase): |
| 306 |
| 307 def testSystemHeaders(self): |
| 308 source = add_header.SerializeIncludes([ |
| 309 add_header.Include('<stdlib.h>', 'include', [], None), |
| 310 add_header.Include('<map>', 'include', [], None), |
| 311 ]) |
| 312 self.assertEqual(source, ['#include <stdlib.h>', '', '#include <map>']) |
| 313 |
| 314 def testUserHeaders(self): |
| 315 source = add_header.SerializeIncludes([ |
| 316 add_header.Include('"goat.h"', 'include', [], None), |
| 317 add_header.Include('"moo.h"', 'include', [], None), |
| 318 ]) |
| 319 self.assertEqual(source, ['#include "goat.h"', '#include "moo.h"']) |
| 320 |
| 321 def testSystemAndUserHeaders(self): |
| 322 source = add_header.SerializeIncludes([ |
| 323 add_header.Include('<stdlib.h>', 'include', [], None), |
| 324 add_header.Include('<map>', 'include', [], None), |
| 325 add_header.Include('"moo.h"', 'include', [], None), |
| 326 ]) |
| 327 self.assertEqual(source, ['#include <stdlib.h>', '', '#include <map>', '', |
| 328 '#include "moo.h"']) |
| 329 |
| 330 def testPrimaryAndSystemHeaders(self): |
| 331 primary_header = add_header.Include('"cow.h"', 'include', [], None) |
| 332 primary_header.is_primary_header = True |
| 333 source = add_header.SerializeIncludes([ |
| 334 primary_header, |
| 335 add_header.Include('<stdlib.h>', 'include', [], None), |
| 336 add_header.Include('<map>', 'include', [], None), |
| 337 ]) |
| 338 self.assertEqual(source, [ |
| 339 '#include "cow.h"', '', '#include <stdlib.h>', '', '#include <map>' |
| 340 ]) |
| 341 |
| 342 def testPrimaryAndUserHeaders(self): |
| 343 primary_header = add_header.Include('"cow.h"', 'include', [], None) |
| 344 primary_header.is_primary_header = True |
| 345 source = add_header.SerializeIncludes([ |
| 346 primary_header, |
| 347 add_header.Include('"moo.h"', 'include', [], None), |
| 348 ]) |
| 349 self.assertEqual(source, ['#include "cow.h"', '', '#include "moo.h"']) |
| 350 |
| 351 def testPrimarySystemAndUserHeaders(self): |
| 352 primary_header = add_header.Include('"cow.h"', 'include', [], None) |
| 353 primary_header.is_primary_header = True |
| 354 source = add_header.SerializeIncludes([ |
| 355 primary_header, |
| 356 add_header.Include('<stdlib.h>', 'include', [], None), |
| 357 add_header.Include('<map>', 'include', [], None), |
| 358 add_header.Include('"moo.h"', 'include', [], None), |
| 359 ]) |
| 360 self.assertEqual(source, [ |
| 361 '#include "cow.h"', '', '#include <stdlib.h>', '', '#include <map>', '', |
| 362 '#include "moo.h"' |
| 363 ]) |
| 364 |
| 365 |
| 366 class InsertHeaderIntoSourceTest(unittest.TestCase): |
| 367 |
| 368 def testAddInclude(self): |
| 369 source = add_header.InsertHeaderIntoSource('cow.cc', '\n'.join( |
| 370 ['// Copyright info here.', '', '#include <utility>', |
| 371 '// For cow speech synthesis.', |
| 372 '#include "moo.h" // TODO: Add Linux audio support.', |
| 373 '#include <time.h>', '#include "cow.h"', 'namespace bovine {', '', |
| 374 '// TODO: Implement.', '} // namespace bovine']), '<memory>') |
| 375 self.assertEqual( |
| 376 source, |
| 377 '\n'.join(['// Copyright info here.', '', '#include "cow.h"', '', |
| 378 '#include <time.h>', '', '#include <memory>', |
| 379 '#include <utility>', '', '// For cow speech synthesis.', |
| 380 '#include "moo.h" // TODO: Add Linux audio support.', |
| 381 'namespace bovine {', '', '// TODO: Implement.', |
| 382 '} // namespace bovine', ''])) |
| 383 |
| 384 def testAlreadyIncluded(self): |
| 385 # To make sure the original source is returned unmodified, the input source |
| 386 # intentionally scrambles the #include order. |
| 387 source = '\n'.join([ |
| 388 '// Copyright info here.', '', '#include "moo.h"', '#include <utility>', |
| 389 '#include <memory>', '#include "cow.h"', 'namespace bovine {', '', |
| 390 '// TODO: Implement.', '} // namespace bovine' |
| 391 ]) |
| 392 self.assertEqual( |
| 393 add_header.InsertHeaderIntoSource('cow.cc', source, '<memory>'), source) |
| 394 |
| 395 def testConditionalIncludesLeftALone(self): |
| 396 # TODO(dcheng): Conditional header handling could probably be more clever. |
| 397 # But for the moment, this is probably Good Enough. |
| 398 source = add_header.InsertHeaderIntoSource( |
| 399 'cow.cc', |
| 400 '\n'.join(['// Copyright info here.', '', '#include "cow.h"', |
| 401 '#include <utility>', '// For cow speech synthesis.', |
| 402 '#include "moo.h" // TODO: Add Linux audio support.', |
| 403 '#if defined(USE_AURA)' |
| 404 '#include <memory>', '#endif // defined(USE_AURA)']), |
| 405 '<memory>') |
| 406 self.assertEqual( |
| 407 source, |
| 408 '\n'.join(['// Copyright info here.', '', '#include "cow.h"', '', |
| 409 '#include <memory>', '#include <utility>', '', |
| 410 '// For cow speech synthesis.', |
| 411 '#include "moo.h" // TODO: Add Linux audio support.', |
| 412 '#if defined(USE_AURA)' |
| 413 '#include <memory>', '#endif // defined(USE_AURA)', ''])) |
| 414 |
| 415 |
| 416 if __name__ == '__main__': |
| 417 unittest.main() |
OLD | NEW |