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