build/pymake/tests/parsertests.py

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 import pymake.data, pymake.parser, pymake.parserdata, pymake.functions
     2 import unittest
     3 import logging
     5 from cStringIO import StringIO
     7 def multitest(cls):
     8     for name in cls.testdata.iterkeys():
     9         def m(self, name=name):
    10             return self.runSingle(*self.testdata[name])
    12         setattr(cls, 'test_%s' % name, m)
    13     return cls
    15 class TestBase(unittest.TestCase):
    16     def assertEqual(self, a, b, msg=""):
    17         """Actually print the values which weren't equal, if things don't work out!"""
    18         unittest.TestCase.assertEqual(self, a, b, "%s got %r expected %r" % (msg, a, b))
    20 class DataTest(TestBase):
    21     testdata = {
    22         'oneline':
    23             ("He\tllo", "f", 1, 0,
    24              ((0, "f", 1, 0), (2, "f", 1, 2), (3, "f", 1, 4))),
    25         'twoline':
    26             ("line1 \n\tl\tine2", "f", 1, 4,
    27              ((0, "f", 1, 4), (5, "f", 1, 9), (6, "f", 1, 10), (7, "f", 2, 0), (8, "f", 2, 4), (10, "f", 2, 8), (13, "f", 2, 11))),
    28     }
    30     def runSingle(self, data, filename, line, col, results):
    31         d = pymake.parser.Data(data, 0, len(data), pymake.parserdata.Location(filename, line, col))
    32         for pos, file, lineno, col in results:
    33             loc = d.getloc(pos)
    34             self.assertEqual(loc.path, file, "data file offset %i" % pos)
    35             self.assertEqual(loc.line, lineno, "data line offset %i" % pos)
    36             self.assertEqual(loc.column, col, "data col offset %i" % pos)
    37 multitest(DataTest)
    39 class LineEnumeratorTest(TestBase):
    40     testdata = {
    41         'simple': (
    42             'Hello, world', [
    43                 ('Hello, world', 1),
    44                 ]
    45             ),
    46         'multi': (
    47             'Hello\nhappy  \n\nworld\n', [
    48                 ('Hello', 1),
    49                 ('happy  ', 2),
    50                 ('', 3),
    51                 ('world', 4),
    52                 ('', 5),
    53                 ]
    54             ),
    55         'continuation': (
    56             'Hello, \\\n world\nJellybeans!', [
    57                 ('Hello, \\\n world', 1),
    58                 ('Jellybeans!', 3),
    59                 ]
    60             ),
    61         'multislash': (
    62             'Hello, \\\\\n world', [
    63                 ('Hello, \\\\', 1),
    64                 (' world', 2),
    65                 ]
    66             )
    67         }
    69     def runSingle(self, s, lines):
    70         gotlines = [(d.s[d.lstart:d.lend], d.loc.line) for d in pymake.parser.enumeratelines(s, 'path')]
    71         self.assertEqual(gotlines, lines)
    73 multitest(LineEnumeratorTest)
    75 class IterTest(TestBase):
    76     testdata = {
    77         'plaindata': (
    78             pymake.parser.iterdata,
    79             "plaindata # test\n",
    80             "plaindata # test\n"
    81             ),
    82         'makecomment': (
    83             pymake.parser.itermakefilechars,
    84             "VAR = val # comment",
    85             "VAR = val "
    86             ),
    87         'makeescapedcomment': (
    88             pymake.parser.itermakefilechars,
    89             "VAR = val \# escaped hash",
    90             "VAR = val # escaped hash"
    91             ),
    92         'makeescapedslash': (
    93             pymake.parser.itermakefilechars,
    94             "VAR = val\\\\",
    95             "VAR = val\\\\",
    96             ),
    97         'makecontinuation': (
    98             pymake.parser.itermakefilechars,
    99             "VAR = VAL  \\\n  continuation # comment \\\n  continuation",
   100             "VAR = VAL continuation "
   101             ),
   102         'makecontinuation2': (
   103             pymake.parser.itermakefilechars,
   104             "VAR = VAL  \\  \\\n continuation",
   105             "VAR = VAL  \\ continuation"
   106             ),
   107         'makeawful': (
   108             pymake.parser.itermakefilechars,
   109             "VAR = VAL  \\\\# comment\n",
   110             "VAR = VAL  \\"
   111             ),
   112         'command': (
   113             pymake.parser.itercommandchars,
   114             "echo boo # comment",
   115             "echo boo # comment",
   116             ),
   117         'commandcomment': (
   118             pymake.parser.itercommandchars,
   119             "echo boo \# comment",
   120             "echo boo \# comment",
   121             ),
   122         'commandcontinue': (
   123             pymake.parser.itercommandchars,
   124             "echo boo # \\\n\t  command 2",
   125             "echo boo # \\\n  command 2"
   126             ),
   127     }
   129     def runSingle(self, ifunc, idata, expected):
   130         d = pymake.parser.Data.fromstring(idata, 'IterTest data')
   132         it = pymake.parser._alltokens.finditer(d.s, 0, d.lend)
   133         actual = ''.join( [c for c, t, o, oo in ifunc(d, 0, ('dummy-token',), it)] )
   134         self.assertEqual(actual, expected)
   136         if ifunc == pymake.parser.itermakefilechars:
   137             print "testing %r" % expected
   138             self.assertEqual(pymake.parser.flattenmakesyntax(d, 0), expected)
   140 multitest(IterTest)
   143 #         'define': (
   144 #             pymake.parser.iterdefinechars,
   145 #             "endef",
   146 #             ""
   147 #             ),
   148 #        'definenesting': (
   149 #            pymake.parser.iterdefinechars,
   150 #            """define BAR # comment
   151 #random text
   152 #endef not what you think!
   153 #endef # comment is ok\n""",
   154 #            """define BAR # comment
   155 #random text
   156 #endef not what you think!"""
   157 #            ),
   158 #        'defineescaped': (
   159 #            pymake.parser.iterdefinechars,
   160 #            """value   \\
   161 #endef
   162 #endef\n""",
   163 #            "value endef"
   164 #        ),
   166 class MakeSyntaxTest(TestBase):
   167     # (string, startat, stopat, stopoffset, expansion
   168     testdata = {
   169         'text': ('hello world', 0, (), None, ['hello world']),
   170         'singlechar': ('hello $W', 0, (), None,
   171                        ['hello ',
   172                         {'type': 'VariableRef',
   173                          '.vname': ['W']}
   174                         ]),
   175         'stopat': ('hello: world', 0, (':', '='), 6, ['hello']),
   176         'funccall': ('h $(flavor FOO)', 0, (), None,
   177                      ['h ',
   178                       {'type': 'FlavorFunction',
   179                        '[0]': ['FOO']}
   180                       ]),
   181         'escapedollar': ('hello$$world', 0, (), None, ['hello$world']),
   182         'varref': ('echo $(VAR)', 0, (), None,
   183                    ['echo ',
   184                     {'type': 'VariableRef',
   185                      '.vname': ['VAR']}
   186                     ]),
   187         'dynamicvarname': ('echo $($(VARNAME):.c=.o)', 0, (':',), None,
   188                            ['echo ',
   189                             {'type': 'SubstitutionRef',
   190                              '.vname': [{'type': 'VariableRef',
   191                                          '.vname': ['VARNAME']}
   192                                         ],
   193                              '.substfrom': ['.c'],
   194                              '.substto': ['.o']}
   195                             ]),
   196         'substref': ('  $(VAR:VAL) := $(VAL)', 0, (':=', '+=', '=', ':'), 15,
   197                      ['  ',
   198                       {'type': 'VariableRef',
   199                        '.vname': ['VAR:VAL']},
   200                       ' ']),
   201         'vadsubstref': ('  $(VAR:VAL) = $(VAL)', 15, (), None,
   202                         [{'type': 'VariableRef',
   203                           '.vname': ['VAL']},
   204                          ]),
   205         }
   207     def compareRecursive(self, actual, expected, path):
   208         self.assertEqual(len(actual), len(expected),
   209                          "compareRecursive: %s %r" % (path, actual))
   210         for i in xrange(0, len(actual)):
   211             ipath = path + [i]
   213             a, isfunc = actual[i]
   214             e = expected[i]
   215             if isinstance(e, str):
   216                 self.assertEqual(a, e, "compareRecursive: %s" % (ipath,))
   217             else:
   218                 self.assertEqual(type(a), getattr(pymake.functions, e['type']),
   219                                  "compareRecursive: %s" % (ipath,))
   220                 for k, v in e.iteritems():
   221                     if k == 'type':
   222                         pass
   223                     elif k[0] == '[':
   224                         item = int(k[1:-1])
   225                         proppath = ipath + [item]
   226                         self.compareRecursive(a[item], v, proppath)
   227                     elif k[0] == '.':
   228                         item = k[1:]
   229                         proppath = ipath + [item]
   230                         self.compareRecursive(getattr(a, item), v, proppath)
   231                     else:
   232                         raise Exception("Unexpected property at %s: %s" % (ipath, k))
   234     def runSingle(self, s, startat, stopat, stopoffset, expansion):
   235         d = pymake.parser.Data.fromstring(s, pymake.parserdata.Location('testdata', 1, 0))
   237         a, t, offset = pymake.parser.parsemakesyntax(d, startat, stopat, pymake.parser.itermakefilechars)
   238         self.compareRecursive(a, expansion, [])
   239         self.assertEqual(offset, stopoffset)
   241 multitest(MakeSyntaxTest)
   243 class VariableTest(TestBase):
   244     testdata = """
   245     VAR = value
   246     VARNAME = TESTVAR
   247     $(VARNAME) = testvalue
   248     $(VARNAME:VAR=VAL) = moretesting
   249     IMM := $(VARNAME) # this is a comment
   250     MULTIVAR = val1 \\
   251   val2
   252     VARNAME = newname
   253     """
   254     expected = {'VAR': 'value',
   255                 'VARNAME': 'newname',
   256                 'TESTVAR': 'testvalue',
   257                 'TESTVAL': 'moretesting',
   258                 'IMM': 'TESTVAR ',
   259                 'MULTIVAR': 'val1 val2',
   260                 'UNDEF': None}
   262     def runTest(self):
   263         stmts = pymake.parser.parsestring(self.testdata, 'VariableTest')
   265         m = pymake.data.Makefile()
   266         stmts.execute(m)
   267         for k, v in self.expected.iteritems():
   268             flavor, source, val = m.variables.get(k)
   269             if val is None:
   270                 self.assertEqual(val, v, 'variable named %s' % k)
   271             else:
   272                 self.assertEqual(val.resolvestr(m, m.variables), v, 'variable named %s' % k)
   274 class SimpleRuleTest(TestBase):
   275     testdata = """
   276     VAR = value
   277 TSPEC = dummy
   278 all: TSPEC = myrule
   279 all:: test test2 $(VAR)
   280 	echo "Hello, $(TSPEC)"
   282 %.o: %.c
   283 	$(CC) -o $@ $<
   284 """
   286     def runTest(self):
   287         stmts = pymake.parser.parsestring(self.testdata, 'SimpleRuleTest')
   289         m = pymake.data.Makefile()
   290         stmts.execute(m)
   291         self.assertEqual(m.defaulttarget, 'all', "Default target")
   293         self.assertTrue(m.hastarget('all'), "Has 'all' target")
   294         target = m.gettarget('all')
   295         rules = target.rules
   296         self.assertEqual(len(rules), 1, "Number of rules")
   297         prereqs = rules[0].prerequisites
   298         self.assertEqual(prereqs, ['test', 'test2', 'value'], "Prerequisites")
   299         commands = rules[0].commands
   300         self.assertEqual(len(commands), 1, "Number of commands")
   301         expanded = commands[0].resolvestr(m, target.variables)
   302         self.assertEqual(expanded, 'echo "Hello, myrule"')
   304         irules = m.implicitrules
   305         self.assertEqual(len(irules), 1, "Number of implicit rules")
   307         irule = irules[0]
   308         self.assertEqual(len(irule.targetpatterns), 1, "%.o target pattern count")
   309         self.assertEqual(len(irule.prerequisites), 1, "%.o prerequisite count")
   310         self.assertEqual(irule.targetpatterns[0].match('foo.o'), 'foo', "%.o stem")
   312 if __name__ == '__main__':
   313     logging.basicConfig(level=logging.DEBUG)
   314     unittest.main()

mercurial