Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
1 # This file contains test code for the formatting of parsed statements back to
2 # make file "source." It essentially verifies to to_source() functions
3 # scattered across the tree.
5 import glob
6 import logging
7 import os.path
8 import unittest
10 from pymake.data import Expansion
11 from pymake.data import StringExpansion
12 from pymake.functions import BasenameFunction
13 from pymake.functions import SubstitutionRef
14 from pymake.functions import VariableRef
15 from pymake.functions import WordlistFunction
16 from pymake.parserdata import Include
17 from pymake.parserdata import SetVariable
18 from pymake.parser import parsestring
19 from pymake.parser import SyntaxError
21 class TestBase(unittest.TestCase):
22 pass
24 class VariableRefTest(TestBase):
25 def test_string_name(self):
26 e = StringExpansion('foo', None)
27 v = VariableRef(None, e)
29 self.assertEqual(v.to_source(), '$(foo)')
31 def test_special_variable(self):
32 e = StringExpansion('<', None)
33 v = VariableRef(None, e)
35 self.assertEqual(v.to_source(), '$<')
37 def test_expansion_simple(self):
38 e = Expansion()
39 e.appendstr('foo')
40 e.appendstr('bar')
42 v = VariableRef(None, e)
44 self.assertEqual(v.to_source(), '$(foobar)')
46 class StandardFunctionTest(TestBase):
47 def test_basename(self):
48 e1 = StringExpansion('foo', None)
49 v = VariableRef(None, e1)
50 e2 = Expansion(None)
51 e2.appendfunc(v)
53 b = BasenameFunction(None)
54 b.append(e2)
56 self.assertEqual(b.to_source(), '$(basename $(foo))')
58 def test_wordlist(self):
59 e1 = StringExpansion('foo', None)
60 e2 = StringExpansion('bar ', None)
61 e3 = StringExpansion(' baz', None)
63 w = WordlistFunction(None)
64 w.append(e1)
65 w.append(e2)
66 w.append(e3)
68 self.assertEqual(w.to_source(), '$(wordlist foo,bar , baz)')
70 def test_curly_brackets(self):
71 e1 = Expansion(None)
72 e1.appendstr('foo')
74 e2 = Expansion(None)
75 e2.appendstr('foo ( bar')
77 f = WordlistFunction(None)
78 f.append(e1)
79 f.append(e2)
81 self.assertEqual(f.to_source(), '${wordlist foo,foo ( bar}')
83 class StringExpansionTest(TestBase):
84 def test_simple(self):
85 e = StringExpansion('foobar', None)
86 self.assertEqual(e.to_source(), 'foobar')
88 e = StringExpansion('$var', None)
89 self.assertEqual(e.to_source(), '$var')
91 def test_escaping(self):
92 e = StringExpansion('$var', None)
93 self.assertEqual(e.to_source(escape_variables=True), '$$var')
95 e = StringExpansion('this is # not a comment', None)
96 self.assertEqual(e.to_source(escape_comments=True),
97 'this is \# not a comment')
99 def test_empty(self):
100 e = StringExpansion('', None)
101 self.assertEqual(e.to_source(), '')
103 e = StringExpansion(' ', None)
104 self.assertEqual(e.to_source(), ' ')
106 class ExpansionTest(TestBase):
107 def test_single_string(self):
108 e = Expansion()
109 e.appendstr('foo')
111 self.assertEqual(e.to_source(), 'foo')
113 def test_multiple_strings(self):
114 e = Expansion()
115 e.appendstr('hello')
116 e.appendstr('world')
118 self.assertEqual(e.to_source(), 'helloworld')
120 def test_string_escape(self):
121 e = Expansion()
122 e.appendstr('$var')
123 self.assertEqual(e.to_source(), '$var')
124 self.assertEqual(e.to_source(escape_variables=True), '$$var')
126 e = Expansion()
127 e.appendstr('foo')
128 e.appendstr(' $bar')
129 self.assertEqual(e.to_source(escape_variables=True), 'foo $$bar')
131 class SubstitutionRefTest(TestBase):
132 def test_simple(self):
133 name = StringExpansion('foo', None)
134 c = StringExpansion('%.c', None)
135 o = StringExpansion('%.o', None)
136 s = SubstitutionRef(None, name, c, o)
138 self.assertEqual(s.to_source(), '$(foo:%.c=%.o)')
140 class SetVariableTest(TestBase):
141 def test_simple(self):
142 v = SetVariable(StringExpansion('foo', None), '=', 'bar', None, None)
143 self.assertEqual(v.to_source(), 'foo = bar')
145 def test_multiline(self):
146 s = 'hello\nworld'
147 foo = StringExpansion('FOO', None)
149 v = SetVariable(foo, '=', s, None, None)
151 self.assertEqual(v.to_source(), 'define FOO\nhello\nworld\nendef')
153 def test_multiline_immediate(self):
154 source = 'define FOO :=\nhello\nworld\nendef'
156 statements = parsestring(source, 'foo.mk')
157 self.assertEqual(statements.to_source(), source)
159 def test_target_specific(self):
160 foo = StringExpansion('FOO', None)
161 bar = StringExpansion('BAR', None)
163 v = SetVariable(foo, '+=', 'value', None, bar)
165 self.assertEqual(v.to_source(), 'BAR: FOO += value')
167 class IncludeTest(TestBase):
168 def test_include(self):
169 e = StringExpansion('rules.mk', None)
170 i = Include(e, True, False)
171 self.assertEqual(i.to_source(), 'include rules.mk')
173 i = Include(e, False, False)
174 self.assertEqual(i.to_source(), '-include rules.mk')
176 class IfdefTest(TestBase):
177 def test_simple(self):
178 source = 'ifdef FOO\nbar := $(value)\nendif'
180 statements = parsestring(source, 'foo.mk')
181 self.assertEqual(statements[0].to_source(), source)
183 def test_nested(self):
184 source = 'ifdef FOO\nifdef BAR\nhello = world\nendif\nendif'
186 statements = parsestring(source, 'foo.mk')
187 self.assertEqual(statements[0].to_source(), source)
189 def test_negation(self):
190 source = 'ifndef FOO\nbar += value\nendif'
192 statements = parsestring(source, 'foo.mk')
193 self.assertEqual(statements[0].to_source(), source)
195 class IfeqTest(TestBase):
196 def test_simple(self):
197 source = 'ifeq ($(foo),bar)\nhello = $(world)\nendif'
199 statements = parsestring(source, 'foo.mk')
200 self.assertEqual(statements[0].to_source(), source)
202 def test_negation(self):
203 source = 'ifneq (foo,bar)\nhello = world\nendif'
205 statements = parsestring(source, 'foo.mk')
206 self.assertEqual(statements.to_source(), source)
208 class ConditionBlocksTest(TestBase):
209 def test_mixed_conditions(self):
210 source = 'ifdef FOO\nifeq ($(FOO),bar)\nvar += $(value)\nendif\nendif'
212 statements = parsestring(source, 'foo.mk')
213 self.assertEqual(statements.to_source(), source)
215 def test_extra_statements(self):
216 source = 'ifdef FOO\nF := 1\nifdef BAR\nB += 1\nendif\nC = 1\nendif'
218 statements = parsestring(source, 'foo.mk')
219 self.assertEqual(statements.to_source(), source)
221 def test_whitespace_preservation(self):
222 source = "ifeq ' x' 'x '\n$(error stripping)\nendif"
224 statements = parsestring(source, 'foo.mk')
225 self.assertEqual(statements.to_source(), source)
227 source = 'ifneq (x , x)\n$(error stripping)\nendif'
228 statements = parsestring(source, 'foo.mk')
229 self.assertEqual(statements.to_source(),
230 'ifneq (x,x)\n$(error stripping)\nendif')
232 class MakefileCorupusTest(TestBase):
233 """Runs the make files from the pymake corpus through the formatter.
235 All the above tests are child's play compared to this.
236 """
238 # Our reformatting isn't perfect. We ignore files with known failures until
239 # we make them work.
240 # TODO Address these formatting corner cases.
241 _IGNORE_FILES = [
242 # We are thrown off by backslashes at end of lines.
243 'comment-parsing.mk',
244 'escape-chars.mk',
245 'include-notfound.mk',
246 ]
248 def _get_test_files(self):
249 ourdir = os.path.dirname(os.path.abspath(__file__))
251 for makefile in glob.glob(os.path.join(ourdir, '*.mk')):
252 if os.path.basename(makefile) in self._IGNORE_FILES:
253 continue
255 source = None
256 with open(makefile, 'rU') as fh:
257 source = fh.read()
259 try:
260 yield (makefile, source, parsestring(source, makefile))
261 except SyntaxError:
262 continue
264 def test_reparse_consistency(self):
265 for filename, source, statements in self._get_test_files():
266 reformatted = statements.to_source()
268 # We should be able to parse the reformatted source fine.
269 new_statements = parsestring(reformatted, filename)
271 # If we do the formatting again, the representation shouldn't
272 # change. i.e. the only lossy change should be the original
273 # (whitespace and some semantics aren't preserved).
274 reformatted_again = new_statements.to_source()
275 self.assertEqual(reformatted, reformatted_again,
276 '%s has lossless reformat.' % filename)
278 self.assertEqual(len(statements), len(new_statements))
280 for i in xrange(0, len(statements)):
281 original = statements[i]
282 formatted = new_statements[i]
284 self.assertEqual(original, formatted, '%s %d: %s != %s' % (filename,
285 i, original, formatted))
287 if __name__ == '__main__':
288 logging.basicConfig(level=logging.DEBUG)
289 unittest.main()