test_pytree.py 16.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
# Copyright 2006 Google, Inc. All Rights Reserved.
# Licensed to PSF under a Contributor Agreement.

"""Unit tests for pytree.py.

NOTE: Please *don't* add doc strings to individual test methods!
In verbose mode, printing of the module, class and method name is much
more helpful than printing of (the first line of) the docstring,
especially when debugging a test.
"""

12 13 14
from __future__ import with_statement

import sys
15 16
import warnings

17 18 19
# Testing imports
from . import support

20
from lib2to3 import pytree
21 22 23 24 25 26 27 28 29 30 31 32 33

try:
    sorted
except NameError:
    def sorted(lst):
        l = list(lst)
        l.sort()
        return l

class TestNodes(support.TestCase):

    """Unit tests for nodes (Base, Leaf, Node)."""

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
    if sys.version_info >= (2,6):
        # warnings.catch_warnings is new in 2.6.
        def test_deprecated_prefix_methods(self):
            l = pytree.Leaf(100, "foo")
            with warnings.catch_warnings(record=True) as w:
                warnings.simplefilter("always", DeprecationWarning)
                self.assertEqual(l.get_prefix(), "")
                l.set_prefix("hi")
            self.assertEqual(l.prefix, "hi")
            self.assertEqual(len(w), 2)
            for warning in w:
                self.assertTrue(warning.category is DeprecationWarning)
            self.assertEqual(str(w[0].message), "get_prefix() is deprecated; " \
                                 "use the prefix property")
            self.assertEqual(str(w[1].message), "set_prefix() is deprecated; " \
                                 "use the prefix property")
50 51

    def test_instantiate_base(self):
52 53 54 55
        if __debug__:
            # Test that instantiating Base() raises an AssertionError
            self.assertRaises(AssertionError, pytree.Base)

56
    def test_leaf(self):
57 58 59 60
        l1 = pytree.Leaf(100, "foo")
        self.assertEqual(l1.type, 100)
        self.assertEqual(l1.value, "foo")

61
    def test_leaf_repr(self):
62 63 64
        l1 = pytree.Leaf(100, "foo")
        self.assertEqual(repr(l1), "Leaf(100, 'foo')")

65
    def test_leaf_str(self):
66 67 68 69 70
        l1 = pytree.Leaf(100, "foo")
        self.assertEqual(str(l1), "foo")
        l2 = pytree.Leaf(100, "foo", context=(" ", (10, 1)))
        self.assertEqual(str(l2), " foo")

71
    def test_leaf_str_numeric_value(self):
72 73 74
        # Make sure that the Leaf's value is stringified. Failing to
        #  do this can cause a TypeError in certain situations.
        l1 = pytree.Leaf(2, 5)
75
        l1.prefix = "foo_"
76 77
        self.assertEqual(str(l1), "foo_5")

78
    def test_leaf_equality(self):
79 80 81 82 83 84 85 86
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "foo", context=(" ", (1, 0)))
        self.assertEqual(l1, l2)
        l3 = pytree.Leaf(101, "foo")
        l4 = pytree.Leaf(100, "bar")
        self.assertNotEqual(l1, l3)
        self.assertNotEqual(l1, l4)

87
    def test_leaf_prefix(self):
88
        l1 = pytree.Leaf(100, "foo")
89
        self.assertEqual(l1.prefix, "")
90
        self.assertFalse(l1.was_changed)
91 92
        l1.prefix = "  ##\n\n"
        self.assertEqual(l1.prefix, "  ##\n\n")
93
        self.assertTrue(l1.was_changed)
94

95
    def test_node(self):
96 97 98 99 100 101
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(200, "bar")
        n1 = pytree.Node(1000, [l1, l2])
        self.assertEqual(n1.type, 1000)
        self.assertEqual(n1.children, [l1, l2])

102
    def test_node_repr(self):
103 104 105 106 107 108
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar", context=(" ", (1, 0)))
        n1 = pytree.Node(1000, [l1, l2])
        self.assertEqual(repr(n1),
                         "Node(1000, [%s, %s])" % (repr(l1), repr(l2)))

