[gobject-introspection] tests: test emitted GTK-Doc parser warning messages



commit 2c071ea938ca7500ed83c9958577eb15b37e139a
Author: Dieter Verfaillie <dieterv optionexplicit be>
Date:   Fri Jul 26 13:48:12 2013 +0200

    tests: test emitted GTK-Doc parser warning messages

 tests/scanner/annotationparser/gi/syntax.xml       |   21 +++++
 .../annotationparser/gi/syntax_identifier.xml      |   83 +++++++++++++++++++
 .../gi/syntax_paragraph_breaks.xml                 |   20 +++++
 .../annotationparser/gi/tag_description.xml        |    5 +
 tests/scanner/annotationparser/test_parser.py      |   86 ++++++++++++++++---
 5 files changed, 201 insertions(+), 14 deletions(-)
---
diff --git a/tests/scanner/annotationparser/gi/syntax.xml b/tests/scanner/annotationparser/gi/syntax.xml
index 1bb8652..7838167 100644
--- a/tests/scanner/annotationparser/gi/syntax.xml
+++ b/tests/scanner/annotationparser/gi/syntax.xml
@@ -91,6 +91,14 @@ something */</input>
       </identifier>
       <description>something</description>
     </docblock>
+    <messages>
+      <message>3: Warning: Test: Comments should end with */ on a new line:
+something */
+         ^</message>
+      <message>2: Warning: Test: missing ':' at column 5:
+Test
+    ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -108,6 +116,14 @@ something **/</input>
       </identifier>
       <description>something</description>
     </docblock>
+    <messages>
+      <message>3: Warning: Test: Comments should end with */ on a new line:
+something **/
+         ^</message>
+      <message>2: Warning: Test: missing ':' at column 5:
+Test
+    ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -136,6 +152,11 @@ something **/</input>
       </parameters>
       <description>The application class handles ...</description>
     </docblock>
+    <messages>
+      <message>4: Warning: Test: '@short_description' parameter unexpected at this location:
+ * @short_description: the application class
+    ^</message>
+    </messages>
   </parser>
 </test>
 
diff --git a/tests/scanner/annotationparser/gi/syntax_identifier.xml 
b/tests/scanner/annotationparser/gi/syntax_identifier.xml
index bd7d5c5..f5453eb 100644
--- a/tests/scanner/annotationparser/gi/syntax_identifier.xml
+++ b/tests/scanner/annotationparser/gi/syntax_identifier.xml
@@ -10,6 +10,13 @@
 *
 * SECTION:meepapp
 */</input>
+  <parser>
+    <messages>
+      <message>2: Warning: Test: ignoring unrecognized GTK-Doc comment block, identifier not found:
+*
+ ^</message>
+    </messages>
+  </parser>
 </test>
 
 <test>
@@ -148,6 +155,29 @@ The application class handles ...</description>
       </parameters>
       <description>The application class handles ...</description>
     </docblock>
+    <messages>
+      <message>4: Warning: Test: '@short_description' parameter unexpected at this location:
+ * @short_description: the application class
+    ^</message>
+      <message>5: Warning: Test: '@title' parameter unexpected at this location:
+ * @title: Meep application
+    ^</message>
+      <message>6: Warning: Test: '@section_id' parameter unexpected at this location:
+ * @section_id:
+    ^</message>
+      <message>7: Warning: Test: '@see_also' parameter unexpected at this location:
+ * @see_also: #MeepSettings
+    ^</message>
+      <message>8: Warning: Test: '@stability' parameter unexpected at this location:
+ * @stability: Stable
+    ^</message>
+      <message>9: Warning: Test: '@include' parameter unexpected at this location:
+ * @include: meep/app.h
+    ^</message>
+      <message>10: Warning: Test: '@image' parameter unexpected at this location:
+ * @image: application.png
+    ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -203,6 +233,29 @@ The application class handles ...</description>
       </parameters>
       <description>The application class handles ...</description>
     </docblock>
+    <messages>
+      <message>5: Warning: Test: '@short_description' parameter unexpected at this location:
+ * @short_description: the application class
+    ^</message>
+      <message>6: Warning: Test: '@title' parameter unexpected at this location:
+ * @title: Meep application
+    ^</message>
+      <message>7: Warning: Test: '@section_id' parameter unexpected at this location:
+ * @section_id:
+    ^</message>
+      <message>8: Warning: Test: '@see_also' parameter unexpected at this location:
+ * @see_also: #MeepSettings
+    ^</message>
+      <message>9: Warning: Test: '@stability' parameter unexpected at this location:
+ * @stability: Stable
+    ^</message>
+      <message>10: Warning: Test: '@include' parameter unexpected at this location:
+ * @include: meep/app.h
+    ^</message>
+      <message>11: Warning: Test: '@image' parameter unexpected at this location:
+ * @image: application.png
+    ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -259,6 +312,29 @@ The application class handles ...</description>
       </parameters>
       <description>The application class handles ...</description>
     </docblock>
