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 grit.node.message''' 7 8from __future__ import print_function 9 10import os 11import sys 12import unittest 13 14if __name__ == '__main__': 15 sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) 16 17from grit import exception 18from grit import tclib 19from grit import util 20from grit.node import message 21 22class MessageUnittest(unittest.TestCase): 23 def testMessage(self): 24 root = util.ParseGrdForUnittest(''' 25 <messages> 26 <message name="IDS_GREETING" 27 desc="Printed to greet the currently logged in user"> 28 Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today? 29 </message> 30 </messages>''') 31 msg, = root.GetChildrenOfType(message.MessageNode) 32 cliques = msg.GetCliques() 33 content = cliques[0].GetMessage().GetPresentableContent() 34 self.failUnless(content == 'Hello USERNAME, how are you doing today?') 35 36 def testMessageWithWhitespace(self): 37 root = util.ParseGrdForUnittest("""\ 38 <messages> 39 <message name="IDS_BLA" desc=""> 40 ''' Hello there <ph name="USERNAME">%s</ph> ''' 41 </message> 42 </messages>""") 43 msg, = root.GetChildrenOfType(message.MessageNode) 44 content = msg.GetCliques()[0].GetMessage().GetPresentableContent() 45 self.failUnless(content == 'Hello there USERNAME') 46 self.failUnless(msg.ws_at_start == ' ') 47 self.failUnless(msg.ws_at_end == ' ') 48 49 def testConstruct(self): 50 msg = tclib.Message(text=" Hello USERNAME, how are you? BINGO\t\t", 51 placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi'), 52 tclib.Placeholder('BINGO', '%d', '11')]) 53 msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO') 54 self.failUnless(msg_node.children[0].name == 'ph') 55 self.failUnless(msg_node.children[0].children[0].name == 'ex') 56 self.failUnless(msg_node.children[0].children[0].GetCdata() == 'Joi') 57 self.failUnless(msg_node.children[1].children[0].GetCdata() == '11') 58 self.failUnless(msg_node.ws_at_start == ' ') 59 self.failUnless(msg_node.ws_at_end == '\t\t') 60 61 def testUnicodeConstruct(self): 62 text = u'Howdie \u00fe' 63 msg = tclib.Message(text=text) 64 msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO') 65 msg_from_node = msg_node.GetCdata() 66 self.failUnless(msg_from_node == text) 67 68 def testFormatterData(self): 69 root = util.ParseGrdForUnittest("""\ 70 <messages> 71 <message name="IDS_BLA" desc="" formatter_data=" foo=123 bar qux=low"> 72 Text 73 </message> 74 </messages>""") 75 msg, = root.GetChildrenOfType(message.MessageNode) 76 expected_formatter_data = { 77 'foo': '123', 78 'bar': '', 79 'qux': 'low'} 80 81 # Can't use assertDictEqual, not available in Python 2.6, so do it 82 # by hand. 83 self.failUnlessEqual(len(expected_formatter_data), 84 len(msg.formatter_data)) 85 for key in expected_formatter_data: 86 self.failUnlessEqual(expected_formatter_data[key], 87 msg.formatter_data[key]) 88 89 def testReplaceEllipsis(self): 90 root = util.ParseGrdForUnittest(''' 91 <messages> 92 <message name="IDS_GREETING" desc=""> 93 A...B.... <ph name="PH">%s<ex>A</ex></ph>... B... C... 94 </message> 95 </messages>''') 96 msg, = root.GetChildrenOfType(message.MessageNode) 97 msg.SetReplaceEllipsis(True) 98 content = msg.Translate('en') 99 self.failUnlessEqual(u'A...B.... %s\u2026 B\u2026 C\u2026', content) 100 101 def testRemoveByteOrderMark(self): 102 root = util.ParseGrdForUnittest(u''' 103 <messages> 104 <message name="IDS_HAS_BOM" desc=""> 105 \uFEFFThis\uFEFF i\uFEFFs OK\uFEFF 106 </message> 107 </messages>''') 108 msg, = root.GetChildrenOfType(message.MessageNode) 109 content = msg.Translate('en') 110 self.failUnlessEqual(u'This is OK', content) 111 112 def testPlaceholderHasTooManyExamples(self): 113 try: 114 util.ParseGrdForUnittest("""\ 115 <messages> 116 <message name="IDS_FOO" desc="foo"> 117 Hi <ph name="NAME">$1<ex>Joi</ex><ex>Joy</ex></ph> 118 </message> 119 </messages>""") 120 except exception.TooManyExamples: 121 return 122 self.fail('Should have gotten exception') 123 124 def testPlaceholderHasInvalidName(self): 125 try: 126 util.ParseGrdForUnittest("""\ 127 <messages> 128 <message name="IDS_FOO" desc="foo"> 129 Hi <ph name="ABC!">$1</ph> 130 </message> 131 </messages>""") 132 except exception.InvalidPlaceholderName: 133 return 134 self.fail('Should have gotten exception') 135 136 def testChromeLocalizedFormatIsInsidePhNode(self): 137 try: 138 util.ParseGrdForUnittest("""\ 139 <messages> 140 <message name="IDS_CHROME_L10N" desc="l10n format"> 141 This message is missing the ph node: $1 142 </message> 143 </messages>""") 144 except exception.PlaceholderNotInsidePhNode: 145 return 146 self.fail('Should have gotten exception') 147 148 def testAndroidStringFormatIsInsidePhNode(self): 149 try: 150 util.ParseGrdForUnittest("""\ 151 <messages> 152 <message name="IDS_ANDROID" desc="string format"> 153 This message is missing a ph node: %1$s 154 </message> 155 </messages>""") 156 except exception.PlaceholderNotInsidePhNode: 157 return 158 self.fail('Should have gotten exception') 159 160 def testAndroidIntegerFormatIsInsidePhNode(self): 161 try: 162 util.ParseGrdForUnittest("""\ 163 <messages> 164 <message name="IDS_ANDROID" desc="integer format"> 165 This message is missing a ph node: %2$d 166 </message> 167 </messages>""") 168 except exception.PlaceholderNotInsidePhNode: 169 return 170 self.fail('Should have gotten exception') 171 172 def testAndroidIntegerWidthFormatIsInsidePhNode(self): 173 try: 174 util.ParseGrdForUnittest("""\ 175 <messages> 176 <message name="IDS_ANDROID" desc="integer width format"> 177 This message is missing a ph node: %2$3d 178 </message> 179 </messages>""") 180 except exception.PlaceholderNotInsidePhNode: 181 return 182 self.fail('Should have gotten exception') 183 184 def testValidAndroidIntegerWidthFormatInPhNode(self): 185 try: 186 util.ParseGrdForUnittest("""\ 187 <messages> 188 <message name="IDS_ANDROID_WIDTH"> 189 <ph name="VALID">%2$3d<ex>042</ex></ph> 190 </message> 191 </messages>""") 192 except: 193 self.fail('Should not have gotten exception') 194 195 def testAndroidFloatFormatIsInsidePhNode(self): 196 try: 197 util.ParseGrdForUnittest("""\ 198 <messages> 199 <message name="IDS_ANDROID" desc="float number format"> 200 This message is missing a ph node: %3$4.5f 201 </message> 202 </messages>""") 203 except exception.PlaceholderNotInsidePhNode: 204 return 205 self.fail('Should have gotten exception') 206 207 def testGritStringFormatIsInsidePhNode(self): 208 try: 209 util.ParseGrdForUnittest("""\ 210 <messages> 211 <message name="IDS_GRIT_STRING" desc="grit string format"> 212 This message is missing the ph node: %s 213 </message> 214 </messages>""") 215 except exception.PlaceholderNotInsidePhNode: 216 return 217 self.fail('Should have gotten exception') 218 219 def testGritIntegerFormatIsInsidePhNode(self): 220 try: 221 util.ParseGrdForUnittest("""\ 222 <messages> 223 <message name="IDS_GRIT_INTEGER" desc="grit integer format"> 224 This message is missing the ph node: %d 225 </message> 226 </messages>""") 227 except exception.PlaceholderNotInsidePhNode: 228 return 229 self.fail('Should have gotten exception') 230 231 def testWindowsETWIntegerFormatIsInsidePhNode(self): 232 try: 233 util.ParseGrdForUnittest("""\ 234 <messages> 235 <message name="IDS_WINDOWS_ETW" desc="ETW tracing integer"> 236 This message is missing the ph node: %1 237 </message> 238 </messages>""") 239 except exception.PlaceholderNotInsidePhNode: 240 return 241 self.fail('Should have gotten exception') 242 243 def testValidMultipleFormattersInsidePhNodes(self): 244 root = util.ParseGrdForUnittest("""\ 245 <messages> 246 <message name="IDS_MULTIPLE_FORMATTERS"> 247 <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning 248 </message> 249 </messages>""") 250 msg, = root.GetChildrenOfType(message.MessageNode) 251 cliques = msg.GetCliques() 252 content = cliques[0].GetMessage().GetPresentableContent() 253 self.failUnless(content == 'ERROR_COUNT error, WARNING_COUNT warning') 254 255 def testMultipleFormattersAreInsidePhNodes(self): 256 failed = True 257 try: 258 util.ParseGrdForUnittest("""\ 259 <messages> 260 <message name="IDS_MULTIPLE_FORMATTERS"> 261 %1$d error, %2$d warning 262 </message> 263 </messages>""") 264 except exception.PlaceholderNotInsidePhNode: 265 failed = False 266 if failed: 267 self.fail('Should have gotten exception') 268 return 269 270 failed = True 271 try: 272 util.ParseGrdForUnittest("""\ 273 <messages> 274 <message name="IDS_MULTIPLE_FORMATTERS"> 275 <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, %2$d warning 276 </message> 277 </messages>""") 278 except exception.PlaceholderNotInsidePhNode: 279 failed = False 280 if failed: 281 self.fail('Should have gotten exception') 282 return 283 284 failed = True 285 try: 286 util.ParseGrdForUnittest("""\ 287 <messages> 288 <message name="IDS_MULTIPLE_FORMATTERS"> 289 <ph name="INVALID">%1$d %2$d</ph> 290 </message> 291 </messages>""") 292 except exception.InvalidCharactersInsidePhNode: 293 failed = False 294 if failed: 295 self.fail('Should have gotten exception') 296 return 297 298 def testValidHTMLFormatInsidePhNode(self): 299 try: 300 util.ParseGrdForUnittest("""\ 301 <messages> 302 <message name="IDS_HTML"> 303 <ph name="VALID"><span>$1</span><ex>1</ex></ph> 304 </message> 305 </messages>""") 306 except: 307 self.fail('Should not have gotten exception') 308 309 def testValidHTMLWithAttributesFormatInsidePhNode(self): 310 try: 311 util.ParseGrdForUnittest("""\ 312 <messages> 313 <message name="IDS_HTML_ATTRIBUTE"> 314 <ph name="VALID"><span attribute="js:$this %">$2</span><ex>2</ex></ph> 315 </message> 316 </messages>""") 317 except: 318 self.fail('Should not have gotten exception') 319 320 def testValidHTMLEntityFormatInsidePhNode(self): 321 try: 322 util.ParseGrdForUnittest("""\ 323 <messages> 324 <message name="IDS_ENTITY"> 325 <ph name="VALID">>%1$d<<ex>1</ex></ph> 326 </message> 327 </messages>""") 328 except: 329 self.fail('Should not have gotten exception') 330 331 def testValidMultipleDollarFormatInsidePhNode(self): 332 try: 333 util.ParseGrdForUnittest("""\ 334 <messages> 335 <message name="IDS_DOLLARS" desc="l10n dollars format"> 336 <ph name="VALID">$$1</ph> 337 </message> 338 </messages>""") 339 except: 340 self.fail('Should not have gotten exception') 341 342 def testInvalidDollarCharacterInsidePhNode(self): 343 try: 344 util.ParseGrdForUnittest("""\ 345 <messages> 346 <message name="IDS_BAD_DOLLAR"> 347 <ph name="INVALID">%1$d $</ph> 348 </message> 349 </messages>""") 350 except exception.InvalidCharactersInsidePhNode: 351 return 352 self.fail('Should have gotten exception') 353 354 def testInvalidPercentCharacterInsidePhNode(self): 355 try: 356 util.ParseGrdForUnittest("""\ 357 <messages> 358 <message name="IDS_BAD_PERCENT"> 359 <ph name="INVALID">%1$d %</ph> 360 </message> 361 </messages>""") 362 except exception.InvalidCharactersInsidePhNode: 363 return 364 self.fail('Should have gotten exception') 365 366 def testInvalidMixedFormatCharactersInsidePhNode(self): 367 try: 368 util.ParseGrdForUnittest("""\ 369 <messages> 370 <message name="IDS_MIXED_FORMATS"> 371 <ph name="INVALID">%1$2</ph> 372 </message> 373 </messages>""") 374 except exception.InvalidCharactersInsidePhNode: 375 return 376 self.fail('Should have gotten exception') 377 378 379if __name__ == '__main__': 380 unittest.main() 381