blob: 2d9c47fba0337eaf729d13344fc9d67a34a6d93d [file] [log] [blame]
Thomas Van Lentenca303392022-04-05 14:07:04 -04001#! /usr/bin/env python3
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002#
3# Protocol Buffers - Google's data interchange format
4# Copyright 2015 Google Inc. All rights reserved.
5# https://developers.google.com/protocol-buffers/
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are
9# met:
10#
11# * Redistributions of source code must retain the above copyright
12# notice, this list of conditions and the following disclaimer.
13# * Redistributions in binary form must reproduce the above
14# copyright notice, this list of conditions and the following disclaimer
15# in the documentation and/or other materials provided with the
16# distribution.
17# * Neither the name of Google Inc. nor the names of its
18# contributors may be used to endorse or promote products derived from
19# this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33"""Tests for pddm.py."""
34
35import io
36import unittest
37
38import pddm
39
40
41class TestParsingMacros(unittest.TestCase):
42
43 def testParseEmpty(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040044 f = io.StringIO('')
Thomas Van Lenten30650d82015-05-01 08:57:16 -040045 result = pddm.MacroCollection(f)
46 self.assertEqual(len(result._macros), 0)
47
48 def testParseOne(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040049 f = io.StringIO("""PDDM-DEFINE foo( )
Thomas Van Lenten30650d82015-05-01 08:57:16 -040050body""")
51 result = pddm.MacroCollection(f)
52 self.assertEqual(len(result._macros), 1)
53 macro = result._macros.get('foo')
54 self.assertIsNotNone(macro)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040055 self.assertEqual(macro.name, 'foo')
56 self.assertEqual(macro.args, tuple())
57 self.assertEqual(macro.body, 'body')
Thomas Van Lenten30650d82015-05-01 08:57:16 -040058
59 def testParseGeneral(self):
60 # Tests multiple defines, spaces in all places, etc.
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040061 f = io.StringIO("""
Thomas Van Lenten30650d82015-05-01 08:57:16 -040062PDDM-DEFINE noArgs( )
63body1
64body2
65
66PDDM-DEFINE-END
67
68PDDM-DEFINE oneArg(foo)
69body3
70PDDM-DEFINE twoArgs( bar_ , baz )
71body4
72body5""")
73 result = pddm.MacroCollection(f)
74 self.assertEqual(len(result._macros), 3)
75 macro = result._macros.get('noArgs')
76 self.assertIsNotNone(macro)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040077 self.assertEqual(macro.name, 'noArgs')
78 self.assertEqual(macro.args, tuple())
79 self.assertEqual(macro.body, 'body1\nbody2\n')
Thomas Van Lenten30650d82015-05-01 08:57:16 -040080 macro = result._macros.get('oneArg')
81 self.assertIsNotNone(macro)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040082 self.assertEqual(macro.name, 'oneArg')
83 self.assertEqual(macro.args, ('foo',))
84 self.assertEqual(macro.body, 'body3')
Thomas Van Lenten30650d82015-05-01 08:57:16 -040085 macro = result._macros.get('twoArgs')
86 self.assertIsNotNone(macro)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040087 self.assertEqual(macro.name, 'twoArgs')
88 self.assertEqual(macro.args, ('bar_', 'baz'))
89 self.assertEqual(macro.body, 'body4\nbody5')
Thomas Van Lenten30650d82015-05-01 08:57:16 -040090 # Add into existing collection
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040091 f = io.StringIO("""
Thomas Van Lenten30650d82015-05-01 08:57:16 -040092PDDM-DEFINE another(a,b,c)
93body1
94body2""")
95 result.ParseInput(f)
96 self.assertEqual(len(result._macros), 4)
97 macro = result._macros.get('another')
98 self.assertIsNotNone(macro)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -040099 self.assertEqual(macro.name, 'another')
100 self.assertEqual(macro.args, ('a', 'b', 'c'))
101 self.assertEqual(macro.body, 'body1\nbody2')
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400102
103 def testParseDirectiveIssues(self):
104 test_list = [
105 # Unknown directive
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400106 ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINED foo\nbaz',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400107 'Hit a line with an unknown directive: '),
108 # End without begin
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400109 ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nPDDM-DEFINE-END\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400110 'Got DEFINE-END directive without an active macro: '),
111 # Line not in macro block
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400112 ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nmumble\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400113 'Hit a line that wasn\'t a directive and no open macro definition: '),
114 # Redefine macro
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400115 ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINE foo(a)\nmumble\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400116 'Attempt to redefine macro: '),
117 ]
118 for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
119 f = io.StringIO(input_str)
120 try:
121 result = pddm.MacroCollection(f)
122 self.fail('Should throw exception, entry %d' % idx)
123 except pddm.PDDMError as e:
124 self.assertTrue(e.message.startswith(expected_prefix),
125 'Entry %d failed: %r' % (idx, e))
126
127 def testParseBeginIssues(self):
128 test_list = [
129 # 1. No name
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400130 ('PDDM-DEFINE\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400131 'Failed to parse macro definition: '),
132 # 2. No name (with spaces)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400133 ('PDDM-DEFINE \nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400134 'Failed to parse macro definition: '),
135 # 3. No open paren
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400136 ('PDDM-DEFINE foo\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400137 'Failed to parse macro definition: '),
138 # 4. No close paren
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400139 ('PDDM-DEFINE foo(\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400140 'Failed to parse macro definition: '),
141 # 5. No close paren (with args)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400142 ('PDDM-DEFINE foo(a, b\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400143 'Failed to parse macro definition: '),
144 # 6. No name before args
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400145 ('PDDM-DEFINE (a, b)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400146 'Failed to parse macro definition: '),
147 # 7. No name before args
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400148 ('PDDM-DEFINE foo bar(a, b)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400149 'Failed to parse macro definition: '),
150 # 8. Empty arg name
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400151 ('PDDM-DEFINE foo(a, ,b)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400152 'Empty arg name in macro definition: '),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400153 ('PDDM-DEFINE foo(a,,b)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400154 'Empty arg name in macro definition: '),
155 # 10. Duplicate name
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400156 ('PDDM-DEFINE foo(a,b,a,c)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400157 'Arg name "a" used more than once in macro definition: '),
158 # 11. Invalid arg name
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400159 ('PDDM-DEFINE foo(a b,c)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400160 'Invalid arg name "a b" in macro definition: '),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400161 ('PDDM-DEFINE foo(a.b,c)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400162 'Invalid arg name "a.b" in macro definition: '),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400163 ('PDDM-DEFINE foo(a-b,c)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400164 'Invalid arg name "a-b" in macro definition: '),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400165 ('PDDM-DEFINE foo(a,b,c.)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400166 'Invalid arg name "c." in macro definition: '),
167 # 15. Extra stuff after the name
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400168 ('PDDM-DEFINE foo(a,c) foo\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400169 'Failed to parse macro definition: '),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400170 ('PDDM-DEFINE foo(a,c) foo)\nmumble',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400171 'Failed to parse macro definition: '),
172 ]
173 for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
174 f = io.StringIO(input_str)
175 try:
176 result = pddm.MacroCollection(f)
177 self.fail('Should throw exception, entry %d' % idx)
178 except pddm.PDDMError as e:
179 self.assertTrue(e.message.startswith(expected_prefix),
180 'Entry %d failed: %r' % (idx, e))
181
182
183class TestExpandingMacros(unittest.TestCase):
184
185 def testExpandBasics(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400186 f = io.StringIO("""
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400187PDDM-DEFINE noArgs( )
188body1
189body2
190
191PDDM-DEFINE-END
192
193PDDM-DEFINE oneArg(a)
194body3 a
195
196PDDM-DEFINE-END
197
198PDDM-DEFINE twoArgs(b,c)
199body4 b c
200body5
201PDDM-DEFINE-END
202
203""")
204 mc = pddm.MacroCollection(f)
205 test_list = [
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400206 ('noArgs()',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400207 'body1\nbody2\n'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400208 ('oneArg(wee)',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400209 'body3 wee\n'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400210 ('twoArgs(having some, fun)',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400211 'body4 having some fun\nbody5'),
212 # One arg, pass empty.
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400213 ('oneArg()',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400214 'body3 \n'),
215 # Two args, gets empty in each slot.
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400216 ('twoArgs(, empty)',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400217 'body4 empty\nbody5'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400218 ('twoArgs(empty, )',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400219 'body4 empty \nbody5'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400220 ('twoArgs(, )',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400221 'body4 \nbody5'),
222 ]
223 for idx, (input_str, expected) in enumerate(test_list, 1):
224 result = mc.Expand(input_str)
225 self.assertEqual(result, expected,
226 'Entry %d --\n Result: %r\n Expected: %r' %
227 (idx, result, expected))
228
229 def testExpandArgOptions(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400230 f = io.StringIO("""
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400231PDDM-DEFINE bar(a)
232a-a$S-a$l-a$L-a$u-a$U
233PDDM-DEFINE-END
234""")
235 mc = pddm.MacroCollection(f)
236
237 self.assertEqual(mc.Expand('bar(xYz)'), 'xYz- -xYz-xyz-XYz-XYZ')
238 self.assertEqual(mc.Expand('bar(MnoP)'), 'MnoP- -mnoP-mnop-MnoP-MNOP')
239 # Test empty
240 self.assertEqual(mc.Expand('bar()'), '-----')
241
242 def testExpandSimpleMacroErrors(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400243 f = io.StringIO("""
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400244PDDM-DEFINE foo(a, b)
245<a-z>
246PDDM-DEFINE baz(a)
247a - a$z
248""")
249 mc = pddm.MacroCollection(f)
250 test_list = [
251 # 1. Unknown macro
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400252 ('bar()',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400253 'No macro named "bar".'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400254 ('bar(a)',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400255 'No macro named "bar".'),
256 # 3. Arg mismatch
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400257 ('foo()',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400258 'Expected 2 args, got: "foo()".'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400259 ('foo(a b)',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400260 'Expected 2 args, got: "foo(a b)".'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400261 ('foo(a,b,c)',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400262 'Expected 2 args, got: "foo(a,b,c)".'),
263 # 6. Unknown option in expansion
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400264 ('baz(mumble)',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400265 'Unknown arg option "a$z" while expanding "baz(mumble)".'),
266 ]
267 for idx, (input_str, expected_err) in enumerate(test_list, 1):
268 try:
269 result = mc.Expand(input_str)
270 self.fail('Should throw exception, entry %d' % idx)
271 except pddm.PDDMError as e:
272 self.assertEqual(e.message, expected_err,
273 'Entry %d failed: %r' % (idx, e))
274
275 def testExpandReferences(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400276 f = io.StringIO("""
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400277PDDM-DEFINE StartIt()
278foo(abc, def)
279foo(ghi, jkl)
280PDDM-DEFINE foo(a, b)
281bar(a, int)
282bar(b, NSString *)
283PDDM-DEFINE bar(n, t)
284- (t)n;
285- (void)set##n$u##:(t)value;
286
287""")
288 mc = pddm.MacroCollection(f)
289 expected = """- (int)abc;
290- (void)setAbc:(int)value;
291
292- (NSString *)def;
293- (void)setDef:(NSString *)value;
294
295- (int)ghi;
296- (void)setGhi:(int)value;
297
298- (NSString *)jkl;
299- (void)setJkl:(NSString *)value;
300"""
301 self.assertEqual(mc.Expand('StartIt()'), expected)
302
303 def testCatchRecursion(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400304 f = io.StringIO("""
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400305PDDM-DEFINE foo(a, b)
306bar(1, a)
307bar(2, b)
308PDDM-DEFINE bar(x, y)
309foo(x, y)
310""")
311 mc = pddm.MacroCollection(f)
312 try:
313 result = mc.Expand('foo(A,B)')
kvukic8529f2a2017-12-27 21:27:47 +0100314 self.fail('Should throw exception! Test failed to catch recursion.')
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400315 except pddm.PDDMError as e:
316 self.assertEqual(e.message,
Brian Wignalla104dff2020-01-08 13:18:20 -0500317 'Found macro recursion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".')
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400318
319
320class TestParsingSource(unittest.TestCase):
321
322 def testBasicParse(self):
323 test_list = [
324 # 1. no directives
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400325 ('a\nb\nc',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400326 (3,) ),
327 # 2. One define
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400328 ('a\n//%PDDM-DEFINE foo()\n//%body\nc',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400329 (1, 2, 1) ),
330 # 3. Two defines
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400331 ('a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE bar()\n//%body2\nc',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400332 (1, 4, 1) ),
333 # 4. Two defines with ends
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400334 ('a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE-END\n'
335 '//%PDDM-DEFINE bar()\n//%body2\n//%PDDM-DEFINE-END\nc',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400336 (1, 6, 1) ),
337 # 5. One expand, one define (that runs to end of file)
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400338 ('a\n//%PDDM-EXPAND foo()\nbody\n//%PDDM-EXPAND-END\n'
339 '//%PDDM-DEFINE bar()\n//%body2\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400340 (1, 1, 2) ),
341 # 6. One define ended with an expand.
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400342 ('a\nb\n//%PDDM-DEFINE bar()\n//%body2\n'
343 '//%PDDM-EXPAND bar()\nbody2\n//%PDDM-EXPAND-END\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400344 (2, 2, 1) ),
345 # 7. Two expands (one end), one define.
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400346 ('a\n//%PDDM-EXPAND foo(1)\nbody\n//%PDDM-EXPAND foo(2)\nbody2\n//%PDDM-EXPAND-END\n'
347 '//%PDDM-DEFINE foo()\n//%body2\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400348 (1, 2, 2) ),
349 ]
350 for idx, (input_str, line_counts) in enumerate(test_list, 1):
351 f = io.StringIO(input_str)
352 sf = pddm.SourceFile(f)
353 sf._ParseFile()
354 self.assertEqual(len(sf._sections), len(line_counts),
355 'Entry %d -- %d != %d' %
356 (idx, len(sf._sections), len(line_counts)))
357 for idx2, (sec, expected) in enumerate(zip(sf._sections, line_counts), 1):
358 self.assertEqual(sec.num_lines_captured, expected,
359 'Entry %d, section %d -- %d != %d' %
360 (idx, idx2, sec.num_lines_captured, expected))
361
362 def testErrors(self):
363 test_list = [
364 # 1. Directive within expansion
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400365 ('//%PDDM-EXPAND a()\n//%PDDM-BOGUS',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400366 'Ran into directive ("//%PDDM-BOGUS", line 2) while in "//%PDDM-EXPAND a()".'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400367 ('//%PDDM-EXPAND a()\n//%PDDM-DEFINE a()\n//%body\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400368 'Ran into directive ("//%PDDM-DEFINE", line 2) while in "//%PDDM-EXPAND a()".'),
369 # 3. Expansion ran off end of file
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400370 ('//%PDDM-EXPAND a()\na\nb\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400371 'Hit the end of the file while in "//%PDDM-EXPAND a()".'),
372 # 4. Directive within define
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400373 ('//%PDDM-DEFINE a()\n//%body\n//%PDDM-BOGUS',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400374 'Ran into directive ("//%PDDM-BOGUS", line 3) while in "//%PDDM-DEFINE a()".'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400375 ('//%PDDM-DEFINE a()\n//%body\n//%PDDM-EXPAND-END a()',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400376 'Ran into directive ("//%PDDM-EXPAND-END", line 3) while in "//%PDDM-DEFINE a()".'),
377 # 6. Directives that shouldn't start sections
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400378 ('a\n//%PDDM-DEFINE-END a()\n//a\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400379 'Unexpected line 2: "//%PDDM-DEFINE-END a()".'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400380 ('a\n//%PDDM-EXPAND-END a()\n//a\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400381 'Unexpected line 2: "//%PDDM-EXPAND-END a()".'),
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400382 ('//%PDDM-BOGUS\n//a\n',
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400383 'Unexpected line 1: "//%PDDM-BOGUS".'),
384 ]
385 for idx, (input_str, expected_err) in enumerate(test_list, 1):
386 f = io.StringIO(input_str)
387 try:
388 pddm.SourceFile(f)._ParseFile()
389 self.fail('Should throw exception, entry %d' % idx)
390 except pddm.PDDMError as e:
391 self.assertEqual(e.message, expected_err,
392 'Entry %d failed: %r' % (idx, e))
393
394class TestProcessingSource(unittest.TestCase):
395
396 def testBasics(self):
Dave MacLachlanab48ecf2020-01-20 13:47:20 -0800397 self.maxDiff = None
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400398 input_str = """
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400399//%PDDM-IMPORT-DEFINES ImportFile
400foo
401//%PDDM-EXPAND mumble(abc)
402//%PDDM-EXPAND-END
403bar
404//%PDDM-EXPAND mumble(def)
405//%PDDM-EXPAND mumble(ghi)
406//%PDDM-EXPAND-END
407baz
408//%PDDM-DEFINE mumble(a_)
409//%a_: getName(a_)
410"""
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400411 input_str2 = """
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400412//%PDDM-DEFINE getName(x_)
413//%do##x_$u##(int x_);
414
415"""
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400416 expected = """
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400417//%PDDM-IMPORT-DEFINES ImportFile
418foo
419//%PDDM-EXPAND mumble(abc)
420// This block of code is generated, do not edit it directly.
421
422abc: doAbc(int abc);
423//%PDDM-EXPAND-END mumble(abc)
424bar
425//%PDDM-EXPAND mumble(def)
426// This block of code is generated, do not edit it directly.
427
428def: doDef(int def);
429//%PDDM-EXPAND mumble(ghi)
430// This block of code is generated, do not edit it directly.
431
432ghi: doGhi(int ghi);
433//%PDDM-EXPAND-END (2 expansions)
434baz
435//%PDDM-DEFINE mumble(a_)
436//%a_: getName(a_)
437"""
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400438 expected_stripped = """
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400439//%PDDM-IMPORT-DEFINES ImportFile
440foo
441//%PDDM-EXPAND mumble(abc)
442//%PDDM-EXPAND-END mumble(abc)
443bar
444//%PDDM-EXPAND mumble(def)
445//%PDDM-EXPAND mumble(ghi)
446//%PDDM-EXPAND-END (2 expansions)
447baz
448//%PDDM-DEFINE mumble(a_)
449//%a_: getName(a_)
450"""
451 def _Resolver(name):
452 self.assertEqual(name, 'ImportFile')
453 return io.StringIO(input_str2)
454 f = io.StringIO(input_str)
455 sf = pddm.SourceFile(f, _Resolver)
456 sf.ProcessContent()
457 self.assertEqual(sf.processed_content, expected)
458 # Feed it through and nothing should change.
459 f2 = io.StringIO(sf.processed_content)
460 sf2 = pddm.SourceFile(f2, _Resolver)
461 sf2.ProcessContent()
462 self.assertEqual(sf2.processed_content, expected)
463 self.assertEqual(sf2.processed_content, sf.processed_content)
464 # Test stripping (with the original input and expanded version).
465 f2 = io.StringIO(input_str)
466 sf2 = pddm.SourceFile(f2)
467 sf2.ProcessContent(strip_expansion=True)
468 self.assertEqual(sf2.processed_content, expected_stripped)
469 f2 = io.StringIO(sf.processed_content)
470 sf2 = pddm.SourceFile(f2, _Resolver)
471 sf2.ProcessContent(strip_expansion=True)
472 self.assertEqual(sf2.processed_content, expected_stripped)
473
474 def testProcessFileWithMacroParseError(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400475 input_str = """
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400476foo
477//%PDDM-DEFINE mumble(a_)
478//%body
479//%PDDM-DEFINE mumble(x_)
480//%body2
481
482"""
483 f = io.StringIO(input_str)
484 sf = pddm.SourceFile(f)
485 try:
486 sf.ProcessContent()
kvukic8529f2a2017-12-27 21:27:47 +0100487 self.fail('Should throw exception! Test failed to catch macro parsing error.')
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400488 except pddm.PDDMError as e:
489 self.assertEqual(e.message,
490 'Attempt to redefine macro: "PDDM-DEFINE mumble(x_)"\n'
491 '...while parsing section that started:\n'
492 ' Line 3: //%PDDM-DEFINE mumble(a_)')
493
494 def testProcessFileWithExpandError(self):
Thomas Van Lenten1e60bd62022-04-05 10:36:07 -0400495 input_str = """
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400496foo
497//%PDDM-DEFINE mumble(a_)
498//%body
499//%PDDM-EXPAND foobar(x_)
500//%PDDM-EXPAND-END
501
502"""
503 f = io.StringIO(input_str)
504 sf = pddm.SourceFile(f)
505 try:
506 sf.ProcessContent()
kvukic8529f2a2017-12-27 21:27:47 +0100507 self.fail('Should throw exception! Test failed to catch expand error.')
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400508 except pddm.PDDMError as e:
509 self.assertEqual(e.message,
510 'No macro named "foobar".\n'
511 '...while expanding "foobar(x_)" from the section that'
512 ' started:\n Line 5: //%PDDM-EXPAND foobar(x_)')
513
514
515if __name__ == '__main__':
516 unittest.main()