build/pymake/tests/parsertests.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial