[gnome-code-assistance] [tests] Implemented testing diagnostics



commit ab93fbfa2f6b5a4dd3e87c31cdc1060288c0bf2a
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Thu Nov 14 15:56:39 2013 +0100

    [tests] Implemented testing diagnostics

 tests/gcatypes.py |  180 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/service     |  109 +++++++++++++++++++++++++++++++-
 2 files changed, 285 insertions(+), 4 deletions(-)
---
diff --git a/tests/gcatypes.py b/tests/gcatypes.py
new file mode 100644
index 0000000..0c4f359
--- /dev/null
+++ b/tests/gcatypes.py
@@ -0,0 +1,180 @@
+# gnome code assistance common
+# Copyright (C) 2013  Jesse van den Kieboom <jessevdk gnome org>
+#
+# 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+
+class OpenDocument:
+    def __init__(self, path='', data_path=''):
+        self.path = path
+        self.data_path = data_path
+
+    @classmethod
+    def from_tuple(cls, tp):
+        return cls(tp[0], tp[1])
+
+    def __repr__(self):
+        return '<OpenDocument: {0}, {1}>'.format(self.path, self.data_path)
+
+class RemoteDocument:
+    def __init__(self, path='', remote_path=''):
+        self.path = path
+        self.remote_path = remote_path
+
+    def __repr__(self):
+        return '<RemoteDocument: {0}, {1}>'.format(self.path, self.remote_path)
+
+    def to_tuple(self):
+        return (self.path, self.remote_path)
+
+class SourceLocation:
+    def __init__(self, line=0, column=0):
+        self.line = line
+        self.column = column
+
+    def __repr__(self):
+        return '{0}.{1}'.format(self.line, self.column)
+
+    def to_range(self, file=0):
+        start = SourceLocation(line=self.line, column=self.column)
+        end = SourceLocation(line=self.line, column=self.column)
+        return SourceRange(file=file, start=start, end=end)
+
+    def to_tuple(self):
+        return (self.line, self.column)
+
+    @classmethod
+    def from_tuple(cls, tp):
+        return cls(line=tp[0], column=tp[1])
+
+    @classmethod
+    def from_json(cls, js):
+        line = 0
+        column = 0
+
+        if 'line' in js:
+            line = js['line']
+
+        if 'column' in js:
+            column = js['column']
+
+        return cls(line=line, column=column)
+
+class SourceRange:
+    def __init__(self, file=0, start=SourceLocation(), end=None):
+        self.file = file
+        self.start = start
+
+        if end is None:
+            end = start
+
+        self.end = end
+
+    def __repr__(self):
+        return '{0}-{1}'.format(self.start, self.end)
+
+    def to_range(self):
+        return self
+
+    def to_tuple(self):
+        return (self.file, self.start.to_tuple(), self.end.to_tuple())
+
+    @classmethod
+    def from_tuple(cls, tp):
+        return cls(file=tp[0], start=SourceLocation.from_tuple(tp[1]), end=SourceLocation.from_tuple(tp[2]))
+
+    @classmethod
+    def from_json(cls, js):
+        file = 0
+        start = SourceLocation()
+
+        if 'file' in js:
+            file = js['file']
+
+        if 'start' in js:
+            start = SourceLocation.from_json(js['start'])
+
+        if 'end' in js:
+            end = SourceLocation.from_json(js['end'])
+        else:
+            end = SourceLocation(line=start.line, column=start.column)
+
+        return cls(file=file, start=start, end=end)
+
+class Fixit:
+    def __init__(self, location=SourceRange(), replacement=''):
+        self.location = location
+        self.replacement = replacement
+
+    def __repr__(self):
+        return '<Fixit: {0}: {1}>'.format(self.location, self.replacement)
+
+    def to_tuple(self):
+        return (self.location.to_tuple(), self.replacement)
+
+    @classmethod
+    def from_tuple(cls, tp):
+        return cls(location=SourceRange.from_tuple(tp[0]), replacement=tp[1])
+
+    @classmethod
+    def from_json(cls, js):
+        return cls(location=SourceRange.from_json(js['location']), replacement=js['replacement'])
+
+class Diagnostic:
+    class Severity:
+        NONE = 0
+        INFO = 1
+        WARNING = 2
+        DEPRECATED = 3
+        ERROR = 4
+        FATAL = 5
+
+    def __init__(self, severity=Severity.NONE, fixits=[], locations=[], message=''):
+        self.severity = severity
+        self.fixits = fixits
+        self.locations = locations
+        self.message = message
+
+    def __repr__(self):
+        return '<Diagnostic: {0}, {1}, {2}, {3}>'.format(self.severity, self.fixits, self.locations, 
self.message)
+
+    def to_tuple(self):
+        return (self.severity, [f.to_tuple() for f in self.fixits], [l.to_tuple() for l in self.locations], 
self.message)
+
+    @classmethod
+    def from_tuple(cls, tp):
+        return cls(severity=tp[0], fixits=[Fixit.from_tuple(f) for f in tp[1]], 
locations=[SourceRange.from_tuple(l) for l in tp[2]], message=tp[3])
+
+    @classmethod
+    def from_json(cls, js):
+        severity = 0
+        fixits = []
+        locations = []
+        message = ''
+
+        if 'severity' in js:
+            severity = js['severity']
+
+        if 'fixits' in js:
+            fixits = [Fixit.from_json(f) for f in js['fixits']]
+
+        if 'locations' in js:
+            locations = [SourceRange.from_json(l) for l in js['locations']]
+
+        if 'message' in js:
+            message = js['message']
+
+        return cls(severity=severity, fixits=fixits, locations=locations, message=message)
+
+# ex:ts=4:et:
diff --git a/tests/service b/tests/service
index 5dd0e96..6ef5a68 100755
--- a/tests/service
+++ b/tests/service
@@ -4,7 +4,7 @@ import sys, dbus, json, subprocess, os, glob, traceback
 import lxml.objectify
 
 sys.path.insert(0, os.path.dirname(__file__))
