| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 | #! /usr/bin/python## Protocol Buffers - Google's data interchange format# Copyright 2015 Google Inc.  All rights reserved.# https://developers.google.com/protocol-buffers/## Redistribution and use in source and binary forms, with or without# modification, are permitted provided that the following conditions are# met:##     * Redistributions of source code must retain the above copyright# notice, this list of conditions and the following disclaimer.#     * Redistributions in binary form must reproduce the above# copyright notice, this list of conditions and the following disclaimer# in the documentation and/or other materials provided with the# distribution.#     * Neither the name of Google Inc. nor the names of its# contributors may be used to endorse or promote products derived from# this software without specific prior written permission.## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."""Tests for pddm.py."""import ioimport unittestimport pddmclass TestParsingMacros(unittest.TestCase):  def testParseEmpty(self):    f = io.StringIO(u'')    result = pddm.MacroCollection(f)    self.assertEqual(len(result._macros), 0)  def testParseOne(self):    f = io.StringIO(u"""PDDM-DEFINE foo( )body""")    result = pddm.MacroCollection(f)    self.assertEqual(len(result._macros), 1)    macro = result._macros.get('foo')    self.assertIsNotNone(macro)    self.assertEquals(macro.name, 'foo')    self.assertEquals(macro.args, tuple())    self.assertEquals(macro.body, 'body')  def testParseGeneral(self):    # Tests multiple defines, spaces in all places, etc.    f = io.StringIO(u"""PDDM-DEFINE noArgs( )body1body2PDDM-DEFINE-ENDPDDM-DEFINE oneArg(foo)body3PDDM-DEFINE  twoArgs( bar_ , baz )body4body5""")    result = pddm.MacroCollection(f)    self.assertEqual(len(result._macros), 3)    macro = result._macros.get('noArgs')    self.assertIsNotNone(macro)    self.assertEquals(macro.name, 'noArgs')    self.assertEquals(macro.args, tuple())    self.assertEquals(macro.body, 'body1\nbody2\n')    macro = result._macros.get('oneArg')    self.assertIsNotNone(macro)    self.assertEquals(macro.name, 'oneArg')    self.assertEquals(macro.args, ('foo',))    self.assertEquals(macro.body, 'body3')    macro = result._macros.get('twoArgs')    self.assertIsNotNone(macro)    self.assertEquals(macro.name, 'twoArgs')    self.assertEquals(macro.args, ('bar_', 'baz'))    self.assertEquals(macro.body, 'body4\nbody5')    # Add into existing collection    f = io.StringIO(u"""PDDM-DEFINE another(a,b,c)body1body2""")    result.ParseInput(f)    self.assertEqual(len(result._macros), 4)    macro = result._macros.get('another')    self.assertIsNotNone(macro)    self.assertEquals(macro.name, 'another')    self.assertEquals(macro.args, ('a', 'b', 'c'))    self.assertEquals(macro.body, 'body1\nbody2')  def testParseDirectiveIssues(self):    test_list = [      # Unknown directive      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINED foo\nbaz',       'Hit a line with an unknown directive: '),      # End without begin      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nPDDM-DEFINE-END\n',       'Got DEFINE-END directive without an active macro: '),      # Line not in macro block      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nmumble\n',       'Hit a line that wasn\'t a directive and no open macro definition: '),      # Redefine macro      (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE foo(a)\nmumble\n',       'Attempt to redefine macro: '),    ]    for idx, (input_str, expected_prefix) in enumerate(test_list, 1):      f = io.StringIO(input_str)      try:        result = pddm.MacroCollection(f)        self.fail('Should throw exception, entry %d' % idx)      except pddm.PDDMError as e:        self.assertTrue(e.message.startswith(expected_prefix),                        'Entry %d failed: %r' % (idx, e))  def testParseBeginIssues(self):    test_list = [      # 1. No name      (u'PDDM-DEFINE\nmumble',       'Failed to parse macro definition: '),      # 2. No name (with spaces)      (u'PDDM-DEFINE  \nmumble',       'Failed to parse macro definition: '),      # 3. No open paren      (u'PDDM-DEFINE  foo\nmumble',       'Failed to parse macro definition: '),      # 4. No close paren      (u'PDDM-DEFINE foo(\nmumble',       'Failed to parse macro definition: '),      # 5. No close paren (with args)      (u'PDDM-DEFINE foo(a, b\nmumble',       'Failed to parse macro definition: '),      # 6. No name before args      (u'PDDM-DEFINE  (a, b)\nmumble',       'Failed to parse macro definition: '),      # 7. No name before args      (u'PDDM-DEFINE foo bar(a, b)\nmumble',       'Failed to parse macro definition: '),      # 8. Empty arg name      (u'PDDM-DEFINE foo(a, ,b)\nmumble',       'Empty arg name in macro definition: '),      (u'PDDM-DEFINE foo(a,,b)\nmumble',       'Empty arg name in macro definition: '),      # 10. Duplicate name      (u'PDDM-DEFINE foo(a,b,a,c)\nmumble',       'Arg name "a" used more than once in macro definition: '),      # 11. Invalid arg name      (u'PDDM-DEFINE foo(a b,c)\nmumble',       'Invalid arg name "a b" in macro definition: '),      (u'PDDM-DEFINE foo(a.b,c)\nmumble',       'Invalid arg name "a.b" in macro definition: '),      (u'PDDM-DEFINE foo(a-b,c)\nmumble',       'Invalid arg name "a-b" in macro definition: '),      (u'PDDM-DEFINE foo(a,b,c.)\nmumble',       'Invalid arg name "c." in macro definition: '),      # 15. Extra stuff after the name      (u'PDDM-DEFINE foo(a,c) foo\nmumble',       'Failed to parse macro definition: '),      (u'PDDM-DEFINE foo(a,c) foo)\nmumble',       'Failed to parse macro definition: '),    ]    for idx, (input_str, expected_prefix) in enumerate(test_list, 1):      f = io.StringIO(input_str)      try:        result = pddm.MacroCollection(f)        self.fail('Should throw exception, entry %d' % idx)      except pddm.PDDMError as e:        self.assertTrue(e.message.startswith(expected_prefix),                        'Entry %d failed: %r' % (idx, e))class TestExpandingMacros(unittest.TestCase):  def testExpandBasics(self):    f = io.StringIO(u"""PDDM-DEFINE noArgs( )body1body2PDDM-DEFINE-ENDPDDM-DEFINE oneArg(a)body3 aPDDM-DEFINE-ENDPDDM-DEFINE twoArgs(b,c)body4 b cbody5PDDM-DEFINE-END""")    mc = pddm.MacroCollection(f)    test_list = [      (u'noArgs()',       'body1\nbody2\n'),      (u'oneArg(wee)',       'body3 wee\n'),      (u'twoArgs(having some, fun)',       'body4 having some fun\nbody5'),      # One arg, pass empty.      (u'oneArg()',       'body3 \n'),      # Two args, gets empty in each slot.      (u'twoArgs(, empty)',       'body4  empty\nbody5'),      (u'twoArgs(empty, )',       'body4 empty \nbody5'),      (u'twoArgs(, )',       'body4  \nbody5'),    ]    for idx, (input_str, expected) in enumerate(test_list, 1):      result = mc.Expand(input_str)      self.assertEqual(result, expected,                       'Entry %d --\n       Result: %r\n     Expected: %r' %                       (idx, result, expected))  def testExpandArgOptions(self):    f = io.StringIO(u"""PDDM-DEFINE bar(a)a-a$S-a$l-a$L-a$u-a$UPDDM-DEFINE-END""")    mc = pddm.MacroCollection(f)    self.assertEqual(mc.Expand('bar(xYz)'), 'xYz-   -xYz-xyz-XYz-XYZ')    self.assertEqual(mc.Expand('bar(MnoP)'), 'MnoP-    -mnoP-mnop-MnoP-MNOP')    # Test empty    self.assertEqual(mc.Expand('bar()'), '-----')  def testExpandSimpleMacroErrors(self):    f = io.StringIO(u"""PDDM-DEFINE foo(a, b)<a-z>PDDM-DEFINE baz(a)a - a$z""")    mc = pddm.MacroCollection(f)    test_list = [      # 1. Unknown macro      (u'bar()',       'No macro named "bar".'),      (u'bar(a)',       'No macro named "bar".'),      # 3. Arg mismatch      (u'foo()',       'Expected 2 args, got: "foo()".'),      (u'foo(a b)',       'Expected 2 args, got: "foo(a b)".'),      (u'foo(a,b,c)',       'Expected 2 args, got: "foo(a,b,c)".'),      # 6. Unknown option in expansion      (u'baz(mumble)',       'Unknown arg option "a$z" while expanding "baz(mumble)".'),    ]    for idx, (input_str, expected_err) in enumerate(test_list, 1):      try:        result = mc.Expand(input_str)        self.fail('Should throw exception, entry %d' % idx)      except pddm.PDDMError as e:        self.assertEqual(e.message, expected_err,                        'Entry %d failed: %r' % (idx, e))  def testExpandReferences(self):    f = io.StringIO(u"""PDDM-DEFINE StartIt()foo(abc, def)foo(ghi, jkl)PDDM-DEFINE foo(a, b)bar(a, int)bar(b, NSString *)PDDM-DEFINE bar(n, t)- (t)n;- (void)set##n$u##:(t)value;""")    mc = pddm.MacroCollection(f)    expected = """- (int)abc;- (void)setAbc:(int)value;- (NSString *)def;- (void)setDef:(NSString *)value;- (int)ghi;- (void)setGhi:(int)value;- (NSString *)jkl;- (void)setJkl:(NSString *)value;"""    self.assertEqual(mc.Expand('StartIt()'), expected)  def testCatchRecursion(self):    f = io.StringIO(u"""PDDM-DEFINE foo(a, b)bar(1, a)bar(2, b)PDDM-DEFINE bar(x, y)foo(x, y)""")    mc = pddm.MacroCollection(f)    try:      result = mc.Expand('foo(A,B)')      self.fail('Should throw exception! Test failed to catch recursion.')    except pddm.PDDMError as e:      self.assertEqual(e.message,                       'Found macro recursion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".')class TestParsingSource(unittest.TestCase):  def testBasicParse(self):    test_list = [      # 1. no directives      (u'a\nb\nc',       (3,) ),      # 2. One define      (u'a\n//%PDDM-DEFINE foo()\n//%body\nc',       (1, 2, 1) ),      # 3. Two defines      (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE bar()\n//%body2\nc',       (1, 4, 1) ),      # 4. Two defines with ends      (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE-END\n'       u'//%PDDM-DEFINE bar()\n//%body2\n//%PDDM-DEFINE-END\nc',       (1, 6, 1) ),      # 5. One expand, one define (that runs to end of file)      (u'a\n//%PDDM-EXPAND foo()\nbody\n//%PDDM-EXPAND-END\n'       u'//%PDDM-DEFINE bar()\n//%body2\n',       (1, 1, 2) ),      # 6. One define ended with an expand.      (u'a\nb\n//%PDDM-DEFINE bar()\n//%body2\n'       u'//%PDDM-EXPAND bar()\nbody2\n//%PDDM-EXPAND-END\n',       (2, 2, 1) ),      # 7. Two expands (one end), one define.      (u'a\n//%PDDM-EXPAND foo(1)\nbody\n//%PDDM-EXPAND foo(2)\nbody2\n//%PDDM-EXPAND-END\n'       u'//%PDDM-DEFINE foo()\n//%body2\n',       (1, 2, 2) ),    ]    for idx, (input_str, line_counts) in enumerate(test_list, 1):      f = io.StringIO(input_str)      sf = pddm.SourceFile(f)      sf._ParseFile()      self.assertEqual(len(sf._sections), len(line_counts),                       'Entry %d -- %d != %d' %                       (idx, len(sf._sections), len(line_counts)))      for idx2, (sec, expected) in enumerate(zip(sf._sections, line_counts), 1):        self.assertEqual(sec.num_lines_captured, expected,                         'Entry %d, section %d -- %d != %d' %                         (idx, idx2, sec.num_lines_captured, expected))  def testErrors(self):    test_list = [      # 1. Directive within expansion      (u'//%PDDM-EXPAND a()\n//%PDDM-BOGUS',       'Ran into directive ("//%PDDM-BOGUS", line 2) while in "//%PDDM-EXPAND a()".'),      (u'//%PDDM-EXPAND a()\n//%PDDM-DEFINE a()\n//%body\n',       'Ran into directive ("//%PDDM-DEFINE", line 2) while in "//%PDDM-EXPAND a()".'),      # 3. Expansion ran off end of file      (u'//%PDDM-EXPAND a()\na\nb\n',       'Hit the end of the file while in "//%PDDM-EXPAND a()".'),      # 4. Directive within define      (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-BOGUS',       'Ran into directive ("//%PDDM-BOGUS", line 3) while in "//%PDDM-DEFINE a()".'),      (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-EXPAND-END a()',       'Ran into directive ("//%PDDM-EXPAND-END", line 3) while in "//%PDDM-DEFINE a()".'),      # 6. Directives that shouldn't start sections      (u'a\n//%PDDM-DEFINE-END a()\n//a\n',       'Unexpected line 2: "//%PDDM-DEFINE-END a()".'),      (u'a\n//%PDDM-EXPAND-END a()\n//a\n',       'Unexpected line 2: "//%PDDM-EXPAND-END a()".'),      (u'//%PDDM-BOGUS\n//a\n',       'Unexpected line 1: "//%PDDM-BOGUS".'),    ]    for idx, (input_str, expected_err) in enumerate(test_list, 1):      f = io.StringIO(input_str)      try:        pddm.SourceFile(f)._ParseFile()        self.fail('Should throw exception, entry %d' % idx)      except pddm.PDDMError as e:        self.assertEqual(e.message, expected_err,                        'Entry %d failed: %r' % (idx, e))class TestProcessingSource(unittest.TestCase):  def testBasics(self):    self.maxDiff = None    input_str = u"""//%PDDM-IMPORT-DEFINES ImportFilefoo//%PDDM-EXPAND mumble(abc)//%PDDM-EXPAND-ENDbar//%PDDM-EXPAND mumble(def)//%PDDM-EXPAND mumble(ghi)//%PDDM-EXPAND-ENDbaz//%PDDM-DEFINE mumble(a_)//%a_: getName(a_)"""    input_str2 = u"""//%PDDM-DEFINE getName(x_)//%do##x_$u##(int x_);"""    expected = u"""//%PDDM-IMPORT-DEFINES ImportFilefoo//%PDDM-EXPAND mumble(abc)// This block of code is generated, do not edit it directly.// clang-format offabc: doAbc(int abc);// clang-format on//%PDDM-EXPAND-END mumble(abc)bar//%PDDM-EXPAND mumble(def)// This block of code is generated, do not edit it directly.// clang-format offdef: doDef(int def);// clang-format on//%PDDM-EXPAND mumble(ghi)// This block of code is generated, do not edit it directly.// clang-format offghi: doGhi(int ghi);// clang-format on//%PDDM-EXPAND-END (2 expansions)baz//%PDDM-DEFINE mumble(a_)//%a_: getName(a_)"""    expected_stripped = u"""//%PDDM-IMPORT-DEFINES ImportFilefoo//%PDDM-EXPAND mumble(abc)//%PDDM-EXPAND-END mumble(abc)bar//%PDDM-EXPAND mumble(def)//%PDDM-EXPAND mumble(ghi)//%PDDM-EXPAND-END (2 expansions)baz//%PDDM-DEFINE mumble(a_)//%a_: getName(a_)"""    def _Resolver(name):      self.assertEqual(name, 'ImportFile')      return io.StringIO(input_str2)    f = io.StringIO(input_str)    sf = pddm.SourceFile(f, _Resolver)    sf.ProcessContent()    self.assertEqual(sf.processed_content, expected)    # Feed it through and nothing should change.    f2 = io.StringIO(sf.processed_content)    sf2 = pddm.SourceFile(f2, _Resolver)    sf2.ProcessContent()    self.assertEqual(sf2.processed_content, expected)    self.assertEqual(sf2.processed_content, sf.processed_content)    # Test stripping (with the original input and expanded version).    f2 = io.StringIO(input_str)    sf2 = pddm.SourceFile(f2)    sf2.ProcessContent(strip_expansion=True)    self.assertEqual(sf2.processed_content, expected_stripped)    f2 = io.StringIO(sf.processed_content)    sf2 = pddm.SourceFile(f2, _Resolver)    sf2.ProcessContent(strip_expansion=True)    self.assertEqual(sf2.processed_content, expected_stripped)  def testProcessFileWithMacroParseError(self):    input_str = u"""foo//%PDDM-DEFINE mumble(a_)//%body//%PDDM-DEFINE mumble(x_)//%body2"""    f = io.StringIO(input_str)    sf = pddm.SourceFile(f)    try:      sf.ProcessContent()      self.fail('Should throw exception! Test failed to catch macro parsing error.')    except pddm.PDDMError as e:      self.assertEqual(e.message,                       'Attempt to redefine macro: "PDDM-DEFINE mumble(x_)"\n'                       '...while parsing section that started:\n'                       '  Line 3: //%PDDM-DEFINE mumble(a_)')  def testProcessFileWithExpandError(self):    input_str = u"""foo//%PDDM-DEFINE mumble(a_)//%body//%PDDM-EXPAND foobar(x_)//%PDDM-EXPAND-END"""    f = io.StringIO(input_str)    sf = pddm.SourceFile(f)    try:      sf.ProcessContent()      self.fail('Should throw exception! Test failed to catch expand error.')    except pddm.PDDMError as e:      self.assertEqual(e.message,                       'No macro named "foobar".\n'                       '...while expanding "foobar(x_)" from the section that'                       ' started:\n   Line 5: //%PDDM-EXPAND foobar(x_)')if __name__ == '__main__':  unittest.main()
 |