PageRenderTime 37ms CodeModel.GetById 10ms app.highlight 21ms RepoModel.GetById 2ms app.codeStats 0ms

/build/pymake/tests/parsertests.py

http://github.com/zpao/v8monkey
Python | 314 lines | 308 code | 6 blank | 0 comment | 2 complexity | 55fb45866bf25b66d93181841d6dddca MD5 | raw file
  1import pymake.data, pymake.parser, pymake.parserdata, pymake.functions
  2import unittest
  3import logging
  4
  5from cStringIO import StringIO
  6
  7def multitest(cls):
  8    for name in cls.testdata.iterkeys():
  9        def m(self, name=name):
 10            return self.runSingle(*self.testdata[name])
 11
 12        setattr(cls, 'test_%s' % name, m)
 13    return cls
 14
 15class 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))
 19
 20class 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    }
 29
 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)
 37multitest(DataTest)
 38
 39class 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        }
 68
 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)
 72
 73multitest(LineEnumeratorTest)
 74
 75class 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    }
128
129    def runSingle(self, ifunc, idata, expected):
130        d = pymake.parser.Data.fromstring(idata, 'IterTest data')
131
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)
135
136        if ifunc == pymake.parser.itermakefilechars:
137            print "testing %r" % expected
138            self.assertEqual(pymake.parser.flattenmakesyntax(d, 0), expected)
139
140multitest(IterTest)
141
142
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#        ),
165
166class 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        }
206
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]
212
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))
233
234    def runSingle(self, s, startat, stopat, stopoffset, expansion):
235        d = pymake.parser.Data.fromstring(s, pymake.parserdata.Location('testdata', 1, 0))
236
237        a, t, offset = pymake.parser.parsemakesyntax(d, startat, stopat, pymake.parser.itermakefilechars)
238        self.compareRecursive(a, expansion, [])
239        self.assertEqual(offset, stopoffset)
240
241multitest(MakeSyntaxTest)
242
243class 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}
261
262    def runTest(self):
263        stmts = pymake.parser.parsestring(self.testdata, 'VariableTest')
264
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)
273
274class SimpleRuleTest(TestBase):
275    testdata = """
276    VAR = value
277TSPEC = dummy
278all: TSPEC = myrule
279all:: test test2 $(VAR)
280	echo "Hello, $(TSPEC)"
281
282%.o: %.c
283	$(CC) -o $@ $<
284"""
285
286    def runTest(self):
287        stmts = pymake.parser.parsestring(self.testdata, 'SimpleRuleTest')
288
289        m = pymake.data.Makefile()
290        stmts.execute(m)
291        self.assertEqual(m.defaulttarget, 'all', "Default target")
292
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"')
303
304        irules = m.implicitrules
305        self.assertEqual(len(irules), 1, "Number of implicit rules")
306
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")
311
312if __name__ == '__main__':
313    logging.basicConfig(level=logging.DEBUG)
314    unittest.main()