+    <messages>
+      <message>6: Warning: Test: '@short_description' parameter unexpected at this location:
+ * @short_description: the application class
+    ^</message>
+      <message>7: Warning: Test: '@title' parameter unexpected at this location:
+ * @title: Meep application
+    ^</message>
+      <message>8: Warning: Test: '@section_id' parameter unexpected at this location:
+ * @section_id:
+    ^</message>
+      <message>9: Warning: Test: '@see_also' parameter unexpected at this location:
+ * @see_also: #MeepSettings
+    ^</message>
+      <message>10: Warning: Test: '@stability' parameter unexpected at this location:
+ * @stability: Stable
+    ^</message>
+      <message>11: Warning: Test: '@include' parameter unexpected at this location:
+ * @include: meep/app.h
+    ^</message>
+      <message>12: Warning: Test: '@image' parameter unexpected at this location:
+ * @image: application.png
+    ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -311,6 +387,13 @@ returns nothing.</description>
  *
  * NOTE : This DOES check for array partitioning.
  */</input>
+  <parser>
+    <messages>
+      <message>2: Warning: Test: ignoring unrecognized GTK-Doc comment block, identifier not found:
+ * gnm_cell_set_expr_and_value: Stores (WITHOUT COPYING) the supplied value, and
+   ^</message>
+    </messages>
+  </parser>
 </test>
 
 </tests>
diff --git a/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml 
b/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml
index 3303af4..7e88bf7 100644
--- a/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml
+++ b/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml
@@ -47,6 +47,11 @@ So this is considered a new paragraph.</description>
 
 So this is considered a new paragraph.</description>
     </docblock>
+    <messages>
+      <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: The following line is ' *' (blank-asterisk).
+   ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -93,6 +98,11 @@ So this is considered a new paragraph.</description>
 
 So this is considered a new paragraph.</description>
     </docblock>
+    <messages>
+      <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: The following line is ' * ' (blank-asterisk-blank).
+   ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -143,6 +153,11 @@ So this is preceded by an empty line and is not considered a new paragraph.</des
  
 So this is preceded by an empty line and is not considered a new paragraph.</description>
     </docblock>
+    <messages>
+      <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: The following line is (blank-asterisk-blank-blank).
+   ^</message>
+    </messages>
   </parser>
 </test>
 
@@ -249,6 +264,11 @@ print_attributes (GIBaseInfo *info)
 </programlisting>
 </example>]]></description>
     </docblock>
+    <messages>
+      <message><![CDATA[4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: <example>
+   ^]]></message>
+    </messages>
   </parser>
 </test>
 
diff --git a/tests/scanner/annotationparser/gi/tag_description.xml 
b/tests/scanner/annotationparser/gi/tag_description.xml
index f16c9d3..eb6c166 100644
--- a/tests/scanner/annotationparser/gi/tag_description.xml
+++ b/tests/scanner/annotationparser/gi/tag_description.xml
@@ -17,6 +17,11 @@
       <description>This is a callback with a 'closure' argument that is not named
 'user_data' and hence has to be annotated.</description>
     </docblock>
+    <messages>
+      <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: This is a callback with a 'closure' argument that is not named
+   ^</message>
+    </messages>
   </parser>
 </test>
 
