1*7249d1a6SKrzysztof Kosiński# Copyright 2015 Google Inc. All Rights Reserved. 2*7249d1a6SKrzysztof Kosiński# 3*7249d1a6SKrzysztof Kosiński# Licensed under the Apache License, Version 2.0 (the "License"); 4*7249d1a6SKrzysztof Kosiński# you may not use this file except in compliance with the License. 5*7249d1a6SKrzysztof Kosiński# You may obtain a copy of the License at 6*7249d1a6SKrzysztof Kosiński# 7*7249d1a6SKrzysztof Kosiński# http://www.apache.org/licenses/LICENSE-2.0 8*7249d1a6SKrzysztof Kosiński# 9*7249d1a6SKrzysztof Kosiński# Unless required by applicable law or agreed to in writing, software 10*7249d1a6SKrzysztof Kosiński# distributed under the License is distributed on an "AS IS" BASIS, 11*7249d1a6SKrzysztof Kosiński# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*7249d1a6SKrzysztof Kosiński# See the License for the specific language governing permissions and 13*7249d1a6SKrzysztof Kosiński# limitations under the License. 14*7249d1a6SKrzysztof Kosiński"""Tests for yapf.pytree_utils.""" 15*7249d1a6SKrzysztof Kosiński 16*7249d1a6SKrzysztof Kosińskiimport unittest 17*7249d1a6SKrzysztof Kosiński 18*7249d1a6SKrzysztof Kosińskifrom lib2to3 import pygram 19*7249d1a6SKrzysztof Kosińskifrom lib2to3 import pytree 20*7249d1a6SKrzysztof Kosińskifrom lib2to3.pgen2 import token 21*7249d1a6SKrzysztof Kosiński 22*7249d1a6SKrzysztof Kosińskifrom yapf.yapflib import pytree_utils 23*7249d1a6SKrzysztof Kosiński 24*7249d1a6SKrzysztof Kosiński# More direct access to the symbol->number mapping living within the grammar 25*7249d1a6SKrzysztof Kosiński# module. 26*7249d1a6SKrzysztof Kosiński_GRAMMAR_SYMBOL2NUMBER = pygram.python_grammar.symbol2number 27*7249d1a6SKrzysztof Kosiński 28*7249d1a6SKrzysztof Kosiński_FOO = 'foo' 29*7249d1a6SKrzysztof Kosiński_FOO1 = 'foo1' 30*7249d1a6SKrzysztof Kosiński_FOO2 = 'foo2' 31*7249d1a6SKrzysztof Kosiński_FOO3 = 'foo3' 32*7249d1a6SKrzysztof Kosiński_FOO4 = 'foo4' 33*7249d1a6SKrzysztof Kosiński_FOO5 = 'foo5' 34*7249d1a6SKrzysztof Kosiński 35*7249d1a6SKrzysztof Kosiński 36*7249d1a6SKrzysztof Kosińskiclass NodeNameTest(unittest.TestCase): 37*7249d1a6SKrzysztof Kosiński 38*7249d1a6SKrzysztof Kosiński def testNodeNameForLeaf(self): 39*7249d1a6SKrzysztof Kosiński leaf = pytree.Leaf(token.LPAR, '(') 40*7249d1a6SKrzysztof Kosiński self.assertEqual('LPAR', pytree_utils.NodeName(leaf)) 41*7249d1a6SKrzysztof Kosiński 42*7249d1a6SKrzysztof Kosiński def testNodeNameForNode(self): 43*7249d1a6SKrzysztof Kosiński leaf = pytree.Leaf(token.LPAR, '(') 44*7249d1a6SKrzysztof Kosiński node = pytree.Node(pygram.python_grammar.symbol2number['suite'], [leaf]) 45*7249d1a6SKrzysztof Kosiński self.assertEqual('suite', pytree_utils.NodeName(node)) 46*7249d1a6SKrzysztof Kosiński 47*7249d1a6SKrzysztof Kosiński 48*7249d1a6SKrzysztof Kosińskiclass ParseCodeToTreeTest(unittest.TestCase): 49*7249d1a6SKrzysztof Kosiński 50*7249d1a6SKrzysztof Kosiński def testParseCodeToTree(self): 51*7249d1a6SKrzysztof Kosiński # Since ParseCodeToTree is a thin wrapper around underlying lib2to3 52*7249d1a6SKrzysztof Kosiński # functionality, only a sanity test here... 53*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree('foo = 2\n') 54*7249d1a6SKrzysztof Kosiński self.assertEqual('file_input', pytree_utils.NodeName(tree)) 55*7249d1a6SKrzysztof Kosiński self.assertEqual(2, len(tree.children)) 56*7249d1a6SKrzysztof Kosiński self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0])) 57*7249d1a6SKrzysztof Kosiński 58*7249d1a6SKrzysztof Kosiński def testPrintFunctionToTree(self): 59*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree( 60*7249d1a6SKrzysztof Kosiński 'print("hello world", file=sys.stderr)\n') 61*7249d1a6SKrzysztof Kosiński self.assertEqual('file_input', pytree_utils.NodeName(tree)) 62*7249d1a6SKrzysztof Kosiński self.assertEqual(2, len(tree.children)) 63*7249d1a6SKrzysztof Kosiński self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0])) 64*7249d1a6SKrzysztof Kosiński 65*7249d1a6SKrzysztof Kosiński def testPrintStatementToTree(self): 66*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree('print "hello world"\n') 67*7249d1a6SKrzysztof Kosiński self.assertEqual('file_input', pytree_utils.NodeName(tree)) 68*7249d1a6SKrzysztof Kosiński self.assertEqual(2, len(tree.children)) 69*7249d1a6SKrzysztof Kosiński self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0])) 70*7249d1a6SKrzysztof Kosiński 71*7249d1a6SKrzysztof Kosiński def testClassNotLocal(self): 72*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree('class nonlocal: pass\n') 73*7249d1a6SKrzysztof Kosiński self.assertEqual('file_input', pytree_utils.NodeName(tree)) 74*7249d1a6SKrzysztof Kosiński self.assertEqual(2, len(tree.children)) 75*7249d1a6SKrzysztof Kosiński self.assertEqual('classdef', pytree_utils.NodeName(tree.children[0])) 76*7249d1a6SKrzysztof Kosiński 77*7249d1a6SKrzysztof Kosiński 78*7249d1a6SKrzysztof Kosińskiclass InsertNodesBeforeAfterTest(unittest.TestCase): 79*7249d1a6SKrzysztof Kosiński 80*7249d1a6SKrzysztof Kosiński def _BuildSimpleTree(self): 81*7249d1a6SKrzysztof Kosiński # Builds a simple tree we can play with in the tests. 82*7249d1a6SKrzysztof Kosiński # The tree looks like this: 83*7249d1a6SKrzysztof Kosiński # 84*7249d1a6SKrzysztof Kosiński # suite: 85*7249d1a6SKrzysztof Kosiński # LPAR 86*7249d1a6SKrzysztof Kosiński # LPAR 87*7249d1a6SKrzysztof Kosiński # simple_stmt: 88*7249d1a6SKrzysztof Kosiński # NAME('foo') 89*7249d1a6SKrzysztof Kosiński # 90*7249d1a6SKrzysztof Kosiński lpar1 = pytree.Leaf(token.LPAR, '(') 91*7249d1a6SKrzysztof Kosiński lpar2 = pytree.Leaf(token.LPAR, '(') 92*7249d1a6SKrzysztof Kosiński simple_stmt = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'], 93*7249d1a6SKrzysztof Kosiński [pytree.Leaf(token.NAME, 'foo')]) 94*7249d1a6SKrzysztof Kosiński return pytree.Node(_GRAMMAR_SYMBOL2NUMBER['suite'], 95*7249d1a6SKrzysztof Kosiński [lpar1, lpar2, simple_stmt]) 96*7249d1a6SKrzysztof Kosiński 97*7249d1a6SKrzysztof Kosiński def _MakeNewNodeRPAR(self): 98*7249d1a6SKrzysztof Kosiński return pytree.Leaf(token.RPAR, ')') 99*7249d1a6SKrzysztof Kosiński 100*7249d1a6SKrzysztof Kosiński def setUp(self): 101*7249d1a6SKrzysztof Kosiński self._simple_tree = self._BuildSimpleTree() 102*7249d1a6SKrzysztof Kosiński 103*7249d1a6SKrzysztof Kosiński def testInsertNodesBefore(self): 104*7249d1a6SKrzysztof Kosiński # Insert before simple_stmt and make sure it went to the right place 105*7249d1a6SKrzysztof Kosiński pytree_utils.InsertNodesBefore([self._MakeNewNodeRPAR()], 106*7249d1a6SKrzysztof Kosiński self._simple_tree.children[2]) 107*7249d1a6SKrzysztof Kosiński self.assertEqual(4, len(self._simple_tree.children)) 108*7249d1a6SKrzysztof Kosiński self.assertEqual('RPAR', 109*7249d1a6SKrzysztof Kosiński pytree_utils.NodeName(self._simple_tree.children[2])) 110*7249d1a6SKrzysztof Kosiński self.assertEqual('simple_stmt', 111*7249d1a6SKrzysztof Kosiński pytree_utils.NodeName(self._simple_tree.children[3])) 112*7249d1a6SKrzysztof Kosiński 113*7249d1a6SKrzysztof Kosiński def testInsertNodesBeforeFirstChild(self): 114*7249d1a6SKrzysztof Kosiński # Insert before the first child of its parent 115*7249d1a6SKrzysztof Kosiński simple_stmt = self._simple_tree.children[2] 116*7249d1a6SKrzysztof Kosiński foo_child = simple_stmt.children[0] 117*7249d1a6SKrzysztof Kosiński pytree_utils.InsertNodesBefore([self._MakeNewNodeRPAR()], foo_child) 118*7249d1a6SKrzysztof Kosiński self.assertEqual(3, len(self._simple_tree.children)) 119*7249d1a6SKrzysztof Kosiński self.assertEqual(2, len(simple_stmt.children)) 120*7249d1a6SKrzysztof Kosiński self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[0])) 121*7249d1a6SKrzysztof Kosiński self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[1])) 122*7249d1a6SKrzysztof Kosiński 123*7249d1a6SKrzysztof Kosiński def testInsertNodesAfter(self): 124*7249d1a6SKrzysztof Kosiński # Insert after and make sure it went to the right place 125*7249d1a6SKrzysztof Kosiński pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()], 126*7249d1a6SKrzysztof Kosiński self._simple_tree.children[2]) 127*7249d1a6SKrzysztof Kosiński self.assertEqual(4, len(self._simple_tree.children)) 128*7249d1a6SKrzysztof Kosiński self.assertEqual('simple_stmt', 129*7249d1a6SKrzysztof Kosiński pytree_utils.NodeName(self._simple_tree.children[2])) 130*7249d1a6SKrzysztof Kosiński self.assertEqual('RPAR', 131*7249d1a6SKrzysztof Kosiński pytree_utils.NodeName(self._simple_tree.children[3])) 132*7249d1a6SKrzysztof Kosiński 133*7249d1a6SKrzysztof Kosiński def testInsertNodesAfterLastChild(self): 134*7249d1a6SKrzysztof Kosiński # Insert after the last child of its parent 135*7249d1a6SKrzysztof Kosiński simple_stmt = self._simple_tree.children[2] 136*7249d1a6SKrzysztof Kosiński foo_child = simple_stmt.children[0] 137*7249d1a6SKrzysztof Kosiński pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()], foo_child) 138*7249d1a6SKrzysztof Kosiński self.assertEqual(3, len(self._simple_tree.children)) 139*7249d1a6SKrzysztof Kosiński self.assertEqual(2, len(simple_stmt.children)) 140*7249d1a6SKrzysztof Kosiński self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[0])) 141*7249d1a6SKrzysztof Kosiński self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[1])) 142*7249d1a6SKrzysztof Kosiński 143*7249d1a6SKrzysztof Kosiński def testInsertNodesWhichHasParent(self): 144*7249d1a6SKrzysztof Kosiński # Try to insert an existing tree node into another place and fail. 145*7249d1a6SKrzysztof Kosiński with self.assertRaises(RuntimeError): 146*7249d1a6SKrzysztof Kosiński pytree_utils.InsertNodesAfter([self._simple_tree.children[1]], 147*7249d1a6SKrzysztof Kosiński self._simple_tree.children[0]) 148*7249d1a6SKrzysztof Kosiński 149*7249d1a6SKrzysztof Kosiński 150*7249d1a6SKrzysztof Kosińskiclass AnnotationsTest(unittest.TestCase): 151*7249d1a6SKrzysztof Kosiński 152*7249d1a6SKrzysztof Kosiński def setUp(self): 153*7249d1a6SKrzysztof Kosiński self._leaf = pytree.Leaf(token.LPAR, '(') 154*7249d1a6SKrzysztof Kosiński self._node = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'], 155*7249d1a6SKrzysztof Kosiński [pytree.Leaf(token.NAME, 'foo')]) 156*7249d1a6SKrzysztof Kosiński 157*7249d1a6SKrzysztof Kosiński def testGetWhenNone(self): 158*7249d1a6SKrzysztof Kosiński self.assertIsNone(pytree_utils.GetNodeAnnotation(self._leaf, _FOO)) 159*7249d1a6SKrzysztof Kosiński 160*7249d1a6SKrzysztof Kosiński def testSetWhenNone(self): 161*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20) 162*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20) 163*7249d1a6SKrzysztof Kosiński 164*7249d1a6SKrzysztof Kosiński def testSetAgain(self): 165*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20) 166*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20) 167*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 30) 168*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 30) 169*7249d1a6SKrzysztof Kosiński 170*7249d1a6SKrzysztof Kosiński def testMultiple(self): 171*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20) 172*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO1, 1) 173*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO2, 2) 174*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO3, 3) 175*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO4, 4) 176*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._leaf, _FOO5, 5) 177*7249d1a6SKrzysztof Kosiński 178*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20) 179*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO1), 1) 180*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO2), 2) 181*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO3), 3) 182*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO4), 4) 183*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO5), 5) 184*7249d1a6SKrzysztof Kosiński 185*7249d1a6SKrzysztof Kosiński def testSubtype(self): 186*7249d1a6SKrzysztof Kosiński pytree_utils.AppendNodeAnnotation(self._leaf, 187*7249d1a6SKrzysztof Kosiński pytree_utils.Annotation.SUBTYPE, _FOO) 188*7249d1a6SKrzysztof Kosiński 189*7249d1a6SKrzysztof Kosiński self.assertSetEqual( 190*7249d1a6SKrzysztof Kosiński pytree_utils.GetNodeAnnotation(self._leaf, 191*7249d1a6SKrzysztof Kosiński pytree_utils.Annotation.SUBTYPE), {_FOO}) 192*7249d1a6SKrzysztof Kosiński 193*7249d1a6SKrzysztof Kosiński pytree_utils.RemoveSubtypeAnnotation(self._leaf, _FOO) 194*7249d1a6SKrzysztof Kosiński 195*7249d1a6SKrzysztof Kosiński self.assertSetEqual( 196*7249d1a6SKrzysztof Kosiński pytree_utils.GetNodeAnnotation(self._leaf, 197*7249d1a6SKrzysztof Kosiński pytree_utils.Annotation.SUBTYPE), set()) 198*7249d1a6SKrzysztof Kosiński 199*7249d1a6SKrzysztof Kosiński def testSetOnNode(self): 200*7249d1a6SKrzysztof Kosiński pytree_utils.SetNodeAnnotation(self._node, _FOO, 20) 201*7249d1a6SKrzysztof Kosiński self.assertEqual(pytree_utils.GetNodeAnnotation(self._node, _FOO), 20) 202*7249d1a6SKrzysztof Kosiński 203*7249d1a6SKrzysztof Kosiński 204*7249d1a6SKrzysztof Kosińskiif __name__ == '__main__': 205*7249d1a6SKrzysztof Kosiński unittest.main() 206