(root)/
glib-2.79.0/
gobject/
tests/
mkenums.py
       1  #!/usr/bin/python3
       2  # -*- coding: utf-8 -*-
       3  #
       4  # Copyright © 2018 Endless Mobile, Inc.
       5  #
       6  # SPDX-License-Identifier: LGPL-2.1-or-later
       7  #
       8  # This library is free software; you can redistribute it and/or
       9  # modify it under the terms of the GNU Lesser General Public
      10  # License as published by the Free Software Foundation; either
      11  # version 2.1 of the License, or (at your option) any later version.
      12  #
      13  # This library is distributed in the hope that it will be useful,
      14  # but WITHOUT ANY WARRANTY; without even the implied warranty of
      15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16  # Lesser General Public License for more details.
      17  #
      18  # You should have received a copy of the GNU Lesser General Public
      19  # License along with this library; if not, write to the Free Software
      20  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      21  # MA  02110-1301  USA
      22  
      23  """Integration tests for glib-mkenums utility."""
      24  
      25  import collections
      26  import os
      27  import shutil
      28  import subprocess
      29  import sys
      30  import tempfile
      31  import textwrap
      32  import unittest
      33  
      34  import taptestrunner
      35  
      36  
      37  Result = collections.namedtuple("Result", ("info", "out", "err", "subs"))
      38  
      39  
      40  class ESC[4;38;5;81mTestMkenums(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      41      """Integration test for running glib-mkenums.
      42  
      43      This can be run when installed or uninstalled. When uninstalled, it
      44      requires G_TEST_BUILDDIR and G_TEST_SRCDIR to be set.
      45  
      46      The idea with this test harness is to test the glib-mkenums utility, its
      47      handling of command line arguments, its exit statuses, and its handling of
      48      various C source codes. In future we could split the core glib-mkenums
      49      parsing and generation code out into a library and unit test that, and
      50      convert this test to just check command line behaviour.
      51      """
      52  
      53      # Track the cwd, we want to back out to that to clean up our tempdir
      54      cwd = ""
      55      rspfile = False
      56  
      57      def setUp(self):
      58          self.timeout_seconds = 10  # seconds per test
      59          self.tmpdir = tempfile.TemporaryDirectory()
      60          self.cwd = os.getcwd()
      61          os.chdir(self.tmpdir.name)
      62          print("tmpdir:", self.tmpdir.name)
      63          if "G_TEST_BUILDDIR" in os.environ:
      64              self.__mkenums = os.path.join(
      65                  os.environ["G_TEST_BUILDDIR"], "..", "glib-mkenums"
      66              )
      67          else:
      68              self.__mkenums = shutil.which("glib-mkenums")
      69          print("rspfile: {}, mkenums:".format(self.rspfile), self.__mkenums)
      70  
      71      def tearDown(self):
      72          os.chdir(self.cwd)
      73          self.tmpdir.cleanup()
      74  
      75      def _write_rspfile(self, argv):
      76          import shlex
      77  
      78          with tempfile.NamedTemporaryFile(
      79              dir=self.tmpdir.name, mode="w", delete=False
      80          ) as f:
      81              contents = " ".join([shlex.quote(arg) for arg in argv])
      82              print("Response file contains:", contents)
      83              f.write(contents)
      84              f.flush()
      85              return f.name
      86  
      87      def runMkenums(self, *args):
      88          if self.rspfile:
      89              rspfile = self._write_rspfile(args)
      90              args = ["@" + rspfile]
      91          argv = [self.__mkenums]
      92  
      93          # shebang lines are not supported on native
      94          # Windows consoles
      95          if os.name == "nt":
      96              argv.insert(0, sys.executable)
      97  
      98          argv.extend(args)
      99          print("Running:", argv)
     100  
     101          env = os.environ.copy()
     102          env["LC_ALL"] = "C.UTF-8"
     103          env["G_DEBUG"] = "fatal-warnings"
     104          print("Environment:", env)
     105  
     106          # We want to ensure consistent line endings...
     107          info = subprocess.run(
     108              argv,
     109              timeout=self.timeout_seconds,
     110              stdout=subprocess.PIPE,
     111              stderr=subprocess.PIPE,
     112              env=env,
     113              universal_newlines=True,
     114          )
     115          info.check_returncode()
     116          out = info.stdout.strip()
     117          err = info.stderr.strip()
     118  
     119          # Known substitutions for standard boilerplate
     120          subs = {
     121              "standard_top_comment": "This file is generated by glib-mkenums, do not modify "
     122              "it. This code is licensed under the same license as the "
     123              "containing project. Note that it links to GLib, so must "
     124              "comply with the LGPL linking clauses.",
     125              "standard_bottom_comment": "Generated data ends here",
     126          }
     127  
     128          result = Result(info, out, err, subs)
     129  
     130          print("Output:", result.out)
     131          return result
     132  
     133      def runMkenumsWithTemplate(self, template_contents, *args):
     134          with tempfile.NamedTemporaryFile(
     135              dir=self.tmpdir.name, suffix=".template", delete=False
     136          ) as template_file:
     137              # Write out the template.
     138              template_file.write(template_contents.encode("utf-8"))
     139              print(template_file.name + ":", template_contents)
     140              template_file.flush()
     141  
     142              return self.runMkenums("--template", template_file.name, *args)
     143  
     144      def runMkenumsWithAllSubstitutions(self, *args):
     145          """Run glib-mkenums with a template which outputs all substitutions."""
     146          template_contents = """
     147  /*** BEGIN file-header ***/
     148  file-header
     149  /*** END file-header ***/
     150  
     151  /*** BEGIN file-production ***/
     152  file-production
     153  filename: @filename@
     154  basename: @basename@
     155  /*** END file-production ***/
     156  
     157  /*** BEGIN enumeration-production ***/
     158  enumeration-production
     159  EnumName: @EnumName@
     160  enum_name: @enum_name@
     161  ENUMNAME: @ENUMNAME@
     162  ENUMSHORT: @ENUMSHORT@
     163  ENUMPREFIX: @ENUMPREFIX@
     164  enumsince: @enumsince@
     165  type: @type@
     166  Type: @Type@
     167  TYPE: @TYPE@
     168  /*** END enumeration-production ***/
     169  
     170  /*** BEGIN value-header ***/
     171  value-header
     172  EnumName: @EnumName@
     173  enum_name: @enum_name@
     174  ENUMNAME: @ENUMNAME@
     175  ENUMSHORT: @ENUMSHORT@
     176  ENUMPREFIX: @ENUMPREFIX@
     177  enumsince: @enumsince@
     178  type: @type@
     179  Type: @Type@
     180  TYPE: @TYPE@
     181  /*** END value-header ***/
     182  
     183  /*** BEGIN value-production ***/
     184  value-production
     185  VALUENAME: @VALUENAME@
     186  valuenick: @valuenick@
     187  valuenum: @valuenum@
     188  type: @type@
     189  Type: @Type@
     190  TYPE: @TYPE@
     191  /*** END value-production ***/
     192  
     193  /*** BEGIN value-tail ***/
     194  value-tail
     195  EnumName: @EnumName@
     196  enum_name: @enum_name@
     197  ENUMNAME: @ENUMNAME@
     198  ENUMSHORT: @ENUMSHORT@
     199  ENUMPREFIX: @ENUMPREFIX@
     200  enumsince: @enumsince@
     201  type: @type@
     202  Type: @Type@
     203  TYPE: @TYPE@
     204  /*** END value-tail ***/
     205  
     206  /*** BEGIN comment ***/
     207  comment
     208  comment: @comment@
     209  /*** END comment ***/
     210  
     211  /*** BEGIN file-tail ***/
     212  file-tail
     213  /*** END file-tail ***/
     214  """
     215          return self.runMkenumsWithTemplate(template_contents, *args)
     216  
     217      def runMkenumsWithHeader(self, h_contents, encoding="utf-8"):
     218          with tempfile.NamedTemporaryFile(
     219              dir=self.tmpdir.name, suffix=".h", delete=False
     220          ) as h_file:
     221              # Write out the header to be scanned.
     222              h_file.write(h_contents.encode(encoding))
     223              print(h_file.name + ":", h_contents)
     224              h_file.flush()
     225  
     226              # Run glib-mkenums with a template which outputs all substitutions.
     227              result = self.runMkenumsWithAllSubstitutions(h_file.name)
     228  
     229              # Known substitutions for generated filenames.
     230              result.subs.update(
     231                  {"filename": h_file.name, "basename": os.path.basename(h_file.name)}
     232              )
     233  
     234              return result
     235  
     236      def assertSingleEnum(
     237          self,
     238          result,
     239          enum_name_camel,
     240          enum_name_lower,
     241          enum_name_upper,
     242          enum_name_short,
     243          enum_prefix,
     244          enum_since,
     245          type_lower,
     246          type_camel,
     247          type_upper,
     248          value_name,
     249          value_nick,
     250          value_num,
     251      ):
     252          """Assert that out (from runMkenumsWithHeader()) contains a single
     253          enum and value matching the given arguments."""
     254          subs = dict(
     255              {
     256                  "enum_name_camel": enum_name_camel,
     257                  "enum_name_lower": enum_name_lower,
     258                  "enum_name_upper": enum_name_upper,
     259                  "enum_name_short": enum_name_short,
     260                  "enum_prefix": enum_prefix,
     261                  "enum_since": enum_since,
     262                  "type_lower": type_lower,
     263                  "type_camel": type_camel,
     264                  "type_upper": type_upper,
     265                  "value_name": value_name,
     266                  "value_nick": value_nick,
     267                  "value_num": value_num,
     268              },
     269              **result.subs
     270          )
     271  
     272          self.assertEqual(
     273              """
     274  comment
     275  comment: {standard_top_comment}
     276  
     277  
     278  file-header
     279  file-production
     280  filename: {filename}
     281  basename: {basename}
     282  enumeration-production
     283  EnumName: {enum_name_camel}
     284  enum_name: {enum_name_lower}
     285  ENUMNAME: {enum_name_upper}
     286  ENUMSHORT: {enum_name_short}
     287  ENUMPREFIX: {enum_prefix}
     288  enumsince: {enum_since}
     289  type: {type_lower}
     290  Type: {type_camel}
     291  TYPE: {type_upper}
     292  value-header
     293  EnumName: {enum_name_camel}
     294  enum_name: {enum_name_lower}
     295  ENUMNAME: {enum_name_upper}
     296  ENUMSHORT: {enum_name_short}
     297  ENUMPREFIX: {enum_prefix}
     298  enumsince: {enum_since}
     299  type: {type_lower}
     300  Type: {type_camel}
     301  TYPE: {type_upper}
     302  value-production
     303  VALUENAME: {value_name}
     304  valuenick: {value_nick}
     305  valuenum: {value_num}
     306  type: {type_lower}
     307  Type: {type_camel}
     308  TYPE: {type_upper}
     309  value-tail
     310  EnumName: {enum_name_camel}
     311  enum_name: {enum_name_lower}
     312  ENUMNAME: {enum_name_upper}
     313  ENUMSHORT: {enum_name_short}
     314  ENUMPREFIX: {enum_prefix}
     315  enumsince: {enum_since}
     316  type: {type_lower}
     317  Type: {type_camel}
     318  TYPE: {type_upper}
     319  file-tail
     320  
     321  comment
     322  comment: {standard_bottom_comment}
     323  """.format(
     324                  **subs
     325              ).strip(),
     326              result.out,
     327          )
     328  
     329      def test_help(self):
     330          """Test the --help argument."""
     331          result = self.runMkenums("--help")
     332          self.assertIn("usage: glib-mkenums", result.out)
     333  
     334      def test_no_args(self):
     335          """Test running with no arguments at all."""
     336          result = self.runMkenums()
     337          self.assertEqual("", result.err)
     338          self.assertEqual(
     339              """/* {standard_top_comment} */
     340  
     341  
     342  /* {standard_bottom_comment} */""".format(
     343                  **result.subs
     344              ),
     345              result.out.strip(),
     346          )
     347  
     348      def test_empty_template(self):
     349          """Test running with an empty template and no header files."""
     350          result = self.runMkenumsWithTemplate("")
     351          self.assertEqual("", result.err)
     352          self.assertEqual(
     353              """/* {standard_top_comment} */
     354  
     355  
     356  /* {standard_bottom_comment} */""".format(
     357                  **result.subs
     358              ),
     359              result.out.strip(),
     360          )
     361  
     362      def test_no_headers(self):
     363          """Test running with a complete template, but no header files."""
     364          result = self.runMkenumsWithAllSubstitutions()
     365          self.assertEqual("", result.err)
     366          self.assertEqual(
     367              """
     368  comment
     369  comment: {standard_top_comment}
     370  
     371  
     372  file-header
     373  file-tail
     374  
     375  comment
     376  comment: {standard_bottom_comment}
     377  """.format(
     378                  **result.subs
     379              ).strip(),
     380              result.out,
     381          )
     382  
     383      def test_empty_header(self):
     384          """Test an empty header."""
     385          result = self.runMkenumsWithHeader("")
     386          self.assertEqual("", result.err)
     387          self.assertEqual(
     388              """
     389  comment
     390  comment: {standard_top_comment}
     391  
     392  
     393  file-header
     394  file-tail
     395  
     396  comment
     397  comment: {standard_bottom_comment}
     398  """.format(
     399                  **result.subs
     400              ).strip(),
     401              result.out,
     402          )
     403  
     404      def test_enum_name(self):
     405          """Test typedefs with an enum and a typedef name. Bug #794506."""
     406          h_contents = """
     407          typedef enum _SomeEnumIdentifier {
     408            ENUM_VALUE
     409          } SomeEnumIdentifier;
     410          """
     411          result = self.runMkenumsWithHeader(h_contents)
     412          self.assertEqual("", result.err)
     413          self.assertSingleEnum(
     414              result,
     415              "SomeEnumIdentifier",
     416              "some_enum_identifier",
     417              "SOME_ENUM_IDENTIFIER",
     418              "ENUM_IDENTIFIER",
     419              "SOME",
     420              "",
     421              "enum",
     422              "Enum",
     423              "ENUM",
     424              "ENUM_VALUE",
     425              "value",
     426              "0",
     427          )
     428  
     429      def test_non_utf8_encoding(self):
     430          """Test source files with non-UTF-8 encoding. Bug #785113."""
     431          h_contents = """
     432          /* Copyright © La Peña */
     433          typedef enum {
     434            ENUM_VALUE
     435          } SomeEnumIdentifier;
     436          """
     437          result = self.runMkenumsWithHeader(h_contents, encoding="iso-8859-1")
     438          self.assertIn("WARNING: UnicodeWarning: ", result.err)
     439          self.assertSingleEnum(
     440              result,
     441              "SomeEnumIdentifier",
     442              "some_enum_identifier",
     443              "SOME_ENUM_IDENTIFIER",
     444              "ENUM_IDENTIFIER",
     445              "SOME",
     446              "",
     447              "enum",
     448              "Enum",
     449              "ENUM",
     450              "ENUM_VALUE",
     451              "value",
     452              "0",
     453          )
     454  
     455      def test_reproducible(self):
     456          """Test builds are reproducible regardless of file ordering.
     457          Bug #691436."""
     458          template_contents = "template"
     459  
     460          h_contents1 = """
     461          typedef enum {
     462            FIRST,
     463          } Header1;
     464          """
     465  
     466          h_contents2 = """
     467          typedef enum {
     468            SECOND,
     469          } Header2;
     470          """
     471  
     472          with tempfile.NamedTemporaryFile(
     473              dir=self.tmpdir.name, suffix="1.h", delete=False
     474          ) as h_file1, tempfile.NamedTemporaryFile(
     475              dir=self.tmpdir.name, suffix="2.h", delete=False
     476          ) as h_file2:
     477              # Write out the headers.
     478              h_file1.write(h_contents1.encode("utf-8"))
     479              h_file2.write(h_contents2.encode("utf-8"))
     480  
     481              h_file1.flush()
     482              h_file2.flush()
     483  
     484              # Run glib-mkenums with the headers in one order, and then again
     485              # in another order.
     486              result1 = self.runMkenumsWithTemplate(
     487                  template_contents, h_file1.name, h_file2.name
     488              )
     489              self.assertEqual("", result1.err)
     490  
     491              result2 = self.runMkenumsWithTemplate(
     492                  template_contents, h_file2.name, h_file1.name
     493              )
     494              self.assertEqual("", result2.err)
     495  
     496              # The output should be the same.
     497              self.assertEqual(result1.out, result2.out)
     498  
     499      def test_no_nick(self):
     500          """Test trigraphs with a desc but no nick. Issue #1360."""
     501          h_contents = """
     502          typedef enum {
     503            GEGL_SAMPLER_NEAREST = 0,   /*< desc="nearest"      >*/
     504          } GeglSamplerType;
     505          """
     506          result = self.runMkenumsWithHeader(h_contents)
     507          self.assertEqual("", result.err)
     508          self.assertSingleEnum(
     509              result,
     510              "GeglSamplerType",
     511              "gegl_sampler_type",
     512              "GEGL_SAMPLER_TYPE",
     513              "SAMPLER_TYPE",
     514              "GEGL",
     515              "",
     516              "enum",
     517              "Enum",
     518              "ENUM",
     519              "GEGL_SAMPLER_NEAREST",
     520              "nearest",
     521              "0",
     522          )
     523  
     524      def test_with_double_quotes(self):
     525          """Test trigraphs with double-quoted expressions. Issue #65."""
     526          h_contents = """
     527          typedef enum {
     528            FOO_VALUE /*< nick="eek, a comma" >*/
     529          } Foo;
     530          """
     531          result = self.runMkenumsWithHeader(h_contents)
     532          self.assertEqual("", result.err)
     533          self.assertSingleEnum(
     534              result,
     535              "Foo",
     536              "foo_",
     537              "FOO_",
     538              "",
     539              "FOO",
     540              "",
     541              "enum",
     542              "Enum",
     543              "ENUM",
     544              "FOO_VALUE",
     545              "eek, a comma",
     546              "0",
     547          )
     548  
     549      def test_filename_basename_in_fhead_ftail(self):
     550          template_contents = """
     551  /*** BEGIN file-header ***/
     552  file-header
     553  filename: @filename@
     554  basename: @basename@
     555  /*** END file-header ***/
     556  
     557  /*** BEGIN comment ***/
     558  comment
     559  comment: @comment@
     560  /*** END comment ***/
     561  
     562  /*** BEGIN file-tail ***/
     563  file-tail
     564  filename: @filename@
     565  basename: @basename@
     566  /*** END file-tail ***/"""
     567          result = self.runMkenumsWithTemplate(template_contents)
     568          self.assertEqual(
     569              textwrap.dedent(
     570                  """
     571                  WARNING: @filename@ used in file-header section.
     572                  WARNING: @basename@ used in file-header section.
     573                  WARNING: @filename@ used in file-tail section.
     574                  WARNING: @basename@ used in file-tail section.
     575                  """
     576              ).strip(),
     577              result.err,
     578          )
     579          self.assertEqual(
     580              """
     581  comment
     582  comment: {standard_top_comment}
     583  
     584  
     585  file-header
     586  filename: @filename@
     587  basename: @basename@
     588  file-tail
     589  filename: @filename@
     590  basename: @basename@
     591  
     592  comment
     593  comment: {standard_bottom_comment}
     594  """.format(
     595                  **result.subs
     596              ).strip(),
     597              result.out,
     598          )
     599  
     600      def test_since(self):
     601          """Test user-provided 'since' version handling
     602          https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1492"""
     603          h_contents = """
     604          typedef enum { /*< since=1.0 >*/
     605              QMI_WMS_MESSAGE_PROTOCOL_CDMA = 0,
     606          } QmiWmsMessageProtocol;
     607          """
     608          result = self.runMkenumsWithHeader(h_contents)
     609          self.assertEqual("", result.err)
     610          self.assertSingleEnum(
     611              result,
     612              "QmiWmsMessageProtocol",
     613              "qmi_wms_message_protocol",
     614              "QMI_WMS_MESSAGE_PROTOCOL",
     615              "WMS_MESSAGE_PROTOCOL",
     616              "QMI",
     617              "1.0",
     618              "enum",
     619              "Enum",
     620              "ENUM",
     621              "QMI_WMS_MESSAGE_PROTOCOL_CDMA",
     622              "cdma",
     623              "0",
     624          )
     625  
     626      def test_enum_private_public(self):
     627          """Test private/public enums. Bug #782162."""
     628          h_contents1 = """
     629          typedef enum {
     630            ENUM_VALUE_PUBLIC1,
     631            /*< private >*/
     632            ENUM_VALUE_PRIVATE,
     633          } SomeEnumA
     634          """
     635  
     636          h_contents2 = """
     637          typedef enum {
     638            /*< private >*/
     639            ENUM_VALUE_PRIVATE,
     640            /*< public >*/
     641            ENUM_VALUE_PUBLIC2,
     642          } SomeEnumB;
     643          """
     644  
     645          result = self.runMkenumsWithHeader(h_contents1)
     646          self.maxDiff = None
     647          self.assertEqual("", result.err)
     648          self.assertSingleEnum(
     649              result,
     650              "SomeEnumA",
     651              "some_enum_a",
     652              "SOME_ENUM_A",
     653              "ENUM_A",
     654              "SOME",
     655              "",
     656              "enum",
     657              "Enum",
     658              "ENUM",
     659              "ENUM_VALUE_PUBLIC1",
     660              "public1",
     661              "0",
     662          )
     663          result = self.runMkenumsWithHeader(h_contents2)
     664          self.assertEqual("", result.err)
     665          self.assertSingleEnum(
     666              result,
     667              "SomeEnumB",
     668              "some_enum_b",
     669              "SOME_ENUM_B",
     670              "ENUM_B",
     671              "SOME",
     672              "",
     673              "enum",
     674              "Enum",
     675              "ENUM",
     676              "ENUM_VALUE_PUBLIC2",
     677              "public2",
     678              "1",
     679          )
     680  
     681      def test_available_in(self):
     682          """Test GLIB_AVAILABLE_ENUMERATOR_IN_2_68 handling
     683          https://gitlab.gnome.org/GNOME/glib/-/issues/2327"""
     684          h_contents = """
     685          typedef enum {
     686            G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER GLIB_AVAILABLE_ENUMERATOR_IN_2_68 = (1<<2)
     687          } GDBusServerFlags;
     688          """
     689          result = self.runMkenumsWithHeader(h_contents)
     690          self.assertEqual("", result.err)
     691          self.assertSingleEnum(
     692              result,
     693              "GDBusServerFlags",
     694              "g_dbus_server_flags",
     695              "G_DBUS_SERVER_FLAGS",
     696              "DBUS_SERVER_FLAGS",
     697              "G",
     698              "",
     699              "flags",
     700              "Flags",
     701              "FLAGS",
     702              "G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER",
     703              "user",
     704              "4",
     705          )
     706  
     707      def test_deprecated_in(self):
     708          """Test GLIB_DEPRECATED_ENUMERATOR_IN_2_68 handling
     709          https://gitlab.gnome.org/GNOME/glib/-/issues/2327"""
     710          h_contents = """
     711          typedef enum {
     712            G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER GLIB_DEPRECATED_ENUMERATOR_IN_2_68 = (1<<2)
     713          } GDBusServerFlags;
     714          """
     715          result = self.runMkenumsWithHeader(h_contents)
     716          self.assertEqual("", result.err)
     717          self.assertSingleEnum(
     718              result,
     719              "GDBusServerFlags",
     720              "g_dbus_server_flags",
     721              "G_DBUS_SERVER_FLAGS",
     722              "DBUS_SERVER_FLAGS",
     723              "G",
     724              "",
     725              "flags",
     726              "Flags",
     727              "FLAGS",
     728              "G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER",
     729              "user",
     730              "4",
     731          )
     732  
     733      def test_deprecated_in_for(self):
     734          """Test GLIB_DEPRECATED_ENUMERATOR_IN_2_68_FOR() handling
     735          https://gitlab.gnome.org/GNOME/glib/-/issues/2327"""
     736          h_contents = """
     737          typedef enum {
     738            G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER GLIB_DEPRECATED_ENUMERATOR_IN_2_68_FOR(G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER2) = (1<<2)
     739          } GDBusServerFlags;
     740          """
     741          result = self.runMkenumsWithHeader(h_contents)
     742          self.assertEqual("", result.err)
     743          self.assertSingleEnum(
     744              result,
     745              "GDBusServerFlags",
     746              "g_dbus_server_flags",
     747              "G_DBUS_SERVER_FLAGS",
     748              "DBUS_SERVER_FLAGS",
     749              "G",
     750              "",
     751              "flags",
     752              "Flags",
     753              "FLAGS",
     754              "G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER",
     755              "user",
     756              "4",
     757          )
     758  
     759      def test_enum_symbolic_expression(self):
     760          """Test use of symbol in value expression."""
     761          h_contents = """
     762          typedef enum {
     763            /*< private >*/
     764            ENUM_VALUE_PRIVATE = 5,
     765            /*< public >*/
     766            ENUM_VALUE_PUBLIC = ENUM_VALUE_PRIVATE + 2,
     767          } TestSymbolicEnum;
     768          """
     769  
     770          result = self.runMkenumsWithHeader(h_contents)
     771          self.assertEqual("", result.err)
     772          self.assertSingleEnum(
     773              result,
     774              "TestSymbolicEnum",
     775              "test_symbolic_enum",
     776              "TEST_SYMBOLIC_ENUM",
     777              "SYMBOLIC_ENUM",
     778              "TEST",
     779              "",
     780              "enum",
     781              "Enum",
     782              "ENUM",
     783              "ENUM_VALUE_PUBLIC",
     784              "public",
     785              "7",
     786          )
     787  
     788      def test_comma_in_enum_value(self):
     789          """Test use of comma in enum value."""
     790          h_contents = """
     791          typedef enum {
     792            ENUM_VALUE_WITH_COMMA = ',',
     793          } TestCommaEnum;
     794          """
     795  
     796          result = self.runMkenumsWithHeader(h_contents)
     797          self.assertEqual("", result.err)
     798          self.assertSingleEnum(
     799              result,
     800              "TestCommaEnum",
     801              "test_comma_enum",
     802              "TEST_COMMA_ENUM",
     803              "COMMA_ENUM",
     804              "TEST",
     805              "",
     806              "enum",
     807              "Enum",
     808              "ENUM",
     809              "ENUM_VALUE_WITH_COMMA",
     810              "comma",
     811              44,
     812          )
     813  
     814  
     815  class ESC[4;38;5;81mTestRspMkenums(ESC[4;38;5;149mTestMkenums):
     816      """Run all tests again in @rspfile mode"""
     817  
     818      rspfile = True
     819  
     820  
     821  if __name__ == "__main__":
     822      unittest.main(testRunner=taptestrunner.TAPTestRunner())