-import config
+import gcatypes
 sys.path = sys.path[1:]
 
 class Interface:
@@ -141,7 +141,7 @@ def test(name):
                     self.kwargs = kwargs
 
                 def __call__(self):
-                    f(*self.args, **self.kwargs)
+                    return f(*self.args, **self.kwargs)
 
                 def __enter__(self):
                     txt = '  TEST {0} ({1}) ... '.format(name, ', '.join([str(x) for x in self.args[1:]]))
@@ -181,7 +181,7 @@ class ServiceTest:
 
     @test('object')
     def test_object(self, path):
-        self.bus.get_object(self.name, self.full_path(path))
+        return self.bus.get_object(self.name, self.full_path(path))
 
     @test('interface')
     def test_interface(self, path, interface):
@@ -199,6 +199,98 @@ class ServiceTest:
 
         introf[interface].assert_equal(self.interfaces[interface])
 
+    def assert_source_location(self, l1, l2):
+        if l1.line != l2.line:
+            raise ValueError("Expected source location line {0} but got {1}".format(l1.line, l2.line))
+
+        if l1.column != l2.column:
+            raise ValueError("Expected source location column {0} but got {1}".format(l1.column, l2.column))
+
+    def assert_source_range(self, r1, r2):
+        if r1.file != r2.file:
+            raise ValueError("Expected source range file {0} but got {1}".format(r1.file, r2.file))
+
+        self.assert_source_location(r1.start, r2.start)
+        self.assert_source_location(r1.end, r2.end)
+
+    def assert_fixit(self, f1, f2):
+        self.assert_source_range(f1.location, f2.location)
+
+        if f1.replacement != f2.replacemnt:
+            raise ValueError("Expected fixit replacement {0} but got {1}".format(f1.replacement, 
f2.replacement))
+
+    def assert_diagnostic(self, d1, d2):
+        if d1.severity != d2.severity:
+            raise ValueError("Expected severity '{0}' but got '{1}'".format(d1.severity, d2.severity))
+
+        for i, v in enumerate(d1.fixits):
+            if i >= len(d2.fixits):
+                raise ValueError("Expected fixit {0}".format(v))
+
+            self.assert_fixit(v, d2.fixits[i])
+
+        for v in d2.fixits[len(d1.fixits):]:
+            raise ValueError("Unexpected fixit {0}".format(v))
+
+        for i, v in enumerate(d1.locations):
+            if i >= len(d2.locations):
+                raise ValueError("Expected source range {0}".format(v))
+
+            self.assert_source_range(v, d2.locations[i])
+
+        for v in d2.locations[len(d1.locations):]:
+            raise ValueError("Unexpected source range {0}".format(v))
+
+        if d1.message != d2.message:
+            raise ValueError("Expected message '{0}' but got '{1}'".format(d1.message, d2.message))
+
+    @test('diagnostics')
+    def test_diagnostics(self, d1, d2):
+        for i, v in enumerate(d1):
+            if i >= len(d2):
+                raise ValueError("Expected diagnostic {0}".format(v))
+
+            self.assert_diagnostic(v, d2[i])
+
+        for v in d2[len(d1):]:
+            raise ValueError("Unexpected diagnostic {0}".format(v))
+
+    def run_parse(self, p):
+        path = p['path']
+        obj = self.bus.get_object(self.name, self.path)
+
+        iface = dbus.Interface(obj, 'org.gnome.CodeAssist.v1.Service')
+
+        dpath = os.path.abspath(os.path.join(os.path.dirname(__file__), 'backends', path))
+        doc = iface.Parse(dpath, '', (0, 0), {})
+
+        doc = doc[len(self.path):]
+
+        with self.test_object(doc) as t:
+            obj = t()
+
+        return doc, obj
+
+    def run_parse_all(self, p):
+        pass
+
+    def run_diagnostic(self, d):
+        if 'parse' in d:
+            path, parsed = self.run_parse(d['parse'])
+        else:
+            raise ValueError('Do not know how to parse diagnostic')
+
+        with self.test_interface(path, 'org.gnome.CodeAssist.v1.Diagnostics') as t:
+            t()
+
+        diag = dbus.Interface(parsed, 'org.gnome.CodeAssist.v1.Diagnostics')
+
+        ret = [gcatypes.Diagnostic.from_tuple(dd) for dd in diag.Diagnostics()]
+        orig = [gcatypes.Diagnostic.from_json(dd) for dd in d['diagnostics']]
+
+        with self.test_diagnostics(orig, ret) as t:
+            t()
+
     def run(self):
         print('TESTING {0}'.format(self.name))
 
@@ -225,6 +317,12 @@ class ServiceTest:
                 with self.test_interface('/document', interface) as t:
                     t()
 
+        if 'diagnostics' in self.test:
+            diagnostics = self.test['diagnostics']
+
+            for d in diagnostics:
+                self.run_diagnostic(d)
+
 def run_test(testfile):
     with open(testfile, 'r') as j:
         test = json.loads(j.read())
@@ -235,7 +333,10 @@ def run_test(testfile):
 
 dirname = os.path.dirname(__file__)
 
-testfiles = glob.glob(os.path.join(dirname, 'backends', '*.json'))
+if len(sys.argv) <= 1:
+    testfiles = glob.glob(os.path.join(dirname, 'backends', '*.json'))
+else:
+    testfiles = sys.argv[1:]
 
 dn = open(os.devnull, 'w')
 daemon = subprocess.Popen(['dbus-daemon', '--print-address', '--nofork', '--config-file', 
os.path.join(dirname, 'dbus.conf')], stdout=subprocess.PIPE, stderr=dn, close_fds=True)


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