109
    def test_node_str(self):
110 111 112 113 114
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar", context=(" ", (1, 0)))
        n1 = pytree.Node(1000, [l1, l2])
        self.assertEqual(str(n1), "foo bar")

115
    def test_node_prefix(self):
116
        l1 = pytree.Leaf(100, "foo")
117
        self.assertEqual(l1.prefix, "")
118
        n1 = pytree.Node(1000, [l1])
119 120 121 122
        self.assertEqual(n1.prefix, "")
        n1.prefix = " "
        self.assertEqual(n1.prefix, " ")
        self.assertEqual(l1.prefix, " ")
123

124
    def test_get_suffix(self):
125 126 127 128
        l1 = pytree.Leaf(100, "foo", prefix="a")
        l2 = pytree.Leaf(100, "bar", prefix="b")
        n1 = pytree.Node(1000, [l1, l2])

129
        self.assertEqual(l1.get_suffix(), l2.prefix)
130 131 132 133 134 135
        self.assertEqual(l2.get_suffix(), "")
        self.assertEqual(n1.get_suffix(), "")

        l3 = pytree.Leaf(100, "bar", prefix="c")
        n2 = pytree.Node(1000, [n1, l3])

136
        self.assertEqual(n1.get_suffix(), l3.prefix)
137 138 139
        self.assertEqual(l3.get_suffix(), "")
        self.assertEqual(n2.get_suffix(), "")

140
    def test_node_equality(self):
141 142 143 144 145 146
        n1 = pytree.Node(1000, ())
        n2 = pytree.Node(1000, [], context=(" ", (1, 0)))
        self.assertEqual(n1, n2)
        n3 = pytree.Node(1001, ())
        self.assertNotEqual(n1, n3)

147
    def test_node_recursive_equality(self):
148 149 150 151 152 153 154 155 156
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1])
        n2 = pytree.Node(1000, [l2])
        self.assertEqual(n1, n2)
        l3 = pytree.Leaf(100, "bar")
        n3 = pytree.Node(1000, [l3])
        self.assertNotEqual(n1, n3)

157
    def test_replace(self):
158 159 160 161 162
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "+")
        l3 = pytree.Leaf(100, "bar")
        n1 = pytree.Node(1000, [l1, l2, l3])
        self.assertEqual(n1.children, [l1, l2, l3])
163 164
        self.assertTrue(isinstance(n1.children, list))
        self.assertFalse(n1.was_changed)
165 166 167
        l2new = pytree.Leaf(100, "-")
        l2.replace(l2new)
        self.assertEqual(n1.children, [l1, l2new, l3])
168 169
        self.assertTrue(isinstance(n1.children, list))
        self.assertTrue(n1.was_changed)
170

171
    def test_replace_with_list(self):
172 173 174 175 176 177 178
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "+")
        l3 = pytree.Leaf(100, "bar")
        n1 = pytree.Node(1000, [l1, l2, l3])

        l2.replace([pytree.Leaf(100, "*"), pytree.Leaf(100, "*")])
        self.assertEqual(str(n1), "foo**bar")
179
        self.assertTrue(isinstance(n1.children, list))
180

181
    def test_post_order(self):
182 183
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar")
Benjamin Peterson's avatar
Benjamin Peterson committed
184 185 186 187
        l3 = pytree.Leaf(100, "fooey")
        c1 = pytree.Node(1000, [l1, l2])
        n1 = pytree.Node(1000, [c1, l3])
        self.assertEqual(list(n1.post_order()), [l1, l2, c1, l3, n1])
188

189
    def test_pre_order(self):
190 191
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar")
Benjamin Peterson's avatar
Benjamin Peterson committed
192 193 194 195
        l3 = pytree.Leaf(100, "fooey")
        c1 = pytree.Node(1000, [l1, l2])
        n1 = pytree.Node(1000, [c1, l3])
        self.assertEqual(list(n1.pre_order()), [n1, c1, l1, l2, l3])
196

197
    def test_changed(self):
198
        l1 = pytree.Leaf(100, "f")
199
        self.assertFalse(l1.was_changed)
