1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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()
32 gettext.install("xyzcmd")
33
37
38
39
40 @raises(XYZValueError)
42 """
43 Raise error on wrong opt type
44 """
45
46 BlockParser(1)
47
48
49
50 @raises(ParseError)
52 """
53 Parsing should raise ParseError on unterminated quotes
54 """
55
56 ParseError(self.p.parse("block {a = \"string\n}"))
57
58
59
61 """
62 Test extended quotes
63 """
64
65 assert len(self.p.parse(
66 "block { x = ''' ssaf \t \n ; \" ' '' ; & }''' }"))
67
68
69
71 """
72 Test parsing empty string value: ""
73 """
74
75 assert len(self.p.parse('block { x = "" }'))
76
77
78
80 """
81 Test parsing empty x-quote
82 """
83
84 assert len(self.p.parse("block { x = '''''' }"))
85
86
87
95
96
97
98 @raises(ParseError)
100 """
101 In STATE_INIT state only keyword is acceptable
102 """
103
104 self.p.parse("anything")
105
106
107
108 @raises(ParseError)
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)
121 """
122 Invalid variable name should raise exception
123 """
124
125 self.p.parse("block {a+-; = 1}")
126
127
128
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
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)
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
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)
176 """
177 Check for unclosed quote upon EOF
178 """
179
180 self.p.parse("block {a = \"string")
181
182
183
184 @raises(ParseError)
186 """
187 Check for unclosed block upon EOF
188 """
189
190 self.p.parse("block {a = value\n")
191
192
193
194 @raises(ParseError)
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)
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)
242
243 _opt = {"var_transform": _f}
244 _p = BlockParser(_opt)
245
246 _p.parse("block { a = VALUE }")
247
248
249
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
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
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
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
303
304
305
307 """
308 Check for proper escaping
309 """
310
311 assert len(self.p.parse("block { var = a\\ b\\ c }"))
312
313
314
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)
329 """
330 Check for undefined macro
331 """
332
333 self.p.parse("block { a = &undef }")
334
338 @raises(XYZValueError)
340 """
341 Check if raises on invalid arg type
342 """
343
344 MultiParser("WRONG")
345
346
347
348 @raises(ParseError)
350 """
351 Test for unknown keyword
352 """
353
354 MultiParser({}).parse("keyword")
355
356
357
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
420
421
422
432
433
434
435 @raises(ParseError)
437 """
438 Test for assign character
439 """
440
441 self.p.parse("X = Y")
442
443
444
445 @raises(ParseError)
447 """
448 Test for delimiter character
449 """
450
451 self.p.parse("X = Y; Y = X")
452
453
454
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)
467 """
468 Check for complete expression
469 """
470
471 self.p.parse("X:")
472
473
474
475 @raises(ParseError)
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
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)
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
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
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
551 res = False
552
553 @raises(ParseError)
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
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)
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