1
import pymake.data, pymake.parser, pymake.parserdata, pymake.functions
5
from cStringIO import StringIO
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)
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):
23
("He\tllo", "f", 1, 0,
24
((0, "f", 1, 0), (2, "f", 1, 2), (3, "f", 1, 4))),
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))),
30
def runSingle(self, data, filename, line, col, results):
31
d = pymake.parser.Data(pymake.parserdata.Location(filename, line, col),
33
for pos, file, lineno, col in results:
35
self.assertEqual(loc.path, file, "data file offset %i" % pos)
36
self.assertEqual(loc.line, lineno, "data line offset %i" % pos)
37
self.assertEqual(loc.column, col, "data col offset %i" % pos)
40
class TokenTest(TestBase):
42
'wsmatch': (' ifdef FOO', 2, ('ifdef', 'else'), True, 'ifdef', 8),
43
'wsnomatch': (' unexpected FOO', 2, ('ifdef', 'else'), True, None, 2),
44
'wsnows': (' ifdefFOO', 2, ('ifdef', 'else'), True, None, 2),
45
'paren': (' "hello"', 1, ('(', "'", '"'), False, '"', 2),
48
def runSingle(self, s, start, tlist, needws, etoken, eoffset):
49
d = pymake.parser.Data.fromstring(s, None)
50
tl = pymake.parser.TokenList.get(tlist)
51
atoken, aoffset = d.findtoken(start, tl, needws)
52
self.assertEqual(atoken, etoken)
53
self.assertEqual(aoffset, eoffset)
56
class IterTest(TestBase):
59
pymake.parser.iterdata,
64
pymake.parser.itermakefilechars,
65
"VAR = val # comment",
68
'makeescapedcomment': (
69
pymake.parser.itermakefilechars,
70
"VAR = val \# escaped hash\n",
71
"VAR = val # escaped hash"
74
pymake.parser.itermakefilechars,
79
pymake.parser.itermakefilechars,
80
"VAR = VAL \\\n continuation # comment \\\n continuation",
81
"VAR = VAL continuation "
83
'makecontinuation2': (
84
pymake.parser.itermakefilechars,
85
"VAR = VAL \\ \\\n continuation",
86
"VAR = VAL \\ continuation"
89
pymake.parser.itermakefilechars,
90
"VAR = VAL \\\\# comment\n",
94
pymake.parser.itercommandchars,
95
"echo boo # comment\n",
99
pymake.parser.itercommandchars,
100
"echo boo \# comment\n",
101
"echo boo \# comment",
104
pymake.parser.itercommandchars,
105
"echo boo # \\\n\t command 2\n",
106
"echo boo # \\\n command 2"
109
pymake.parser.iterdefinechars,
114
pymake.parser.iterdefinechars,
115
"""define BAR # comment
117
endef not what you think!
118
endef # comment is ok\n""",
119
"""define BAR # comment
121
endef not what you think!"""
124
pymake.parser.iterdefinechars,
132
def runSingle(self, ifunc, idata, expected):
134
lineiter = enumerate(fd)
136
d = pymake.parser.DynamicData(lineiter, 'PlainIterTest-data')
138
actual = ''.join( (c for c, t, o, oo in ifunc(d, 0, pymake.parser._emptytokenlist)) )
139
self.assertEqual(actual, expected)
141
self.assertRaises(StopIteration, lambda: fd.next())
144
class MakeSyntaxTest(TestBase):
145
# (string, startat, stopat, stopoffset, expansion
147
'text': ('hello world', 0, (), None, ['hello world']),
148
'singlechar': ('hello $W', 0, (), None,
150
{'type': 'VariableRef',
153
'stopat': ('hello: world', 0, (':', '='), 6, ['hello']),
154
'funccall': ('h $(flavor FOO)', 0, (), None,
156
{'type': 'FlavorFunction',
159
'escapedollar': ('hello$$world', 0, (), None, ['hello$world']),
160
'varref': ('echo $(VAR)', 0, (), None,
162
{'type': 'VariableRef',
165
'dynamicvarname': ('echo $($(VARNAME):.c=.o)', 0, (':',), None,
167
{'type': 'SubstitutionRef',
168
'.vname': [{'type': 'VariableRef',
169
'.vname': ['VARNAME']}
171
'.substfrom': ['.c'],
174
'substref': (' $(VAR:VAL) := $(VAL)', 0, (':=', '+=', '=', ':'), 15,
176
{'type': 'VariableRef',
177
'.vname': ['VAR:VAL']},
179
'vadsubstref': (' $(VAR:VAL) = $(VAL)', 15, (), None,
180
[{'type': 'VariableRef',
185
def compareRecursive(self, actual, expected, path):
186
self.assertEqual(len(actual), len(expected),
187
"compareRecursive: %s" % (path,))
188
for i in xrange(0, len(actual)):
191
a, isfunc = actual[i]
193
if isinstance(e, str):
194
self.assertEqual(a, e, "compareRecursive: %s" % (ipath,))
196
self.assertEqual(type(a), getattr(pymake.functions, e['type']),
197
"compareRecursive: %s" % (ipath,))
198
for k, v in e.iteritems():
203
proppath = ipath + [item]
204
self.compareRecursive(a[item], v, proppath)
207
proppath = ipath + [item]
208
self.compareRecursive(getattr(a, item), v, proppath)
210
raise Exception("Unexpected property at %s: %s" % (ipath, k))
212
def runSingle(self, s, startat, stopat, stopoffset, expansion):
213
d = pymake.parser.Data.fromstring(s, pymake.parserdata.Location('testdata', 1, 0))
215
a, t, offset = pymake.parser.parsemakesyntax(d, startat, stopat, pymake.parser.itermakefilechars)
216
self.compareRecursive(a, expansion, [])
217
self.assertEqual(offset, stopoffset)
219
multitest(MakeSyntaxTest)
221
class VariableTest(TestBase):
225
$(VARNAME) = testvalue
226
$(VARNAME:VAR=VAL) = moretesting
227
IMM := $(VARNAME) # this is a comment
232
expected = {'VAR': 'value',
233
'VARNAME': 'newname',
234
'TESTVAR': 'testvalue',
235
'TESTVAL': 'moretesting',
237
'MULTIVAR': 'val1 val2',
241
stream = StringIO(self.testdata)
242
stmts = pymake.parser.parsestream(stream, 'testdata')
244
m = pymake.data.Makefile()
246
for k, v in self.expected.iteritems():
247
flavor, source, val = m.variables.get(k)
249
self.assertEqual(val, v, 'variable named %s' % k)
251
self.assertEqual(val.resolvestr(m, m.variables), v, 'variable named %s' % k)
253
class SimpleRuleTest(TestBase):
258
all:: test test2 $(VAR)
259
echo "Hello, $(TSPEC)"
266
stream = StringIO(self.testdata)
267
stmts = pymake.parser.parsestream(stream, 'testdata')
269
m = pymake.data.Makefile()
271
self.assertEqual(m.defaulttarget, 'all', "Default target")
273
self.assertTrue(m.hastarget('all'), "Has 'all' target")
274
target = m.gettarget('all')
276
self.assertEqual(len(rules), 1, "Number of rules")
277
prereqs = rules[0].prerequisites
278
self.assertEqual(prereqs, ['test', 'test2', 'value'], "Prerequisites")
279
commands = rules[0].commands
280
self.assertEqual(len(commands), 1, "Number of commands")
281
expanded = commands[0].resolvestr(m, target.variables)
282
self.assertEqual(expanded, 'echo "Hello, myrule"')
284
irules = m.implicitrules
285
self.assertEqual(len(irules), 1, "Number of implicit rules")
288
self.assertEqual(len(irule.targetpatterns), 1, "%.o target pattern count")
289
self.assertEqual(len(irule.prerequisites), 1, "%.o prerequisite count")
290
self.assertEqual(irule.targetpatterns[0].match('foo.o'), 'foo', "%.o stem")
292
if __name__ == '__main__':
293
logging.basicConfig(level=logging.DEBUG)