200
        l1.changed()
201
        self.assertTrue(l1.was_changed)
202 203 204

        l1 = pytree.Leaf(100, "f")
        n1 = pytree.Node(1000, [l1])
205
        self.assertFalse(n1.was_changed)
206
        n1.changed()
207
        self.assertTrue(n1.was_changed)
208 209 210 211 212 213

        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "+")
        l3 = pytree.Leaf(100, "bar")
        n1 = pytree.Node(1000, [l1, l2, l3])
        n2 = pytree.Node(1000, [n1])
214 215 216
        self.assertFalse(l1.was_changed)
        self.assertFalse(n1.was_changed)
        self.assertFalse(n2.was_changed)
217 218

        n1.changed()
219 220 221
        self.assertTrue(n1.was_changed)
        self.assertTrue(n2.was_changed)
        self.assertFalse(l1.was_changed)
222

223
    def test_leaf_constructor_prefix(self):
224 225
        for prefix in ("xyz_", ""):
            l1 = pytree.Leaf(100, "self", prefix=prefix)
226
            self.assertTrue(str(l1), prefix + "self")
227
            self.assertEqual(l1.prefix, prefix)
228

229
    def test_node_constructor_prefix(self):
230 231 232 233
        for prefix in ("xyz_", ""):
            l1 = pytree.Leaf(100, "self")
            l2 = pytree.Leaf(100, "foo", prefix="_")
            n1 = pytree.Node(1000, [l1, l2], prefix=prefix)
234
            self.assertTrue(str(n1), prefix + "self_foo")
235 236 237
            self.assertEqual(n1.prefix, prefix)
            self.assertEqual(l1.prefix, prefix)
            self.assertEqual(l2.prefix, "_")
238

239
    def test_remove(self):
240 241 242 243 244 245 246 247 248 249
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1, l2])
        n2 = pytree.Node(1000, [n1])

        self.assertEqual(n1.remove(), 0)
        self.assertEqual(n2.children, [])
        self.assertEqual(l1.parent, n1)
        self.assertEqual(n1.parent, None)
        self.assertEqual(n2.parent, None)
250 251
        self.assertFalse(n1.was_changed)
        self.assertTrue(n2.was_changed)
252 253 254 255 256 257 258

        self.assertEqual(l2.remove(), 1)
        self.assertEqual(l1.remove(), 0)
        self.assertEqual(n1.children, [])
        self.assertEqual(l1.parent, None)
        self.assertEqual(n1.parent, None)
        self.assertEqual(n2.parent, None)
259 260
        self.assertTrue(n1.was_changed)
        self.assertTrue(n2.was_changed)
261

262
    def test_remove_parentless(self):
263 264 265 266 267 268 269 270
        n1 = pytree.Node(1000, [])
        n1.remove()
        self.assertEqual(n1.parent, None)

        l1 = pytree.Leaf(100, "foo")
        l1.remove()
        self.assertEqual(l1.parent, None)

271
    def test_node_set_child(self):
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
        l1 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1])

        l2 = pytree.Leaf(100, "bar")
        n1.set_child(0, l2)
        self.assertEqual(l1.parent, None)
        self.assertEqual(l2.parent, n1)
        self.assertEqual(n1.children, [l2])

        n2 = pytree.Node(1000, [l1])
        n2.set_child(0, n1)
        self.assertEqual(l1.parent, None)
        self.assertEqual(n1.parent, n2)
        self.assertEqual(n2.parent, None)
        self.assertEqual(n2.children, [n1])

        self.assertRaises(IndexError, n1.set_child, 4, l2)
        # I don't care what it raises, so long as it's an exception
        self.assertRaises(Exception, n1.set_child, 0, list)

292
    def test_node_insert_child(self):
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
        l1 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1])

        l2 = pytree.Leaf(100, "bar")
        n1.insert_child(0, l2)
        self.assertEqual(l2.parent, n1)
        self.assertEqual(n1.children, [l2, l1])

        l3 = pytree.Leaf(100, "abc")
        n1.insert_child(2, l3)
        self.assertEqual(n1.children, [l2, l1, l3])

        # I don't care what it raises, so long as it's an exception
        self.assertRaises(Exception, n1.insert_child, 0, list)

