1ffe3c632Sopenharmony_ci#! /usr/bin/python
2ffe3c632Sopenharmony_ci#
3ffe3c632Sopenharmony_ci# Protocol Buffers - Google's data interchange format
4ffe3c632Sopenharmony_ci# Copyright 2015 Google Inc.  All rights reserved.
5ffe3c632Sopenharmony_ci# https://developers.google.com/protocol-buffers/
6ffe3c632Sopenharmony_ci#
7ffe3c632Sopenharmony_ci# Redistribution and use in source and binary forms, with or without
8ffe3c632Sopenharmony_ci# modification, are permitted provided that the following conditions are
9ffe3c632Sopenharmony_ci# met:
10ffe3c632Sopenharmony_ci#
11ffe3c632Sopenharmony_ci#     * Redistributions of source code must retain the above copyright
12ffe3c632Sopenharmony_ci# notice, this list of conditions and the following disclaimer.
13ffe3c632Sopenharmony_ci#     * Redistributions in binary form must reproduce the above
14ffe3c632Sopenharmony_ci# copyright notice, this list of conditions and the following disclaimer
15ffe3c632Sopenharmony_ci# in the documentation and/or other materials provided with the
16ffe3c632Sopenharmony_ci# distribution.
17ffe3c632Sopenharmony_ci#     * Neither the name of Google Inc. nor the names of its
18ffe3c632Sopenharmony_ci# contributors may be used to endorse or promote products derived from
19ffe3c632Sopenharmony_ci# this software without specific prior written permission.
20ffe3c632Sopenharmony_ci#
21ffe3c632Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22ffe3c632Sopenharmony_ci# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23ffe3c632Sopenharmony_ci# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24ffe3c632Sopenharmony_ci# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25ffe3c632Sopenharmony_ci# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26ffe3c632Sopenharmony_ci# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27ffe3c632Sopenharmony_ci# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28ffe3c632Sopenharmony_ci# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29ffe3c632Sopenharmony_ci# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30ffe3c632Sopenharmony_ci# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31ffe3c632Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32ffe3c632Sopenharmony_ci
33ffe3c632Sopenharmony_ci"""Tests for pddm.py."""
34ffe3c632Sopenharmony_ci
35ffe3c632Sopenharmony_ciimport io
36ffe3c632Sopenharmony_ciimport unittest
37ffe3c632Sopenharmony_ci
38ffe3c632Sopenharmony_ciimport pddm
39ffe3c632Sopenharmony_ci
40ffe3c632Sopenharmony_ci
41ffe3c632Sopenharmony_ciclass TestParsingMacros(unittest.TestCase):
42ffe3c632Sopenharmony_ci
43ffe3c632Sopenharmony_ci  def testParseEmpty(self):
44ffe3c632Sopenharmony_ci    f = io.StringIO(u'')
45ffe3c632Sopenharmony_ci    result = pddm.MacroCollection(f)
46ffe3c632Sopenharmony_ci    self.assertEqual(len(result._macros), 0)
47ffe3c632Sopenharmony_ci
48ffe3c632Sopenharmony_ci  def testParseOne(self):
49ffe3c632Sopenharmony_ci    f = io.StringIO(u"""PDDM-DEFINE foo( )
50ffe3c632Sopenharmony_cibody""")
51ffe3c632Sopenharmony_ci    result = pddm.MacroCollection(f)
52ffe3c632Sopenharmony_ci    self.assertEqual(len(result._macros), 1)
53ffe3c632Sopenharmony_ci    macro = result._macros.get('foo')
54ffe3c632Sopenharmony_ci    self.assertIsNotNone(macro)
55ffe3c632Sopenharmony_ci    self.assertEquals(macro.name, 'foo')
56ffe3c632Sopenharmony_ci    self.assertEquals(macro.args, tuple())
57ffe3c632Sopenharmony_ci    self.assertEquals(macro.body, 'body')
58ffe3c632Sopenharmony_ci
59ffe3c632Sopenharmony_ci  def testParseGeneral(self):
60ffe3c632Sopenharmony_ci    # Tests multiple defines, spaces in all places, etc.
61ffe3c632Sopenharmony_ci    f = io.StringIO(u"""
62ffe3c632Sopenharmony_ciPDDM-DEFINE noArgs( )
63ffe3c632Sopenharmony_cibody1
64ffe3c632Sopenharmony_cibody2
65ffe3c632Sopenharmony_ci
66ffe3c632Sopenharmony_ciPDDM-DEFINE-END
67ffe3c632Sopenharmony_ci
68ffe3c632Sopenharmony_ciPDDM-DEFINE oneArg(foo)
69ffe3c632Sopenharmony_cibody3
70ffe3c632Sopenharmony_ciPDDM-DEFINE  twoArgs( bar_ , baz )
71ffe3c632Sopenharmony_cibody4
72ffe3c632Sopenharmony_cibody5""")
73ffe3c632Sopenharmony_ci    result = pddm.MacroCollection(f)
74ffe3c632Sopenharmony_ci    self.assertEqual(len(result._macros), 3)
75ffe3c632Sopenharmony_ci    macro = result._macros.get('noArgs')
76ffe3c632Sopenharmony_ci    self.assertIsNotNone(macro)
77ffe3c632Sopenharmony_ci    self.assertEquals(macro.name, 'noArgs')
78ffe3c632Sopenharmony_ci    self.assertEquals(macro.args, tuple())
79ffe3c632Sopenharmony_ci    self.assertEquals(macro.body, 'body1\nbody2\n')
80ffe3c632Sopenharmony_ci    macro = result._macros.get('oneArg')
81ffe3c632Sopenharmony_ci    self.assertIsNotNone(macro)
82ffe3c632Sopenharmony_ci    self.assertEquals(macro.name, 'oneArg')
83ffe3c632Sopenharmony_ci    self.assertEquals(macro.args, ('foo',))
84ffe3c632Sopenharmony_ci    self.assertEquals(macro.body, 'body3')
85ffe3c632Sopenharmony_ci    macro = result._macros.get('twoArgs')
86ffe3c632Sopenharmony_ci    self.assertIsNotNone(macro)
87ffe3c632Sopenharmony_ci    self.assertEquals(macro.name, 'twoArgs')
88ffe3c632Sopenharmony_ci    self.assertEquals(macro.args, ('bar_', 'baz'))
89ffe3c632Sopenharmony_ci    self.assertEquals(macro.body, 'body4\nbody5')
90ffe3c632Sopenharmony_ci    # Add into existing collection
91ffe3c632Sopenharmony_ci    f = io.StringIO(u"""
92ffe3c632Sopenharmony_ciPDDM-DEFINE another(a,b,c)
93ffe3c632Sopenharmony_cibody1
94ffe3c632Sopenharmony_cibody2""")
95ffe3c632Sopenharmony_ci    result.ParseInput(f)
96ffe3c632Sopenharmony_ci    self.assertEqual(len(result._macros), 4)
97ffe3c632Sopenharmony_ci    macro = result._macros.get('another')
98ffe3c632Sopenharmony_ci    self.assertIsNotNone(macro)
99ffe3c632Sopenharmony_ci    self.assertEquals(macro.name, 'another')
100ffe3c632Sopenharmony_ci    self.assertEquals(macro.args, ('a', 'b', 'c'))
101ffe3c632Sopenharmony_ci    self.assertEquals(macro.body, 'body1\nbody2')
102ffe3c632Sopenharmony_ci
103ffe3c632Sopenharmony_ci  def testParseDirectiveIssues(self):
104ffe3c632Sopenharmony_ci    test_list = [
105ffe3c632Sopenharmony_ci      # Unknown directive
106ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINED foo\nbaz',
107ffe3c632Sopenharmony_ci       'Hit a line with an unknown directive: '),
108ffe3c632Sopenharmony_ci      # End without begin
109ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nPDDM-DEFINE-END\n',
110ffe3c632Sopenharmony_ci       'Got DEFINE-END directive without an active macro: '),
111ffe3c632Sopenharmony_ci      # Line not in macro block
112ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nmumble\n',
113ffe3c632Sopenharmony_ci       'Hit a line that wasn\'t a directive and no open macro definition: '),
114ffe3c632Sopenharmony_ci      # Redefine macro
115ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE foo(a)\nmumble\n',
116ffe3c632Sopenharmony_ci       'Attempt to redefine macro: '),
117ffe3c632Sopenharmony_ci    ]
118ffe3c632Sopenharmony_ci    for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
119ffe3c632Sopenharmony_ci      f = io.StringIO(input_str)
120ffe3c632Sopenharmony_ci      try:
121ffe3c632Sopenharmony_ci        result = pddm.MacroCollection(f)
122ffe3c632Sopenharmony_ci        self.fail('Should throw exception, entry %d' % idx)
123ffe3c632Sopenharmony_ci      except pddm.PDDMError as e:
124ffe3c632Sopenharmony_ci        self.assertTrue(e.message.startswith(expected_prefix),
125ffe3c632Sopenharmony_ci                        'Entry %d failed: %r' % (idx, e))
126ffe3c632Sopenharmony_ci
127ffe3c632Sopenharmony_ci  def testParseBeginIssues(self):
128ffe3c632Sopenharmony_ci    test_list = [
129ffe3c632Sopenharmony_ci      # 1. No name
130ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE\nmumble',
131ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
132ffe3c632Sopenharmony_ci      # 2. No name (with spaces)
133ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE  \nmumble',
134ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
135ffe3c632Sopenharmony_ci      # 3. No open paren
136ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE  foo\nmumble',
137ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
138ffe3c632Sopenharmony_ci      # 4. No close paren
139ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(\nmumble',
140ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
141ffe3c632Sopenharmony_ci      # 5. No close paren (with args)
142ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a, b\nmumble',
143ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
144ffe3c632Sopenharmony_ci      # 6. No name before args
145ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE  (a, b)\nmumble',
146ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
147ffe3c632Sopenharmony_ci      # 7. No name before args
148ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo bar(a, b)\nmumble',
149ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
150ffe3c632Sopenharmony_ci      # 8. Empty arg name
151ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a, ,b)\nmumble',
152ffe3c632Sopenharmony_ci       'Empty arg name in macro definition: '),
153ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a,,b)\nmumble',
154ffe3c632Sopenharmony_ci       'Empty arg name in macro definition: '),
155ffe3c632Sopenharmony_ci      # 10. Duplicate name
156ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a,b,a,c)\nmumble',
157ffe3c632Sopenharmony_ci       'Arg name "a" used more than once in macro definition: '),
158ffe3c632Sopenharmony_ci      # 11. Invalid arg name
159ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a b,c)\nmumble',
160ffe3c632Sopenharmony_ci       'Invalid arg name "a b" in macro definition: '),
161ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a.b,c)\nmumble',
162ffe3c632Sopenharmony_ci       'Invalid arg name "a.b" in macro definition: '),
163ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a-b,c)\nmumble',
164ffe3c632Sopenharmony_ci       'Invalid arg name "a-b" in macro definition: '),
165ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a,b,c.)\nmumble',
166ffe3c632Sopenharmony_ci       'Invalid arg name "c." in macro definition: '),
167ffe3c632Sopenharmony_ci      # 15. Extra stuff after the name
168ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a,c) foo\nmumble',
169ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
170ffe3c632Sopenharmony_ci      (u'PDDM-DEFINE foo(a,c) foo)\nmumble',
171ffe3c632Sopenharmony_ci       'Failed to parse macro definition: '),
172ffe3c632Sopenharmony_ci    ]
173ffe3c632Sopenharmony_ci    for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
174ffe3c632Sopenharmony_ci      f = io.StringIO(input_str)
175ffe3c632Sopenharmony_ci      try:
176ffe3c632Sopenharmony_ci        result = pddm.MacroCollection(f)
177ffe3c632Sopenharmony_ci        self.fail('Should throw exception, entry %d' % idx)
178ffe3c632Sopenharmony_ci      except pddm.PDDMError as e:
179ffe3c632Sopenharmony_ci        self.assertTrue(e.message.startswith(expected_prefix),
180ffe3c632Sopenharmony_ci                        'Entry %d failed: %r' % (idx, e))
181ffe3c632Sopenharmony_ci
182ffe3c632Sopenharmony_ci
183ffe3c632Sopenharmony_ciclass TestExpandingMacros(unittest.TestCase):
184ffe3c632Sopenharmony_ci
185ffe3c632Sopenharmony_ci  def testExpandBasics(self):
186ffe3c632Sopenharmony_ci    f = io.StringIO(u"""
187ffe3c632Sopenharmony_ciPDDM-DEFINE noArgs( )
188ffe3c632Sopenharmony_cibody1
189ffe3c632Sopenharmony_cibody2
190ffe3c632Sopenharmony_ci
191ffe3c632Sopenharmony_ciPDDM-DEFINE-END
192ffe3c632Sopenharmony_ci
193ffe3c632Sopenharmony_ciPDDM-DEFINE oneArg(a)
194ffe3c632Sopenharmony_cibody3 a
195ffe3c632Sopenharmony_ci
196ffe3c632Sopenharmony_ciPDDM-DEFINE-END
197ffe3c632Sopenharmony_ci
198ffe3c632Sopenharmony_ciPDDM-DEFINE twoArgs(b,c)
199ffe3c632Sopenharmony_cibody4 b c
200ffe3c632Sopenharmony_cibody5
201ffe3c632Sopenharmony_ciPDDM-DEFINE-END
202ffe3c632Sopenharmony_ci
203ffe3c632Sopenharmony_ci""")
204ffe3c632Sopenharmony_ci    mc = pddm.MacroCollection(f)
205ffe3c632Sopenharmony_ci    test_list = [
206ffe3c632Sopenharmony_ci      (u'noArgs()',
207ffe3c632Sopenharmony_ci       'body1\nbody2\n'),
208ffe3c632Sopenharmony_ci      (u'oneArg(wee)',
209ffe3c632Sopenharmony_ci       'body3 wee\n'),
210ffe3c632Sopenharmony_ci      (u'twoArgs(having some, fun)',
211ffe3c632Sopenharmony_ci       'body4 having some fun\nbody5'),
212ffe3c632Sopenharmony_ci      # One arg, pass empty.
213ffe3c632Sopenharmony_ci      (u'oneArg()',
214ffe3c632Sopenharmony_ci       'body3 \n'),
215ffe3c632Sopenharmony_ci      # Two args, gets empty in each slot.
216ffe3c632Sopenharmony_ci      (u'twoArgs(, empty)',
217ffe3c632Sopenharmony_ci       'body4  empty\nbody5'),
218ffe3c632Sopenharmony_ci      (u'twoArgs(empty, )',
219ffe3c632Sopenharmony_ci       'body4 empty \nbody5'),
220ffe3c632Sopenharmony_ci      (u'twoArgs(, )',
221ffe3c632Sopenharmony_ci       'body4  \nbody5'),
222ffe3c632Sopenharmony_ci    ]
223ffe3c632Sopenharmony_ci    for idx, (input_str, expected) in enumerate(test_list, 1):
224ffe3c632Sopenharmony_ci      result = mc.Expand(input_str)
225ffe3c632Sopenharmony_ci      self.assertEqual(result, expected,
226ffe3c632Sopenharmony_ci                       'Entry %d --\n       Result: %r\n     Expected: %r' %
227ffe3c632Sopenharmony_ci                       (idx, result, expected))
228ffe3c632Sopenharmony_ci
229ffe3c632Sopenharmony_ci  def testExpandArgOptions(self):
230ffe3c632Sopenharmony_ci    f = io.StringIO(u"""
231ffe3c632Sopenharmony_ciPDDM-DEFINE bar(a)
232ffe3c632Sopenharmony_cia-a$S-a$l-a$L-a$u-a$U
233ffe3c632Sopenharmony_ciPDDM-DEFINE-END
234ffe3c632Sopenharmony_ci""")
235ffe3c632Sopenharmony_ci    mc = pddm.MacroCollection(f)
236ffe3c632Sopenharmony_ci
237ffe3c632Sopenharmony_ci    self.assertEqual(mc.Expand('bar(xYz)'), 'xYz-   -xYz-xyz-XYz-XYZ')
238ffe3c632Sopenharmony_ci    self.assertEqual(mc.Expand('bar(MnoP)'), 'MnoP-    -mnoP-mnop-MnoP-MNOP')
239ffe3c632Sopenharmony_ci    # Test empty
240ffe3c632Sopenharmony_ci    self.assertEqual(mc.Expand('bar()'), '-----')
241ffe3c632Sopenharmony_ci
242ffe3c632Sopenharmony_ci  def testExpandSimpleMacroErrors(self):
243ffe3c632Sopenharmony_ci    f = io.StringIO(u"""
244ffe3c632Sopenharmony_ciPDDM-DEFINE foo(a, b)
245ffe3c632Sopenharmony_ci<a-z>
246ffe3c632Sopenharmony_ciPDDM-DEFINE baz(a)
247ffe3c632Sopenharmony_cia - a$z
248ffe3c632Sopenharmony_ci""")
249ffe3c632Sopenharmony_ci    mc = pddm.MacroCollection(f)
250ffe3c632Sopenharmony_ci    test_list = [
251ffe3c632Sopenharmony_ci      # 1. Unknown macro
252ffe3c632Sopenharmony_ci      (u'bar()',
253ffe3c632Sopenharmony_ci       'No macro named "bar".'),
254ffe3c632Sopenharmony_ci      (u'bar(a)',
255ffe3c632Sopenharmony_ci       'No macro named "bar".'),
256ffe3c632Sopenharmony_ci      # 3. Arg mismatch
257ffe3c632Sopenharmony_ci      (u'foo()',
258ffe3c632Sopenharmony_ci       'Expected 2 args, got: "foo()".'),
259ffe3c632Sopenharmony_ci      (u'foo(a b)',
260ffe3c632Sopenharmony_ci       'Expected 2 args, got: "foo(a b)".'),
261ffe3c632Sopenharmony_ci      (u'foo(a,b,c)',
262ffe3c632Sopenharmony_ci       'Expected 2 args, got: "foo(a,b,c)".'),
263ffe3c632Sopenharmony_ci      # 6. Unknown option in expansion
264ffe3c632Sopenharmony_ci      (u'baz(mumble)',
265ffe3c632Sopenharmony_ci       'Unknown arg option "a$z" while expanding "baz(mumble)".'),
266ffe3c632Sopenharmony_ci    ]
267ffe3c632Sopenharmony_ci    for idx, (input_str, expected_err) in enumerate(test_list, 1):
268ffe3c632Sopenharmony_ci      try:
269ffe3c632Sopenharmony_ci        result = mc.Expand(input_str)
270ffe3c632Sopenharmony_ci        self.fail('Should throw exception, entry %d' % idx)
271ffe3c632Sopenharmony_ci      except pddm.PDDMError as e:
272ffe3c632Sopenharmony_ci        self.assertEqual(e.message, expected_err,
273ffe3c632Sopenharmony_ci                        'Entry %d failed: %r' % (idx, e))
274ffe3c632Sopenharmony_ci
275ffe3c632Sopenharmony_ci  def testExpandReferences(self):
276ffe3c632Sopenharmony_ci    f = io.StringIO(u"""
277ffe3c632Sopenharmony_ciPDDM-DEFINE StartIt()
278ffe3c632Sopenharmony_cifoo(abc, def)
279ffe3c632Sopenharmony_cifoo(ghi, jkl)
280ffe3c632Sopenharmony_ciPDDM-DEFINE foo(a, b)
281ffe3c632Sopenharmony_cibar(a, int)
282ffe3c632Sopenharmony_cibar(b, NSString *)
283ffe3c632Sopenharmony_ciPDDM-DEFINE bar(n, t)
284ffe3c632Sopenharmony_ci- (t)n;
285ffe3c632Sopenharmony_ci- (void)set##n$u##:(t)value;
286ffe3c632Sopenharmony_ci
287ffe3c632Sopenharmony_ci""")
288ffe3c632Sopenharmony_ci    mc = pddm.MacroCollection(f)
289ffe3c632Sopenharmony_ci    expected = """- (int)abc;
290ffe3c632Sopenharmony_ci- (void)setAbc:(int)value;
291ffe3c632Sopenharmony_ci
292ffe3c632Sopenharmony_ci- (NSString *)def;
293ffe3c632Sopenharmony_ci- (void)setDef:(NSString *)value;
294ffe3c632Sopenharmony_ci
295ffe3c632Sopenharmony_ci- (int)ghi;
296ffe3c632Sopenharmony_ci- (void)setGhi:(int)value;
297ffe3c632Sopenharmony_ci
298ffe3c632Sopenharmony_ci- (NSString *)jkl;
299ffe3c632Sopenharmony_ci- (void)setJkl:(NSString *)value;
300ffe3c632Sopenharmony_ci"""
301ffe3c632Sopenharmony_ci    self.assertEqual(mc.Expand('StartIt()'), expected)
302ffe3c632Sopenharmony_ci
303ffe3c632Sopenharmony_ci  def testCatchRecursion(self):
304ffe3c632Sopenharmony_ci    f = io.StringIO(u"""
305ffe3c632Sopenharmony_ciPDDM-DEFINE foo(a, b)
306ffe3c632Sopenharmony_cibar(1, a)
307ffe3c632Sopenharmony_cibar(2, b)
308ffe3c632Sopenharmony_ciPDDM-DEFINE bar(x, y)
309ffe3c632Sopenharmony_cifoo(x, y)
310ffe3c632Sopenharmony_ci""")
311ffe3c632Sopenharmony_ci    mc = pddm.MacroCollection(f)
312ffe3c632Sopenharmony_ci    try:
313ffe3c632Sopenharmony_ci      result = mc.Expand('foo(A,B)')
314ffe3c632Sopenharmony_ci      self.fail('Should throw exception! Test failed to catch recursion.')
315ffe3c632Sopenharmony_ci    except pddm.PDDMError as e:
316ffe3c632Sopenharmony_ci      self.assertEqual(e.message,
317ffe3c632Sopenharmony_ci                       'Found macro recursion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".')
318ffe3c632Sopenharmony_ci
319ffe3c632Sopenharmony_ci
320ffe3c632Sopenharmony_ciclass TestParsingSource(unittest.TestCase):
321ffe3c632Sopenharmony_ci
322ffe3c632Sopenharmony_ci  def testBasicParse(self):
323ffe3c632Sopenharmony_ci    test_list = [
324ffe3c632Sopenharmony_ci      # 1. no directives
325ffe3c632Sopenharmony_ci      (u'a\nb\nc',
326ffe3c632Sopenharmony_ci       (3,) ),
327ffe3c632Sopenharmony_ci      # 2. One define
328ffe3c632Sopenharmony_ci      (u'a\n//%PDDM-DEFINE foo()\n//%body\nc',
329ffe3c632Sopenharmony_ci       (1, 2, 1) ),
330ffe3c632Sopenharmony_ci      # 3. Two defines
331ffe3c632Sopenharmony_ci      (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE bar()\n//%body2\nc',
332ffe3c632Sopenharmony_ci       (1, 4, 1) ),
333ffe3c632Sopenharmony_ci      # 4. Two defines with ends
334ffe3c632Sopenharmony_ci      (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE-END\n'
335ffe3c632Sopenharmony_ci       u'//%PDDM-DEFINE bar()\n//%body2\n//%PDDM-DEFINE-END\nc',
336ffe3c632Sopenharmony_ci       (1, 6, 1) ),
337ffe3c632Sopenharmony_ci      # 5. One expand, one define (that runs to end of file)
338ffe3c632Sopenharmony_ci      (u'a\n//%PDDM-EXPAND foo()\nbody\n//%PDDM-EXPAND-END\n'
339ffe3c632Sopenharmony_ci       u'//%PDDM-DEFINE bar()\n//%body2\n',
340ffe3c632Sopenharmony_ci       (1, 1, 2) ),
341ffe3c632Sopenharmony_ci      # 6. One define ended with an expand.
342ffe3c632Sopenharmony_ci      (u'a\nb\n//%PDDM-DEFINE bar()\n//%body2\n'
343ffe3c632Sopenharmony_ci       u'//%PDDM-EXPAND bar()\nbody2\n//%PDDM-EXPAND-END\n',
344ffe3c632Sopenharmony_ci       (2, 2, 1) ),
345ffe3c632Sopenharmony_ci      # 7. Two expands (one end), one define.
346ffe3c632Sopenharmony_ci      (u'a\n//%PDDM-EXPAND foo(1)\nbody\n//%PDDM-EXPAND foo(2)\nbody2\n//%PDDM-EXPAND-END\n'
347ffe3c632Sopenharmony_ci       u'//%PDDM-DEFINE foo()\n//%body2\n',
348ffe3c632Sopenharmony_ci       (1, 2, 2) ),
349ffe3c632Sopenharmony_ci    ]
350ffe3c632Sopenharmony_ci    for idx, (input_str, line_counts) in enumerate(test_list, 1):
351ffe3c632Sopenharmony_ci      f = io.StringIO(input_str)
352ffe3c632Sopenharmony_ci      sf = pddm.SourceFile(f)
353ffe3c632Sopenharmony_ci      sf._ParseFile()
354ffe3c632Sopenharmony_ci      self.assertEqual(len(sf._sections), len(line_counts),
355ffe3c632Sopenharmony_ci                       'Entry %d -- %d != %d' %
356ffe3c632Sopenharmony_ci                       (idx, len(sf._sections), len(line_counts)))
357ffe3c632Sopenharmony_ci      for idx2, (sec, expected) in enumerate(zip(sf._sections, line_counts), 1):
358ffe3c632Sopenharmony_ci        self.assertEqual(sec.num_lines_captured, expected,
359ffe3c632Sopenharmony_ci                         'Entry %d, section %d -- %d != %d' %
360ffe3c632Sopenharmony_ci                         (idx, idx2, sec.num_lines_captured, expected))
361ffe3c632Sopenharmony_ci
362ffe3c632Sopenharmony_ci  def testErrors(self):
363ffe3c632Sopenharmony_ci    test_list = [
364ffe3c632Sopenharmony_ci      # 1. Directive within expansion
365ffe3c632Sopenharmony_ci      (u'//%PDDM-EXPAND a()\n//%PDDM-BOGUS',
366ffe3c632Sopenharmony_ci       'Ran into directive ("//%PDDM-BOGUS", line 2) while in "//%PDDM-EXPAND a()".'),
367ffe3c632Sopenharmony_ci      (u'//%PDDM-EXPAND a()\n//%PDDM-DEFINE a()\n//%body\n',
368ffe3c632Sopenharmony_ci       'Ran into directive ("//%PDDM-DEFINE", line 2) while in "//%PDDM-EXPAND a()".'),
369ffe3c632Sopenharmony_ci      # 3. Expansion ran off end of file
370ffe3c632Sopenharmony_ci      (u'//%PDDM-EXPAND a()\na\nb\n',
371ffe3c632Sopenharmony_ci       'Hit the end of the file while in "//%PDDM-EXPAND a()".'),
372ffe3c632Sopenharmony_ci      # 4. Directive within define
373ffe3c632Sopenharmony_ci      (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-BOGUS',
374ffe3c632Sopenharmony_ci       'Ran into directive ("//%PDDM-BOGUS", line 3) while in "//%PDDM-DEFINE a()".'),
375ffe3c632Sopenharmony_ci      (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-EXPAND-END a()',
376ffe3c632Sopenharmony_ci       'Ran into directive ("//%PDDM-EXPAND-END", line 3) while in "//%PDDM-DEFINE a()".'),
377ffe3c632Sopenharmony_ci      # 6. Directives that shouldn't start sections
378ffe3c632Sopenharmony_ci      (u'a\n//%PDDM-DEFINE-END a()\n//a\n',
379ffe3c632Sopenharmony_ci       'Unexpected line 2: "//%PDDM-DEFINE-END a()".'),
380ffe3c632Sopenharmony_ci      (u'a\n//%PDDM-EXPAND-END a()\n//a\n',
381ffe3c632Sopenharmony_ci       'Unexpected line 2: "//%PDDM-EXPAND-END a()".'),
382ffe3c632Sopenharmony_ci      (u'//%PDDM-BOGUS\n//a\n',
383ffe3c632Sopenharmony_ci       'Unexpected line 1: "//%PDDM-BOGUS".'),
384ffe3c632Sopenharmony_ci    ]
385ffe3c632Sopenharmony_ci    for idx, (input_str, expected_err) in enumerate(test_list, 1):
386ffe3c632Sopenharmony_ci      f = io.StringIO(input_str)
387ffe3c632Sopenharmony_ci      try:
388ffe3c632Sopenharmony_ci        pddm.SourceFile(f)._ParseFile()
389ffe3c632Sopenharmony_ci        self.fail('Should throw exception, entry %d' % idx)
390ffe3c632Sopenharmony_ci      except pddm.PDDMError as e:
391ffe3c632Sopenharmony_ci        self.assertEqual(e.message, expected_err,
392ffe3c632Sopenharmony_ci                        'Entry %d failed: %r' % (idx, e))
393ffe3c632Sopenharmony_ci
394ffe3c632Sopenharmony_ciclass TestProcessingSource(unittest.TestCase):
395ffe3c632Sopenharmony_ci
396ffe3c632Sopenharmony_ci  def testBasics(self):
397ffe3c632Sopenharmony_ci    self.maxDiff = None
398ffe3c632Sopenharmony_ci    input_str = u"""
399ffe3c632Sopenharmony_ci//%PDDM-IMPORT-DEFINES ImportFile
400ffe3c632Sopenharmony_cifoo
401ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(abc)
402ffe3c632Sopenharmony_ci//%PDDM-EXPAND-END
403ffe3c632Sopenharmony_cibar
404ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(def)
405ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(ghi)
406ffe3c632Sopenharmony_ci//%PDDM-EXPAND-END
407ffe3c632Sopenharmony_cibaz
408ffe3c632Sopenharmony_ci//%PDDM-DEFINE mumble(a_)
409ffe3c632Sopenharmony_ci//%a_: getName(a_)
410ffe3c632Sopenharmony_ci"""
411ffe3c632Sopenharmony_ci    input_str2 = u"""
412ffe3c632Sopenharmony_ci//%PDDM-DEFINE getName(x_)
413ffe3c632Sopenharmony_ci//%do##x_$u##(int x_);
414ffe3c632Sopenharmony_ci
415ffe3c632Sopenharmony_ci"""
416ffe3c632Sopenharmony_ci    expected = u"""
417ffe3c632Sopenharmony_ci//%PDDM-IMPORT-DEFINES ImportFile
418ffe3c632Sopenharmony_cifoo
419ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(abc)
420ffe3c632Sopenharmony_ci// This block of code is generated, do not edit it directly.
421ffe3c632Sopenharmony_ci// clang-format off
422ffe3c632Sopenharmony_ci
423ffe3c632Sopenharmony_ciabc: doAbc(int abc);
424ffe3c632Sopenharmony_ci// clang-format on
425ffe3c632Sopenharmony_ci//%PDDM-EXPAND-END mumble(abc)
426ffe3c632Sopenharmony_cibar
427ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(def)
428ffe3c632Sopenharmony_ci// This block of code is generated, do not edit it directly.
429ffe3c632Sopenharmony_ci// clang-format off
430ffe3c632Sopenharmony_ci
431ffe3c632Sopenharmony_cidef: doDef(int def);
432ffe3c632Sopenharmony_ci// clang-format on
433ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(ghi)
434ffe3c632Sopenharmony_ci// This block of code is generated, do not edit it directly.
435ffe3c632Sopenharmony_ci// clang-format off
436ffe3c632Sopenharmony_ci
437ffe3c632Sopenharmony_cighi: doGhi(int ghi);
438ffe3c632Sopenharmony_ci// clang-format on
439ffe3c632Sopenharmony_ci//%PDDM-EXPAND-END (2 expansions)
440ffe3c632Sopenharmony_cibaz
441ffe3c632Sopenharmony_ci//%PDDM-DEFINE mumble(a_)
442ffe3c632Sopenharmony_ci//%a_: getName(a_)
443ffe3c632Sopenharmony_ci"""
444ffe3c632Sopenharmony_ci    expected_stripped = u"""
445ffe3c632Sopenharmony_ci//%PDDM-IMPORT-DEFINES ImportFile
446ffe3c632Sopenharmony_cifoo
447ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(abc)
448ffe3c632Sopenharmony_ci//%PDDM-EXPAND-END mumble(abc)
449ffe3c632Sopenharmony_cibar
450ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(def)
451ffe3c632Sopenharmony_ci//%PDDM-EXPAND mumble(ghi)
452ffe3c632Sopenharmony_ci//%PDDM-EXPAND-END (2 expansions)
453ffe3c632Sopenharmony_cibaz
454ffe3c632Sopenharmony_ci//%PDDM-DEFINE mumble(a_)
455ffe3c632Sopenharmony_ci//%a_: getName(a_)
456ffe3c632Sopenharmony_ci"""
457ffe3c632Sopenharmony_ci    def _Resolver(name):
458ffe3c632Sopenharmony_ci      self.assertEqual(name, 'ImportFile')
459ffe3c632Sopenharmony_ci      return io.StringIO(input_str2)
460ffe3c632Sopenharmony_ci    f = io.StringIO(input_str)
461ffe3c632Sopenharmony_ci    sf = pddm.SourceFile(f, _Resolver)
462ffe3c632Sopenharmony_ci    sf.ProcessContent()
463ffe3c632Sopenharmony_ci    self.assertEqual(sf.processed_content, expected)
464ffe3c632Sopenharmony_ci    # Feed it through and nothing should change.
465ffe3c632Sopenharmony_ci    f2 = io.StringIO(sf.processed_content)
466ffe3c632Sopenharmony_ci    sf2 = pddm.SourceFile(f2, _Resolver)
467ffe3c632Sopenharmony_ci    sf2.ProcessContent()
468ffe3c632Sopenharmony_ci    self.assertEqual(sf2.processed_content, expected)
469ffe3c632Sopenharmony_ci    self.assertEqual(sf2.processed_content, sf.processed_content)
470ffe3c632Sopenharmony_ci    # Test stripping (with the original input and expanded version).
471ffe3c632Sopenharmony_ci    f2 = io.StringIO(input_str)
472ffe3c632Sopenharmony_ci    sf2 = pddm.SourceFile(f2)
473ffe3c632Sopenharmony_ci    sf2.ProcessContent(strip_expansion=True)
474ffe3c632Sopenharmony_ci    self.assertEqual(sf2.processed_content, expected_stripped)
475ffe3c632Sopenharmony_ci    f2 = io.StringIO(sf.processed_content)
476ffe3c632Sopenharmony_ci    sf2 = pddm.SourceFile(f2, _Resolver)
477ffe3c632Sopenharmony_ci    sf2.ProcessContent(strip_expansion=True)
478ffe3c632Sopenharmony_ci    self.assertEqual(sf2.processed_content, expected_stripped)
479ffe3c632Sopenharmony_ci
480ffe3c632Sopenharmony_ci  def testProcessFileWithMacroParseError(self):
481ffe3c632Sopenharmony_ci    input_str = u"""
482ffe3c632Sopenharmony_cifoo
483ffe3c632Sopenharmony_ci//%PDDM-DEFINE mumble(a_)
484ffe3c632Sopenharmony_ci//%body
485ffe3c632Sopenharmony_ci//%PDDM-DEFINE mumble(x_)
486ffe3c632Sopenharmony_ci//%body2
487ffe3c632Sopenharmony_ci
488ffe3c632Sopenharmony_ci"""
489ffe3c632Sopenharmony_ci    f = io.StringIO(input_str)
490ffe3c632Sopenharmony_ci    sf = pddm.SourceFile(f)
491ffe3c632Sopenharmony_ci    try:
492ffe3c632Sopenharmony_ci      sf.ProcessContent()
493ffe3c632Sopenharmony_ci      self.fail('Should throw exception! Test failed to catch macro parsing error.')
494ffe3c632Sopenharmony_ci    except pddm.PDDMError as e:
495ffe3c632Sopenharmony_ci      self.assertEqual(e.message,
496ffe3c632Sopenharmony_ci                       'Attempt to redefine macro: "PDDM-DEFINE mumble(x_)"\n'
497ffe3c632Sopenharmony_ci                       '...while parsing section that started:\n'
498ffe3c632Sopenharmony_ci                       '  Line 3: //%PDDM-DEFINE mumble(a_)')
499ffe3c632Sopenharmony_ci
500ffe3c632Sopenharmony_ci  def testProcessFileWithExpandError(self):
501ffe3c632Sopenharmony_ci    input_str = u"""
502ffe3c632Sopenharmony_cifoo
503ffe3c632Sopenharmony_ci//%PDDM-DEFINE mumble(a_)
504ffe3c632Sopenharmony_ci//%body
505ffe3c632Sopenharmony_ci//%PDDM-EXPAND foobar(x_)
506ffe3c632Sopenharmony_ci//%PDDM-EXPAND-END
507ffe3c632Sopenharmony_ci
508ffe3c632Sopenharmony_ci"""
509ffe3c632Sopenharmony_ci    f = io.StringIO(input_str)
510ffe3c632Sopenharmony_ci    sf = pddm.SourceFile(f)
511ffe3c632Sopenharmony_ci    try:
512ffe3c632Sopenharmony_ci      sf.ProcessContent()
513ffe3c632Sopenharmony_ci      self.fail('Should throw exception! Test failed to catch expand error.')
514ffe3c632Sopenharmony_ci    except pddm.PDDMError as e:
515ffe3c632Sopenharmony_ci      self.assertEqual(e.message,
516ffe3c632Sopenharmony_ci                       'No macro named "foobar".\n'
517ffe3c632Sopenharmony_ci                       '...while expanding "foobar(x_)" from the section that'
518ffe3c632Sopenharmony_ci                       ' started:\n   Line 5: //%PDDM-EXPAND foobar(x_)')
519ffe3c632Sopenharmony_ci
520ffe3c632Sopenharmony_ci
521ffe3c632Sopenharmony_ciif __name__ == '__main__':
522ffe3c632Sopenharmony_ci  unittest.main()
523