2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2012 Dieter Verfaillie <dieterv@optionexplicit.be>
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program 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 General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Tests ensuring the regular expression programs used
26 in annotationparser.py continue to function correctly.
27 Each regular expression program is tested on input that
28 should not match and input that should match. When input
29 should match, resulting symbolic groups are verified
30 against the expected output.
34 from giscanner.annotationparser import (SECTION_RE, SYMBOL_RE, PROPERTY_RE,
35 SIGNAL_RE, PARAMETER_RE, TAG_RE,
37 from unittest import (TestCase, main)
40 identifier_section_tests = [
41 (SECTION_RE, 'TSIEOCN',
43 (SECTION_RE, 'section',
45 (SECTION_RE, 'section:',
47 (SECTION_RE, 'section:test',
49 (SECTION_RE, 'SECTION',
51 'section_name': None}),
52 (SECTION_RE, 'SECTION \t ',
54 'section_name': None}),
55 (SECTION_RE, ' \t SECTION \t ',
57 'section_name': None}),
58 (SECTION_RE, 'SECTION: \t ',
60 'section_name': None}),
61 (SECTION_RE, 'SECTION : ',
63 'section_name': None}),
64 (SECTION_RE, ' SECTION : ',
66 'section_name': None}),
67 (SECTION_RE, 'SECTION:gtkwidget',
69 'section_name': 'gtkwidget'}),
70 (SECTION_RE, 'SECTION:gtkwidget ',
72 'section_name': 'gtkwidget'}),
73 (SECTION_RE, ' SECTION:gtkwidget',
75 'section_name': 'gtkwidget'}),
76 (SECTION_RE, ' SECTION:gtkwidget\t ',
78 'section_name': 'gtkwidget'}),
79 (SECTION_RE, 'SECTION: gtkwidget ',
81 'section_name': 'gtkwidget'}),
82 (SECTION_RE, 'SECTION : gtkwidget',
84 'section_name': 'gtkwidget'}),
85 (SECTION_RE, 'SECTION gtkwidget \f ',
87 'section_name': 'gtkwidget'})]
89 identifier_symbol_tests = [
90 (SYMBOL_RE, 'GBaseFinalizeFunc:',
92 'symbol_name': 'GBaseFinalizeFunc',
94 (SYMBOL_RE, 'gtk_widget_show ',
96 'symbol_name': 'gtk_widget_show',
98 (SYMBOL_RE, ' gtk_widget_show',
100 'symbol_name': 'gtk_widget_show',
102 (SYMBOL_RE, ' gtk_widget_show ',
104 'symbol_name': 'gtk_widget_show',
106 (SYMBOL_RE, 'gtk_widget_show:',
108 'symbol_name': 'gtk_widget_show',
110 (SYMBOL_RE, 'gtk_widget_show :',
112 'symbol_name': 'gtk_widget_show',
114 (SYMBOL_RE, 'gtk_widget_show: ',
116 'symbol_name': 'gtk_widget_show',
118 (SYMBOL_RE, 'gtk_widget_show : ',
120 'symbol_name': 'gtk_widget_show',
122 (SYMBOL_RE, ' gtk_widget_show:',
124 'symbol_name': 'gtk_widget_show',
126 (SYMBOL_RE, ' gtk_widget_show :',
128 'symbol_name': 'gtk_widget_show',
130 (SYMBOL_RE, ' gtk_widget_show: ',
132 'symbol_name': 'gtk_widget_show',
134 (SYMBOL_RE, ' gtk_widget_show : ',
136 'symbol_name': 'gtk_widget_show',
138 (SYMBOL_RE, 'gtk_widget_show (skip)',
140 'symbol_name': 'gtk_widget_show',
141 'annotations': '(skip)'}),
142 (SYMBOL_RE, 'gtk_widget_show: (skip)',
144 'symbol_name': 'gtk_widget_show',
145 'annotations': '(skip)'}),
146 (SYMBOL_RE, 'gtk_widget_show : (skip)',
148 'symbol_name': 'gtk_widget_show',
149 'annotations': '(skip)'}),
150 (SYMBOL_RE, 'gtk_widget_show: (skip)',
152 'symbol_name': 'gtk_widget_show',
153 'annotations': '(skip)'}),
154 (SYMBOL_RE, 'gtk_widget_show : (skip)',
156 'symbol_name': 'gtk_widget_show',
157 'annotations': '(skip)'}),
158 (SYMBOL_RE, ' gtk_widget_show:(skip)',
160 'symbol_name': 'gtk_widget_show',
161 'annotations': '(skip)'}),
162 (SYMBOL_RE, ' gtk_widget_show :(skip)',
164 'symbol_name': 'gtk_widget_show',
165 'annotations': '(skip)'}),
166 (SYMBOL_RE, ' gtk_widget_show: (skip)',
168 'symbol_name': 'gtk_widget_show',
169 'annotations': '(skip)'}),
170 (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
172 'symbol_name': 'gtk_widget_show',
173 'annotations': '(skip) \t '}),
174 (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
176 'symbol_name': 'gtk_widget_show',
177 'annotations': '(skip) \t '}),
178 (SYMBOL_RE, 'gtk_widget_show:(skip)(test1)',
180 'symbol_name': 'gtk_widget_show',
181 'annotations': '(skip)(test1)'}),
182 (SYMBOL_RE, 'gtk_widget_show (skip)(test1)',
184 'symbol_name': 'gtk_widget_show',
185 'annotations': '(skip)(test1)'}),
186 (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
188 'symbol_name': 'gtk_widget_show',
189 'annotations': '(skip) (test1)'}),
190 (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
192 'symbol_name': 'gtk_widget_show',
193 'annotations': '(skip) (test1)'}),
194 (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
196 'symbol_name': 'gtk_widget_show',
197 'annotations': '(skip) (test1)'}),
198 (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
200 'symbol_name': 'gtk_widget_show',
201 'annotations': '(skip) (test1)'}),
202 (SYMBOL_RE, ' gtk_widget_show:(skip) (test1)',
204 'symbol_name': 'gtk_widget_show',
205 'annotations': '(skip) (test1)'}),
206 (SYMBOL_RE, ' gtk_widget_show :(skip) (test1)',
208 'symbol_name': 'gtk_widget_show',
209 'annotations': '(skip) (test1)'}),
210 (SYMBOL_RE, ' gtk_widget_show: (skip) (test1)',
212 'symbol_name': 'gtk_widget_show',
213 'annotations': '(skip) (test1)'}),
214 (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) ',
216 'symbol_name': 'gtk_widget_show',
217 'annotations': '(skip) (test1) '}),
218 (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
220 'symbol_name': 'gtk_widget_show',
221 'annotations': '(skip) (test1) (test-2)'}),
222 (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
224 'symbol_name': 'gtk_widget_show',
225 'annotations': '(skip) (test1) (test-2)'}),
226 (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
228 'symbol_name': 'gtk_widget_show',
229 'annotations': '(skip) (test1) (test-2)'}),
230 (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
232 'symbol_name': 'gtk_widget_show',
233 'annotations': '(skip) (test1) (test-2)'}),
234 (SYMBOL_RE, ' gtk_widget_show:(skip) (test1) (test-2)',
236 'symbol_name': 'gtk_widget_show',
237 'annotations': '(skip) (test1) (test-2)'}),
238 (SYMBOL_RE, ' gtk_widget_show :(skip) (test1) (test-2)',
240 'symbol_name': 'gtk_widget_show',
241 'annotations': '(skip) (test1) (test-2)'}),
242 (SYMBOL_RE, ' gtk_widget_show: (skip) (test1) (test-2)',
244 'symbol_name': 'gtk_widget_show',
245 'annotations': '(skip) (test1) (test-2)'}),
246 (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
248 'symbol_name': 'gtk_widget_show',
249 'annotations': '(skip) (test1) (test-2) '}),
250 (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
252 'symbol_name': 'gtk_widget_show',
253 'annotations': '(skip) (test1) (test-2) '}),
255 (SYMBOL_RE, 'MY_CONSTANT:',
257 'symbol_name': 'MY_CONSTANT',
260 (SYMBOL_RE, 'FooWidget:',
262 'symbol_name': 'FooWidget',
265 (SYMBOL_RE, 'Something:',
267 'symbol_name': 'Something',
270 identifier_property_tests = [
271 # simple property name
272 (PROPERTY_RE, 'GtkWidget:name (skip)',
273 {'class_name': 'GtkWidget',
274 'property_name': 'name',
276 'annotations': '(skip)'}),
277 (PROPERTY_RE, 'GtkWidget:name',
278 {'class_name': 'GtkWidget',
279 'property_name': 'name',
282 (PROPERTY_RE, ' GtkWidget :name',
283 {'class_name': 'GtkWidget',
284 'property_name': 'name',
287 (PROPERTY_RE, 'GtkWidget: name ',
288 {'class_name': 'GtkWidget',
289 'property_name': 'name',
292 (PROPERTY_RE, ' GtkWidget : name ',
293 {'class_name': 'GtkWidget',
294 'property_name': 'name',
297 (PROPERTY_RE, 'GtkWidget:name:',
298 {'class_name': 'GtkWidget',
299 'property_name': 'name',
302 (PROPERTY_RE, 'GtkWidget:name: ',
303 {'class_name': 'GtkWidget',
304 'property_name': 'name',
307 (PROPERTY_RE, ' GtkWidget:name:',
308 {'class_name': 'GtkWidget',
309 'property_name': 'name',
312 (PROPERTY_RE, 'Something:name:',
313 {'class_name': 'Something',
314 'property_name': 'name',
317 (PROPERTY_RE, 'Something:name: ',
318 {'class_name': 'Something',
319 'property_name': 'name',
322 (PROPERTY_RE, ' Something:name:',
323 {'class_name': 'Something',
324 'property_name': 'name',
327 (PROPERTY_RE, 'Weird-thing:name:',
329 (PROPERTY_RE, 'really-weird_thing:name:',
331 (PROPERTY_RE, 'GWin32InputStream:handle:',
332 {'class_name': 'GWin32InputStream',
333 'property_name': 'handle',
336 # property name that contains a dash
337 (PROPERTY_RE, 'GtkWidget:double-buffered (skip)',
338 {'class_name': 'GtkWidget',
339 'property_name': 'double-buffered',
341 'annotations': '(skip)'}),
342 (PROPERTY_RE, 'GtkWidget:double-buffered',
343 {'class_name': 'GtkWidget',
344 'property_name': 'double-buffered',
347 (PROPERTY_RE, ' GtkWidget :double-buffered',
348 {'class_name': 'GtkWidget',
349 'property_name': 'double-buffered',
352 (PROPERTY_RE, 'GtkWidget: double-buffered ',
353 {'class_name': 'GtkWidget',
354 'property_name': 'double-buffered',
357 (PROPERTY_RE, ' GtkWidget : double-buffered ',
358 {'class_name': 'GtkWidget',
359 'property_name': 'double-buffered',
362 (PROPERTY_RE, 'GtkWidget:double-buffered:',
363 {'class_name': 'GtkWidget',
364 'property_name': 'double-buffered',
367 (PROPERTY_RE, 'GtkWidget:double-buffered: ',
368 {'class_name': 'GtkWidget',
369 'property_name': 'double-buffered',
372 (PROPERTY_RE, ' GtkWidget:double-buffered:',
373 {'class_name': 'GtkWidget',
374 'property_name': 'double-buffered',
377 (PROPERTY_RE, 'Something:double-buffered:',
378 {'class_name': 'Something',
379 'property_name': 'double-buffered',
382 (PROPERTY_RE, 'Something:double-buffered: ',
383 {'class_name': 'Something',
384 'property_name': 'double-buffered',
387 (PROPERTY_RE, ' Something:double-buffered:',
388 {'class_name': 'Something',
389 'property_name': 'double-buffered',
392 (PROPERTY_RE, 'Weird-thing:double-buffered:',
394 (PROPERTY_RE, 'really-weird_thing:double-buffered:',
396 (PROPERTY_RE, ' GMemoryOutputStream:realloc-function: (skip)',
397 {'class_name': 'GMemoryOutputStream',
398 'property_name': 'realloc-function',
400 'annotations': '(skip)'})]
402 identifier_signal_tests = [
403 # simple property name
404 (SIGNAL_RE, 'GtkWidget::changed: (skip)',
405 {'class_name': 'GtkWidget',
406 'signal_name': 'changed',
408 'annotations': '(skip)'}),
409 (SIGNAL_RE, 'GtkWidget::changed:',
410 {'class_name': 'GtkWidget',
411 'signal_name': 'changed',
414 (SIGNAL_RE, 'Something::changed:',
415 {'class_name': 'Something',
416 'signal_name': 'changed',
419 (SIGNAL_RE, 'Weird-thing::changed:',
421 (SIGNAL_RE, 'really-weird_thing::changed:',
423 # signal name that contains a dash
424 (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (skip)',
425 {'class_name': 'GtkWidget',
426 'signal_name': 'hierarchy-changed',
428 'annotations': '(skip)'}),
429 (SIGNAL_RE, 'GtkWidget::hierarchy-changed:',
430 {'class_name': 'GtkWidget',
431 'signal_name': 'hierarchy-changed',
434 (SIGNAL_RE, 'Something::hierarchy-changed:',
435 {'class_name': 'Something',
436 'signal_name': 'hierarchy-changed',
439 (SIGNAL_RE, 'Weird-thing::hierarchy-changed:',
441 (SIGNAL_RE, 'really-weird_thing::hierarchy-changed:',
445 (PARAMETER_RE, '@Short_description: Base class for all widgets ',
446 {'parameter_name': 'Short_description',
449 'description': 'Base class for all widgets'}),
450 (PARAMETER_RE, '@...: the value of the first property, followed optionally by more',
451 {'parameter_name': '...',
454 'description': 'the value of the first property, followed optionally by more'}),
455 (PARAMETER_RE, '@widget: a #GtkWidget',
456 {'parameter_name': 'widget',
459 'description': 'a #GtkWidget'}),
460 (PARAMETER_RE, '@widget_pointer: (inout) (transfer none): '
461 'address of a variable that contains @widget',
462 {'parameter_name': 'widget_pointer',
463 'annotations': '(inout) (transfer none)',
465 'description': 'address of a variable that contains @widget'}),
466 (PARAMETER_RE, '@weird_thing: (inout) (transfer none) (allow-none) (attribute) (destroy) '
467 '(foreign) (inout) (out) (transfer) (skip) (method): some weird @thing',
468 {'parameter_name': 'weird_thing',
469 'annotations': '(inout) (transfer none) (allow-none) (attribute) (destroy) '
470 '(foreign) (inout) (out) (transfer) (skip) (method)',
472 'description': 'some weird @thing'}),
473 (PARAMETER_RE, '@data: a pointer to the element data. The data may be moved as elements '
474 'are added to the #GByteArray.',
475 {'parameter_name': 'data',
478 'description': 'a pointer to the element data. The data may be moved as elements '
479 'are added to the #GByteArray.'}),
480 (PARAMETER_RE, '@a: a #GSequenceIter',
481 {'parameter_name': 'a',
484 'description': 'a #GSequenceIter'}),
485 (PARAMETER_RE, '@keys: (array length=n_keys) (element-type GQuark) (allow-none):',
486 {'parameter_name': 'keys',
487 'annotations': '(array length=n_keys) (element-type GQuark) (allow-none)',
492 (TAG_RE, 'Since 3.0',
494 (TAG_RE, 'Since: 3.0',
495 {'tag_name': 'Since',
498 'description': '3.0'}),
499 (TAG_RE, 'Attributes: (inout) (transfer none): some note about attributes',
500 {'tag_name': 'Attributes',
501 'annotations': '(inout) (transfer none)',
503 'description': 'some note about attributes'}),
504 (TAG_RE, 'Rename to: something_else',
505 {'tag_name': 'Rename to',
508 'description': 'something_else'}),
509 (TAG_RE, '@Deprecated: Since 2.8, reference counting is done atomically',
511 (TAG_RE, 'Returns %TRUE and does weird things',
513 (TAG_RE, 'Returns: a #GtkWidget',
514 {'tag_name': 'Returns',
517 'description': 'a #GtkWidget'}),
518 (TAG_RE, 'Return value: (transfer none): The binary data that @text responds. '
520 {'tag_name': 'Return value',
521 'annotations': '(transfer none)',
523 'description': 'The binary data that @text responds. This pointer'}),
524 (TAG_RE, 'Return value: (transfer full) (array length=out_len) (element-type guint8):',
525 {'tag_name': 'Return value',
526 'annotations': '(transfer full) (array length=out_len) (element-type guint8)',
529 (TAG_RE, 'Returns: A boolean value, but let me tell you a bit about this boolean. It',
530 {'tag_name': 'Returns',
533 'description': 'A boolean value, but let me tell you a bit about this boolean. '
535 (TAG_RE, 'Returns: (transfer container) (element-type GObject.ParamSpec): a',
536 {'tag_name': 'Returns',
537 'annotations': '(transfer container) (element-type GObject.ParamSpec)',
539 'description': 'a'}),
540 (TAG_RE, 'Return value: (type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) '
542 {'tag_name': 'Return value',
543 'annotations': '(type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) '
548 comment_end_tests = [
549 (COMMENT_END_RE, '*/',
550 {'description': ''}),
551 (COMMENT_END_RE, ' */',
552 {'description': ''}),
553 (COMMENT_END_RE, ' */ ',
554 {'description': ''}),
555 (COMMENT_END_RE, '**/',
556 {'description': ''}),
557 (COMMENT_END_RE, ' **/',
558 {'description': ''}),
559 (COMMENT_END_RE, ' **/ ',
560 {'description': ''}),
561 (COMMENT_END_RE, 'test */',
562 {'description': 'test'}),
563 (COMMENT_END_RE, ' test*/',
564 {'description': 'test'}),
565 (COMMENT_END_RE, 'test **/',
566 {'description': 'test'}),
567 (COMMENT_END_RE, ' test**/',
568 {'description': 'test'}),
569 (COMMENT_END_RE, 'test *****/',
570 {'description': 'test'}),
571 (COMMENT_END_RE, ' test*****/',
572 {'description': 'test'})]
575 def create_tests(tests_name, testcases):
576 for (index, testcase) in enumerate(testcases):
577 real_test_name = '%s_%03d' % (tests_name, index)
579 test_method = TestProgram.__create_test__(testcase)
580 test_method.__name__ = real_test_name
581 setattr(TestProgram, real_test_name, test_method)
584 class TestProgram(TestCase):
586 def __create_test__(cls, testcase):
588 (program, text, expected) = testcase
590 match = program.match(text)
593 msg = 'Program matched text but shouldn\'t:\n"%s"'
594 self.assertTrue(match is None, msg % (text, ))
596 msg = 'Program should match text but didn\'t:\n"%s"'
597 self.assertTrue(match is not None, msg % (text, ))
599 for key, value in expected.items():
600 msg = 'expected "%s" for "%s" but match returned "%s"'
601 msg = msg % (value, key, match.group(key))
602 self.assertEqual(match.group(key), value, msg)
607 if __name__ == '__main__':
608 # Create tests from data
609 create_tests('test_identifier_section', identifier_section_tests)
610 create_tests('test_identifier_symbol', identifier_symbol_tests)
611 create_tests('test_identifier_property', identifier_property_tests)
612 create_tests('test_identifier_signal', identifier_signal_tests)
613 create_tests('test_parameter', parameter_tests)
614 create_tests('test_tag', tag_tests)
615 create_tests('test_comment_end', comment_end_tests)