diff --git a/tests/scanner/annotationparser/test_parser.py b/tests/scanner/annotationparser/test_parser.py
index 50a4fcc..5234451 100644
--- a/tests/scanner/annotationparser/test_parser.py
+++ b/tests/scanner/annotationparser/test_parser.py
@@ -43,6 +43,17 @@ XML_SCHEMA = os.path.abspath(os.path.join(os.path.dirname(__file__), 'tests.xsd'
 XML_LINT = None
 
 
+class ChunkedIO(object):
+    def __init__(self):
+        self.buffer = []
+
+    def write(self, s):
+        self.buffer.append(s)
+
+    def getvalue(self):
+        return self.buffer
+
+
 def ns(x):
     return x.replace('{}', '{%s}' % (XML_NS, ))
 
@@ -65,18 +76,26 @@ def validate(tests_file):
 
 class TestCommentBlock(unittest.TestCase):
     @classmethod
-    def __create_test__(cls, testcase):
+    def __create_test__(cls, logger, testcase):
         def do_test(self):
+            output = ChunkedIO()
+            logger._output = output
+
             # Parse GTK-Doc comment block
             commentblock = testcase.find(ns('{}input')).text
             parsed_docblock = AnnotationParser().parse_comment_block((commentblock, 'test.c', 1))
             parsed_tree = self.parsed2tree(parsed_docblock).split('\n')
+            emitted_messages = [w[w.find(':') + 1:].strip() for w in output.getvalue()]
 
             # Get expected parser output
             expected_docblock = testcase.find(ns('{}parser/{}docblock'))
             expected_tree = self.expected2tree(expected_docblock).split('\n')
 
-            # Construct a meaningful message
+            expected_messages = []
+            for w in testcase.findall(ns('{}parser/{}messages/{}message')):
+                expected_messages.append(w.text.strip())
+
+            # Compare parsed with expected GtkDocCommentBlock
             msg = 'Parsed DocBlock object tree does not match expected output:\n\n'
             msg += '%s\n\n' % (commentblock, )
 
@@ -87,8 +106,19 @@ class TestCommentBlock(unittest.TestCase):
             for line in diff:
                 msg += '%s\n' % (line, )
 
-            # Compare parsed with expected DocBlock tree
-            self.assertEqual(parsed_tree, expected_tree, msg)
+            self.assertTrue(parsed_tree == expected_tree, msg)
+
+            # Compare emitted with expected messages
+            msg = 'Emitted messages do not match expected messages:\n\n'
+            msg += '%s\n\n' % (commentblock, )
+            msg += self._diff_messages(expected_messages, emitted_messages)
+            self.assertTrue(len(expected_messages) == len(emitted_messages), msg)
+
+            for emitted_message, expected_message in zip(emitted_messages, expected_messages):
+                msg = 'Emitted message does not match expected message:\n\n'
+                msg += '%s\n\n' % (commentblock, )
+                msg += self._diff_messages([expected_message], [emitted_message])
+                self.assertTrue(expected_message == emitted_message, msg)
 
         return do_test
 
@@ -276,11 +306,41 @@ class TestCommentBlock(unittest.TestCase):
 
         return expected
 
-
-def create_tests(tests_dir, tests_file):
-    tests_name = os.path.relpath(tests_file[:-4], tests_dir)
-    tests_name = tests_name.replace('/', '.').replace('\\', '.')
-
+    def _diff_messages(self, a, b):
+        retval = ''
+        started = False
+
+        for group in difflib.SequenceMatcher(None, a, b).get_grouped_opcodes(3):
+            if not started:
+                started = True
+                retval += '--- expected\n'
+                retval += '+++ emitted\n'
+
+            for tag, i1, i2, j1, j2 in group:
+                if tag == 'equal':
+                    for line in a[i1:i2]:
+                        for l in line.split('\n'):
+                            if l != '':
+                                retval += ' ' + l + '\n'
+                    continue
+
+                if tag in ('replace', 'delete'):
+                    for line in a[i1:i2]:
+                        for l in line.split('\n'):
+                            if l != '':
+                                retval += '-' + l + '\n'
+
+                if tag in ('replace', 'insert'):
+                    for line in b[j1:j2]:
+                        for l in line.split('\n'):
+                            if l != '':
+                                retval += '+' + l + '\n'
+
+        return retval
+
+
+def create_tests(logger, tests_dir, tests_file):
+    tests_name = os.path.relpath(tests_file[:-4], tests_dir).replace('/', '.').replace('\\', '.')
     tests_tree = etree.parse(tests_file).getroot()
 
     fix_cdata_elements = tests_tree.findall(ns('{}test/{}input'))
@@ -293,17 +353,15 @@ def create_tests(tests_dir, tests_file):
 
     for counter, test in enumerate(tests_tree.findall(ns('{}test'))):
         test_name = 'test_%s.%03d' % (tests_name, counter + 1)
-        test_method = TestCommentBlock.__create_test__(test)
+        test_method = TestCommentBlock.__create_test__(logger, test)
         setattr(TestCommentBlock, test_name, test_method)
 
 
 if __name__ == '__main__':
     # Initialize message logger
-    # TODO: at some point it might be a good idea to test warnings emitted
-    # by annotationparser here, instead of having them in tests/warn/annotationparser.h?
     namespace = Namespace('Test', '1.0')
     logger = MessageLogger.get(namespace=namespace)
-    logger.enable_warnings(False)
+    logger.enable_warnings(True)
 
     # Load test cases from disc
     tests_dir = os.path.dirname(os.path.abspath(__file__))
@@ -313,7 +371,7 @@ if __name__ == '__main__':
             tests_file = os.path.join(dirpath, filename)
             if os.path.basename(tests_file).endswith('.xml'):
                 validate(tests_file)
-                create_tests(tests_dir, tests_file)
+                create_tests(logger, tests_dir, tests_file)
 
     # Run test suite
     unittest.main()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]