Back to index

enigmail  1.4.3
parsertests.py
Go to the documentation of this file.
00001 import pymake.data, pymake.parser, pymake.parserdata, pymake.functions
00002 import unittest
00003 import logging
00004 
00005 from cStringIO import StringIO
00006 
00007 def multitest(cls):
00008     for name in cls.testdata.iterkeys():
00009         def m(self, name=name):
00010             return self.runSingle(*self.testdata[name])
00011 
00012         setattr(cls, 'test_%s' % name, m)
00013     return cls
00014 
00015 class TestBase(unittest.TestCase):
00016     def assertEqual(self, a, b, msg=""):
00017         """Actually print the values which weren't equal, if things don't work out!"""
00018         unittest.TestCase.assertEqual(self, a, b, "%s got %r expected %r" % (msg, a, b))
00019 
00020 class DataTest(TestBase):
00021     testdata = {
00022         'oneline':
00023             ("He\tllo", "f", 1, 0,
00024              ((0, "f", 1, 0), (2, "f", 1, 2), (3, "f", 1, 4))),
00025         'twoline':
00026             ("line1 \n\tl\tine2", "f", 1, 4,
00027              ((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))),
00028     }
00029 
00030     def runSingle(self, data, filename, line, col, results):
00031         d = pymake.parser.Data(data, 0, len(data), pymake.parserdata.Location(filename, line, col))
00032         for pos, file, lineno, col in results:
00033             loc = d.getloc(pos)
00034             self.assertEqual(loc.path, file, "data file offset %i" % pos)
00035             self.assertEqual(loc.line, lineno, "data line offset %i" % pos)
00036             self.assertEqual(loc.column, col, "data col offset %i" % pos)
00037 multitest(DataTest)
00038 
00039 class LineEnumeratorTest(TestBase):
00040     testdata = {
00041         'simple': (
00042             'Hello, world', [
00043                 ('Hello, world', 1),
00044                 ]
00045             ),
00046         'multi': (
00047             'Hello\nhappy  \n\nworld\n', [
00048                 ('Hello', 1),
00049                 ('happy  ', 2),
00050                 ('', 3),
00051                 ('world', 4),
00052                 ('', 5),
00053                 ]
00054             ),
00055         'continuation': (
00056             'Hello, \\\n world\nJellybeans!', [
00057                 ('Hello, \\\n world', 1),
00058                 ('Jellybeans!', 3),
00059                 ]
00060             ),
00061         'multislash': (
00062             'Hello, \\\\\n world', [
00063                 ('Hello, \\\\', 1),
00064                 (' world', 2),
00065                 ]
00066             )
00067         }
00068 
00069     def runSingle(self, s, lines):
00070         gotlines = [(d.s[d.lstart:d.lend], d.loc.line) for d in pymake.parser.enumeratelines(s, 'path')]
00071         self.assertEqual(gotlines, lines)
00072 
00073 multitest(LineEnumeratorTest)
00074 
00075 class IterTest(TestBase):
00076     testdata = {
00077         'plaindata': (
00078             pymake.parser.iterdata,
00079             "plaindata # test\n",
00080             "plaindata # test\n"
00081             ),
00082         'makecomment': (
00083             pymake.parser.itermakefilechars,
00084             "VAR = val # comment",
00085             "VAR = val "
00086             ),
00087         'makeescapedcomment': (
00088             pymake.parser.itermakefilechars,
00089             "VAR = val \# escaped hash",
00090             "VAR = val # escaped hash"
00091             ),
00092         'makeescapedslash': (
00093             pymake.parser.itermakefilechars,
00094             "VAR = val\\\\",
00095             "VAR = val\\\\",
00096             ),
00097         'makecontinuation': (
00098             pymake.parser.itermakefilechars,
00099             "VAR = VAL  \\\n  continuation # comment \\\n  continuation",
00100             "VAR = VAL continuation "
00101             ),
00102         'makecontinuation2': (
00103             pymake.parser.itermakefilechars,
00104             "VAR = VAL  \\  \\\n continuation",
00105             "VAR = VAL  \\ continuation"
00106             ),
00107         'makeawful': (
00108             pymake.parser.itermakefilechars,
00109             "VAR = VAL  \\\\# comment\n",
00110             "VAR = VAL  \\"
00111             ),
00112         'command': (
00113             pymake.parser.itercommandchars,
00114             "echo boo # comment",
00115             "echo boo # comment",
00116             ),
00117         'commandcomment': (
00118             pymake.parser.itercommandchars,
00119             "echo boo \# comment",
00120             "echo boo \# comment",
00121             ),
00122         'commandcontinue': (
00123             pymake.parser.itercommandchars,
00124             "echo boo # \\\n\t  command 2",
00125             "echo boo # \\\n  command 2"
00126             ),
00127     }
00128 
00129     def runSingle(self, ifunc, idata, expected):
00130         d = pymake.parser.Data.fromstring(idata, 'IterTest data')
00131 
00132         it = pymake.parser._alltokens.finditer(d.s, 0, d.lend)
00133         actual = ''.join( [c for c, t, o, oo in ifunc(d, 0, ('dummy-token',), it)] )
00134         self.assertEqual(actual, expected)
00135 
00136         if ifunc == pymake.parser.itermakefilechars:
00137             print "testing %r" % expected
00138             self.assertEqual(pymake.parser.flattenmakesyntax(d, 0), expected)
00139 
00140 multitest(IterTest)
00141 
00142 
00143 #         'define': (
00144 #             pymake.parser.iterdefinechars,
00145 #             "endef",
00146 #             ""
00147 #             ),
00148 #        'definenesting': (
00149 #            pymake.parser.iterdefinechars,
00150 #            """define BAR # comment
00151 #random text
00152 #endef not what you think!
00153 #endef # comment is ok\n""",
00154 #            """define BAR # comment
00155 #random text
00156 #endef not what you think!"""
00157 #            ),
00158 #        'defineescaped': (
00159 #            pymake.parser.iterdefinechars,
00160 #            """value   \\
00161 #endef
00162 #endef\n""",
00163 #            "value endef"
00164 #        ),
00165 
00166 class MakeSyntaxTest(TestBase):
00167     # (string, startat, stopat, stopoffset, expansion
00168     testdata = {
00169         'text': ('hello world', 0, (), None, ['hello world']),
00170         'singlechar': ('hello $W', 0, (), None,
00171                        ['hello ',
00172                         {'type': 'VariableRef',
00173                          '.vname': ['W']}
00174                         ]),
00175         'stopat': ('hello: world', 0, (':', '='), 6, ['hello']),
00176         'funccall': ('h $(flavor FOO)', 0, (), None,
00177                      ['h ',
00178                       {'type': 'FlavorFunction',
00179                        '[0]': ['FOO']}
00180                       ]),
00181         'escapedollar': ('hello$$world', 0, (), None, ['hello$world']),
00182         'varref': ('echo $(VAR)', 0, (), None,
00183                    ['echo ',
00184                     {'type': 'VariableRef',
00185                      '.vname': ['VAR']}
00186                     ]),
00187         'dynamicvarname': ('echo $($(VARNAME):.c=.o)', 0, (':',), None,
00188                            ['echo ',
00189                             {'type': 'SubstitutionRef',
00190                              '.vname': [{'type': 'VariableRef',
00191                                          '.vname': ['VARNAME']}
00192                                         ],
00193                              '.substfrom': ['.c'],
00194                              '.substto': ['.o']}
00195                             ]),
00196         'substref': ('  $(VAR:VAL) := $(VAL)', 0, (':=', '+=', '=', ':'), 15,
00197                      ['  ',
00198                       {'type': 'VariableRef',
00199                        '.vname': ['VAR:VAL']},
00200                       ' ']),
00201         'vadsubstref': ('  $(VAR:VAL) = $(VAL)', 15, (), None,
00202                         [{'type': 'VariableRef',
00203                           '.vname': ['VAL']},
00204                          ]),
00205         }
00206 
00207     def compareRecursive(self, actual, expected, path):
00208         self.assertEqual(len(actual), len(expected),
00209                          "compareRecursive: %s %r" % (path, actual))
00210         for i in xrange(0, len(actual)):
00211             ipath = path + [i]
00212 
00213             a, isfunc = actual[i]
00214             e = expected[i]
00215             if isinstance(e, str):
00216                 self.assertEqual(a, e, "compareRecursive: %s" % (ipath,))
00217             else:
00218                 self.assertEqual(type(a), getattr(pymake.functions, e['type']),
00219                                  "compareRecursive: %s" % (ipath,))
00220                 for k, v in e.iteritems():
00221                     if k == 'type':
00222                         pass
00223                     elif k[0] == '[':
00224                         item = int(k[1:-1])
00225                         proppath = ipath + [item]
00226                         self.compareRecursive(a[item], v, proppath)
00227                     elif k[0] == '.':
00228                         item = k[1:]
00229                         proppath = ipath + [item]
00230                         self.compareRecursive(getattr(a, item), v, proppath)
00231                     else:
00232                         raise Exception("Unexpected property at %s: %s" % (ipath, k))
00233 
00234     def runSingle(self, s, startat, stopat, stopoffset, expansion):
00235         d = pymake.parser.Data.fromstring(s, pymake.parserdata.Location('testdata', 1, 0))
00236 
00237         a, t, offset = pymake.parser.parsemakesyntax(d, startat, stopat, pymake.parser.itermakefilechars)
00238         self.compareRecursive(a, expansion, [])
00239         self.assertEqual(offset, stopoffset)
00240 
00241 multitest(MakeSyntaxTest)
00242 
00243 class VariableTest(TestBase):
00244     testdata = """
00245     VAR = value
00246     VARNAME = TESTVAR
00247     $(VARNAME) = testvalue
00248     $(VARNAME:VAR=VAL) = moretesting
00249     IMM := $(VARNAME) # this is a comment
00250     MULTIVAR = val1 \\
00251   val2
00252     VARNAME = newname
00253     """
00254     expected = {'VAR': 'value',
00255                 'VARNAME': 'newname',
00256                 'TESTVAR': 'testvalue',
00257                 'TESTVAL': 'moretesting',
00258                 'IMM': 'TESTVAR ',
00259                 'MULTIVAR': 'val1 val2',
00260                 'UNDEF': None}
00261 
00262     def runTest(self):
00263         stmts = pymake.parser.parsestring(self.testdata, 'VariableTest')
00264 
00265         m = pymake.data.Makefile()
00266         stmts.execute(m)
00267         for k, v in self.expected.iteritems():
00268             flavor, source, val = m.variables.get(k)
00269             if val is None:
00270                 self.assertEqual(val, v, 'variable named %s' % k)
00271             else:
00272                 self.assertEqual(val.resolvestr(m, m.variables), v, 'variable named %s' % k)
00273 
00274 class SimpleRuleTest(TestBase):
00275     testdata = """
00276     VAR = value
00277 TSPEC = dummy
00278 all: TSPEC = myrule
00279 all:: test test2 $(VAR)
00280        echo "Hello, $(TSPEC)"
00281 
00282 %.o: %.c
00283        $(CC) -o $@ $<
00284 """
00285 
00286     def runTest(self):
00287         stmts = pymake.parser.parsestring(self.testdata, 'SimpleRuleTest')
00288 
00289         m = pymake.data.Makefile()
00290         stmts.execute(m)
00291         self.assertEqual(m.defaulttarget, 'all', "Default target")
00292 
00293         self.assertTrue(m.hastarget('all'), "Has 'all' target")
00294         target = m.gettarget('all')
00295         rules = target.rules
00296         self.assertEqual(len(rules), 1, "Number of rules")
00297         prereqs = rules[0].prerequisites
00298         self.assertEqual(prereqs, ['test', 'test2', 'value'], "Prerequisites")
00299         commands = rules[0].commands
00300         self.assertEqual(len(commands), 1, "Number of commands")
00301         expanded = commands[0].resolvestr(m, target.variables)
00302         self.assertEqual(expanded, 'echo "Hello, myrule"')
00303 
00304         irules = m.implicitrules
00305         self.assertEqual(len(irules), 1, "Number of implicit rules")
00306 
00307         irule = irules[0]
00308         self.assertEqual(len(irule.targetpatterns), 1, "%.o target pattern count")
00309         self.assertEqual(len(irule.prerequisites), 1, "%.o prerequisite count")
00310         self.assertEqual(irule.targetpatterns[0].match('foo.o'), 'foo', "%.o stem")
00311 
00312 if __name__ == '__main__':
00313     logging.basicConfig(level=logging.DEBUG)
00314     unittest.main()