]> git.proxmox.com Git - mirror_qemu.git/blobdiff - tests/qapi-schema/test-qapi.py
qapi: Speed up frontend tests
[mirror_qemu.git] / tests / qapi-schema / test-qapi.py
old mode 100644 (file)
new mode 100755 (executable)
index b0f770b..42baa70
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 #
 # QAPI parser test harness
 #
 #
 
 from __future__ import print_function
+import argparse
+import difflib
+import os
 import sys
+if sys.version_info[0] < 3:
+    from cStringIO import StringIO
+else:
+    from io import StringIO
 from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor
 
 
@@ -87,21 +95,102 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             print('%sif %s' % (' ' * indent, ifcond))
 
 
-try:
-    schema = QAPISchema(sys.argv[1])
-except QAPIError as err:
-    print(err, file=sys.stderr)
-    exit(1)
-
-schema.visit(QAPISchemaTestVisitor())
-
-for doc in schema.docs:
-    if doc.symbol:
-        print('doc symbol=%s' % doc.symbol)
+def test_frontend(fname):
+    schema = QAPISchema(fname)
+    schema.visit(QAPISchemaTestVisitor())
+
+    for doc in schema.docs:
+        if doc.symbol:
+            print('doc symbol=%s' % doc.symbol)
+        else:
+            print('doc freeform')
+        print('    body=\n%s' % doc.body.text)
+        for arg, section in doc.args.items():
+            print('    arg=%s\n%s' % (arg, section.text))
+        for section in doc.sections:
+            print('    section=%s\n%s' % (section.name, section.text))
+
+
+def test_and_diff(test_name, dir_name, update):
+    sys.stdout = StringIO()
+    try:
+        test_frontend(os.path.join(dir_name, test_name + '.json'))
+    except QAPIError as err:
+        if err.info.fname is None:
+            print("%s" % err, file=sys.stderr)
+            return 2
+        errstr = str(err) + '\n'
+        if dir_name:
+            errstr = errstr.replace(dir_name + '/', '')
+        actual_err = errstr.splitlines(True)
     else:
-        print('doc freeform')
-    print('    body=\n%s' % doc.body.text)
-    for arg, section in doc.args.items():
-        print('    arg=%s\n%s' % (arg, section.text))
-    for section in doc.sections:
-        print('    section=%s\n%s' % (section.name, section.text))
+        actual_err = []
+    finally:
+        actual_out = sys.stdout.getvalue().splitlines(True)
+        sys.stdout.close()
+        sys.stdout = sys.__stdout__
+
+    mode = 'r+' if update else 'r'
+    try:
+        outfp = open(os.path.join(dir_name, test_name + '.out'), mode)
+        errfp = open(os.path.join(dir_name, test_name + '.err'), mode)
+        expected_out = outfp.readlines()
+        expected_err = errfp.readlines()
+    except IOError as err:
+        print("%s: can't open '%s': %s"
+              % (sys.argv[0], err.filename, err.strerror),
+              file=sys.stderr)
+        return 2
+
+    if actual_out == expected_out and actual_err == expected_err:
+        return 0
+
+    print("%s %s" % (test_name, 'UPDATE' if update else 'FAIL'),
+          file=sys.stderr)
+    out_diff = difflib.unified_diff(expected_out, actual_out, outfp.name)
+    err_diff = difflib.unified_diff(expected_err, actual_err, errfp.name)
+    sys.stdout.writelines(out_diff)
+    sys.stdout.writelines(err_diff)
+
+    if not update:
+        return 1
+
+    try:
+        outfp.truncate(0)
+        outfp.seek(0)
+        outfp.writelines(actual_out)
+        errfp.truncate(0)
+        errfp.seek(0)
+        errfp.writelines(actual_err)
+    except IOError as err:
+        print("%s: can't write '%s': %s"
+              % (sys.argv[0], err.filename, err.strerror),
+              file=sys.stderr)
+        return 2
+
+    return 0
+
+
+def main(argv):
+    parser = argparse.ArgumentParser(
+        description='QAPI schema tester')
+    parser.add_argument('-d', '--dir', action='store', default='',
+                        help="directory containing tests")
+    parser.add_argument('-u', '--update', action='store_true',
+                        help="update expected test results")
+    parser.add_argument('tests', nargs='*', metavar='TEST', action='store')
+    args = parser.parse_args()
+
+    status = 0
+    for t in args.tests:
+        (dir_name, base_name) = os.path.split(t)
+        dir_name = dir_name or args.dir
+        test_name = os.path.splitext(base_name)[0]
+        status |= test_and_diff(test_name, dir_name, args.update)
+
+    exit(status)
+
+
+if __name__ == '__main__':
+    main(sys.argv)
+    exit(0)