[gjs/wip/gdbus-2: 10/13] GDBus: introduce new convenience wrappers
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/gdbus-2: 10/13] GDBus: introduce new convenience wrappers
- Date: Fri, 2 Nov 2012 13:10:50 +0000 (UTC)
commit 6a9b8bbe8e4304b960d75271792849272dbeaa4b
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Thu Jun 14 22:25:26 2012 +0200
GDBus: introduce new convenience wrappers
Using the new metaclass system, introduce Gio.DBusProxyClass and
Gio.DBusImplementerClass, that allow declaring specialized proxies/
implementations for specific interfaces.
https://bugzilla.gnome.org/show_bug.cgi?id=669350
modules/overrides/Gio.js | 201 ++++++++++++++++-
test/js/testGDBus2.js | 563 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 759 insertions(+), 5 deletions(-)
---
diff --git a/modules/overrides/Gio.js b/modules/overrides/Gio.js
index 6251f91..0c157dd 100644
--- a/modules/overrides/Gio.js
+++ b/modules/overrides/Gio.js
@@ -54,10 +54,10 @@ function _proxyInvoker(methodName, sync, inSignature, arg_array) {
if (arg_array.length < minNumberArgs) {
throw new Error("Not enough arguments passed for method: " + methodName +
- ". Expected " + minNumberArgs + ", got " + arg_array.length);
+ ". Expected " + minNumberArgs + ", got " + arg_array.length);
} else if (arg_array.length > maxNumberArgs) {
throw new Error("Too many arguments passed for method: " + methodName +
- ". Maximum is " + maxNumberArgs +
+ ". Maximum is " + maxNumberArgs +
" + one callback and/or flags");
}
@@ -109,7 +109,7 @@ function _logReply(result, exc) {
}
}
-function _makeProxyMethod(method, sync) {
+function _makeProxyMethod(method, sync, insideClass) {
var i;
var name = method.name;
var inArgs = method.in_args;
@@ -117,9 +117,14 @@ function _makeProxyMethod(method, sync) {
for (i = 0; i < inArgs.length; i++)
inSignature.push(inArgs[i].signature);
- return function() {
+ var f = function() {
return _proxyInvoker.call(this, name, sync, inSignature, arguments);
- };
+ }
+
+ if (insideClass)
+ return this.wrapFunction(method, f);
+ else
+ return f;
}
function _convertToNativeSignal(proxy, sender_name, signal_name, parameters) {
@@ -151,6 +156,10 @@ function _propertySetter(value, name, signature) {
}
function _addDBusConvenience() {
+ // Check if this is actually using new-style bindings
+ if (this.constructor instanceof DBusProxyClass)
+ return;
+
let info = this.g_interface_info;
if (!info)
return;
@@ -175,7 +184,100 @@ function _addDBusConvenience() {
}
}
+const DBusProxyClass = new Lang.Class({
+ Name: 'DBusProxyClass',
+ Extends: GObject.Class,
+
+ _construct: function(params) {
+ params.Extends = Gio.DBusProxy;
+
+ return this.parent(params);
+ },
+
+ _init: function(classParams) {
+ if (!classParams.Interface)
+ throw new TypeError('Interface must be specified in the declaration of a DBusProxyClass');
+ if (!(classParams.Interface instanceof Gio.DBusInterfaceInfo))
+ classParams.Interface = _newInterfaceInfo(classParams.Interface);
+
+ classParams._init = function(params) {
+ let klass = this.constructor;
+ if (!params)
+ params = { };
+ params.g_interface_name = this.Interface.name;
+ params.g_interface_info = this.Interface;
+
+ let asyncCallback, cancellable = null;
+ if ('g_async_callback' in params) {
+ asyncCallback = params.g_async_callback;
+ delete params.g_async_callback;
+ }
+ if ('g_cancellable' in params) {
+ cancellable = params.g_cancellable;
+ delete params.g_cancellable;
+ }
+
+ this.parent(params);
+
+ if (asyncCallback) {
+ this.init_async(GLib.PRIORITY_DEFAULT, cancellable, function(initable, result) {
+ try {
+ initable.init_finish(result);
+ asyncCallback(initable, null);
+ } catch(e) {
+ asyncCallback(null, e);
+ }
+ });
+ } else {
+ this.init(cancellable);
+ }
+
+ this.connect('g-signal', _convertToNativeSignal);
+ }
+
+ // build the actual class
+ this.parent(classParams);
+
+ // add convenience methods
+ this._addDBusConvenience(classParams);
+ },
+
+ _addDBusConvenience: function(classParams) {
+ let info = classParams.Interface;
+
+ let i, methods = info.methods;
+ for (i = 0; i < methods.length; i++) {
+ var method = methods[i];
+ this.prototype[method.name + 'Remote'] = _makeProxyMethod.call(this, methods[i], false, true);
+ this.prototype[method.name + 'Sync'] = _makeProxyMethod.call(this, methods[i], true, true);
+ }
+
+ let properties = info.properties;
+ for (i = 0; i < properties.length; i++) {
+ let name = properties[i].name;
+ let signature = properties[i].signature;
+ let flags = properties[i].flags;
+ let getter = undefined, setter = undefined;
+
+ if (flags & Gio.DBusPropertyInfoFlags.READABLE) {
+ getter = function() {
+ return _propertyGetter.call(this, name);
+ };
+ }
+ if (flags & Gio.DBusPropertyInfoFlags.WRITABLE) {
+ setter = function(val) {
+ return _propertySetter.call(this, name, val, signature);
+ };
+ }
+
+ Lang.defineAccessorProperty(this.prototype, name, getter, setter);
+ }
+ }
+});
+
function _makeProxyWrapper(interfaceXml) {
+ log ('makeProxyWrapper is deprecated. Use Gio.DBusProxyClass instead');
+
var info = _newInterfaceInfo(interfaceXml);
var iname = info.name;
return function(bus, name, object, asyncCallback, cancellable) {
@@ -329,6 +431,91 @@ function _handlePropertySet(info, impl, property_name, new_value) {
this[property_name] = new_value.deep_unpack();
}
+const DBusImplementerBase = new Lang.Class({
+ Name: 'DBusImplementerBase',
+
+ _init: function() {
+ this._dbusImpl = new GjsPrivate.DBusImplementation({ g_interface_info: this.constructor.Interface });
+
+ this._dbusImpl.connect('handle-method-call', Lang.bind(this, this._handleMethodCall));
+ this._dbusImpl.connect('handle-property-get', Lang.bind(this, this._handlePropertyGet));
+ this._dbusImpl.connect('handle-property-set', Lang.bind(this, this._handlePropertySet));
+
+ let klass = this.constructor;
+ if (klass.ObjectPath && klass.BusType)
+ this.export(Gio.bus_get_sync(klass.BusType, null), klass.ObjectPath);
+ },
+
+ _handleMethodCall: function(impl, method_name, parameters, invocation) {
+ return _handleMethodCall.call(this, this.constructor.Interface, impl, method_name, parameters, invocation);
+ },
+
+ _handlePropertyGet: function(impl, property_name) {
+ return _handlePropertyGet.call(this, this.constructor.Interface, impl, property_name);
+ },
+
+ _handlePropertySet: function(impl, property_name, value) {
+ return _handlePropertySet.call(this, this.constructor.Interface, impl, property_name, value);
+ },
+
+ export: function(bus, path) {
+ this._dbusImpl.export(bus, path);
+ },
+
+ unexport: function() {
+ this._dbusImpl.unexport();
+ },
+
+ emit_signal: function(signal_name) {
+ let klass = this.constructor;
+
+ let signalInfo = klass.Interface.lookup_signal(signal_name);
+ let signalType = _makeOutSignature(signalInfo.args);
+
+ let argArray = Array.prototype.slice.call(arguments);
+ argArray.shift();
+
+ if (argArray.length == 0)
+ this._dbusImpl.emit_signal(signal_name, null);
+ else
+ this._dbusImpl.emit_signal(signal_name, GLib.Variant.new(signalType, argArray));
+ },
+
+ emit_property_changed: function(property_name, new_value) {
+ let klass = this.constructor;
+
+ let propertyInfo = klass.Inteface.lookup_property(property_name);
+ if (new_value != undefined)
+ new_value = GLib.Variant.new(propertyInfo.signature, new_value);
+
+ this._dbusImpl.emit_property_changed(property_name, new_value);
+ },
+});
+
+const DBusImplementerClass = new Lang.Class({
+ Name: 'DBusImplementerClass',
+ Extends: Lang.Class,
+
+ _construct: function(params) {
+ params.Extends = DBusImplementerBase;
+
+ return this.parent(params);
+ },
+
+ _init: function(params) {
+ if (!params.Interface)
+ throw new TypeError('Interface must be specified in the declaration of a DBusImplementerClass');
+ if (!(params.Interface instanceof Gio.DBusInterfaceInfo))
+ params.Interface = _newInterfaceInfo(params.Interface);
+ params.Interface.cache_build();
+
+ this.Interface = params.Interface;
+ delete params.Interface;
+
+ this.parent(params);
+ }
+});
+
function _wrapJSObject(interfaceInfo, jsObj) {
var info;
if (interfaceInfo instanceof Gio.DBusInterfaceInfo)
@@ -391,6 +578,9 @@ function _init() {
_injectToMethod(Gio.DBusProxy.prototype, 'init', _addDBusConvenience);
_injectToMethod(Gio.DBusProxy.prototype, 'init_async', _addDBusConvenience);
+
+ Gio.DBusProxyClass = DBusProxyClass;
+ Gio.DBusProxy.prototype.__metaclass__ = DBusProxyClass;
Gio.DBusProxy.prototype.connectSignal = Signals._connect;
Gio.DBusProxy.prototype.disconnectSignal = Signals._disconnect;
@@ -400,6 +590,7 @@ function _init() {
_wrapFunction(Gio.DBusNodeInfo, 'new_for_xml', _newNodeInfo);
Gio.DBusInterfaceInfo.new_for_xml = _newInterfaceInfo;
+ Gio.DBusImplementerClass = DBusImplementerClass;
Gio.DBusExportedObject = GjsPrivate.DBusImplementation;
Gio.DBusExportedObject.wrapJSObject = _wrapJSObject;
}
diff --git a/test/js/testGDBus2.js b/test/js/testGDBus2.js
new file mode 100644
index 0000000..7255285
--- /dev/null
+++ b/test/js/testGDBus2.js
@@ -0,0 +1,563 @@
+// application/javascript;version=1.8
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+
+/* The methods list with their signatures.
+ *
+ * *** NOTE: If you add stuff here, you need to update testIntrospectReal
+ */
+var TestIface = <interface name="org.gnome.gjs.Test">
+<method name="nonJsonFrobateStuff">
+ <arg type="i" direction="in"/>
+ <arg type="s" direction="out"/>
+</method>
+<method name="frobateStuff">
+ <arg type="a{sv}" direction="in"/>
+ <arg type="a{sv}" direction="out"/>
+</method>
+<method name="alwaysThrowException">
+ <arg type="a{sv}" direction="in"/>
+ <arg type="a{sv}" direction="out"/>
+</method>
+<method name="noInParameter">
+ <arg type="s" direction="out"/>
+</method>
+<method name="multipleInArgs">
+ <arg type="i" direction="in"/>
+ <arg type="i" direction="in"/>
+ <arg type="i" direction="in"/>
+ <arg type="i" direction="in"/>
+ <arg type="i" direction="in"/>
+ <arg type="s" direction="out"/>
+</method>
+<method name="noReturnValue"/>
+<method name="emitSignal"/>
+<method name="multipleOutValues">
+ <arg type="s" direction="out"/>
+ <arg type="s" direction="out"/>
+ <arg type="s" direction="out"/>
+</method>
+<method name="oneArrayOut">
+ <arg type="as" direction="out"/>
+</method>
+<method name="arrayOfArrayOut">
+ <arg type="aas" direction="out"/>
+</method>
+<method name="multipleArrayOut">
+ <arg type="as" direction="out"/>
+ <arg type="as" direction="out"/>
+</method>
+<method name="arrayOutBadSig">
+ <arg type="i" direction="out"/>
+</method>
+<method name="byteArrayEcho">
+ <arg type="ay" direction="in"/>
+ <arg type="ay" direction="out"/>
+</method>
+<method name="byteEcho">
+ <arg type="y" direction="in"/>
+ <arg type="y" direction="out"/>
+</method>
+<method name="dictEcho">
+ <arg type="a{sv}" direction="in"/>
+ <arg type="a{sv}" direction="out"/>
+</method>
+<method name="echo">
+ <arg type="s" direction="in"/>
+ <arg type="i" direction="in"/>
+ <arg type="s" direction="out"/>
+ <arg type="i" direction="out"/>
+</method>
+<method name="structArray">
+ <arg type="a(ii)" direction="out"/>
+</method>
+<signal name="signalFoo">
+ <arg type="s" direction="out"/>
+</signal>
+<property name="PropReadOnly" type="b" access="read" />
+<property name="PropWriteOnly" type="s" access="write" />
+<property name="PropReadWrite" type="v" access="readwrite" />
+</interface>
+
+const PROP_READ_WRITE_INITIAL_VALUE = 58;
+const PROP_WRITE_ONLY_INITIAL_VALUE = "Initial value";
+
+const Test = new Gio.DBusImplementerClass({
+ Name: 'Test',
+ Interface: TestIface,
+
+ _init: function() {
+ this.parent();
+
+ this._propWriteOnly = PROP_WRITE_ONLY_INITIAL_VALUE;
+ this._propReadWrite = PROP_READ_WRITE_INITIAL_VALUE;
+ },
+
+ frobateStuff: function(args) {
+ return { hello: GLib.Variant.new('s', 'world') };
+ },
+
+ nonJsonFrobateStuff: function(i) {
+ if (i == 42) {
+ return "42 it is!";
+ } else {
+ return "Oops";
+ }
+ },
+
+ alwaysThrowException: function() {
+ throw Error("Exception!");
+ },
+
+ noInParameter: function() {
+ return "Yes!";
+ },
+
+ multipleInArgs: function(a, b, c, d, e) {
+ return a + " " + b + " " + c + " " + d + " " + e;
+ },
+
+ emitSignal: function() {
+ this.emit_signal('signalFoo', "foobar");
+ },
+
+ noReturnValue: function() {
+ /* Empty! */
+ },
+
+ /* The following two functions have identical return values
+ * in JS, but the bus message will be different.
+ * multipleOutValues is "sss", while oneArrayOut is "as"
+ */
+ multipleOutValues: function() {
+ return [ "Hello", "World", "!" ];
+ },
+
+ oneArrayOut: function() {
+ return [ "Hello", "World", "!" ];
+ },
+
+ /* Same thing again. In this case multipleArrayOut is "asas",
+ * while arrayOfArrayOut is "aas".
+ */
+ multipleArrayOut: function() {
+ return [[ "Hello", "World" ], [ "World", "Hello" ]];
+ },
+
+ arrayOfArrayOut: function() {
+ return [[ "Hello", "World" ], [ "World", "Hello" ]];
+ },
+
+ arrayOutBadSig: function() {
+ return [ "Hello", "World", "!" ];
+ },
+
+ byteArrayEcho: function(binaryString) {
+ return binaryString;
+ },
+
+ byteEcho: function(aByte) {
+ return aByte;
+ },
+
+ dictEcho: function(dict) {
+ return dict;
+ },
+
+ /* This one is implemented asynchronously. Returns
+ * the input arguments */
+ echoAsync: function(parameters, invocation) {
+ var [someString, someInt] = parameters;
+ Mainloop.idle_add(function() {
+ invocation.return_value(GLib.Variant.new('(si)', [someString, someInt]));
+ return false;
+ });
+ },
+
+ // boolean
+ get PropReadOnly() {
+ return true;
+ },
+
+ // string
+ set PropWriteOnly(value) {
+ this._propWriteOnly = value;
+ },
+
+ // variant
+ get PropReadWrite() {
+ return GLib.Variant.new('u', this._propReadWrite);
+ },
+
+ set PropReadWrite(value) {
+ this._propReadWrite = value.deep_unpack();
+ },
+
+ structArray: function () {
+ return [[128, 123456], [42, 654321]];
+ }
+});
+
+var own_name_id;
+
+const TestProxy = new Lang.Class({
+ Name: 'TestProxy',
+ Extends: Gio.DBusProxy,
+ Interface: TestIface,
+});
+
+var proxy, exporter;
+
+function testExportStuff() {
+ exporter = new Test();
+ exporter.export(Gio.DBus.session, '/org/gnome/gjs/Test');
+
+ own_name_id = Gio.DBus.session.own_name('org.gnome.gjs.Test',
+ Gio.BusNameOwnerFlags.NONE,
+ function(connection, name) {
+ log("Acquired name " + name);
+
+ Mainloop.quit('testGDBus');
+ },
+ function(connection, name) {
+ log("Lost name " + name);
+ });
+
+ Mainloop.run('testGDBus');
+}
+
+function testInitStuff() {
+ var theError;
+ proxy = new TestProxy({ g_connection: Gio.DBus.session,
+ g_name: 'org.gnome.gjs.Test',
+ g_object_path: '/org/gnome/gjs/Test',
+ g_async_callback: function (obj, error) {
+ theError = error;
+ proxy = obj;
+
+ Mainloop.quit('testGDBus');
+ } });
+
+ log(typeof(proxy._init) + " " + typeof(proxy._construct) + " " + typeof(proxy.frobateStuffRemote));
+
+ Mainloop.run('testGDBus');
+
+ assertNull(theError);
+ assertNotNull(proxy);
+}
+
+function testFrobateStuff() {
+ let theResult, theExcp;
+ proxy.frobateStuffRemote({}, function(result, excp) {
+ theResult = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertNull(theExcp);
+ assertEquals("world", theResult[0].hello.deep_unpack());
+}
+
+/* excp must be exactly the exception thrown by the remote method
+ (more or less) */
+function testThrowException() {
+ let theResult, theExcp;
+ proxy.alwaysThrowExceptionRemote({}, function(result, excp) {
+ theResult = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertNull(theResult);
+ assertNotNull(theExcp);
+}
+
+function testNonJsonFrobateStuff() {
+ let theResult, theExcp;
+ proxy.nonJsonFrobateStuffRemote(42, function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertEquals("42 it is!", theResult);
+ assertNull(theExcp);
+}
+
+function testNoInParameter() {
+ let theResult, theExcp;
+ proxy.noInParameterRemote(function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertEquals("Yes!", theResult);
+ assertNull(theExcp);
+}
+
+function testMultipleInArgs() {
+ let theResult, theExcp;
+ proxy.multipleInArgsRemote(1, 2, 3, 4, 5, function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertEquals("1 2 3 4 5", theResult);
+ assertNull(theExcp);
+}
+
+function testNoReturnValue() {
+ let theResult, theExcp;
+ proxy.noReturnValueRemote(function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertEquals(undefined, theResult);
+ assertNull(theExcp);
+}
+
+function testEmitSignal() {
+ let theResult, theExcp;
+ let signalReceived = 0;
+ let signalArgument = null;
+ let id = proxy.connectSignal('signalFoo',
+ function(emitter, senderName, parameters) {
+ signalReceived ++;
+ [signalArgument] = parameters;
+
+ proxy.disconnectSignal(id);
+ });
+ proxy.emitSignalRemote(function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ if (excp)
+ log("Signal emission exception: " + excp);
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertUndefined('result should be undefined', theResult);
+ assertNull('no exception set', theExcp);
+ assertEquals('number of signals received', signalReceived, 1);
+ assertEquals('signal argument', signalArgument, "foobar");
+
+}
+
+function testMultipleOutValues() {
+ let theResult, theExcp;
+ proxy.multipleOutValuesRemote(function(result, excp) {
+ theResult = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertEquals("Hello", theResult[0]);
+ assertEquals("World", theResult[1]);
+ assertEquals("!", theResult[2]);
+ assertNull(theExcp);
+}
+
+function testOneArrayOut() {
+ let theResult, theExcp;
+ proxy.oneArrayOutRemote(function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ assertEquals("Hello", theResult[0]);
+ assertEquals("World", theResult[1]);
+ assertEquals("!", theResult[2]);
+ assertNull(theExcp);
+}
+
+function testArrayOfArrayOut() {
+ let theResult, theExcp;
+ proxy.arrayOfArrayOutRemote(function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ let a1 = theResult[0];
+ let a2 = theResult[1];
+
+ assertEquals("Hello", a1[0]);
+ assertEquals("World", a1[1]);
+
+ assertEquals("World", a2[0]);
+ assertEquals("Hello", a2[1]);;
+
+ assertNull(theExcp);
+}
+
+function testMultipleArrayOut() {
+ let theResult, theExcp;
+ proxy.multipleArrayOutRemote(function(result, excp) {
+ theResult = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+
+ let a1 = theResult[0];
+ let a2 = theResult[1];
+
+ assertEquals("Hello", a1[0]);
+ assertEquals("World", a1[1]);
+
+ assertEquals("World", a2[0]);
+ assertEquals("Hello", a2[1]);;
+
+ assertNull(theExcp);
+}
+
+/* We are returning an array but the signature says it's an integer,
+ * so this should fail
+ */
+function testArrayOutBadSig() {
+ let theResult, theExcp;
+ proxy.arrayOutBadSigRemote(function(result, excp) {
+ theResult = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+ assertNull(theResult);
+ assertNotNull(theExcp);
+}
+
+function testAsyncImplementation() {
+ let someString = "Hello world!";
+ let someInt = 42;
+ let theResult, theExcp;
+ proxy.echoRemote(someString, someInt,
+ function(result, excp) {
+ theResult = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+ assertNull(theExcp);
+ assertNotNull(theResult);
+ assertEquals(theResult[0], someString);
+ assertEquals(theResult[1], someInt);
+}
+
+function testBytes() {
+ let someBytes = [ 0, 63, 234 ];
+ let theResult, theExcp;
+ for (let i = 0; i < someBytes.length; ++i) {
+ theResult = null;
+ theExcp = null;
+ proxy.byteEchoRemote(someBytes[i], function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+ assertNull(theExcp);
+ assertNotNull(theResult);
+ assertEquals(someBytes[i], theResult);
+ }
+}
+
+function testStructArray() {
+ let theResult, theExcp;
+ proxy.structArrayRemote(function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+ Mainloop.run('testGDBus');
+ assertNull(theExcp);
+ assertNotNull(theResult);
+ assertEquals(theResult[0][0], 128);
+ assertEquals(theResult[0][1], 123456);
+ assertEquals(theResult[1][0], 42);
+ assertEquals(theResult[1][1], 654321);
+}
+
+function testDictSignatures() {
+ let someDict = {
+ aDouble: GLib.Variant.new('d', 10),
+ // should be an integer after round trip
+ anInteger: GLib.Variant.new('i', 10.5),
+ // should remain a double
+ aDoubleBeforeAndAfter: GLib.Variant.new('d', 10.5),
+ };
+ let theResult, theExcp;
+ proxy.dictEchoRemote(someDict, function(result, excp) {
+ [theResult] = result;
+ theExcp = excp;
+ Mainloop.quit('testGDBus');
+ });
+
+ Mainloop.run('testGDBus');
+ assertNull(theExcp);
+ assertNotNull(theResult);
+
+ // verify the fractional part was dropped off int
+ assertEquals(11, theResult['anInteger'].deep_unpack());
+
+ // and not dropped off a double
+ assertEquals(10.5, theResult['aDoubleBeforeAndAfter'].deep_unpack());
+
+ // this assertion is useless, it will work
+ // anyway if the result is really an int,
+ // but it at least checks we didn't lose data
+ assertEquals(10.0, theResult['aDouble'].deep_unpack());
+}
+
+function testProperties() {
+ let readonly = proxy.PropReadOnly;
+ assertEquals(true, readonly);
+
+ let readwrite = proxy.PropReadWrite;
+ assertTrue(readwrite instanceof GLib.Variant);
+ assertEquals(PROP_READ_WRITE_INITIAL_VALUE, readwrite.deep_unpack());
+
+ // we cannot test property sets, as those happen asynchronously
+}
+
+function testFinalize() {
+ // clean everything up, before we destroy the context
+ // (otherwise, gio will report a name owner changed signal
+ // in idle, which will be called in some other test)
+ Gio.DBus.session.unown_name(own_name_id);
+
+ proxy = exporter = null;
+ context = GLib.MainContext.default();
+ while (context.iteration(false));
+}
+
+gjstestRun();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]