1#!/usr/bin/env python3 2# Copyright 2014 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Tests for enum_preprocess.py. 7 8This test suite contains various tests for the C++ -> Java enum generator. 9""" 10 11import collections 12from datetime import date 13import unittest 14 15import java_cpp_enum 16from java_cpp_enum import EnumDefinition, GenerateOutput 17from java_cpp_enum import HeaderParser 18from util import java_cpp_utils 19 20 21class TestPreprocess(unittest.TestCase): 22 def testOutput(self): 23 definition = EnumDefinition(original_enum_name='ClassName', 24 enum_package='some.package', 25 entries=[('E1', 1), ('E2', '2 << 2')], 26 comments=[('E2', 'This is a comment.'), 27 ('E1', 'This is a multiple line ' 28 'comment that is really long. ' 29 'This is a multiple line ' 30 'comment that is really ' 31 'really long.')]) 32 output = GenerateOutput('path/to/file', definition) 33 expected = """ 34// Copyright %d The Chromium Authors 35// Use of this source code is governed by a BSD-style license that can be 36// found in the LICENSE file. 37 38// This file is autogenerated by 39// %s 40// From 41// path/to/file 42 43package some.package; 44 45import androidx.annotation.IntDef; 46 47import java.lang.annotation.ElementType; 48import java.lang.annotation.Retention; 49import java.lang.annotation.RetentionPolicy; 50import java.lang.annotation.Target; 51 52@IntDef({ 53 ClassName.E1, ClassName.E2 54}) 55@Target(ElementType.TYPE_USE) 56@Retention(RetentionPolicy.SOURCE) 57public @interface ClassName { 58 /** 59 * %s 60 * really really long. 61 */ 62 int E1 = 1; 63 /** 64 * This is a comment. 65 */ 66 int E2 = 2 << 2; 67} 68""" 69 long_comment = ('This is a multiple line comment that is really long. ' 70 'This is a multiple line comment that is') 71 self.assertEqual( 72 expected % (date.today().year, java_cpp_utils.GetScriptName(), 73 long_comment), output) 74 75 def testParseSimpleEnum(self): 76 test_data = """ 77 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 78 enum EnumName { 79 VALUE_ZERO, 80 VALUE_ONE, 81 }; 82 """.split('\n') 83 definitions = HeaderParser(test_data).ParseDefinitions() 84 self.assertEqual(1, len(definitions)) 85 definition = definitions[0] 86 self.assertEqual('EnumName', definition.class_name) 87 self.assertEqual('test.namespace', definition.enum_package) 88 self.assertEqual(collections.OrderedDict([('VALUE_ZERO', 0), 89 ('VALUE_ONE', 1)]), 90 definition.entries) 91 92 def testOutputFlag(self): 93 for [attr, want_flag] in [ 94 ['0', False], 95 ['1', True], 96 ['false', False], 97 ['true', True], 98 ]: 99 test_data = (""" 100 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 101 // GENERATED_JAVA_IS_FLAG: %s 102 enum EnumName { 103 ZERO = 1 << 0, 104 ONE = 1 << 1, 105 }; 106 """ % attr).split('\n') 107 definitions = HeaderParser(test_data).ParseDefinitions() 108 output = GenerateOutput('/path/to/file', definitions[0]) 109 int_def = output[output.index("@IntDef"):] 110 expected = """@IntDef(%s{ 111 EnumName.ZERO, EnumName.ONE 112}) 113@Target(ElementType.TYPE_USE) 114@Retention(RetentionPolicy.SOURCE) 115public @interface EnumName { 116 int ZERO = 1 << 0; 117 int ONE = 1 << 1; 118} 119""" % ('flag = true, value = ' if want_flag else '') 120 self.assertEqual(int_def, expected) 121 122 def testParseBitShifts(self): 123 test_data = """ 124 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 125 enum EnumName { 126 VALUE_ZERO = 1 << 0, 127 VALUE_ONE = 1 << 1, 128 }; 129 130 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 131 enum EnumName { 132 ENUM_NAME_ZERO = 1 << 0, 133 ENUM_NAME_ONE = 1 << 1, 134 ENUM_NAME_TWO = ENUM_NAME_ZERO | ENUM_NAME_ONE, 135 }; 136 """.split('\n') 137 definitions = HeaderParser(test_data).ParseDefinitions() 138 self.assertEqual(2, len(definitions)) 139 definition = definitions[0] 140 self.assertEqual('EnumName', definition.class_name) 141 self.assertEqual('test.namespace', definition.enum_package) 142 self.assertEqual(collections.OrderedDict([('VALUE_ZERO', '1 << 0'), 143 ('VALUE_ONE', '1 << 1')]), 144 definition.entries) 145 146 definition = definitions[1] 147 expected_entries = collections.OrderedDict([ 148 ('ZERO', '1 << 0'), 149 ('ONE', '1 << 1'), 150 ('TWO', 'ZERO | ONE')]) 151 self.assertEqual(expected_entries, definition.entries) 152 153 def testParseMultilineEnumEntry(self): 154 test_data = """ 155 // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace 156 enum Foo { 157 VALUE_ZERO = 1 << 0, 158 VALUE_ONE = 159 SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | ControlKey, 160 VALUE_TWO = 1 << 18, 161 }; 162 """.split('\n') 163 expected_entries = collections.OrderedDict([ 164 ('VALUE_ZERO', '1 << 0'), 165 ('VALUE_ONE', 'SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | ' 166 'ControlKey'), 167 ('VALUE_TWO', '1 << 18')]) 168 definitions = HeaderParser(test_data).ParseDefinitions() 169 self.assertEqual(1, len(definitions)) 170 definition = definitions[0] 171 self.assertEqual('Foo', definition.class_name) 172 self.assertEqual('bar.namespace', definition.enum_package) 173 self.assertEqual(expected_entries, definition.entries) 174 175 def testParseEnumEntryWithTrailingMultilineEntry(self): 176 test_data = """ 177 // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace 178 enum Foo { 179 VALUE_ZERO = 1, 180 VALUE_ONE = 181 SymbolKey | FnKey | AltGrKey | MetaKey | 182 AltKey | ControlKey | ShiftKey, 183 }; 184 """.split('\n') 185 expected_entries = collections.OrderedDict([ 186 ('VALUE_ZERO', '1'), 187 ('VALUE_ONE', 'SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | ' 188 'ControlKey | ShiftKey')]) 189 definitions = HeaderParser(test_data).ParseDefinitions() 190 self.assertEqual(1, len(definitions)) 191 definition = definitions[0] 192 self.assertEqual('Foo', definition.class_name) 193 self.assertEqual('bar.namespace', definition.enum_package) 194 self.assertEqual(expected_entries, definition.entries) 195 196 def testParseNoCommaAfterLastEntry(self): 197 test_data = """ 198 // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace 199 enum Foo { 200 VALUE_ZERO = 1, 201 202 // This is a multiline 203 // 204 // comment with an empty line. 205 VALUE_ONE = 2 206 }; 207 """.split('\n') 208 expected_entries = collections.OrderedDict([ 209 ('VALUE_ZERO', '1'), 210 ('VALUE_ONE', '2')]) 211 expected_comments = collections.OrderedDict([ 212 ('VALUE_ONE', 'This is a multiline comment with an empty line.')]) 213 definitions = HeaderParser(test_data).ParseDefinitions() 214 self.assertEqual(1, len(definitions)) 215 definition = definitions[0] 216 self.assertEqual('Foo', definition.class_name) 217 self.assertEqual('bar.namespace', definition.enum_package) 218 self.assertEqual(expected_entries, definition.entries) 219 self.assertEqual(expected_comments, definition.comments) 220 221 def testParseClassNameOverride(self): 222 test_data = """ 223 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 224 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName 225 enum EnumName { 226 FOO 227 }; 228 229 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 230 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OtherOverride 231 enum PrefixTest { 232 PREFIX_TEST_A, 233 PREFIX_TEST_B, 234 }; 235 """.split('\n') 236 definitions = HeaderParser(test_data).ParseDefinitions() 237 self.assertEqual(2, len(definitions)) 238 definition = definitions[0] 239 self.assertEqual('OverrideName', definition.class_name) 240 241 definition = definitions[1] 242 self.assertEqual('OtherOverride', definition.class_name) 243 self.assertEqual(collections.OrderedDict([('A', 0), 244 ('B', 1)]), 245 definition.entries) 246 247 def testParsePreservesCommentsWhenPrefixStripping(self): 248 test_data = """ 249 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 250 enum EnumOne { 251 ENUM_ONE_A = 1, 252 // Comment there 253 ENUM_ONE_B = A, 254 }; 255 256 enum EnumIgnore { 257 C, D, E 258 }; 259 260 // GENERATED_JAVA_ENUM_PACKAGE: other.package 261 // GENERATED_JAVA_PREFIX_TO_STRIP: P_ 262 enum EnumTwo { 263 P_A, 264 // This comment spans 265 // two lines. 266 P_B 267 }; 268 """.split('\n') 269 definitions = HeaderParser(test_data).ParseDefinitions() 270 self.assertEqual(2, len(definitions)) 271 definition = definitions[0] 272 self.assertEqual('EnumOne', definition.class_name) 273 self.assertEqual('test.namespace', definition.enum_package) 274 self.assertEqual(collections.OrderedDict([('A', '1'), 275 ('B', 'A')]), 276 definition.entries) 277 self.assertEqual(collections.OrderedDict([('B', 'Comment there')]), 278 definition.comments) 279 definition = definitions[1] 280 self.assertEqual('EnumTwo', definition.class_name) 281 self.assertEqual('other.package', definition.enum_package) 282 self.assertEqual(collections.OrderedDict( 283 [('B', 'This comment spans two lines.')]), definition.comments) 284 self.assertEqual(collections.OrderedDict([('A', 0), 285 ('B', 1)]), 286 definition.entries) 287 288 def testParseTwoEnums(self): 289 test_data = """ 290 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 291 enum AnEnum { 292 ENUM_ONE_A = 1, 293 ENUM_ONE_B = A, 294 }; 295 296 enum EnumIgnore { 297 C, D, E 298 }; 299 300 // GENERATED_JAVA_ENUM_PACKAGE: other.package 301 enum EnumTwo { 302 P_A, 303 P_B 304 }; 305 """.split('\n') 306 definitions = HeaderParser(test_data).ParseDefinitions() 307 self.assertEqual(2, len(definitions)) 308 definition = definitions[0] 309 self.assertEqual('AnEnum', definition.class_name) 310 self.assertEqual('test.namespace', definition.enum_package) 311 self.assertEqual(collections.OrderedDict([('ENUM_ONE_A', '1'), 312 ('ENUM_ONE_B', 'A')]), 313 definition.entries) 314 definition = definitions[1] 315 self.assertEqual('EnumTwo', definition.class_name) 316 self.assertEqual('other.package', definition.enum_package) 317 self.assertEqual(collections.OrderedDict([('P_A', 0), 318 ('P_B', 1)]), 319 definition.entries) 320 321 def testParseSingleLineEnum(self): 322 test_data = """ 323 // GENERATED_JAVA_ENUM_PACKAGE: other.package 324 // GENERATED_JAVA_PREFIX_TO_STRIP: P_ 325 enum EnumTwo { P_A, P_B }; 326 """.split('\n') 327 definitions = HeaderParser(test_data).ParseDefinitions() 328 definition = definitions[0] 329 self.assertEqual('EnumTwo', definition.class_name) 330 self.assertEqual('other.package', definition.enum_package) 331 self.assertEqual(collections.OrderedDict([('A', 0), 332 ('B', 1)]), 333 definition.entries) 334 335 def testParseWithStrippingAndRelativeReferences(self): 336 test_data = """ 337 // GENERATED_JAVA_ENUM_PACKAGE: other.package 338 // GENERATED_JAVA_PREFIX_TO_STRIP: P_ 339 enum EnumTwo { 340 P_A = 1, 341 // P_A is old-don't use P_A. 342 P_B = P_A, 343 }; 344 """.split('\n') 345 definitions = HeaderParser(test_data).ParseDefinitions() 346 definition = definitions[0] 347 self.assertEqual('EnumTwo', definition.class_name) 348 self.assertEqual('other.package', definition.enum_package) 349 self.assertEqual(collections.OrderedDict([('A', '1'), 350 ('B', 'A')]), 351 definition.entries) 352 self.assertEqual(collections.OrderedDict([('B', 'A is old-don\'t use A.')]), 353 definition.comments) 354 355 def testParseSingleLineAndRegularEnum(self): 356 test_data = """ 357 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 358 enum EnumOne { 359 ENUM_ONE_A = 1, 360 // Comment there 361 ENUM_ONE_B = A, 362 }; 363 364 // GENERATED_JAVA_ENUM_PACKAGE: other.package 365 enum EnumTwo { P_A, P_B }; 366 367 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 368 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName 369 enum EnumName { 370 ENUM_NAME_FOO 371 }; 372 """.split('\n') 373 definitions = HeaderParser(test_data).ParseDefinitions() 374 definition = definitions[0] 375 self.assertEqual( 376 collections.OrderedDict([('A', '1'), ('B', 'A')]), definition.entries) 377 self.assertEqual(collections.OrderedDict([('B', 'Comment there')]), 378 definition.comments) 379 380 self.assertEqual(3, len(definitions)) 381 definition = definitions[1] 382 self.assertEqual( 383 collections.OrderedDict([('P_A', 0), ('P_B', 1)]), definition.entries) 384 385 definition = definitions[2] 386 self.assertEqual(collections.OrderedDict([('FOO', 0)]), definition.entries) 387 388 def testParseWithCamelCaseNames(self): 389 test_data = """ 390 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 391 enum EnumTest { 392 EnumTestA = 1, 393 // comment for EnumTestB. 394 EnumTestB = 2, 395 }; 396 397 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 398 // GENERATED_JAVA_PREFIX_TO_STRIP: Test 399 enum AnEnum { 400 TestHTTPOption, 401 TestHTTPSOption, 402 }; 403 404 """.split('\n') 405 definitions = HeaderParser(test_data).ParseDefinitions() 406 definition = definitions[0] 407 self.assertEqual( 408 collections.OrderedDict([('A', '1'), ('B', '2')]), 409 definition.entries) 410 self.assertEqual( 411 collections.OrderedDict([('B', 'comment for B.')]), 412 definition.comments) 413 414 definition = definitions[1] 415 self.assertEqual( 416 collections.OrderedDict([('HTTP_OPTION', 0), ('HTTPS_OPTION', 1)]), 417 definition.entries) 418 419 def testParseWithKCamelCaseNames(self): 420 test_data = """ 421 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 422 enum EnumOne { 423 kEnumOne = 1, 424 // comment for kEnumTwo. 425 kEnumTwo = 2, 426 }; 427 428 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 429 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName 430 enum EnumName { 431 kEnumNameFoo, 432 kEnumNameBar 433 }; 434 435 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 436 enum EnumName { 437 kEnumNameFoo, 438 kEnumBar, 439 }; 440 441 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 442 enum Keys { 443 kSymbolKey = 1 << 0, 444 kAltKey = 1 << 1, 445 kUpKey = 1 << 2, 446 kKeyModifiers = kSymbolKey | kAltKey | kUpKey | kKeyModifiers, 447 }; 448 449 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 450 enum Mixed { 451 kTestVal, 452 kCodecMPEG2 453 }; 454 """.split('\n') 455 definitions = HeaderParser(test_data).ParseDefinitions() 456 definition = definitions[0] 457 self.assertEqual( 458 collections.OrderedDict([('ENUM_ONE', '1'), ('ENUM_TWO', '2')]), 459 definition.entries) 460 self.assertEqual( 461 collections.OrderedDict([('ENUM_TWO', 'comment for ENUM_TWO.')]), 462 definition.comments) 463 464 definition = definitions[1] 465 self.assertEqual( 466 collections.OrderedDict([('FOO', 0), ('BAR', 1)]), 467 definition.entries) 468 469 definition = definitions[2] 470 self.assertEqual( 471 collections.OrderedDict([('ENUM_NAME_FOO', 0), ('ENUM_BAR', 1)]), 472 definition.entries) 473 474 definition = definitions[3] 475 expected_entries = collections.OrderedDict([ 476 ('SYMBOL_KEY', '1 << 0'), 477 ('ALT_KEY', '1 << 1'), 478 ('UP_KEY', '1 << 2'), 479 ('KEY_MODIFIERS', 'SYMBOL_KEY | ALT_KEY | UP_KEY | KEY_MODIFIERS')]) 480 self.assertEqual(expected_entries, definition.entries) 481 482 definition = definitions[4] 483 self.assertEqual( 484 collections.OrderedDict([('TEST_VAL', 0), ('CODEC_MPEG2', 1)]), 485 definition.entries) 486 487 def testParseThrowsOnUnknownDirective(self): 488 test_data = """ 489 // GENERATED_JAVA_UNKNOWN: Value 490 enum EnumName { 491 VALUE_ONE, 492 }; 493 """.split('\n') 494 with self.assertRaises(Exception): 495 HeaderParser(test_data).ParseDefinitions() 496 497 def testParseReturnsEmptyListWithoutDirectives(self): 498 test_data = """ 499 enum EnumName { 500 VALUE_ONE, 501 }; 502 """.split('\n') 503 self.assertEqual([], HeaderParser(test_data).ParseDefinitions()) 504 505 def testParseEnumClass(self): 506 test_data = """ 507 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 508 enum class Foo { 509 FOO_A, 510 }; 511 """.split('\n') 512 definitions = HeaderParser(test_data).ParseDefinitions() 513 self.assertEqual(1, len(definitions)) 514 definition = definitions[0] 515 self.assertEqual('Foo', definition.class_name) 516 self.assertEqual('test.namespace', definition.enum_package) 517 self.assertEqual(collections.OrderedDict([('A', 0)]), 518 definition.entries) 519 520 def testParseEnumClassOneValueSubstringOfAnother(self): 521 test_data = """ 522 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 523 enum class SafeBrowsingStatus { 524 kChecking = 0, 525 kEnabled = 1, 526 kDisabled = 2, 527 kDisabledByAdmin = 3, 528 kDisabledByExtension = 4, 529 kEnabledStandard = 5, 530 kEnabledEnhanced = 6, 531 // New enum values must go above here. 532 kMaxValue = kEnabledEnhanced, 533 }; 534 """.split('\n') 535 definitions = HeaderParser(test_data).ParseDefinitions() 536 self.assertEqual(1, len(definitions)) 537 definition = definitions[0] 538 self.assertEqual('SafeBrowsingStatus', definition.class_name) 539 self.assertEqual('test.namespace', definition.enum_package) 540 self.assertEqual( 541 collections.OrderedDict([ 542 ('CHECKING', '0'), 543 ('ENABLED', '1'), 544 ('DISABLED', '2'), 545 ('DISABLED_BY_ADMIN', '3'), 546 ('DISABLED_BY_EXTENSION', '4'), 547 ('ENABLED_STANDARD', '5'), 548 ('ENABLED_ENHANCED', '6'), 549 ('MAX_VALUE', 'ENABLED_ENHANCED'), 550 ]), definition.entries) 551 self.assertEqual( 552 collections.OrderedDict([ 553 ('MAX_VALUE', 'New enum values must go above here.') 554 ]), definition.comments) 555 556 def testParseEnumWithConditionallyDefinedValues(self): 557 test_data = """ 558// GENERATED_JAVA_ENUM_PACKAGE: test.namespace 559// GENERATED_JAVA_PREFIX_TO_STRIP: TERMINATION_STATUS_ 560enum TerminationStatus { 561 // Zero exit status. 562 TERMINATION_STATUS_NORMAL_TERMINATION = 0, 563 // Child hasn't exited yet. 564 TERMINATION_STATUS_STILL_RUNNING = 4, 565#if BUILDFLAG(IS_CHROMEOS) 566 // OOM-killer killed the process on ChromeOS. 567 TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM = 5, 568#endif 569#if BUILDFLAG(IS_ANDROID) 570 // On Android processes are spawned from the system Zygote and we do not get 571 // the termination status. 572 TERMINATION_STATUS_OOM_PROTECTED = 6, 573#endif 574 // Out of memory. 575 TERMINATION_STATUS_OOM = 8, 576#if BUILDFLAG(IS_WIN) 577 // On Windows, the OS terminated process due to code integrity failure. 578 TERMINATION_STATUS_INTEGRITY_FAILURE = 9, 579#endif 580#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) 581 TERMINATION_STATUS_TEN = 10, 582#if BUILDFLAG(IS_POSIX) 583 TERMINATION_STATUS_ELEVEN = 11, 584#endif 585#endif 586#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) 587 TERMINATION_STATUS_TWELVE = 12, 588#endif 589}; 590 """.split('\n') 591 definitions = HeaderParser(test_data).ParseDefinitions() 592 self.assertEqual(1, len(definitions)) 593 definition = definitions[0] 594 self.assertEqual('TerminationStatus', definition.class_name) 595 self.assertEqual('test.namespace', definition.enum_package) 596 self.assertEqual( 597 collections.OrderedDict([ 598 ('NORMAL_TERMINATION', '0'), 599 ('STILL_RUNNING', '4'), 600 # PROCESS_WAS_KILLED_BY_OOM value should not appear here. 601 # 602 # OOM_PROTECTED should appear because the script supports the case 603 # where '#if BUILDFLAG(IS_ANDROID)' is used. 604 ('OOM_PROTECTED', '6'), 605 ('OOM', '8'), 606 # INTEGRITY_FAILURE value should not appear here. 607 # TEN and ELEVEN should not appear here. 608 ('TWELVE', '12'), 609 ]), 610 definition.entries) 611 self.assertEqual( 612 collections.OrderedDict([ 613 ('NORMAL_TERMINATION', 'Zero exit status.'), 614 ('STILL_RUNNING', 'Child hasn\'t exited yet.'), 615 ('OOM_PROTECTED', 616 'On Android processes are spawned from the system Zygote and we ' + 617 'do not get the termination status.'), 618 ('OOM', 'Out of memory.'), 619 ]), definition.comments) 620 621 def testParseEnumStruct(self): 622 test_data = """ 623 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 624 enum struct Foo { 625 FOO_A, 626 }; 627 """.split('\n') 628 definitions = HeaderParser(test_data).ParseDefinitions() 629 self.assertEqual(1, len(definitions)) 630 definition = definitions[0] 631 self.assertEqual('Foo', definition.class_name) 632 self.assertEqual('test.namespace', definition.enum_package) 633 self.assertEqual(collections.OrderedDict([('A', 0)]), 634 definition.entries) 635 636 def testParseFixedTypeEnum(self): 637 test_data = """ 638 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 639 enum Foo : int { 640 FOO_A, 641 }; 642 """.split('\n') 643 definitions = HeaderParser(test_data).ParseDefinitions() 644 self.assertEqual(1, len(definitions)) 645 definition = definitions[0] 646 self.assertEqual('Foo', definition.class_name) 647 self.assertEqual('test.namespace', definition.enum_package) 648 self.assertEqual('int', definition.fixed_type) 649 self.assertEqual(collections.OrderedDict([('A', 0)]), 650 definition.entries) 651 652 def testParseFixedTypeEnum(self): 653 test_data = """ 654 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.signin.metrics 655 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: SigninAccessPoint 656 enum class AccessPoint : int { 657 ACCESS_POINT_DRIVE_FILE_PICKER_IOS = 0, 658 ACCESS_POINT_COLLABORATION_TAB_GROUP = 1, 659 ACCESS_POINT_MAX, 660 }; 661 """.split('\n') 662 definitions = HeaderParser(test_data).ParseDefinitions() 663 self.assertEqual(1, len(definitions)) 664 definition = definitions[0] 665 self.assertEqual('SigninAccessPoint', definition.class_name) 666 self.assertEqual('org.chromium.components.signin.metrics', 667 definition.enum_package) 668 self.assertEqual('int', definition.fixed_type) 669 self.assertEqual( 670 collections.OrderedDict([('DRIVE_FILE_PICKER_IOS', 0), 671 ('COLLABORATION_TAB_GROUP', 1), ('MAX', 2)]), 672 definition.entries) 673 674 def testParseFixedTypeEnumWithMaxValue(self): 675 test_data = """ 676 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.signin.metrics 677 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: SigninAccessPoint 678 enum class AccessPoint : int { 679 ACCESS_POINT_DRIVE_FILE_PICKER_IOS = 0, 680 ACCESS_POINT_COLLABORATION_TAB_GROUP = 1, 681 kMaxValue = ACCESS_POINT_COLLABORATION_TAB_GROUP, 682 }; 683 """.split('\n') 684 definitions = HeaderParser(test_data).ParseDefinitions() 685 self.assertEqual(1, len(definitions)) 686 definition = definitions[0] 687 self.assertEqual('SigninAccessPoint', definition.class_name) 688 self.assertEqual('org.chromium.components.signin.metrics', 689 definition.enum_package) 690 self.assertEqual('int', definition.fixed_type) 691 self.assertEqual( 692 collections.OrderedDict([('DRIVE_FILE_PICKER_IOS', '0'), 693 ('COLLABORATION_TAB_GROUP', '1'), 694 ('MAX_VALUE', 'COLLABORATION_TAB_GROUP')]), 695 definition.entries) 696 697 def testParseFixedTypeEnumClass(self): 698 test_data = """ 699 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 700 enum class Foo: unsigned short { 701 FOO_A, 702 }; 703 """.split('\n') 704 definitions = HeaderParser(test_data).ParseDefinitions() 705 self.assertEqual(1, len(definitions)) 706 definition = definitions[0] 707 self.assertEqual('Foo', definition.class_name) 708 self.assertEqual('test.namespace', definition.enum_package) 709 self.assertEqual('unsigned short', definition.fixed_type) 710 self.assertEqual(collections.OrderedDict([('A', 0)]), 711 definition.entries) 712 713 def testParseUnknownFixedTypeRaises(self): 714 test_data = """ 715 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace 716 enum class Foo: foo_type { 717 FOO_A, 718 }; 719 """.split('\n') 720 with self.assertRaises(Exception): 721 HeaderParser(test_data).ParseDefinitions() 722 723 def testParseSimpleMultiLineDirective(self): 724 test_data = """ 725 // GENERATED_JAVA_ENUM_PACKAGE: ( 726 // test.namespace) 727 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Bar 728 enum Foo { 729 FOO_A, 730 }; 731 """.split('\n') 732 definitions = HeaderParser(test_data).ParseDefinitions() 733 self.assertEqual('test.namespace', definitions[0].enum_package) 734 self.assertEqual('Bar', definitions[0].class_name) 735 736 def testParseMultiLineDirective(self): 737 test_data = """ 738 // GENERATED_JAVA_ENUM_PACKAGE: (te 739 // st.name 740 // space) 741 enum Foo { 742 FOO_A, 743 }; 744 """.split('\n') 745 definitions = HeaderParser(test_data).ParseDefinitions() 746 self.assertEqual('test.namespace', definitions[0].enum_package) 747 748 def testParseMultiLineDirectiveWithOtherDirective(self): 749 test_data = """ 750 // GENERATED_JAVA_ENUM_PACKAGE: ( 751 // test.namespace) 752 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: ( 753 // Ba 754 // r 755 // ) 756 enum Foo { 757 FOO_A, 758 }; 759 """.split('\n') 760 definitions = HeaderParser(test_data).ParseDefinitions() 761 self.assertEqual('test.namespace', definitions[0].enum_package) 762 self.assertEqual('Bar', definitions[0].class_name) 763 764 def testParseMalformedMultiLineDirectiveWithOtherDirective(self): 765 test_data = """ 766 // GENERATED_JAVA_ENUM_PACKAGE: ( 767 // test.name 768 // space 769 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Bar 770 enum Foo { 771 FOO_A, 772 }; 773 """.split('\n') 774 with self.assertRaises(Exception): 775 HeaderParser(test_data).ParseDefinitions() 776 777 def testParseMalformedMultiLineDirective(self): 778 test_data = """ 779 // GENERATED_JAVA_ENUM_PACKAGE: ( 780 // test.name 781 // space 782 enum Foo { 783 FOO_A, 784 }; 785 """.split('\n') 786 with self.assertRaises(Exception): 787 HeaderParser(test_data).ParseDefinitions() 788 789 def testParseMalformedMultiLineDirectiveShort(self): 790 test_data = """ 791 // GENERATED_JAVA_ENUM_PACKAGE: ( 792 enum Foo { 793 FOO_A, 794 }; 795 """.split('\n') 796 with self.assertRaises(Exception): 797 HeaderParser(test_data).ParseDefinitions() 798 799 def testParseMalformedMultiLineDirectiveMissingBrackets(self): 800 test_data = """ 801 // GENERATED_JAVA_ENUM_PACKAGE: 802 // test.namespace 803 enum Foo { 804 FOO_A, 805 }; 806 """.split('\n') 807 with self.assertRaises(Exception): 808 HeaderParser(test_data).ParseDefinitions() 809 810 def testEnumValueAssignmentNoneDefined(self): 811 definition = EnumDefinition(original_enum_name='c', enum_package='p') 812 definition.AppendEntry('A', None) 813 definition.AppendEntry('B', None) 814 definition.AppendEntry('C', None) 815 definition.Finalize() 816 self.assertEqual(collections.OrderedDict([('A', 0), 817 ('B', 1), 818 ('C', 2)]), 819 definition.entries) 820 821 def testEnumValueAssignmentAllDefined(self): 822 definition = EnumDefinition(original_enum_name='c', enum_package='p') 823 definition.AppendEntry('A', '1') 824 definition.AppendEntry('B', '2') 825 definition.AppendEntry('C', '3') 826 definition.Finalize() 827 self.assertEqual(collections.OrderedDict([('A', '1'), 828 ('B', '2'), 829 ('C', '3')]), 830 definition.entries) 831 832 def testEnumValueAssignmentReferences(self): 833 definition = EnumDefinition(original_enum_name='c', enum_package='p') 834 definition.AppendEntry('A', None) 835 definition.AppendEntry('B', 'A') 836 definition.AppendEntry('C', None) 837 definition.AppendEntry('D', 'C') 838 definition.Finalize() 839 self.assertEqual(collections.OrderedDict([('A', 0), 840 ('B', 0), 841 ('C', 1), 842 ('D', 1)]), 843 definition.entries) 844 845 def testEnumValueAssignmentSet(self): 846 definition = EnumDefinition(original_enum_name='c', enum_package='p') 847 definition.AppendEntry('A', None) 848 definition.AppendEntry('B', '2') 849 definition.AppendEntry('C', None) 850 definition.Finalize() 851 self.assertEqual(collections.OrderedDict([('A', 0), 852 ('B', 2), 853 ('C', 3)]), 854 definition.entries) 855 856 def testEnumValueAssignmentSetReferences(self): 857 definition = EnumDefinition(original_enum_name='c', enum_package='p') 858 definition.AppendEntry('A', None) 859 definition.AppendEntry('B', 'A') 860 definition.AppendEntry('C', 'B') 861 definition.AppendEntry('D', None) 862 definition.Finalize() 863 self.assertEqual(collections.OrderedDict([('A', 0), 864 ('B', 0), 865 ('C', 0), 866 ('D', 1)]), 867 definition.entries) 868 869 def testEnumValueAssignmentRaises(self): 870 definition = EnumDefinition(original_enum_name='c', enum_package='p') 871 definition.AppendEntry('A', None) 872 definition.AppendEntry('B', 'foo') 873 definition.AppendEntry('C', None) 874 with self.assertRaises(Exception): 875 definition.Finalize() 876 877 def testExplicitPrefixStripping(self): 878 definition = EnumDefinition(original_enum_name='c', enum_package='p') 879 definition.AppendEntry('P_A', None) 880 definition.AppendEntry('B', None) 881 definition.AppendEntry('P_C', None) 882 definition.AppendEntry('P_LAST', 'P_C') 883 definition.prefix_to_strip = 'P_' 884 definition.Finalize() 885 self.assertEqual(collections.OrderedDict([('A', 0), 886 ('B', 1), 887 ('C', 2), 888 ('LAST', 2)]), 889 definition.entries) 890 891 def testImplicitPrefixStripping(self): 892 definition = EnumDefinition(original_enum_name='ClassName', 893 enum_package='p') 894 definition.AppendEntry('CLASS_NAME_A', None) 895 definition.AppendEntry('CLASS_NAME_B', None) 896 definition.AppendEntry('CLASS_NAME_C', None) 897 definition.AppendEntry('CLASS_NAME_LAST', 'CLASS_NAME_C') 898 definition.Finalize() 899 self.assertEqual(collections.OrderedDict([('A', 0), 900 ('B', 1), 901 ('C', 2), 902 ('LAST', 2)]), 903 definition.entries) 904 905 def testImplicitPrefixStrippingRequiresAllConstantsToBePrefixed(self): 906 definition = EnumDefinition(original_enum_name='Name', 907 enum_package='p') 908 definition.AppendEntry('A', None) 909 definition.AppendEntry('B', None) 910 definition.AppendEntry('NAME_LAST', None) 911 definition.Finalize() 912 self.assertEqual(['A', 'B', 'NAME_LAST'], list(definition.entries.keys())) 913 914 def testGenerateThrowsOnEmptyInput(self): 915 with self.assertRaises(Exception): 916 original_do_parse = java_cpp_enum.DoParseHeaderFile 917 try: 918 java_cpp_enum.DoParseHeaderFile = lambda _: [] 919 for _ in java_cpp_enum.DoGenerate(['file']): 920 pass 921 finally: 922 java_cpp_enum.DoParseHeaderFile = original_do_parse 923 924 925if __name__ == '__main__': 926 unittest.main() 927