1 #!/usr/bin/env python 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 '''Unit tests for base.Node functionality (as used in various subclasses)''' 7 8 9 import os 10 import sys 11 if __name__ == '__main__': 12 sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) 13 14 import StringIO 15 import unittest 16 17 from grit import grd_reader 18 from grit import util 19 from grit.node import base 20 from grit.node import message 21 22 23 def MakePlaceholder(phname='BINGO'): 24 ph = message.PhNode() 25 ph.StartParsing(u'ph', None) 26 ph.HandleAttribute(u'name', phname) 27 ph.AppendContent(u'bongo') 28 ph.EndParsing() 29 return ph 30 31 32 class NodeUnittest(unittest.TestCase): 33 def testWhitespaceHandling(self): 34 # We test using the Message node type. 35 node = message.MessageNode() 36 node.StartParsing(u'hello', None) 37 node.HandleAttribute(u'name', u'bla') 38 node.AppendContent(u" ''' two spaces ") 39 node.EndParsing() 40 self.failUnless(node.GetCdata() == u' two spaces') 41 42 node = message.MessageNode() 43 node.StartParsing(u'message', None) 44 node.HandleAttribute(u'name', u'bla') 45 node.AppendContent(u" two spaces ''' ") 46 node.EndParsing() 47 self.failUnless(node.GetCdata() == u'two spaces ') 48 49 def testWhitespaceHandlingWithChildren(self): 50 # We test using the Message node type. 51 node = message.MessageNode() 52 node.StartParsing(u'message', None) 53 node.HandleAttribute(u'name', u'bla') 54 node.AppendContent(u" ''' two spaces ") 55 node.AddChild(MakePlaceholder()) 56 node.AppendContent(u' space before and after ') 57 node.AddChild(MakePlaceholder('BONGO')) 58 node.AppendContent(u" space before two after '''") 59 node.EndParsing() 60 self.failUnless(node.mixed_content[0] == u' two spaces ') 61 self.failUnless(node.mixed_content[2] == u' space before and after ') 62 self.failUnless(node.mixed_content[-1] == u' space before two after ') 63 64 def testXmlFormatMixedContent(self): 65 # Again test using the Message node type, because it is the only mixed 66 # content node. 67 node = message.MessageNode() 68 node.StartParsing(u'message', None) 69 node.HandleAttribute(u'name', u'name') 70 node.AppendContent(u'Hello <young> ') 71 72 ph = message.PhNode() 73 ph.StartParsing(u'ph', None) 74 ph.HandleAttribute(u'name', u'USERNAME') 75 ph.AppendContent(u'$1') 76 ex = message.ExNode() 77 ex.StartParsing(u'ex', None) 78 ex.AppendContent(u'Joi') 79 ex.EndParsing() 80 ph.AddChild(ex) 81 ph.EndParsing() 82 83 node.AddChild(ph) 84 node.EndParsing() 85 86 non_indented_xml = node.FormatXml() 87 self.failUnless(non_indented_xml == u'<message name="name">\n Hello ' 88 u'<young> <ph name="USERNAME">$1<ex>Joi</ex></ph>' 89 u'\n</message>') 90 91 indented_xml = node.FormatXml(u' ') 92 self.failUnless(indented_xml == u' <message name="name">\n Hello ' 93 u'<young> <ph name="USERNAME">$1<ex>Joi</ex></ph>' 94 u'\n </message>') 95 96 def testXmlFormatMixedContentWithLeadingWhitespace(self): 97 # Again test using the Message node type, because it is the only mixed 98 # content node. 99 node = message.MessageNode() 100 node.StartParsing(u'message', None) 101 node.HandleAttribute(u'name', u'name') 102 node.AppendContent(u"''' Hello <young> ") 103 104 ph = message.PhNode() 105 ph.StartParsing(u'ph', None) 106 ph.HandleAttribute(u'name', u'USERNAME') 107 ph.AppendContent(u'$1') 108 ex = message.ExNode() 109 ex.StartParsing(u'ex', None) 110 ex.AppendContent(u'Joi') 111 ex.EndParsing() 112 ph.AddChild(ex) 113 ph.EndParsing() 114 115 node.AddChild(ph) 116 node.AppendContent(u" yessiree '''") 117 node.EndParsing() 118 119 non_indented_xml = node.FormatXml() 120 self.failUnless(non_indented_xml == 121 u"<message name=\"name\">\n ''' Hello" 122 u' <young> <ph name="USERNAME">$1<ex>Joi</ex></ph>' 123 u" yessiree '''\n</message>") 124 125 indented_xml = node.FormatXml(u' ') 126 self.failUnless(indented_xml == 127 u" <message name=\"name\">\n ''' Hello" 128 u' <young> <ph name="USERNAME">$1<ex>Joi</ex></ph>' 129 u" yessiree '''\n </message>") 130 131 self.failUnless(node.GetNodeById('name')) 132 133 def testXmlFormatContentWithEntities(self): 134 '''Tests a bug where would not be escaped correctly.''' 135 from grit import tclib 136 msg_node = message.MessageNode.Construct(None, tclib.Message( 137 text = 'BEGIN_BOLDHelloWHITESPACEthere!END_BOLD Bingo!', 138 placeholders = [ 139 tclib.Placeholder('BEGIN_BOLD', '<b>', 'bla'), 140 tclib.Placeholder('WHITESPACE', ' ', 'bla'), 141 tclib.Placeholder('END_BOLD', '</b>', 'bla')]), 142 'BINGOBONGO') 143 xml = msg_node.FormatXml() 144 self.failUnless(xml.find(' ') == -1, 'should have no entities') 145 146 def testIter(self): 147 # First build a little tree of message and ph nodes. 148 node = message.MessageNode() 149 node.StartParsing(u'message', None) 150 node.HandleAttribute(u'name', u'bla') 151 node.AppendContent(u" ''' two spaces ") 152 node.AppendContent(u' space before and after ') 153 ph = message.PhNode() 154 ph.StartParsing(u'ph', None) 155 ph.AddChild(message.ExNode()) 156 ph.HandleAttribute(u'name', u'BINGO') 157 ph.AppendContent(u'bongo') 158 node.AddChild(ph) 159 node.AddChild(message.PhNode()) 160 node.AppendContent(u" space before two after '''") 161 162 order = [message.MessageNode, message.PhNode, message.ExNode, message.PhNode] 163 for n in node: 164 self.failUnless(type(n) == order[0]) 165 order = order[1:] 166 self.failUnless(len(order) == 0) 167 168 def testGetChildrenOfType(self): 169 xml = '''<?xml version="1.0" encoding="UTF-8"?> 170 <grit latest_public_release="2" source_lang_id="en-US" 171 current_release="3" base_dir="."> 172 <outputs> 173 <output filename="resource.h" type="rc_header" /> 174 <output filename="en/generated_resources.rc" type="rc_all" 175 lang="en" /> 176 <if expr="pp_if('NOT_TRUE')"> 177 <output filename="de/generated_resources.rc" type="rc_all" 178 lang="de" /> 179 </if> 180 </outputs> 181 <release seq="3"> 182 <messages> 183 <message name="ID_HELLO">Hello!</message> 184 </messages> 185 </release> 186 </grit>''' 187 grd = grd_reader.Parse(StringIO.StringIO(xml), 188 util.PathFromRoot('grit/test/data')) 189 from grit.node import io 190 output_nodes = grd.GetChildrenOfType(io.OutputNode) 191 self.failUnlessEqual(len(output_nodes), 3) 192 self.failUnlessEqual(output_nodes[2].attrs['filename'], 193 'de/generated_resources.rc') 194 195 def testEvaluateExpression(self): 196 def AssertExpr(expected_value, expr, defs, target_platform, 197 extra_variables): 198 self.failUnlessEqual(expected_value, base.Node.EvaluateExpression( 199 expr, defs, target_platform, extra_variables)) 200 201 AssertExpr(True, "True", {}, 'linux', {}) 202 AssertExpr(False, "False", {}, 'linux', {}) 203 AssertExpr(True, "True or False", {}, 'linux', {}) 204 AssertExpr(False, "True and False", {}, 'linux', {}) 205 AssertExpr(True, "os == 'linux'", {}, 'linux', {}) 206 AssertExpr(False, "os == 'linux'", {}, 'ios', {}) 207 AssertExpr(True, "'foo' in defs", {'foo': 'bar'}, 'ios', {}) 208 AssertExpr(False, "'foo' in defs", {'baz': 'bar'}, 'ios', {}) 209 AssertExpr(False, "'foo' in defs", {}, 'ios', {}) 210 AssertExpr(True, "is_linux", {}, 'linux2', {}) 211 AssertExpr(False, "is_linux", {}, 'win32', {}) 212 AssertExpr(True, "is_macosx", {}, 'darwin', {}) 213 AssertExpr(False, "is_macosx", {}, 'ios', {}) 214 AssertExpr(True, "is_win", {}, 'win32', {}) 215 AssertExpr(False, "is_win", {}, 'darwin', {}) 216 AssertExpr(True, "is_android", {}, 'android', {}) 217 AssertExpr(False, "is_android", {}, 'linux3', {}) 218 AssertExpr(True, "is_ios", {}, 'ios', {}) 219 AssertExpr(False, "is_ios", {}, 'darwin', {}) 220 AssertExpr(True, "is_posix", {}, 'linux2', {}) 221 AssertExpr(True, "is_posix", {}, 'darwin', {}) 222 AssertExpr(True, "is_posix", {}, 'android', {}) 223 AssertExpr(True, "is_posix", {}, 'ios', {}) 224 AssertExpr(True, "is_posix", {}, 'freebsd7', {}) 225 AssertExpr(False, "is_posix", {}, 'win32', {}) 226 AssertExpr(True, "pp_ifdef('foo')", {'foo': True}, 'win32', {}) 227 AssertExpr(True, "pp_ifdef('foo')", {'foo': False}, 'win32', {}) 228 AssertExpr(False, "pp_ifdef('foo')", {'bar': True}, 'win32', {}) 229 AssertExpr(True, "pp_if('foo')", {'foo': True}, 'win32', {}) 230 AssertExpr(False, "pp_if('foo')", {'foo': False}, 'win32', {}) 231 AssertExpr(False, "pp_if('foo')", {'bar': True}, 'win32', {}) 232 AssertExpr(True, "foo", {'foo': True}, 'win32', {}) 233 AssertExpr(False, "foo", {'foo': False}, 'win32', {}) 234 AssertExpr(False, "foo", {'bar': True}, 'win32', {}) 235 AssertExpr(True, "foo == 'baz'", {'foo': 'baz'}, 'win32', {}) 236 AssertExpr(False, "foo == 'baz'", {'foo': True}, 'win32', {}) 237 AssertExpr(False, "foo == 'baz'", {}, 'win32', {}) 238 AssertExpr(True, "lang == 'de'", {}, 'win32', {'lang': 'de'}) 239 AssertExpr(False, "lang == 'de'", {}, 'win32', {'lang': 'fr'}) 240 AssertExpr(False, "lang == 'de'", {}, 'win32', {}) 241 242 # Test a couple more complex expressions for good measure. 243 AssertExpr(True, "is_ios and (lang in ['de', 'fr'] or foo)", 244 {'foo': 'bar'}, 'ios', {'lang': 'fr', 'context': 'today'}) 245 AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)", 246 {'foo': False}, 'linux2', {'lang': 'fr', 'context': 'today'}) 247 AssertExpr(False, "is_ios and (lang in ['de', 'fr'] or foo)", 248 {'baz': 'bar'}, 'ios', {'lang': 'he', 'context': 'today'}) 249 AssertExpr(True, "foo == 'bar' or not baz", 250 {'foo': 'bar', 'fun': True}, 'ios', {'lang': 'en'}) 251 AssertExpr(True, "foo == 'bar' or not baz", 252 {}, 'ios', {'lang': 'en', 'context': 'java'}) 253 AssertExpr(False, "foo == 'bar' or not baz", 254 {'foo': 'ruz', 'baz': True}, 'ios', {'lang': 'en'}) 255 256 if __name__ == '__main__': 257 unittest.main() 258 259