Package libxyz :: Package parser :: Module tests
[hide private]
[frames] | no frames]

Source Code for Module libxyz.parser.tests

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <mek@mek.uz.ua> 2008-2009 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 16   
 17  # Parsers tests 
 18   
 19  import re 
 20  import unittest 
 21  import locale 
 22  import gettext 
 23  import __builtin__ 
 24  from nose.tools import raises 
 25   
 26  from libxyz.parser import BlockParser, MultiParser, FlatParser, RegexpParser 
 27  from libxyz.exceptions import ParseError, XYZValueError 
 28   
 29  __builtin__.__dict__["xyzenc"] = locale.getpreferredencoding() 
30 31 -def setup():
32 gettext.install("xyzcmd")
33
34 -class TestBlock(object):
35 - def setUp(self):
36 self.p = BlockParser()
37 38 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 40 @raises(XYZValueError)
41 - def testOptType(self):
42 """ 43 Raise error on wrong opt type 44 """ 45 46 BlockParser(1)
47 48 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 49 50 @raises(ParseError)
51 - def testQuote(self):
52 """ 53 Parsing should raise ParseError on unterminated quotes 54 """ 55 56 ParseError(self.p.parse("block {a = \"string\n}"))
57 58 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 59
60 - def testXQuote(self):
61 """ 62 Test extended quotes 63 """ 64 65 assert len(self.p.parse( 66 "block { x = ''' ssaf \t \n ; \" ' '' ; & }''' }"))
67 68 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69
70 - def testEmptyQuote(self):
71 """ 72 Test parsing empty string value: "" 73 """ 74 75 assert len(self.p.parse('block { x = "" }'))
76 77 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 78
79 - def testEmptyXQuote(self):
80 """ 81 Test parsing empty x-quote 82 """ 83 84 assert len(self.p.parse("block { x = '''''' }"))
85 86 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 87
88 - def testComments(self):
89 """ 90 Test proper commenting 91 """ 92 93 assert len(self.p.parse( 94 "# \tComment 1\n#Comment 2 ''' = }{\n block {}")) == 0
95 96 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 97 98 @raises(ParseError)
99 - def testInit(self):
100 """ 101 In STATE_INIT state only keyword is acceptable 102 """ 103 104 self.p.parse("anything")
105 106 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 107 108 @raises(ParseError)
109 - def testUnknownVar(self):
110 """ 111 Variable not in valid list is not allowed 112 """ 113 114 _opt = {"validvars": ("a",)} 115 BlockParser(_opt).parse("block {b = 1}")
116 117 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 118 119 @raises(ParseError)
120 - def testValidVar(self):
121 """ 122 Invalid variable name should raise exception 123 """ 124 125 self.p.parse("block {a+-; = 1}")
126 127 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 128
129 - def testAssignChar1(self):
130 """ 131 Test for assign character 132 """ 133 134 _opt = {"assignchar": ":"} 135 _p = BlockParser(_opt) 136 assert len(_p.parse("block {a: 1}"))
137 138 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 139
140 - def testAssignChar2(self):
141 """ 142 Test for assign character 143 """ 144 145 _opt = {"assignchar": ":"} 146 _p = BlockParser(_opt) 147 assert len(_p.parse("block {a: 1}"))
148 149 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 150 151 @raises(ParseError)
152 - def testDelimiter1(self):
153 """ 154 Correct delimiter should be supplied 155 """ 156 157 _opt = {"delimiter": ";"} 158 _p = BlockParser(_opt) 159 _p.parse("block {a = 1\nb = 2\n}")
160 161 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 162
163 - def testDelimiter2(self):
164 """ 165 Correct delimiter should be supplied 166 """ 167 168 _opt = {"delimiter": ";"} 169 _p = BlockParser(_opt) 170 assert len(_p.parse("block {a = 1;b = 2} block2 {x=y;y=x}"))
171 172 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 173 174 @raises(ParseError)
175 - def testCompleteQuote(self):
176 """ 177 Check for unclosed quote upon EOF 178 """ 179 180 self.p.parse("block {a = \"string")
181 182 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 183 184 @raises(ParseError)
185 - def testCompleteBlock(self):
186 """ 187 Check for unclosed block upon EOF 188 """ 189 190 self.p.parse("block {a = value\n")
191 192 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 193 194 @raises(ParseError)
195 - def testValueValidator1(self):
196 """ 197 Check if value_validator raises exception1 198 """ 199 200 def _f(block, var, val): 201 if val != "CORRECT_VALUE": 202 raise XYZValueError("Incorrect value %s!" % val) 203 204 return val
205 206 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 207 208 _opt = {"value_validator": _f} 209 _p = BlockParser(_opt) 210 _p.parse("block { a = INCORRECT_VALUE }")
211 212 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 213 214 @raises(ParseError)
215 - def testMacroValueValidator1(self):
216 """ 217 Check if value_validator raises exception on macro 218 """ 219 220 def _f(block, var, val): 221 if val != "CORRECT_VALUE": 222 raise XYZValueError("Incorrect value %s!" % val) 223 224 return val
225 226 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 227 228 _opt = {"value_validator": _f} 229 _p = BlockParser(_opt) 230 _p.parse("block { &m = INCORRECT_VALUE\n test = &m }") 231 232 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 233 234 @raises(ParseError)
235 - def testVarTransformation1(self):
236 """ 237 Check for correct var transformation 238 """ 239 240 def _f(a): 241 raise XYZValueError(a)
242 243 _opt = {"var_transform": _f} 244 _p = BlockParser(_opt) 245 246 _p.parse("block { a = VALUE }") 247 248 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 249
250 - def testValueValidator2(self):
251 """ 252 Check for value_validator correct value 253 """ 254 255 def _f(block, var, val): 256 if val != "CORRECT_VALUE": 257 raise XYZValueError("Incorrect value %s!" % val) 258 259 # Returning modified value 260 return 1
261 262 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 263 264 _opt = {"value_validator": _f} 265 _p = BlockParser(_opt) 266 267 assert len(_p.parse("block { a = CORRECT_VALUE }")) 268 269 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 270
271 - def testMacroValueValidator2(self):
272 """ 273 Check for value_validator correct value on macro 274 """ 275 276 def _f(block, var, val): 277 if val != "CORRECT_VALUE": 278 raise XYZValueError("Incorrect value %s!" % val) 279 280 # Returning modified value 281 return 1
282 283 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 284 285 _opt = {"value_validator": _f} 286 _p = BlockParser(_opt) 287 288 len(_p.parse("block { &m = CORRECT_VALUE\n a = &m }")) 289 290 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 291
292 - def testVarTransformation2(self):
293 """ 294 Check for correct var transformation 295 """ 296 297 _opt = {"var_transform": lambda x: x * 3} 298 299 _p = BlockParser(_opt) 300 _data = _p.parse("block { X = 1 }") 301 302 assert "XXX" in _data["block"]
303 304 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 305
306 - def testEscaping(self):
307 """ 308 Check for proper escaping 309 """ 310 311 assert len(self.p.parse("block { var = a\\ b\\ c }"))
312 313 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 314
315 - def testListValue(self):
316 """ 317 Check for proper list values parsing 318 """ 319 320 _src = "block { var = l, i, s ,t }" 321 322 _r = self.p.parse(_src) 323 assert isinstance(_r["block"]["var"], tuple)
324 325 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 326 327 @raises(ParseError)
328 - def testUndefinedMacro(self):
329 """ 330 Check for undefined macro 331 """ 332 333 self.p.parse("block { a = &undef }")
334
335 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 336 337 -class TestMulti(object):
338 @raises(XYZValueError)
339 - def testArgs(self):
340 """ 341 Check if raises on invalid arg type 342 """ 343 344 MultiParser("WRONG")
345 346 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 347 348 @raises(ParseError)
349 - def testUnknownKeyword(self):
350 """ 351 Test for unknown keyword 352 """ 353 354 MultiParser({}).parse("keyword")
355 356 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 357
358 - def testParsing(self):
359 """ 360 Try to parse some dummy config file 361 """ 362 363 src = """\ 364 AUTHOR: "Max E. Kuznecov <syhpoon@syhpoon.name>" 365 VERSION: "0.1" 366 DESCRIPTION: "Default XYZ skin" 367 368 fs.type { 369 file = LIGHT_GRAY 370 dir = WHITE 371 block = DARK_MAGENTA 372 char = LIGHT_MAGENTA 373 link = LIGHT_CYAN 374 fifo = DARK_CYAN 375 socket = DARK_RED 376 } 377 378 fs.regexp { 379 '''.+\.core$''' = DARK_RED 380 '''\.+''' = LIGHT_GREY 381 } 382 383 ui.block1 { 384 a = 1 385 b = 2 386 } 387 388 ui.block2 { 389 c = 1 390 d = 2 391 } 392 393 """ 394 _opt = {"count": 1} 395 396 _type = BlockParser(_opt) 397 _flat = FlatParser(_opt) 398 _ui = BlockParser(_opt) 399 _opt["varre"] = re.compile(".+") 400 _regexp = BlockParser(_opt) 401 402 _parsers = {"fs.type": _type, 403 "fs.regexp": _regexp, 404 ("AUTHOR", "VERSION", "DESCRIPTION"): _flat, 405 re.compile("^ui\.(\w+)$"): _ui, 406 } 407 408 _opt2 = {"tokens": (":",)} 409 410 multi = MultiParser(_parsers, _opt2) 411 412 data = multi.parse(src) 413 assert data
414
415 #++++++++++++++++++++++++++++++++++++++++++++++++ 416 417 -class TestFlat(object):
418 - def setUp(self):
419 self.p = FlatParser()
420 421 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 422
423 - def testComments(self):
424 """ 425 Test for source type 426 """ 427 428 _opt = {"comment": "*"} 429 _p = FlatParser(_opt) 430 431 assert len(_p.parse("* \tComment 1\n*Comment 2 ''' = }{\n A: B"))
432 433 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 434 435 @raises(ParseError)
436 - def testAssignChar(self):
437 """ 438 Test for assign character 439 """ 440 441 self.p.parse("X = Y")
442 443 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 444 445 @raises(ParseError)
446 - def testDelimChar1(self):
447 """ 448 Test for delimiter character 449 """ 450 451 self.p.parse("X = Y; Y = X")
452 453 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 454
455 - def testDelimChar2(self):
456 """ 457 Test for delimiter character 458 """ 459 460 _p = FlatParser({"delimiter": ";"}) 461 assert len(_p.parse("X: Y; Y: X"))
462 463 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 464 465 @raises(ParseError)
466 - def testComplete(self):
467 """ 468 Check for complete expression 469 """ 470 471 self.p.parse("X:")
472 473 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 474 475 @raises(ParseError)
476 - def testUnknownVar1(self):
477 """ 478 Variable not in valid list is not allowed 479 """ 480 481 _opt = {"validvars": ("A",)} 482 FlatParser(_opt).parse("X: Y")
483 484 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 485
486 - def testUnknownVar2(self):
487 """ 488 Variable in valid list is allowed 489 """ 490 491 _opt = {"validvars": ("A",)} 492 assert FlatParser(_opt).parse("A: Y")
493 494 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 495 496 @raises(ParseError)
497 - def testValueValidator1(self):
498 """ 499 Check if value_validator raises exception 2 500 """ 501 502 def _f(var, val): 503 if val != "CORRECT_VALUE": 504 raise XYZValueError("Incorrect value %s!" % val) 505 506 return val
507 508 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 509 510 _opt = {"value_validator": _f} 511 _p = FlatParser(_opt) 512 513 _p.parse("A: INCORRECT_VALUE")
514 515 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 516
517 - def testValueValidator2(self):
518 """ 519 Check if value_validator accepts correct value 520 """ 521 522 def _f(var, val): 523 if val != "CORRECT_VALUE": 524 raise XYZValueError("Incorrect value %s!" % val) 525 526 return val
527 528 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 529 530 _opt = {"value_validator": _f} 531 _p = FlatParser(_opt) 532 533 assert self.p.parse("A: CORRECT_VALUE") 534 535 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 536
537 - def testListValue(self):
538 """ 539 Check for proper list values parsing 540 """ 541 542 _p = FlatParser() 543 _src = "var : l, i, s ,t" 544 545 _r = _p.parse(_src) 546 assert isinstance(_r["var"], tuple)
547
548 #++++++++++++++++++++++++++++++++++++++++++++++++ 549 550 -class TestRegexp(unittest.TestCase):
551 res = False 552 553 @raises(ParseError)
554 - def testCBFailure(self):
555 """ 556 Test for callback raising exceptions 557 """ 558 559 def cb(mo): 560 raise XYZValueError(u"Test error")
561 562 _p = RegexpParser({re.compile("^test line$"): cb}) 563 _src = "test line" 564 565 _p.parse(_src)
566 567 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 568
569 - def testCBSuccess(self):
570 """ 571 Test for callback success 572 """ 573 574 self.res = False 575 576 def cb(mo): 577 self.res = True
578 579 _p = RegexpParser({re.compile("^test line$"): cb}) 580 _src = "test line" 581 582 _p.parse(_src) 583 584 assert self.res 585 586 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 587 588 @raises(ParseError)
589 - def testUnmatched(self):
590 """ 591 Test for umatched line 592 """ 593 594 def cb(mo): 595 return
596 597 _p = RegexpParser({re.compile("^test line$"): cb}) 598 _src = "NOT a test line" 599 600 _p.parse(_src) 601