[gnome-code-assistance] Added start of basic tests
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-code-assistance] Added start of basic tests
- Date: Thu, 14 Nov 2013 13:51:09 +0000 (UTC)
commit c253993b68d7840e54aef5ff787881f7cbc17c02
Author: Jesse van den Kieboom <jessevdk gmail com>
Date: Thu Nov 14 14:49:43 2013 +0100
Added start of basic tests
Makefile.am | 2 +
configure.ac | 8 +-
tests/Makefile.am | 1 +
tests/backends/c.json | 5 +
tests/backends/css.json | 5 +
tests/backends/go.json | 5 +
tests/backends/js.json | 5 +
tests/backends/python.json | 5 +
tests/backends/ruby.json | 27 +++++
tests/backends/ruby.rb | 5 +
tests/backends/sh.json | 5 +
tests/backends/vala.json | 5 +
tests/backends/xml.json | 5 +
tests/config.py.in | 1 +
tests/dbus.conf.in | 21 ++++
tests/interfaces.json | 21 ++++
tests/service | 255 ++++++++++++++++++++++++++++++++++++++++++++
17 files changed, 379 insertions(+), 2 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 5da0e02..834cb6f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -29,9 +29,11 @@ GITIGNOREDEPS =
BUILT_SOURCES =
DISTCLEANFILES =
gsettings_SCHEMAS =
+TESTS =
include data/Makefile.am
include backends/Makefile.am
+include tests/Makefile.am
@GSETTINGS_RULES@
diff --git a/configure.ac b/configure.ac
index a27e197..4642503 100644
--- a/configure.ac
+++ b/configure.ac
@@ -467,8 +467,10 @@ backendexecdir_unex="$libexecdir/gnome-code-assistance"
adl_RECURSIVE_EVAL("$backendexecdir_unex", [backendexecdir])
AC_SUBST(backendexecdir)
-GCA_BACKENDS_EXEC_DIR="$libexecdir/gnome-code-assistance"
-AC_SUBST(GCA_BACKENDS_EXEC_DIR)
+adl_RECURSIVE_EVAL("$datadir", [datadirex])
+AC_SUBST(datadirex)
+
+GCA_BACKENDS_EXEC_DIR="$backendexecdir_unex"
GCA_BACKENDS_DIR="$GCA_BACKENDS_EXEC_DIR/backends"
AC_SUBST(GCA_BACKENDS_DIR)
@@ -546,6 +548,8 @@ backends/sh/sh
backends/css/org.gnome.CodeAssist.v1.css.service
backends/css/css
data/org.gnome.codeassistance.gschema.xml
+tests/config.py
+tests/dbus.conf
])
AC_OUTPUT
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..f51f67c
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1 @@
+TESTS += tests/service
diff --git a/tests/backends/c.json b/tests/backends/c.json
new file mode 100644
index 0000000..b36bc4d
--- /dev/null
+++ b/tests/backends/c.json
@@ -0,0 +1,5 @@
+{
+ "language": "python",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/backends/css.json b/tests/backends/css.json
new file mode 100644
index 0000000..7325616
--- /dev/null
+++ b/tests/backends/css.json
@@ -0,0 +1,5 @@
+{
+ "language": "css",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/backends/go.json b/tests/backends/go.json
new file mode 100644
index 0000000..50ddb83
--- /dev/null
+++ b/tests/backends/go.json
@@ -0,0 +1,5 @@
+{
+ "language": "go",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/backends/js.json b/tests/backends/js.json
new file mode 100644
index 0000000..0103ab0
--- /dev/null
+++ b/tests/backends/js.json
@@ -0,0 +1,5 @@
+{
+ "language": "js",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/backends/python.json b/tests/backends/python.json
new file mode 100644
index 0000000..b36bc4d
--- /dev/null
+++ b/tests/backends/python.json
@@ -0,0 +1,5 @@
+{
+ "language": "python",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/backends/ruby.json b/tests/backends/ruby.json
new file mode 100644
index 0000000..c021d03
--- /dev/null
+++ b/tests/backends/ruby.json
@@ -0,0 +1,27 @@
+{
+ "language": "ruby",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"],
+ "diagnostics": [
+ {
+ "parse": {
+ "path": "ruby_fail.rb"
+ },
+ "diagnostics": [
+ {
+ "severity": 4,
+ "locations": [
+ {
+ "start": {
+ "line": 4,
+ "column": 8
+ }
+ }
+ ],
+ "fixits": [],
+ "message": "unexpected '<'"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/backends/ruby.rb b/tests/backends/ruby.rb
new file mode 100644
index 0000000..7f0121e
--- /dev/null
+++ b/tests/backends/ruby.rb
@@ -0,0 +1,5 @@
+def method
+end
+
+class < noname
+end
diff --git a/tests/backends/sh.json b/tests/backends/sh.json
new file mode 100644
index 0000000..20056de
--- /dev/null
+++ b/tests/backends/sh.json
@@ -0,0 +1,5 @@
+{
+ "language": "sh",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/backends/vala.json b/tests/backends/vala.json
new file mode 100644
index 0000000..55ef263
--- /dev/null
+++ b/tests/backends/vala.json
@@ -0,0 +1,5 @@
+{
+ "language": "vala",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/backends/xml.json b/tests/backends/xml.json
new file mode 100644
index 0000000..cdae475
--- /dev/null
+++ b/tests/backends/xml.json
@@ -0,0 +1,5 @@
+{
+ "language": "xml",
+ "interfaces": [],
+ "document_interfaces": ["org.gnome.CodeAssist.v1.Diagnostics"]
+}
diff --git a/tests/config.py.in b/tests/config.py.in
new file mode 100644
index 0000000..c48f24b
--- /dev/null
+++ b/tests/config.py.in
@@ -0,0 +1 @@
+execdir = '@backendexecdir@'
diff --git a/tests/dbus.conf.in b/tests/dbus.conf.in
new file mode 100644
index 0000000..378cff8
--- /dev/null
+++ b/tests/dbus.conf.in
@@ -0,0 +1,21 @@
+<!-- This configuration file controls the per-user-login-session message bus.
+ Add a session-local.conf and edit that rather than changing this
+ file directly. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>unix:tmpdir=/tmp</listen>
+ <servicedir>@datadirex@/dbus-1/services</servicedir>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+</busconfig>
diff --git a/tests/interfaces.json b/tests/interfaces.json
new file mode 100644
index 0000000..5d5500a
--- /dev/null
+++ b/tests/interfaces.json
@@ -0,0 +1,21 @@
+{
+ "org.gnome.CodeAssist.v1.Service": {
+ "Parse": [
+ {"name": "path", "direction": "in", "type": "s"},
+ {"name": "data_path", "direction": "in", "type": "s"},
+ {"name": "cursor", "direction": "in", "type": "(xx)"},
+ {"name": "options", "direction": "in", "type": "a{sv}"},
+ {"name": "document", "direction": "out", "type": "o"}
+ ],
+ "Dispose": [
+ {"name": "path", "direction": "in", "type": "s"}
+ ]
+ },
+ "org.gnome.CodeAssist.v1.Document": {
+ },
+ "org.gnome.CodeAssist.v1.Diagnostics": {
+ "Diagnostics": [
+ {"name": "result", "direction": "out", "type": "a(ua((x(xx)(xx))s)a(x(xx)(xx))s)"}
+ ]
+ }
+}
diff --git a/tests/service b/tests/service
new file mode 100755
index 0000000..5dd0e96
--- /dev/null
+++ b/tests/service
@@ -0,0 +1,255 @@
+#!/usr/bin/python3
+
+import sys, dbus, json, subprocess, os, glob, traceback
+import lxml.objectify
+
+sys.path.insert(0, os.path.dirname(__file__))
+import config
+sys.path = sys.path[1:]
+
+class Interface:
+ class Arg:
+ def __init__(self):
+ self.name = ''
+ self.direction = 'in'
+ self.signature = ''
+
+ def assert_equal(self, other):
+ if self.direction != other.direction:
+ raise ValueError("Expected direction {0} for argument {1}, but got
{2}".format(self.direction, self.name, other.direction))
+
+ if self.signature != other.signature:
+ raise ValueError("Expected signature {0} for argument {1}, but got
{2}".format(self.signature, self.name, other.signature))
+
+ class Method:
+ def __init__(self):
+ self.name = ''
+ self.args = []
+
+ def assert_equal(self, other):
+ if self.name != other.name:
+ raise ValueError("Methods have different names, expected {0} but got {1}".format(self.name,
other.name))
+
+ for i, a in enumerate(self.args):
+ if i >= len(other.args):
+ raise ValueError("Missing expected argument {0}:{1} missing".format(a.name, a.signature))
+
+ a.assert_equal(other.args[i])
+
+ for a in other.args[len(self.args):]:
+ raise ValueError("Unexpected argument {0}:{1}".format(a.name, a.signature))
+
+ def __init__(self):
+ self.name = ''
+ self.methods = {}
+
+ def assert_equal(self, other):
+ if self.name != other.name:
+ raise ValueError("Interfaces have different names, expected {0} but got {1}".format(self.name,
other.name))
+
+ otherm = {m: True for m in other.methods}
+
+ for m in self.methods:
+ m1 = self.methods[m]
+
+ if not m in otherm:
+ raise ValueError("Missing method {0}".format(m))
+
+ del otherm[m]
+ m1.assert_equal(other.methods[m])
+
+ for k in otherm:
+ raise ValueError("Unexpected method {0}".format(k))
+
+ @classmethod
+ def from_xml(cls, xml):
+ ret = {}
+ obj = lxml.objectify.fromstring(xml)
+
+ for i in obj.interface:
+ ii = cls()
+
+ ii.name = i.attrib['name']
+ ret[ii.name] = ii
+
+ if not hasattr(i, 'method'):
+ continue
+
+ for m in i.method:
+ meth = cls.Method()
+ meth.name = m.attrib['name']
+
+ ii.methods[meth.name] = meth
+
+ if not hasattr(m, 'arg'):
+ continue
+
+ for a in m.arg:
+ aa = cls.Arg()
+ aa.direction = a.attrib['direction']
+ aa.signature = a.attrib['type']
+
+ if 'name' in a.attrib:
+ aa.name = a.attrib['name']
+
+ meth.args.append(aa)
+
+ return ret
+
+ @classmethod
+ def from_json(cls, js):
+ with open(js) as f:
+ contents = f.read()
+
+ js = json.loads(contents)
+ ret = {}
+
+ for k in js:
+ ii = cls()
+ ii.name = k
+
+ ret[k] = ii
+
+ methods = js[k]
+
+ for mname in methods:
+ meth = cls.Method()
+ meth.name = mname
+
+ m = methods[mname]
+
+ ii.methods[meth.name] = meth
+
+ for a in m:
+ aa = cls.Arg()
+ aa.direction = a['direction']
+ aa.signature = a['type']
+
+ if 'name' in a:
+ aa.name = a['name']
+
+ meth.args.append(aa)
+
+ return ret
+
+def test(name):
+ def decorator(f):
+ def dummy(*args, **kwargs):
+ class C:
+ def __init__(self, args, kwargs):
+ self.args = args
+ self.kwargs = kwargs
+
+ def __call__(self):
+ f(*self.args, **self.kwargs)
+
+ def __enter__(self):
+ txt = ' TEST {0} ({1}) ... '.format(name, ', '.join([str(x) for x in self.args[1:]]))
+ sys.stdout.write(txt)
+ return self
+
+ def __exit__(self, typ, value, tb):
+ if not value is None:
+ print('[FAIL]: {0}'.format(value))
+ print(' {0}'.format(''.join(traceback.format_tb(tb)).replace("\n", '\n ')))
+ else:
+ print('[OK]')
+
+ return True
+
+ return C(args, kwargs)
+
+ return dummy
+
+ return decorator
+
+class ServiceTest:
+ interfaces = Interface.from_json(os.path.join(os.path.dirname(__file__), 'interfaces.json'))
+
+ def __init__(self, bus, test):
+ self.test = test
+ self.language = test['language']
+ self.name = 'org.gnome.CodeAssist.v1.' + self.language
+ self.path = '/org/gnome/CodeAssist/v1/' + self.language
+ self.bus = bus
+
+ def full_path(self, path):
+ if path != '/':
+ return self.path + path
+ else:
+ return self.path
+
+ @test('object')
+ def test_object(self, path):
+ self.bus.get_object(self.name, self.full_path(path))
+
+ @test('interface')
+ def test_interface(self, path, interface):
+ obj = self.bus.get_object(self.name, self.full_path(path))
+
+ intro = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
+ xml = intro.Introspect()
+ introf = Interface.from_xml(xml)
+
+ if not interface in introf:
+ raise ValueError("Missing interface {0}".format(interface))
+
+ if not interface in self.interfaces:
+ raise ValueError("Unknown interface {0}".format(interface))
+
+ introf[interface].assert_equal(self.interfaces[interface])
+
+ def run(self):
+ print('TESTING {0}'.format(self.name))
+
+ # Test for default interfaces and paths
+ with self.test_object('/') as t:
+ t()
+
+ with self.test_interface('/', 'org.gnome.CodeAssist.v1.Service') as t:
+ t()
+
+ if 'interfaces' in self.test:
+ for interface in self.test['interfaces']:
+ with self.test_interface('/', interface) as t:
+ t()
+
+ with self.test_object('/document') as t:
+ t()
+
+ with self.test_interface('/document', 'org.gnome.CodeAssist.v1.Document') as t:
+ t()
+
+ if 'document_interfaces' in self.test:
+ for interface in self.test['document_interfaces']:
+ with self.test_interface('/document', interface) as t:
+ t()
+
+def run_test(testfile):
+ with open(testfile, 'r') as j:
+ test = json.loads(j.read())
+
+ bus = dbus.SessionBus(private=True)
+ t = ServiceTest(bus, test)
+ t.run()
+
+dirname = os.path.dirname(__file__)
+
+testfiles = glob.glob(os.path.join(dirname, 'backends', '*.json'))
+
+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)
+
+try:
+ address = daemon.stdout.readline().rstrip()
+
+ os.environ['DBUS_SESSION_BUS_ADDRESS'] = address.decode('utf-8')
+ os.environ['DBUS_SESSION_BUS_PID'] = str(daemon.pid)
+
+ for testfile in testfiles:
+ run_test(testfile)
+finally:
+ daemon.terminate()
+ daemon.wait()
+
+# vi:ts=4:et
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]