308
    def test_node_append_child(self):
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
        n1 = pytree.Node(1000, [])

        l1 = pytree.Leaf(100, "foo")
        n1.append_child(l1)
        self.assertEqual(l1.parent, n1)
        self.assertEqual(n1.children, [l1])

        l2 = pytree.Leaf(100, "bar")
        n1.append_child(l2)
        self.assertEqual(l2.parent, n1)
        self.assertEqual(n1.children, [l1, l2])

        # I don't care what it raises, so long as it's an exception
        self.assertRaises(Exception, n1.append_child, list)

324
    def test_node_next_sibling(self):
325 326 327 328
        n1 = pytree.Node(1000, [])
        n2 = pytree.Node(1000, [])
        p1 = pytree.Node(1000, [n1, n2])

329
        self.assertTrue(n1.next_sibling is n2)
330 331
        self.assertEqual(n2.next_sibling, None)
        self.assertEqual(p1.next_sibling, None)
332

333
    def test_leaf_next_sibling(self):
334 335 336 337
        l1 = pytree.Leaf(100, "a")
        l2 = pytree.Leaf(100, "b")
        p1 = pytree.Node(1000, [l1, l2])

338
        self.assertTrue(l1.next_sibling is l2)
339 340
        self.assertEqual(l2.next_sibling, None)
        self.assertEqual(p1.next_sibling, None)
341

342
    def test_node_prev_sibling(self):
343 344 345 346
        n1 = pytree.Node(1000, [])
        n2 = pytree.Node(1000, [])
        p1 = pytree.Node(1000, [n1, n2])

347
        self.assertTrue(n2.prev_sibling is n1)
348 349
        self.assertEqual(n1.prev_sibling, None)
        self.assertEqual(p1.prev_sibling, None)
350

351
    def test_leaf_prev_sibling(self):
352 353 354 355
        l1 = pytree.Leaf(100, "a")
        l2 = pytree.Leaf(100, "b")
        p1 = pytree.Node(1000, [l1, l2])

356
        self.assertTrue(l2.prev_sibling is l1)
357 358
        self.assertEqual(l1.prev_sibling, None)
        self.assertEqual(p1.prev_sibling, None)
359

360 361 362 363 364

class TestPatterns(support.TestCase):

    """Unit tests for tree matching patterns."""

365
    def test_basic_patterns(self):
366 367 368 369 370 371 372 373 374 375
        # Build a tree
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar")
        l3 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1, l2])
        n2 = pytree.Node(1000, [l3])
        root = pytree.Node(1000, [n1, n2])
        # Build a pattern matching a leaf
        pl = pytree.LeafPattern(100, "foo", name="pl")
        r = {}
Benjamin Peterson's avatar
Benjamin Peterson committed
376
        self.assertFalse(pl.match(root, results=r))
377
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
378
        self.assertFalse(pl.match(n1, results=r))
379
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
380
        self.assertFalse(pl.match(n2, results=r))
381
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
382
        self.assertTrue(pl.match(l1, results=r))
383 384
        self.assertEqual(r, {"pl": l1})
        r = {}
Benjamin Peterson's avatar
Benjamin Peterson committed
385
        self.assertFalse(pl.match(l2, results=r))
386 387 388
        self.assertEqual(r, {})
        # Build a pattern matching a node
        pn = pytree.NodePattern(1000, [pl], name="pn")
Benjamin Peterson's avatar
Benjamin Peterson committed
389
        self.assertFalse(pn.match(root, results=r))
390
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
391
        self.assertFalse(pn.match(n1, results=r))
392
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
393
        self.assertTrue(pn.match(n2, results=r))
394 395
        self.assertEqual(r, {"pn": n2, "pl": l3})
        r = {}
Benjamin Peterson's avatar
Benjamin Peterson committed
396
        self.assertFalse(pn.match(l1, results=r))
397
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
398
        self.assertFalse(pn.match(l2, results=r))
399 400
        self.assertEqual(r, {})

