summaryrefslogtreecommitdiff
path: root/tests/scanner/annotationparser/test_patterns.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/scanner/annotationparser/test_patterns.py')
-rw-r--r--tests/scanner/annotationparser/test_patterns.py943
1 files changed, 943 insertions, 0 deletions
diff --git a/tests/scanner/annotationparser/test_patterns.py b/tests/scanner/annotationparser/test_patterns.py
new file mode 100644
index 00000000..774d674c
--- /dev/null
+++ b/tests/scanner/annotationparser/test_patterns.py
@@ -0,0 +1,943 @@
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2012 Dieter Verfaillie <dieterv@optionexplicit.be>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+
+'''
+test_patterns.py
+
+Tests ensuring the regular expression programs used
+in annotationparser.py continue to function correctly.
+Each regular expression program is tested on input that
+should not match and input that should match. When input
+should match, resulting symbolic groups are verified
+against the expected output.
+'''
+
+
+from giscanner.annotationparser import (COMMENT_BLOCK_START_RE, COMMENT_BLOCK_END_RE,
+ COMMENT_ASTERISK_RE, INDENTATION_RE, EMPTY_LINE_RE,
+ SECTION_RE, SYMBOL_RE, PROPERTY_RE,
+ SIGNAL_RE, PARAMETER_RE, TAG_RE,
+ TAG_VALUE_VERSION_RE, TAG_VALUE_STABILITY_RE)
+import unittest
+
+
+comment_start_tests = [
+ (COMMENT_BLOCK_START_RE, '/**',
+ {'code': '',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, ' /**',
+ {'code': '',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, ' /** ',
+ {'code': '',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, 'xyz /** ',
+ {'code': 'xyz',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, ' xyz /** ',
+ {'code': ' xyz',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, '/** xyz',
+ {'code': '',
+ 'token': '/**',
+ 'comment': 'xyz'}),
+ (COMMENT_BLOCK_START_RE, ' /**xyz',
+ {'code': '',
+ 'token': '/**',
+ 'comment': 'xyz'}),
+ (COMMENT_BLOCK_START_RE, ' /** xyz',
+ {'code': '',
+ 'token': '/**',
+ 'comment': 'xyz'}),
+ (COMMENT_BLOCK_START_RE, '/***',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /***',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /*** ',
+ None),
+ (COMMENT_BLOCK_START_RE, '/*** xyz',
+ None),
+ (COMMENT_BLOCK_START_RE, '/***** xyz',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /*****xyz',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /**/',
+ None),
+]
+
+
+comment_end_tests = [
+ (COMMENT_BLOCK_END_RE, '*/',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' */',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' */ ',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, '*/xyz',
+ {'comment': '',
+ 'token': '*/',
+ 'code': 'xyz'}),
+ (COMMENT_BLOCK_END_RE, ' */xyz',
+ {'comment': '',
+ 'token': '*/',
+ 'code': 'xyz'}),
+ (COMMENT_BLOCK_END_RE, ' */ xyz',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ' xyz'}),
+ (COMMENT_BLOCK_END_RE, '**/',
+ {'comment': '',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' **/',
+ {'comment': '',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' **/ ',
+ {'comment': '',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, 'test */',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' test*/',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, 'test */ xyz',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ' xyz'}),
+ (COMMENT_BLOCK_END_RE, ' test*/ xyz ',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ' xyz'}),
+ (COMMENT_BLOCK_END_RE, 'test **/',
+ {'comment': 'test',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' test**/',
+ {'comment': 'test',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, 'test *****/',
+ {'comment': 'test',
+ 'token': '*****/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' test*****/',
+ {'comment': 'test',
+ 'token': '*****/',
+ 'code': ''})]
+
+
+comment_asterisk_tests = [
+ (COMMENT_ASTERISK_RE, '*',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, '* ',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' *',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' * ',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' * ',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' * test',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, 'test * ',
+ {'comment': 'test'})]
+
+
+indentaton_tests = [
+ (INDENTATION_RE, '',
+ {'indentation': ''}),
+ (INDENTATION_RE, ' ',
+ {'indentation': ' '}),
+ (INDENTATION_RE, ' ',
+ {'indentation': ' '}),
+ (INDENTATION_RE, ' x',
+ {'indentation': ' '}),
+ (INDENTATION_RE, ' *',
+ {'indentation': ' '})]
+
+
+empty_line_tests = [
+ (EMPTY_LINE_RE, '',
+ {}),
+ (EMPTY_LINE_RE, ' ',
+ {}),
+ (EMPTY_LINE_RE, ' .',
+ None)]
+
+
+identifier_section_tests = [
+ (SECTION_RE, 'TSIEOCN',
+ None),
+ (SECTION_RE, 'section',
+ None),
+ (SECTION_RE, 'section:',
+ None),
+ (SECTION_RE, 'section:test',
+ None),
+ (SECTION_RE, 'SECTION',
+ None),
+ (SECTION_RE, 'SECTION \t ',
+ None),
+ (SECTION_RE, ' \t SECTION \t ',
+ None),
+ (SECTION_RE, 'SECTION: \t ',
+ None),
+ (SECTION_RE, 'SECTION : ',
+ None),
+ (SECTION_RE, ' SECTION : ',
+ None),
+ (SECTION_RE, 'SECTION:gtkwidget',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION:gtkwidget ',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, ' SECTION:gtkwidget',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, ' SECTION:gtkwidget\t ',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION: gtkwidget ',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION : gtkwidget',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION gtkwidget \f ',
+ {'delimiter': '',
+ 'section_name': 'gtkwidget'})]
+
+identifier_symbol_tests = [
+ (SYMBOL_RE, 'GBaseFinalizeFunc:',
+ {'delimiter': ':',
+ 'symbol_name': 'GBaseFinalizeFunc',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show ',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show ',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show:',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show :',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show: ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show : ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show:',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show :',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show: ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show : ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show:(skip):',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show (skip)',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show:(skip)(test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)(test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show (skip)(test1)',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)(test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ # constants
+ (SYMBOL_RE, 'MY_CONSTANT:',
+ {'delimiter': ':',
+ 'symbol_name': 'MY_CONSTANT',
+ 'fields': ''}),
+ # structs
+ (SYMBOL_RE, 'FooWidget:',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': ''}),
+ # enums
+ (SYMBOL_RE, 'Something:',
+ {'delimiter': ':',
+ 'symbol_name': 'Something',
+ 'fields': ''}),
+ # annotations with multiple closing parentheses
+ (SYMBOL_RE, 'FooWidget: (transfer full) (type GLib.List(utf8))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(transfer full) (type GLib.List(utf8))'}),
+ (SYMBOL_RE, 'FooWidget: (transfer full) (type GLib.List((utf8)))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(transfer full) (type GLib.List((utf8)))'}),
+ (SYMBOL_RE, 'FooWidget: (transfer full) (type GLib.List(GLib.List(utf8)))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(transfer full) (type GLib.List(GLib.List(utf8)))'}),
+ (SYMBOL_RE, 'FooWidget: (type GLib.List(GLib.List(utf8))) (transfer full)',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(type GLib.List(GLib.List(utf8))) (transfer full)'}),
+ (SYMBOL_RE, 'FooWidget: (type GLib.List(GLib.List(utf8)))(transfer full)(type GLib.List(GLib.List(utf8)))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(type GLib.List(GLib.List(utf8)))(transfer full)(type GLib.List(GLib.List(utf8)))'})]
+
+identifier_property_tests = [
+ # simple property name
+ (PROPERTY_RE, 'GtkWidget:name (skip)',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': '(skip)'}),
+ (PROPERTY_RE, 'GtkWidget:name',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget :name',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget: name ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget : name ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:name:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:name: ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget:name:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:name:',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:name: ',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' Something:name:',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Weird-thing:name:',
+ None),
+ (PROPERTY_RE, 'really-weird_thing:name:',
+ None),
+ (PROPERTY_RE, 'GWin32InputStream:handle:',
+ {'class_name': 'GWin32InputStream',
+ 'property_name': 'handle',
+ 'delimiter': ':',
+ 'fields': ''}),
+ # properties: property name that contains a dash
+ (PROPERTY_RE, 'GtkWidget:double-buffered (skip)',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': '(skip)'}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget :double-buffered',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget: double-buffered ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget : double-buffered ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered: ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget:double-buffered:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:double-buffered:',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:double-buffered: ',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' Something:double-buffered:',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Weird-thing:double-buffered:',
+ None),
+ (PROPERTY_RE, 'really-weird_thing:double-buffered:',
+ None),
+ (PROPERTY_RE, ' GMemoryOutputStream:realloc-function: (skip)',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(skip)'}),
+ # properties: data with multiple closing parentheses
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (transfer full) (type GLib.List(utf8))',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(utf8))'}),
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (transfer full) (type GLib.List((utf8)))',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List((utf8)))'}),
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (transfer full) (type GLib.List(GLib.List(utf8)))',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(GLib.List(utf8)))'}),
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (type GLib.List(GLib.List(utf8))) (transfer full)',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(type GLib.List(GLib.List(utf8))) (transfer full)'})]
+
+identifier_signal_tests = [
+ # simple signal name
+ (SIGNAL_RE, 'GtkWidget::changed: (skip)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'changed',
+ 'delimiter': ':',
+ 'fields': '(skip)'}),
+ (SIGNAL_RE, 'GtkWidget::changed:',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Something::changed:',
+ {'class_name': 'Something',
+ 'signal_name': 'changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Weird-thing::changed:',
+ None),
+ (SIGNAL_RE, 'really-weird_thing::changed:',
+ None),
+ # signals: signal name that contains a dash
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (skip)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(skip)'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed:',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Something::hierarchy-changed:',
+ {'class_name': 'Something',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Weird-thing::hierarchy-changed:',
+ None),
+ (SIGNAL_RE, 'really-weird_thing::hierarchy-changed:',
+ None),
+ # signals: data with multiple closing parentheses
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (transfer full) (type GLib.List(utf8))',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(utf8))'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (transfer full) (type GLib.List((utf8)))',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List((utf8)))'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (transfer full) (type GLib.List(GLib.List(utf8)))',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(GLib.List(utf8)))'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (type GLib.List(GLib.List(utf8))) (transfer full)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(type GLib.List(GLib.List(utf8))) (transfer full)'})]
+
+parameter_tests = [
+ (PARAMETER_RE, '@Short_description: Base class for all widgets ',
+ {'parameter_name': 'Short_description',
+ 'fields': 'Base class for all widgets'}),
+ (PARAMETER_RE, '@...: the value of the first property, followed optionally by more',
+ {'parameter_name': '...',
+ 'fields': 'the value of the first property, followed optionally by more'}),
+ (PARAMETER_RE, '@args...: list of arguments',
+ {'parameter_name': 'args...',
+ 'fields': 'list of arguments'}),
+ (PARAMETER_RE, '@widget: a #GtkWidget',
+ {'parameter_name': 'widget',
+ 'fields': 'a #GtkWidget'}),
+ (PARAMETER_RE, '@widget_pointer: (inout) (transfer none): '
+ 'address of a variable that contains @widget',
+ {'parameter_name': 'widget_pointer',
+ 'fields': '(inout) (transfer none): address of a variable that contains @widget'}),
+ (PARAMETER_RE, '@weird_thing: (inout) (transfer none) (allow-none) (attribute) (destroy) '
+ '(foreign) (inout) (out) (transfer) (skip) (method): some weird @thing',
+ {'parameter_name': 'weird_thing',
+ 'fields': '(inout) (transfer none) (allow-none) (attribute) (destroy) '
+ '(foreign) (inout) (out) (transfer) (skip) (method): '
+ 'some weird @thing'}),
+ (PARAMETER_RE, '@data: a pointer to the element data. The data may be moved as elements '
+ 'are added to the #GByteArray.',
+ {'parameter_name': 'data',
+ 'fields': 'a pointer to the element data. The data may be moved as elements '
+ 'are added to the #GByteArray.'}),
+ (PARAMETER_RE, '@a: a #GSequenceIter',
+ {'parameter_name': 'a',
+ 'fields': 'a #GSequenceIter'}),
+ (PARAMETER_RE, '@keys: (array length=n_keys) (element-type GQuark) (allow-none):',
+ {'parameter_name': 'keys',
+ 'fields': '(array length=n_keys) (element-type GQuark) (allow-none):'}),
+ # parentheses in description
+ (PARAMETER_RE, '@foo: This is a foo (be careful using it)',
+ {'parameter_name': 'foo',
+ 'fields': 'This is a foo (be careful using it)'}),
+ (PARAMETER_RE, '@foo: This is a foo (be careful using it) and see also: bar',
+ {'parameter_name': 'foo',
+ 'fields': 'This is a foo (be careful using it) and see also: bar'}),
+ (PARAMETER_RE, '@foo: This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': 'This is a foo (be careful using it) and see also: bar and baz'}),
+ # annotations with multiple closing parentheses, combined with parentheses in description
+ (PARAMETER_RE, '@foo: (transfer full) (element-type guint8): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type guint8): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (transfer full) (element-type GLib.List(utf8)): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type GLib.List(utf8)): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (transfer full) (element-type GLib.List((utf8))): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type GLib.List((utf8))): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (transfer full) (element-type GLib.List(GLib.List(utf8))): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type GLib.List(GLib.List(utf8))): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (element-type GLib.List(GLib.List(utf8))) (transfer full): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(element-type GLib.List(GLib.List(utf8))) (transfer full): This is a foo (be careful using it) and see also: bar and baz'})]
+
+tag_tests = [
+ (TAG_RE, 'Since 3.0',
+ None),
+ (TAG_RE, 'Since: 3.0',
+ {'tag_name': 'Since',
+ 'fields': '3.0'}),
+ (TAG_RE, 'Attributes: (inout) (transfer none): some note about attributes',
+ {'tag_name': 'Attributes',
+ 'fields': '(inout) (transfer none): some note about attributes'}),
+ (TAG_RE, 'Rename to: something_else',
+ {'tag_name': 'Rename to',
+ 'fields': 'something_else'}),
+ (TAG_RE, '@Deprecated: Since 2.8, reference counting is done atomically',
+ None),
+ (TAG_RE, 'Returns %TRUE and does weird things',
+ None),
+ (TAG_RE, 'Returns: a #GtkWidget',
+ {'tag_name': 'Returns',
+ 'fields': 'a #GtkWidget'}),
+ (TAG_RE, 'Return value: (transfer none): The binary data that @text responds. '
+ 'This pointer',
+ {'tag_name': 'Return value',
+ 'fields': '(transfer none): The binary data that @text responds. This pointer'}),
+ (TAG_RE, 'Return value: (transfer full) (array length=out_len) (element-type guint8):',
+ {'tag_name': 'Return value',
+ 'fields': '(transfer full) (array length=out_len) (element-type guint8):'}),
+ (TAG_RE, 'Returns: A boolean value, but let me tell you a bit about this boolean. It',
+ {'tag_name': 'Returns',
+ 'fields': 'A boolean value, but let me tell you a bit about this boolean. It'}),
+ (TAG_RE, 'Returns: (transfer container) (element-type GObject.ParamSpec): a',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer container) (element-type GObject.ParamSpec): a'}),
+ (TAG_RE, 'Return value: (type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) '
+ '(transfer full):',
+ {'tag_name': 'Return value',
+ 'fields': '(type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) (transfer full):'}),
+ # parentheses in description
+ (TAG_RE, 'Returns: Returns a foo (be careful using it)',
+ {'tag_name': 'Returns',
+ 'fields': 'Returns a foo (be careful using it)'}),
+ (TAG_RE, 'Returns: Returns a foo (be careful using it) and see also: bar',
+ {'tag_name': 'Returns',
+ 'fields': 'Returns a foo (be careful using it) and see also: bar'}),
+ (TAG_RE, 'Returns: Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': 'Returns a foo (be careful using it) and see also: bar and baz'}),
+ # annotations with multiple closing parentheses, combined with parentheses in description
+ (TAG_RE, 'Returns: (transfer full) (element-type guint8): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type guint8): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (transfer full) (element-type GLib.List(utf8)): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type GLib.List(utf8)): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (transfer full) (element-type GLib.List((utf8))): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type GLib.List((utf8))): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (transfer full) (element-type GLib.List(GLib.List(utf8))): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type GLib.List(GLib.List(utf8))): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (element-type GLib.List(GLib.List(utf8))) (transfer full): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(element-type GLib.List(GLib.List(utf8))) (transfer full): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (element-type utf8=invalid GLib.HashTable(utf8,utf8) invalid): returns %NULL.',
+ {'tag_name': 'Returns',
+ 'fields': '(element-type utf8=invalid GLib.HashTable(utf8,utf8) invalid): returns %NULL.'})]
+
+
+tag_value_version_tests = [
+ (TAG_VALUE_VERSION_RE, ' abc',
+ {'value': '',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, '5 abc',
+ {'value': '5',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, '5:abc',
+ {'value': '5',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, ' 0.1: abc',
+ {'value': '0.1',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, ' 12.10.3698: abc',
+ {'value': '12.10.3698',
+ 'delimiter': ':',
+ 'description': 'abc'})]
+
+
+tag_value_stability_tests = [
+ (TAG_VALUE_STABILITY_RE, ' abc',
+ {'value': '',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'stable abc',
+ {'value': 'stable',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'unstable abc',
+ {'value': 'unstable',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'private abc',
+ {'value': 'private',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'internal abc',
+ {'value': 'internal',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'StAbLe: abc',
+ {'value': 'StAbLe',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'uNsTaBlE: abc',
+ {'value': 'uNsTaBlE',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'PRIVATE: abc',
+ {'value': 'PRIVATE',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, ' internal : abc',
+ {'value': 'internal',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'xyz: abc',
+ {'value': '',
+ 'delimiter': '',
+ 'description': 'xyz: abc'})]
+
+
+def create_test_method(testcase):
+ def do_test(self):
+ (program, text, expected) = testcase
+
+ match = program.match(text)
+
+ if match is not None:
+ msg = 'Test matched pattern but specifies no expected named groups.'
+ self.assertTrue(isinstance(expected, dict), msg)
+
+ for group in match.groupdict().keys():
+ msg = 'Test case is missing expected results for named group "%s".' % (group)
+ self.assertTrue(group in expected.keys(), msg)
+
+ if expected is None:
+ msg = 'Program matched text but shouldn\'t:\n"%s"'
+ self.assertTrue(match is None, msg % (text, ))
+ else:
+ msg = 'Program should match text but didn\'t:\n"%s"'
+ self.assertTrue(match is not None, msg % (text, ))
+
+ for key, value in expected.items():
+ msg = 'expected "%s" for "%s" but match returned "%s"'
+ msg = msg % (value, key, match.group(key))
+ self.assertEqual(match.group(key), value, msg)
+
+ return do_test
+
+
+def create_test_case(tests_class_name, testcases):
+ test_methods = {}
+ for (index, testcase) in enumerate(testcases):
+ test_method_name = 'test_%03d' % index
+
+ test_method = create_test_method(testcase)
+ test_method.__name__ = test_method_name
+ test_methods[test_method_name] = test_method
+
+ return type(tests_class_name, (unittest.TestCase,), test_methods)
+
+
+def create_test_cases():
+ test_cases = {}
+ for name, test_data in (('TestCommentStart', comment_start_tests),
+ ('TestCommentEnd', comment_end_tests),
+ ('TestCommentAsterisk', comment_asterisk_tests),
+ ('TestIndentaton', indentaton_tests),
+ ('TestEmptyLine', empty_line_tests),
+ ('TestIdentifierSection', identifier_section_tests),
+ ('TestIdentifierSymbol', identifier_symbol_tests),
+ ('TestIdentifierProperty', identifier_property_tests),
+ ('TestIdentifierSignal', identifier_signal_tests),
+ ('TestParameter', parameter_tests),
+ ('TestTag', tag_tests),
+ ('TestTagValueVersion', tag_value_version_tests),
+ ('TestTagValueStability', tag_value_stability_tests)):
+ test_cases[name] = create_test_case(name, test_data)
+
+ return test_cases
+
+
+# We currently need to push all the new test cases into the modules globals
+# in order for parameterized tests to work. Ideally all that should be needed
+# is the "load_tests" hook, but this does not work in the case were the tests
+# are run in parameterized mode, e.g: python -m unittest test_parser.Test...
+_all_tests = create_test_cases()
+globals().update(_all_tests)
+
+
+# Hook function for Python test loader.
+def load_tests(loader, tests, pattern):
+ suite = unittest.TestSuite()
+ # add standard tests from module
+ suite.addTests(tests)
+
+ for name, test_case in _all_tests.iteritems():
+ tests = loader.loadTestsFromTestCase(test_case)
+ suite.addTests(tests)
+ return suite
+
+
+if __name__ == '__main__':
+ unittest.main()