Thomas Van Lenten | ca30339 | 2022-04-05 14:07:04 -0400 | [diff] [blame] | 1 | #! /usr/bin/env python3 |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 2 | # |
| 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 | |
| 35 | import io |
| 36 | import unittest |
| 37 | |
| 38 | import pddm |
| 39 | |
| 40 | |
| 41 | class TestParsingMacros(unittest.TestCase): |
| 42 | |
| 43 | def testParseEmpty(self): |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 44 | f = io.StringIO('') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 45 | result = pddm.MacroCollection(f) |
| 46 | self.assertEqual(len(result._macros), 0) |
| 47 | |
| 48 | def testParseOne(self): |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 49 | f = io.StringIO("""PDDM-DEFINE foo( ) |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 50 | body""") |
| 51 | result = pddm.MacroCollection(f) |
| 52 | self.assertEqual(len(result._macros), 1) |
| 53 | macro = result._macros.get('foo') |
| 54 | self.assertIsNotNone(macro) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 55 | self.assertEqual(macro.name, 'foo') |
| 56 | self.assertEqual(macro.args, tuple()) |
| 57 | self.assertEqual(macro.body, 'body') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 58 | |
| 59 | def testParseGeneral(self): |
| 60 | # Tests multiple defines, spaces in all places, etc. |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 61 | f = io.StringIO(""" |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 62 | PDDM-DEFINE noArgs( ) |
| 63 | body1 |
| 64 | body2 |
| 65 | |
| 66 | PDDM-DEFINE-END |
| 67 | |
| 68 | PDDM-DEFINE oneArg(foo) |
| 69 | body3 |
| 70 | PDDM-DEFINE twoArgs( bar_ , baz ) |
| 71 | body4 |
| 72 | body5""") |
| 73 | result = pddm.MacroCollection(f) |
| 74 | self.assertEqual(len(result._macros), 3) |
| 75 | macro = result._macros.get('noArgs') |
| 76 | self.assertIsNotNone(macro) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 77 | self.assertEqual(macro.name, 'noArgs') |
| 78 | self.assertEqual(macro.args, tuple()) |
| 79 | self.assertEqual(macro.body, 'body1\nbody2\n') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 80 | macro = result._macros.get('oneArg') |
| 81 | self.assertIsNotNone(macro) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 82 | self.assertEqual(macro.name, 'oneArg') |
| 83 | self.assertEqual(macro.args, ('foo',)) |
| 84 | self.assertEqual(macro.body, 'body3') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 85 | macro = result._macros.get('twoArgs') |
| 86 | self.assertIsNotNone(macro) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 87 | self.assertEqual(macro.name, 'twoArgs') |
| 88 | self.assertEqual(macro.args, ('bar_', 'baz')) |
| 89 | self.assertEqual(macro.body, 'body4\nbody5') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 90 | # Add into existing collection |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 91 | f = io.StringIO(""" |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 92 | PDDM-DEFINE another(a,b,c) |
| 93 | body1 |
| 94 | body2""") |
| 95 | result.ParseInput(f) |
| 96 | self.assertEqual(len(result._macros), 4) |
| 97 | macro = result._macros.get('another') |
| 98 | self.assertIsNotNone(macro) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 99 | self.assertEqual(macro.name, 'another') |
| 100 | self.assertEqual(macro.args, ('a', 'b', 'c')) |
| 101 | self.assertEqual(macro.body, 'body1\nbody2') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 102 | |
| 103 | def testParseDirectiveIssues(self): |
| 104 | test_list = [ |
| 105 | # Unknown directive |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 106 | ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINED foo\nbaz', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 107 | 'Hit a line with an unknown directive: '), |
| 108 | # End without begin |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 109 | ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nPDDM-DEFINE-END\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 110 | 'Got DEFINE-END directive without an active macro: '), |
| 111 | # Line not in macro block |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 112 | ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nmumble\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 113 | 'Hit a line that wasn\'t a directive and no open macro definition: '), |
| 114 | # Redefine macro |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 115 | ('PDDM-DEFINE foo()\nbody\nPDDM-DEFINE foo(a)\nmumble\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 116 | '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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 130 | ('PDDM-DEFINE\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 131 | 'Failed to parse macro definition: '), |
| 132 | # 2. No name (with spaces) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 133 | ('PDDM-DEFINE \nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 134 | 'Failed to parse macro definition: '), |
| 135 | # 3. No open paren |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 136 | ('PDDM-DEFINE foo\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 137 | 'Failed to parse macro definition: '), |
| 138 | # 4. No close paren |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 139 | ('PDDM-DEFINE foo(\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 140 | 'Failed to parse macro definition: '), |
| 141 | # 5. No close paren (with args) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 142 | ('PDDM-DEFINE foo(a, b\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 143 | 'Failed to parse macro definition: '), |
| 144 | # 6. No name before args |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 145 | ('PDDM-DEFINE (a, b)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 146 | 'Failed to parse macro definition: '), |
| 147 | # 7. No name before args |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 148 | ('PDDM-DEFINE foo bar(a, b)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 149 | 'Failed to parse macro definition: '), |
| 150 | # 8. Empty arg name |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 151 | ('PDDM-DEFINE foo(a, ,b)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 152 | 'Empty arg name in macro definition: '), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 153 | ('PDDM-DEFINE foo(a,,b)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 154 | 'Empty arg name in macro definition: '), |
| 155 | # 10. Duplicate name |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 156 | ('PDDM-DEFINE foo(a,b,a,c)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 157 | 'Arg name "a" used more than once in macro definition: '), |
| 158 | # 11. Invalid arg name |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 159 | ('PDDM-DEFINE foo(a b,c)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 160 | 'Invalid arg name "a b" in macro definition: '), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 161 | ('PDDM-DEFINE foo(a.b,c)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 162 | 'Invalid arg name "a.b" in macro definition: '), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 163 | ('PDDM-DEFINE foo(a-b,c)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 164 | 'Invalid arg name "a-b" in macro definition: '), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 165 | ('PDDM-DEFINE foo(a,b,c.)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 166 | 'Invalid arg name "c." in macro definition: '), |
| 167 | # 15. Extra stuff after the name |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 168 | ('PDDM-DEFINE foo(a,c) foo\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 169 | 'Failed to parse macro definition: '), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 170 | ('PDDM-DEFINE foo(a,c) foo)\nmumble', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 171 | '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 | |
| 183 | class TestExpandingMacros(unittest.TestCase): |
| 184 | |
| 185 | def testExpandBasics(self): |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 186 | f = io.StringIO(""" |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 187 | PDDM-DEFINE noArgs( ) |
| 188 | body1 |
| 189 | body2 |
| 190 | |
| 191 | PDDM-DEFINE-END |
| 192 | |
| 193 | PDDM-DEFINE oneArg(a) |
| 194 | body3 a |
| 195 | |
| 196 | PDDM-DEFINE-END |
| 197 | |
| 198 | PDDM-DEFINE twoArgs(b,c) |
| 199 | body4 b c |
| 200 | body5 |
| 201 | PDDM-DEFINE-END |
| 202 | |
| 203 | """) |
| 204 | mc = pddm.MacroCollection(f) |
| 205 | test_list = [ |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 206 | ('noArgs()', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 207 | 'body1\nbody2\n'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 208 | ('oneArg(wee)', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 209 | 'body3 wee\n'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 210 | ('twoArgs(having some, fun)', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 211 | 'body4 having some fun\nbody5'), |
| 212 | # One arg, pass empty. |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 213 | ('oneArg()', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 214 | 'body3 \n'), |
| 215 | # Two args, gets empty in each slot. |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 216 | ('twoArgs(, empty)', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 217 | 'body4 empty\nbody5'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 218 | ('twoArgs(empty, )', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 219 | 'body4 empty \nbody5'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 220 | ('twoArgs(, )', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 221 | '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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 230 | f = io.StringIO(""" |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 231 | PDDM-DEFINE bar(a) |
| 232 | a-a$S-a$l-a$L-a$u-a$U |
| 233 | PDDM-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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 243 | f = io.StringIO(""" |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 244 | PDDM-DEFINE foo(a, b) |
| 245 | <a-z> |
| 246 | PDDM-DEFINE baz(a) |
| 247 | a - a$z |
| 248 | """) |
| 249 | mc = pddm.MacroCollection(f) |
| 250 | test_list = [ |
| 251 | # 1. Unknown macro |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 252 | ('bar()', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 253 | 'No macro named "bar".'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 254 | ('bar(a)', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 255 | 'No macro named "bar".'), |
| 256 | # 3. Arg mismatch |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 257 | ('foo()', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 258 | 'Expected 2 args, got: "foo()".'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 259 | ('foo(a b)', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 260 | 'Expected 2 args, got: "foo(a b)".'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 261 | ('foo(a,b,c)', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 262 | 'Expected 2 args, got: "foo(a,b,c)".'), |
| 263 | # 6. Unknown option in expansion |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 264 | ('baz(mumble)', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 265 | '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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 276 | f = io.StringIO(""" |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 277 | PDDM-DEFINE StartIt() |
| 278 | foo(abc, def) |
| 279 | foo(ghi, jkl) |
| 280 | PDDM-DEFINE foo(a, b) |
| 281 | bar(a, int) |
| 282 | bar(b, NSString *) |
| 283 | PDDM-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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 304 | f = io.StringIO(""" |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 305 | PDDM-DEFINE foo(a, b) |
| 306 | bar(1, a) |
| 307 | bar(2, b) |
| 308 | PDDM-DEFINE bar(x, y) |
| 309 | foo(x, y) |
| 310 | """) |
| 311 | mc = pddm.MacroCollection(f) |
| 312 | try: |
| 313 | result = mc.Expand('foo(A,B)') |
kvukic | 8529f2a | 2017-12-27 21:27:47 +0100 | [diff] [blame] | 314 | self.fail('Should throw exception! Test failed to catch recursion.') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 315 | except pddm.PDDMError as e: |
| 316 | self.assertEqual(e.message, |
Brian Wignall | a104dff | 2020-01-08 13:18:20 -0500 | [diff] [blame] | 317 | 'Found macro recursion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 318 | |
| 319 | |
| 320 | class TestParsingSource(unittest.TestCase): |
| 321 | |
| 322 | def testBasicParse(self): |
| 323 | test_list = [ |
| 324 | # 1. no directives |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 325 | ('a\nb\nc', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 326 | (3,) ), |
| 327 | # 2. One define |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 328 | ('a\n//%PDDM-DEFINE foo()\n//%body\nc', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 329 | (1, 2, 1) ), |
| 330 | # 3. Two defines |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 331 | ('a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE bar()\n//%body2\nc', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 332 | (1, 4, 1) ), |
| 333 | # 4. Two defines with ends |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 334 | ('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 Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 336 | (1, 6, 1) ), |
| 337 | # 5. One expand, one define (that runs to end of file) |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 338 | ('a\n//%PDDM-EXPAND foo()\nbody\n//%PDDM-EXPAND-END\n' |
| 339 | '//%PDDM-DEFINE bar()\n//%body2\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 340 | (1, 1, 2) ), |
| 341 | # 6. One define ended with an expand. |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 342 | ('a\nb\n//%PDDM-DEFINE bar()\n//%body2\n' |
| 343 | '//%PDDM-EXPAND bar()\nbody2\n//%PDDM-EXPAND-END\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 344 | (2, 2, 1) ), |
| 345 | # 7. Two expands (one end), one define. |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 346 | ('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 Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 348 | (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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 365 | ('//%PDDM-EXPAND a()\n//%PDDM-BOGUS', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 366 | 'Ran into directive ("//%PDDM-BOGUS", line 2) while in "//%PDDM-EXPAND a()".'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 367 | ('//%PDDM-EXPAND a()\n//%PDDM-DEFINE a()\n//%body\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 368 | 'Ran into directive ("//%PDDM-DEFINE", line 2) while in "//%PDDM-EXPAND a()".'), |
| 369 | # 3. Expansion ran off end of file |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 370 | ('//%PDDM-EXPAND a()\na\nb\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 371 | 'Hit the end of the file while in "//%PDDM-EXPAND a()".'), |
| 372 | # 4. Directive within define |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 373 | ('//%PDDM-DEFINE a()\n//%body\n//%PDDM-BOGUS', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 374 | 'Ran into directive ("//%PDDM-BOGUS", line 3) while in "//%PDDM-DEFINE a()".'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 375 | ('//%PDDM-DEFINE a()\n//%body\n//%PDDM-EXPAND-END a()', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 376 | 'Ran into directive ("//%PDDM-EXPAND-END", line 3) while in "//%PDDM-DEFINE a()".'), |
| 377 | # 6. Directives that shouldn't start sections |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 378 | ('a\n//%PDDM-DEFINE-END a()\n//a\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 379 | 'Unexpected line 2: "//%PDDM-DEFINE-END a()".'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 380 | ('a\n//%PDDM-EXPAND-END a()\n//a\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 381 | 'Unexpected line 2: "//%PDDM-EXPAND-END a()".'), |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 382 | ('//%PDDM-BOGUS\n//a\n', |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 383 | '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 | |
| 394 | class TestProcessingSource(unittest.TestCase): |
| 395 | |
| 396 | def testBasics(self): |
Dave MacLachlan | ab48ecf | 2020-01-20 13:47:20 -0800 | [diff] [blame] | 397 | self.maxDiff = None |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 398 | input_str = """ |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 399 | //%PDDM-IMPORT-DEFINES ImportFile |
| 400 | foo |
| 401 | //%PDDM-EXPAND mumble(abc) |
| 402 | //%PDDM-EXPAND-END |
| 403 | bar |
| 404 | //%PDDM-EXPAND mumble(def) |
| 405 | //%PDDM-EXPAND mumble(ghi) |
| 406 | //%PDDM-EXPAND-END |
| 407 | baz |
| 408 | //%PDDM-DEFINE mumble(a_) |
| 409 | //%a_: getName(a_) |
| 410 | """ |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 411 | input_str2 = """ |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 412 | //%PDDM-DEFINE getName(x_) |
| 413 | //%do##x_$u##(int x_); |
| 414 | |
| 415 | """ |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 416 | expected = """ |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 417 | //%PDDM-IMPORT-DEFINES ImportFile |
| 418 | foo |
| 419 | //%PDDM-EXPAND mumble(abc) |
| 420 | // This block of code is generated, do not edit it directly. |
| 421 | |
| 422 | abc: doAbc(int abc); |
| 423 | //%PDDM-EXPAND-END mumble(abc) |
| 424 | bar |
| 425 | //%PDDM-EXPAND mumble(def) |
| 426 | // This block of code is generated, do not edit it directly. |
| 427 | |
| 428 | def: doDef(int def); |
| 429 | //%PDDM-EXPAND mumble(ghi) |
| 430 | // This block of code is generated, do not edit it directly. |
| 431 | |
| 432 | ghi: doGhi(int ghi); |
| 433 | //%PDDM-EXPAND-END (2 expansions) |
| 434 | baz |
| 435 | //%PDDM-DEFINE mumble(a_) |
| 436 | //%a_: getName(a_) |
| 437 | """ |
Thomas Van Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 438 | expected_stripped = """ |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 439 | //%PDDM-IMPORT-DEFINES ImportFile |
| 440 | foo |
| 441 | //%PDDM-EXPAND mumble(abc) |
| 442 | //%PDDM-EXPAND-END mumble(abc) |
| 443 | bar |
| 444 | //%PDDM-EXPAND mumble(def) |
| 445 | //%PDDM-EXPAND mumble(ghi) |
| 446 | //%PDDM-EXPAND-END (2 expansions) |
| 447 | baz |
| 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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 475 | input_str = """ |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 476 | foo |
| 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() |
kvukic | 8529f2a | 2017-12-27 21:27:47 +0100 | [diff] [blame] | 487 | self.fail('Should throw exception! Test failed to catch macro parsing error.') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 488 | 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 Lenten | 1e60bd6 | 2022-04-05 10:36:07 -0400 | [diff] [blame] | 495 | input_str = """ |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 496 | foo |
| 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() |
kvukic | 8529f2a | 2017-12-27 21:27:47 +0100 | [diff] [blame] | 507 | self.fail('Should throw exception! Test failed to catch expand error.') |
Thomas Van Lenten | 30650d8 | 2015-05-01 08:57:16 -0400 | [diff] [blame] | 508 | 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 | |
| 515 | if __name__ == '__main__': |
| 516 | unittest.main() |