401
    def test_wildcard(self):
402 403 404 405 406 407 408 409 410 411 412 413
        # Build a tree for testing
        l1 = pytree.Leaf(100, "foo")
        l2 = pytree.Leaf(100, "bar")
        l3 = pytree.Leaf(100, "foo")
        n1 = pytree.Node(1000, [l1, l2])
        n2 = pytree.Node(1000, [l3])
        root = pytree.Node(1000, [n1, n2])
        # Build a pattern
        pl = pytree.LeafPattern(100, "foo", name="pl")
        pn = pytree.NodePattern(1000, [pl], name="pn")
        pw = pytree.WildcardPattern([[pn], [pl, pl]], name="pw")
        r = {}
Benjamin Peterson's avatar
Benjamin Peterson committed
414
        self.assertFalse(pw.match_seq([root], r))
415
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
416
        self.assertFalse(pw.match_seq([n1], r))
417
        self.assertEqual(r, {})
Benjamin Peterson's avatar
Benjamin Peterson committed
418
        self.assertTrue(pw.match_seq([n2], r))
419 420 421 422 423 424 425 426
        # These are easier to debug
        self.assertEqual(sorted(r.keys()), ["pl", "pn", "pw"])
        self.assertEqual(r["pl"], l1)
        self.assertEqual(r["pn"], n2)
        self.assertEqual(r["pw"], [n2])
        # But this is equivalent
        self.assertEqual(r, {"pl": l1, "pn": n2, "pw": [n2]})
        r = {}
Benjamin Peterson's avatar
Benjamin Peterson committed
427
        self.assertTrue(pw.match_seq([l1, l3], r))
428
        self.assertEqual(r, {"pl": l3, "pw": [l1, l3]})
429
        self.assertTrue(r["pl"] is l3)
430 431
        r = {}

432
    def test_generate_matches(self):
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
        la = pytree.Leaf(1, "a")
        lb = pytree.Leaf(1, "b")
        lc = pytree.Leaf(1, "c")
        ld = pytree.Leaf(1, "d")
        le = pytree.Leaf(1, "e")
        lf = pytree.Leaf(1, "f")
        leaves = [la, lb, lc, ld, le, lf]
        root = pytree.Node(1000, leaves)
        pa = pytree.LeafPattern(1, "a", "pa")
        pb = pytree.LeafPattern(1, "b", "pb")
        pc = pytree.LeafPattern(1, "c", "pc")
        pd = pytree.LeafPattern(1, "d", "pd")
        pe = pytree.LeafPattern(1, "e", "pe")
        pf = pytree.LeafPattern(1, "f", "pf")
        pw = pytree.WildcardPattern([[pa, pb, pc], [pd, pe],
448
                                     [pa, pb], [pc, pd], [pe, pf]],
449 450
                                    min=1, max=4, name="pw")
        self.assertEqual([x[0] for x in pw.generate_matches(leaves)],
451
                         [3, 5, 2, 4, 6])
452 453 454 455 456 457 458 459 460 461
        pr = pytree.NodePattern(type=1000, content=[pw], name="pr")
        matches = list(pytree.generate_matches([pr], [root]))
        self.assertEqual(len(matches), 1)
        c, r = matches[0]
        self.assertEqual(c, 1)
        self.assertEqual(str(r["pr"]), "abcdef")
        self.assertEqual(r["pw"], [la, lb, lc, ld, le, lf])
        for c in "abcdef":
            self.assertEqual(r["p" + c], pytree.Leaf(1, c))

462
    def test_has_key_example(self):
463 464 465 466 467 468 469 470 471
        pattern = pytree.NodePattern(331,
                                     (pytree.LeafPattern(7),
                                      pytree.WildcardPattern(name="args"),
                                      pytree.LeafPattern(8)))
        l1 = pytree.Leaf(7, "(")
        l2 = pytree.Leaf(3, "x")
        l3 = pytree.Leaf(8, ")")
        node = pytree.Node(331, [l1, l2, l3])
        r = {}
472
        self.assertTrue(pattern.match(node, r))
473
        self.assertEqual(r["args"], [l2])