Index: third_party/protobuf/objectivec/DevTools/pddm_tests.py |
diff --git a/third_party/protobuf/objectivec/DevTools/pddm_tests.py b/third_party/protobuf/objectivec/DevTools/pddm_tests.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..8a73b8427bcf5ed50f85842842cbed3e7cbbf57f |
--- /dev/null |
+++ b/third_party/protobuf/objectivec/DevTools/pddm_tests.py |
@@ -0,0 +1,515 @@ |
+#! /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 io |
+import unittest |
+ |
+import pddm |
+ |
+ |
+class 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( ) |
+body1 |
+body2 |
+ |
+PDDM-DEFINE-END |
+ |
+PDDM-DEFINE oneArg(foo) |
+body3 |
+PDDM-DEFINE twoArgs( bar_ , baz ) |
+body4 |
+body5""") |
+ 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) |
+body1 |
+body2""") |
+ 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( ) |
+body1 |
+body2 |
+ |
+PDDM-DEFINE-END |
+ |
+PDDM-DEFINE oneArg(a) |
+body3 a |
+ |
+PDDM-DEFINE-END |
+ |
+PDDM-DEFINE twoArgs(b,c) |
+body4 b c |
+body5 |
+PDDM-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$U |
+PDDM-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, entry %d' % idx) |
+ except pddm.PDDMError as e: |
+ self.assertEqual(e.message, |
+ 'Found macro recusion, 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): |
+ input_str = u""" |
+//%PDDM-IMPORT-DEFINES ImportFile |
+foo |
+//%PDDM-EXPAND mumble(abc) |
+//%PDDM-EXPAND-END |
+bar |
+//%PDDM-EXPAND mumble(def) |
+//%PDDM-EXPAND mumble(ghi) |
+//%PDDM-EXPAND-END |
+baz |
+//%PDDM-DEFINE mumble(a_) |
+//%a_: getName(a_) |
+""" |
+ input_str2 = u""" |
+//%PDDM-DEFINE getName(x_) |
+//%do##x_$u##(int x_); |
+ |
+""" |
+ expected = u""" |
+//%PDDM-IMPORT-DEFINES ImportFile |
+foo |
+//%PDDM-EXPAND mumble(abc) |
+// This block of code is generated, do not edit it directly. |
+ |
+abc: doAbc(int abc); |
+//%PDDM-EXPAND-END mumble(abc) |
+bar |
+//%PDDM-EXPAND mumble(def) |
+// This block of code is generated, do not edit it directly. |
+ |
+def: doDef(int def); |
+//%PDDM-EXPAND mumble(ghi) |
+// This block of code is generated, do not edit it directly. |
+ |
+ghi: doGhi(int ghi); |
+//%PDDM-EXPAND-END (2 expansions) |
+baz |
+//%PDDM-DEFINE mumble(a_) |
+//%a_: getName(a_) |
+""" |
+ expected_stripped = u""" |
+//%PDDM-IMPORT-DEFINES ImportFile |
+foo |
+//%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, entry %d' % idx) |
+ 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, entry %d' % idx) |
+ 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() |