1#!/usr/bin/env python
2# Copyright 2014 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"""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. All rights reserved.
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 testParseBitShifts(self):
90    test_data = """
91      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
92      enum EnumName {
93        VALUE_ZERO = 1 << 0,
94        VALUE_ONE = 1 << 1,
95      };
96
97      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
98      enum EnumName {
99        ENUM_NAME_ZERO = 1 << 0,
100        ENUM_NAME_ONE = 1 << 1,
101        ENUM_NAME_TWO = ENUM_NAME_ZERO | ENUM_NAME_ONE,
102      };
103    """.split('\n')
104    definitions = HeaderParser(test_data).ParseDefinitions()
105    self.assertEqual(2, len(definitions))
106    definition = definitions[0]
107    self.assertEqual('EnumName', definition.class_name)
108    self.assertEqual('test.namespace', definition.enum_package)
109    self.assertEqual(collections.OrderedDict([('VALUE_ZERO', '1 << 0'),
110                                              ('VALUE_ONE', '1 << 1')]),
111                     definition.entries)
112
113    definition = definitions[1]
114    expected_entries = collections.OrderedDict([
115        ('ZERO', '1 << 0'),
116        ('ONE', '1 << 1'),
117        ('TWO', 'ZERO | ONE')])
118    self.assertEqual(expected_entries, definition.entries)
119
120  def testParseMultilineEnumEntry(self):
121    test_data = """
122      // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace
123      enum Foo {
124        VALUE_ZERO = 1 << 0,
125        VALUE_ONE =
126            SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | ControlKey,
127        VALUE_TWO = 1 << 18,
128      };
129    """.split('\n')
130    expected_entries = collections.OrderedDict([
131        ('VALUE_ZERO', '1 << 0'),
132        ('VALUE_ONE', 'SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | '
133         'ControlKey'),
134        ('VALUE_TWO', '1 << 18')])
135    definitions = HeaderParser(test_data).ParseDefinitions()
136    self.assertEqual(1, len(definitions))
137    definition = definitions[0]
138    self.assertEqual('Foo', definition.class_name)
139    self.assertEqual('bar.namespace', definition.enum_package)
140    self.assertEqual(expected_entries, definition.entries)
141
142  def testParseEnumEntryWithTrailingMultilineEntry(self):
143    test_data = """
144      // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace
145      enum Foo {
146        VALUE_ZERO = 1,
147        VALUE_ONE =
148            SymbolKey | FnKey | AltGrKey | MetaKey |
149            AltKey | ControlKey | ShiftKey,
150      };
151    """.split('\n')
152    expected_entries = collections.OrderedDict([
153        ('VALUE_ZERO', '1'),
154        ('VALUE_ONE', 'SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | '
155         'ControlKey | ShiftKey')])
156    definitions = HeaderParser(test_data).ParseDefinitions()
157    self.assertEqual(1, len(definitions))
158    definition = definitions[0]
159    self.assertEqual('Foo', definition.class_name)
160    self.assertEqual('bar.namespace', definition.enum_package)
161    self.assertEqual(expected_entries, definition.entries)
162
163  def testParseNoCommaAfterLastEntry(self):
164    test_data = """
165      // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace
166      enum Foo {
167        VALUE_ZERO = 1,
168
169        // This is a multiline
170        //
171        // comment with an empty line.
172        VALUE_ONE = 2
173      };
174    """.split('\n')
175    expected_entries = collections.OrderedDict([
176        ('VALUE_ZERO', '1'),
177        ('VALUE_ONE', '2')])
178    expected_comments = collections.OrderedDict([
179        ('VALUE_ONE', 'This is a multiline comment with an empty line.')])
180    definitions = HeaderParser(test_data).ParseDefinitions()
181    self.assertEqual(1, len(definitions))
182    definition = definitions[0]
183    self.assertEqual('Foo', definition.class_name)
184    self.assertEqual('bar.namespace', definition.enum_package)
185    self.assertEqual(expected_entries, definition.entries)
186    self.assertEqual(expected_comments, definition.comments)
187
188  def testParseClassNameOverride(self):
189    test_data = """
190      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
191      // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName
192      enum EnumName {
193        FOO
194      };
195
196      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
197      // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OtherOverride
198      enum PrefixTest {
199        PREFIX_TEST_A,
200        PREFIX_TEST_B,
201      };
202    """.split('\n')
203    definitions = HeaderParser(test_data).ParseDefinitions()
204    self.assertEqual(2, len(definitions))
205    definition = definitions[0]
206    self.assertEqual('OverrideName', definition.class_name)
207
208    definition = definitions[1]
209    self.assertEqual('OtherOverride', definition.class_name)
210    self.assertEqual(collections.OrderedDict([('A', 0),
211                                              ('B', 1)]),
212                     definition.entries)
213
214  def testParsePreservesCommentsWhenPrefixStripping(self):
215    test_data = """
216      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
217      enum EnumOne {
218        ENUM_ONE_A = 1,
219        // Comment there
220        ENUM_ONE_B = A,
221      };
222
223      enum EnumIgnore {
224        C, D, E
225      };
226
227      // GENERATED_JAVA_ENUM_PACKAGE: other.package
228      // GENERATED_JAVA_PREFIX_TO_STRIP: P_
229      enum EnumTwo {
230        P_A,
231        // This comment spans
232        // two lines.
233        P_B
234      };
235    """.split('\n')
236    definitions = HeaderParser(test_data).ParseDefinitions()
237    self.assertEqual(2, len(definitions))
238    definition = definitions[0]
239    self.assertEqual('EnumOne', definition.class_name)
240    self.assertEqual('test.namespace', definition.enum_package)
241    self.assertEqual(collections.OrderedDict([('A', '1'),
242                                              ('B', 'A')]),
243                     definition.entries)
244    self.assertEqual(collections.OrderedDict([('B', 'Comment there')]),
245                     definition.comments)
246    definition = definitions[1]
247    self.assertEqual('EnumTwo', definition.class_name)
248    self.assertEqual('other.package', definition.enum_package)
249    self.assertEqual(collections.OrderedDict(
250        [('B', 'This comment spans two lines.')]), definition.comments)
251    self.assertEqual(collections.OrderedDict([('A', 0),
252                                              ('B', 1)]),
253                     definition.entries)
254
255  def testParseTwoEnums(self):
256    test_data = """
257      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
258      enum AnEnum {
259        ENUM_ONE_A = 1,
260        ENUM_ONE_B = A,
261      };
262
263      enum EnumIgnore {
264        C, D, E
265      };
266
267      // GENERATED_JAVA_ENUM_PACKAGE: other.package
268      enum EnumTwo {
269        P_A,
270        P_B
271      };
272    """.split('\n')
273    definitions = HeaderParser(test_data).ParseDefinitions()
274    self.assertEqual(2, len(definitions))
275    definition = definitions[0]
276    self.assertEqual('AnEnum', definition.class_name)
277    self.assertEqual('test.namespace', definition.enum_package)
278    self.assertEqual(collections.OrderedDict([('ENUM_ONE_A', '1'),
279                                              ('ENUM_ONE_B', 'A')]),
280                     definition.entries)
281    definition = definitions[1]
282    self.assertEqual('EnumTwo', definition.class_name)
283    self.assertEqual('other.package', definition.enum_package)
284    self.assertEqual(collections.OrderedDict([('P_A', 0),
285                                              ('P_B', 1)]),
286                     definition.entries)
287
288  def testParseSingleLineEnum(self):
289    test_data = """
290      // GENERATED_JAVA_ENUM_PACKAGE: other.package
291      // GENERATED_JAVA_PREFIX_TO_STRIP: P_
292      enum EnumTwo { P_A, P_B };
293    """.split('\n')
294    definitions = HeaderParser(test_data).ParseDefinitions()
295    definition = definitions[0]
296    self.assertEqual('EnumTwo', definition.class_name)
297    self.assertEqual('other.package', definition.enum_package)
298    self.assertEqual(collections.OrderedDict([('A', 0),
299                                              ('B', 1)]),
300                     definition.entries)
301
302  def testParseWithStrippingAndRelativeReferences(self):
303    test_data = """
304      // GENERATED_JAVA_ENUM_PACKAGE: other.package
305      // GENERATED_JAVA_PREFIX_TO_STRIP: P_
306      enum EnumTwo {
307        P_A = 1,
308        // P_A is old-don't use P_A.
309        P_B = P_A,
310      };
311    """.split('\n')
312    definitions = HeaderParser(test_data).ParseDefinitions()
313    definition = definitions[0]
314    self.assertEqual('EnumTwo', definition.class_name)
315    self.assertEqual('other.package', definition.enum_package)
316    self.assertEqual(collections.OrderedDict([('A', '1'),
317                                              ('B', 'A')]),
318                     definition.entries)
319    self.assertEqual(collections.OrderedDict([('B', 'A is old-don\'t use A.')]),
320                     definition.comments)
321
322  def testParseSingleLineAndRegularEnum(self):
323    test_data = """
324      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
325      enum EnumOne {
326        ENUM_ONE_A = 1,
327        // Comment there
328        ENUM_ONE_B = A,
329      };
330
331      // GENERATED_JAVA_ENUM_PACKAGE: other.package
332      enum EnumTwo { P_A, P_B };
333
334      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
335      // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName
336      enum EnumName {
337        ENUM_NAME_FOO
338      };
339    """.split('\n')
340    definitions = HeaderParser(test_data).ParseDefinitions()
341    definition = definitions[0]
342    self.assertEqual(
343        collections.OrderedDict([('A', '1'), ('B', 'A')]), definition.entries)
344    self.assertEqual(collections.OrderedDict([('B', 'Comment there')]),
345                     definition.comments)
346
347    self.assertEqual(3, len(definitions))
348    definition = definitions[1]
349    self.assertEqual(
350        collections.OrderedDict([('P_A', 0), ('P_B', 1)]), definition.entries)
351
352    definition = definitions[2]
353    self.assertEqual(collections.OrderedDict([('FOO', 0)]), definition.entries)
354
355  def testParseWithCamelCaseNames(self):
356    test_data = """
357      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
358      enum EnumTest {
359        EnumTestA = 1,
360        // comment for EnumTestB.
361        EnumTestB = 2,
362      };
363
364      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
365      // GENERATED_JAVA_PREFIX_TO_STRIP: Test
366      enum AnEnum {
367        TestHTTPOption,
368        TestHTTPSOption,
369      };
370
371    """.split('\n')
372    definitions = HeaderParser(test_data).ParseDefinitions()
373    definition = definitions[0]
374    self.assertEqual(
375        collections.OrderedDict([('A', '1'), ('B', '2')]),
376        definition.entries)
377    self.assertEqual(
378        collections.OrderedDict([('B', 'comment for B.')]),
379        definition.comments)
380
381    definition = definitions[1]
382    self.assertEqual(
383        collections.OrderedDict([('HTTP_OPTION', 0), ('HTTPS_OPTION', 1)]),
384        definition.entries)
385
386  def testParseWithKCamelCaseNames(self):
387    test_data = """
388      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
389      enum EnumOne {
390        kEnumOne = 1,
391        // comment for kEnumTwo.
392        kEnumTwo = 2,
393      };
394
395      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
396      // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName
397      enum EnumName {
398        kEnumNameFoo,
399        kEnumNameBar
400      };
401
402      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
403      enum EnumName {
404        kEnumNameFoo,
405        kEnumBar,
406      };
407
408      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
409      enum Keys {
410        kSymbolKey = 1 << 0,
411        kAltKey = 1 << 1,
412        kUpKey = 1 << 2,
413        kKeyModifiers = kSymbolKey | kAltKey | kUpKey | kKeyModifiers,
414      };
415
416      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
417      enum Mixed {
418        kTestVal,
419        kCodecMPEG2
420      };
421    """.split('\n')
422    definitions = HeaderParser(test_data).ParseDefinitions()
423    definition = definitions[0]
424    self.assertEqual(
425        collections.OrderedDict([('ENUM_ONE', '1'), ('ENUM_TWO', '2')]),
426        definition.entries)
427    self.assertEqual(
428        collections.OrderedDict([('ENUM_TWO', 'comment for ENUM_TWO.')]),
429        definition.comments)
430
431    definition = definitions[1]
432    self.assertEqual(
433        collections.OrderedDict([('FOO', 0), ('BAR', 1)]),
434        definition.entries)
435
436    definition = definitions[2]
437    self.assertEqual(
438        collections.OrderedDict([('ENUM_NAME_FOO', 0), ('ENUM_BAR', 1)]),
439        definition.entries)
440
441    definition = definitions[3]
442    expected_entries = collections.OrderedDict([
443        ('SYMBOL_KEY', '1 << 0'),
444        ('ALT_KEY', '1 << 1'),
445        ('UP_KEY', '1 << 2'),
446        ('KEY_MODIFIERS', 'SYMBOL_KEY | ALT_KEY | UP_KEY | KEY_MODIFIERS')])
447    self.assertEqual(expected_entries, definition.entries)
448
449    definition = definitions[4]
450    self.assertEqual(
451        collections.OrderedDict([('TEST_VAL', 0), ('CODEC_MPEG2', 1)]),
452        definition.entries)
453
454  def testParseThrowsOnUnknownDirective(self):
455    test_data = """
456      // GENERATED_JAVA_UNKNOWN: Value
457      enum EnumName {
458        VALUE_ONE,
459      };
460    """.split('\n')
461    with self.assertRaises(Exception):
462      HeaderParser(test_data).ParseDefinitions()
463
464  def testParseReturnsEmptyListWithoutDirectives(self):
465    test_data = """
466      enum EnumName {
467        VALUE_ONE,
468      };
469    """.split('\n')
470    self.assertEqual([], HeaderParser(test_data).ParseDefinitions())
471
472  def testParseEnumClass(self):
473    test_data = """
474      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
475      enum class Foo {
476        FOO_A,
477      };
478    """.split('\n')
479    definitions = HeaderParser(test_data).ParseDefinitions()
480    self.assertEqual(1, len(definitions))
481    definition = definitions[0]
482    self.assertEqual('Foo', definition.class_name)
483    self.assertEqual('test.namespace', definition.enum_package)
484    self.assertEqual(collections.OrderedDict([('A', 0)]),
485                     definition.entries)
486
487  def testParseEnumClassOneValueSubstringOfAnother(self):
488    test_data = """
489      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
490      enum class SafeBrowsingStatus {
491        kChecking = 0,
492        kEnabled = 1,
493        kDisabled = 2,
494        kDisabledByAdmin = 3,
495        kDisabledByExtension = 4,
496        kEnabledStandard = 5,
497        kEnabledEnhanced = 6,
498        // New enum values must go above here.
499        kMaxValue = kEnabledEnhanced,
500      };
501    """.split('\n')
502    definitions = HeaderParser(test_data).ParseDefinitions()
503    self.assertEqual(1, len(definitions))
504    definition = definitions[0]
505    self.assertEqual('SafeBrowsingStatus', definition.class_name)
506    self.assertEqual('test.namespace', definition.enum_package)
507    self.assertEqual(
508        collections.OrderedDict([
509            ('CHECKING', '0'),
510            ('ENABLED', '1'),
511            ('DISABLED', '2'),
512            ('DISABLED_BY_ADMIN', '3'),
513            ('DISABLED_BY_EXTENSION', '4'),
514            ('ENABLED_STANDARD', '5'),
515            ('ENABLED_ENHANCED', '6'),
516            ('MAX_VALUE', 'ENABLED_ENHANCED'),
517        ]), definition.entries)
518    self.assertEqual(
519        collections.OrderedDict([
520            ('MAX_VALUE', 'New enum values must go above here.')
521        ]), definition.comments)
522
523  def testParseEnumStruct(self):
524    test_data = """
525      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
526      enum struct Foo {
527        FOO_A,
528      };
529    """.split('\n')
530    definitions = HeaderParser(test_data).ParseDefinitions()
531    self.assertEqual(1, len(definitions))
532    definition = definitions[0]
533    self.assertEqual('Foo', definition.class_name)
534    self.assertEqual('test.namespace', definition.enum_package)
535    self.assertEqual(collections.OrderedDict([('A', 0)]),
536                     definition.entries)
537
538  def testParseFixedTypeEnum(self):
539    test_data = """
540      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
541      enum Foo : int {
542        FOO_A,
543      };
544    """.split('\n')
545    definitions = HeaderParser(test_data).ParseDefinitions()
546    self.assertEqual(1, len(definitions))
547    definition = definitions[0]
548    self.assertEqual('Foo', definition.class_name)
549    self.assertEqual('test.namespace', definition.enum_package)
550    self.assertEqual('int', definition.fixed_type)
551    self.assertEqual(collections.OrderedDict([('A', 0)]),
552                     definition.entries)
553
554  def testParseFixedTypeEnumClass(self):
555    test_data = """
556      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
557      enum class Foo: unsigned short {
558        FOO_A,
559      };
560    """.split('\n')
561    definitions = HeaderParser(test_data).ParseDefinitions()
562    self.assertEqual(1, len(definitions))
563    definition = definitions[0]
564    self.assertEqual('Foo', definition.class_name)
565    self.assertEqual('test.namespace', definition.enum_package)
566    self.assertEqual('unsigned short', definition.fixed_type)
567    self.assertEqual(collections.OrderedDict([('A', 0)]),
568                     definition.entries)
569
570  def testParseUnknownFixedTypeRaises(self):
571    test_data = """
572      // GENERATED_JAVA_ENUM_PACKAGE: test.namespace
573      enum class Foo: foo_type {
574        FOO_A,
575      };
576    """.split('\n')
577    with self.assertRaises(Exception):
578      HeaderParser(test_data).ParseDefinitions()
579
580  def testParseSimpleMultiLineDirective(self):
581    test_data = """
582      // GENERATED_JAVA_ENUM_PACKAGE: (
583      //   test.namespace)
584      // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Bar
585      enum Foo {
586        FOO_A,
587      };
588    """.split('\n')
589    definitions = HeaderParser(test_data).ParseDefinitions()
590    self.assertEqual('test.namespace', definitions[0].enum_package)
591    self.assertEqual('Bar', definitions[0].class_name)
592
593  def testParseMultiLineDirective(self):
594    test_data = """
595      // GENERATED_JAVA_ENUM_PACKAGE: (te
596      //   st.name
597      //   space)
598      enum Foo {
599        FOO_A,
600      };
601    """.split('\n')
602    definitions = HeaderParser(test_data).ParseDefinitions()
603    self.assertEqual('test.namespace', definitions[0].enum_package)
604
605  def testParseMultiLineDirectiveWithOtherDirective(self):
606    test_data = """
607      // GENERATED_JAVA_ENUM_PACKAGE: (
608      //   test.namespace)
609      // GENERATED_JAVA_CLASS_NAME_OVERRIDE: (
610      //   Ba
611      //   r
612      //   )
613      enum Foo {
614        FOO_A,
615      };
616    """.split('\n')
617    definitions = HeaderParser(test_data).ParseDefinitions()
618    self.assertEqual('test.namespace', definitions[0].enum_package)
619    self.assertEqual('Bar', definitions[0].class_name)
620
621  def testParseMalformedMultiLineDirectiveWithOtherDirective(self):
622    test_data = """
623      // GENERATED_JAVA_ENUM_PACKAGE: (
624      //   test.name
625      //   space
626      // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Bar
627      enum Foo {
628        FOO_A,
629      };
630    """.split('\n')
631    with self.assertRaises(Exception):
632      HeaderParser(test_data).ParseDefinitions()
633
634  def testParseMalformedMultiLineDirective(self):
635    test_data = """
636      // GENERATED_JAVA_ENUM_PACKAGE: (
637      //   test.name
638      //   space
639      enum Foo {
640        FOO_A,
641      };
642    """.split('\n')
643    with self.assertRaises(Exception):
644      HeaderParser(test_data).ParseDefinitions()
645
646  def testParseMalformedMultiLineDirectiveShort(self):
647    test_data = """
648      // GENERATED_JAVA_ENUM_PACKAGE: (
649      enum Foo {
650        FOO_A,
651      };
652    """.split('\n')
653    with self.assertRaises(Exception):
654      HeaderParser(test_data).ParseDefinitions()
655
656  def testParseMalformedMultiLineDirectiveMissingBrackets(self):
657    test_data = """
658      // GENERATED_JAVA_ENUM_PACKAGE:
659      // test.namespace
660      enum Foo {
661        FOO_A,
662      };
663    """.split('\n')
664    with self.assertRaises(Exception):
665      HeaderParser(test_data).ParseDefinitions()
666
667  def testEnumValueAssignmentNoneDefined(self):
668    definition = EnumDefinition(original_enum_name='c', enum_package='p')
669    definition.AppendEntry('A', None)
670    definition.AppendEntry('B', None)
671    definition.AppendEntry('C', None)
672    definition.Finalize()
673    self.assertEqual(collections.OrderedDict([('A', 0),
674                                              ('B', 1),
675                                              ('C', 2)]),
676                     definition.entries)
677
678  def testEnumValueAssignmentAllDefined(self):
679    definition = EnumDefinition(original_enum_name='c', enum_package='p')
680    definition.AppendEntry('A', '1')
681    definition.AppendEntry('B', '2')
682    definition.AppendEntry('C', '3')
683    definition.Finalize()
684    self.assertEqual(collections.OrderedDict([('A', '1'),
685                                              ('B', '2'),
686                                              ('C', '3')]),
687                     definition.entries)
688
689  def testEnumValueAssignmentReferences(self):
690    definition = EnumDefinition(original_enum_name='c', enum_package='p')
691    definition.AppendEntry('A', None)
692    definition.AppendEntry('B', 'A')
693    definition.AppendEntry('C', None)
694    definition.AppendEntry('D', 'C')
695    definition.Finalize()
696    self.assertEqual(collections.OrderedDict([('A', 0),
697                                              ('B', 0),
698                                              ('C', 1),
699                                              ('D', 1)]),
700                     definition.entries)
701
702  def testEnumValueAssignmentSet(self):
703    definition = EnumDefinition(original_enum_name='c', enum_package='p')
704    definition.AppendEntry('A', None)
705    definition.AppendEntry('B', '2')
706    definition.AppendEntry('C', None)
707    definition.Finalize()
708    self.assertEqual(collections.OrderedDict([('A', 0),
709                                              ('B', 2),
710                                              ('C', 3)]),
711                     definition.entries)
712
713  def testEnumValueAssignmentSetReferences(self):
714    definition = EnumDefinition(original_enum_name='c', enum_package='p')
715    definition.AppendEntry('A', None)
716    definition.AppendEntry('B', 'A')
717    definition.AppendEntry('C', 'B')
718    definition.AppendEntry('D', None)
719    definition.Finalize()
720    self.assertEqual(collections.OrderedDict([('A', 0),
721                                              ('B', 0),
722                                              ('C', 0),
723                                              ('D', 1)]),
724                     definition.entries)
725
726  def testEnumValueAssignmentRaises(self):
727    definition = EnumDefinition(original_enum_name='c', enum_package='p')
728    definition.AppendEntry('A', None)
729    definition.AppendEntry('B', 'foo')
730    definition.AppendEntry('C', None)
731    with self.assertRaises(Exception):
732      definition.Finalize()
733
734  def testExplicitPrefixStripping(self):
735    definition = EnumDefinition(original_enum_name='c', enum_package='p')
736    definition.AppendEntry('P_A', None)
737    definition.AppendEntry('B', None)
738    definition.AppendEntry('P_C', None)
739    definition.AppendEntry('P_LAST', 'P_C')
740    definition.prefix_to_strip = 'P_'
741    definition.Finalize()
742    self.assertEqual(collections.OrderedDict([('A', 0),
743                                              ('B', 1),
744                                              ('C', 2),
745                                              ('LAST', 2)]),
746                     definition.entries)
747
748  def testImplicitPrefixStripping(self):
749    definition = EnumDefinition(original_enum_name='ClassName',
750                                enum_package='p')
751    definition.AppendEntry('CLASS_NAME_A', None)
752    definition.AppendEntry('CLASS_NAME_B', None)
753    definition.AppendEntry('CLASS_NAME_C', None)
754    definition.AppendEntry('CLASS_NAME_LAST', 'CLASS_NAME_C')
755    definition.Finalize()
756    self.assertEqual(collections.OrderedDict([('A', 0),
757                                              ('B', 1),
758                                              ('C', 2),
759                                              ('LAST', 2)]),
760                     definition.entries)
761
762  def testImplicitPrefixStrippingRequiresAllConstantsToBePrefixed(self):
763    definition = EnumDefinition(original_enum_name='Name',
764                                enum_package='p')
765    definition.AppendEntry('A', None)
766    definition.AppendEntry('B', None)
767    definition.AppendEntry('NAME_LAST', None)
768    definition.Finalize()
769    self.assertEqual(['A', 'B', 'NAME_LAST'], list(definition.entries.keys()))
770
771  def testGenerateThrowsOnEmptyInput(self):
772    with self.assertRaises(Exception):
773      original_do_parse = java_cpp_enum.DoParseHeaderFile
774      try:
775        java_cpp_enum.DoParseHeaderFile = lambda _: []
776        for _ in java_cpp_enum.DoGenerate(['file']):
777          pass
778      finally:
779        java_cpp_enum.DoParseHeaderFile = original_do_parse
780
781
782if __name__ == '__main__':
783  unittest.main()
784