[gnome-chess/chess-telepathy-networking-support-664946-communicate: 10/10] Add a test for tube-application in Vala



commit dfa075c4402928a3257ef30fbaedc8b7b2ed3b19
Author: Chandni Verma <chandniverma2112 gmail com>
Date:   Fri Dec 28 09:28:48 2012 +0530

    Add a test for tube-application in Vala

 tests/Makefile.am        |    7 +-
 tests/test-tube-app.vala |  362 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 367 insertions(+), 2 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b210d4f..bd4043a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -11,7 +11,8 @@ LDADD = \
 telepathy_networking_tests = \
 	test-fetch-contacts \
 	offerer \
-	accepter
+	accepter \
+	test-tube-app
 
 plain_tests = \
 	test-demo-gdbus-client \
@@ -35,7 +36,8 @@ LDADD += \
 	$(GIO_LIBS)
 
 VALAFLAGS = \
-	--pkg gio-2.0
+	--pkg gio-2.0 \
+	--pkg telepathy-glib
 endif #ENABLE_NETWORKING
 
 
@@ -47,3 +49,4 @@ test_demo_gdbus_client_SOURCES = test-demo-gdbus-client.vala
 offerer_SOURCES = offerer.c constants.h
 accepter_SOURCES = accepter.c constants.h
 
+test_tube_app_SOURCES = test-tube-app.vala
diff --git a/tests/test-tube-app.vala b/tests/test-tube-app.vala
new file mode 100644
index 0000000..99dbbd5
--- /dev/null
+++ b/tests/test-tube-app.vala
@@ -0,0 +1,362 @@
+/* A test app. to show performing DBus-Tube communication in Vala */
+
+[DBus (name = "org.gnome.RemoteGame.OfferedObject")]
+public interface RemoteObjectIface : Object {
+    public abstract string word {get; construct;}
+    public signal bool do_move_remote (string verb);
+    public abstract void remote_yell () throws GLib.IOError;
+}
+
+[DBus (name = "org.gnome.RemoteGame.OfferedObject")]
+public class LocalObject : Object
+{
+    public string word {get; construct;}
+    public signal bool do_move ();
+
+    public LocalObject (string word)
+    {
+        Object (word:word);
+    }
+}
+
+public class RemoteObject : LocalObject, RemoteObjectIface
+{
+    public RemoteObject (string word)
+    {
+        base (word);
+    }
+
+    public void remote_yell ()
+    {
+        stdout.printf ("I am happy!");
+    }
+}
+
+public class RemoteGameHandler : Application
+{
+    public string my_account {get; construct;}
+    public string remote_id {get; construct;}
+    string service;
+    TelepathyGLib.SimpleHandler tp_handler;
+
+    public RemoteGameHandler (string my_account, string remote_id)
+    {
+        Object (my_account:my_account, remote_id:remote_id);
+        service = TelepathyGLib.CLIENT_BUS_NAME_BASE + "Remote.Game";
+    }
+
+    private void register_objects (DBusConnection connection, TelepathyGLib.DBusTubeChannel tube, string side)
+    {
+        debug ("Registering objects over dbus connection");
+
+        Variant tube_params = tube.dup_parameters_vardict ();
+        string say = (tube_params.lookup_value ("say", VariantType.STRING)).get_string ();
+
+        RemoteObject my_object = new RemoteObject (say);
+        my_object.do_move_remote.connect ((obj, verb)=>{stdout.printf (verb + "ing the " + obj.word);});
+
+        try {
+                connection.register_object<RemoteObject> ("/org/freedesktop/Telepathy/Client/RemoteGame/OfferedObject", my_object);
+
+                debug ("Object registered successfully");
+        } catch (IOError e) {
+            debug ("Could not register object");
+        }
+    }
+
+    private void use_object (RemoteObject object)
+    {
+        stdout.printf ("I got a " + object.word);
+        stdout.printf ("Using fetched objects.");
+        object.do_move_remote ("bake");
+        stdout.printf ("Hurting fetched objects.");
+        try {
+            object.remote_yell ();
+        } catch (IOError e)
+        {
+            stdout.printf ("Couldn't hurt.. : %s", e.message);
+        }
+    }
+
+    private void fetch_objects (DBusConnection conn, TelepathyGLib.DBusTubeChannel tube)
+    {
+        RemoteObject close_object = null;
+
+        conn.get_proxy<RemoteObjectIface>.begin (null, "/org/freedesktop/Telepathy/Client/RemoteGame/OfferedObject", 0, null,
+            (obj, res)=>{
+
+                try {
+                    close_object = (RemoteObject) conn.get_proxy<RemoteObjectIface>.end (res);
+                    if (close_object != null)
+                    {
+                        use_object (close_object);
+                    }
+                }
+                catch (IOError e)
+                {
+                   debug ("couldn't fetch the white player: %s\n", e.message);
+                }
+              }
+            );
+    }
+
+    private void offer_tube (TelepathyGLib.DBusTubeChannel tube)
+    {
+        DBusConnection? connection = null;
+        string say = "Yay!";
+        Value say_val = say;
+
+        HashTable<string, Value?>? tube_params = new HashTable<string, Value?> (str_hash, str_equal);
+        tube_params.insert ("say", say_val);
+
+        /* This hashtable is purely offerer defined and cast here is the secret gotcha */
+        tube.offer_async.begin ((HashTable<void*, void*>?)tube_params,
+            (obj, res)=>{
+                try
+                {
+                    connection = tube.offer_async.end (res);
+                }
+                catch (Error e)
+                {
+                    debug ("Failed to offer tube to %s: %s",
+                        (tube as TelepathyGLib.Channel).target_contact.identifier,
+                        e.message);
+
+                    return;
+                }
+
+                assert (connection != null);
+
+                debug ("Offered tube opened.");
+                connection.notify["closed"].connect (
+                    (s, p)=>{
+                        debug ("Connection to %s closed unexpectedly",
+                            (tube as
+                            TelepathyGLib.Channel).target_contact.identifier);
+                    }
+                );
+
+                /* First load player objects. Then wait on them for creating Game */
+                register_objects (connection, tube, "offerer");
+                fetch_objects (connection, tube);
+              }
+            );
+    }
+
+    private void accept_tube (TelepathyGLib.DBusTubeChannel tube)
+    {
+        DBusConnection? connection = null;
+
+        debug ("Accepting tube");
+        tube.accept_async.begin (
+            (obj, res)=>{
+                try
+                {
+                    connection = tube.accept_async.end (res);
+                }
+                catch (Error e)
+                {
+                    debug ("Failed to accept tube from %s: %s",
+                        (tube as TelepathyGLib.Channel).target_contact.identifier, e.message);
+
+                    return;
+                }
+
+                assert (connection != null);
+
+                debug ("Accepted tube opened.");
+                connection.notify["closed"].connect (
+                    (s, p)=>{
+                        debug ("Connection to %s closed unexpectedly",
+                            (tube as
+                            TelepathyGLib.Channel).target_contact.identifier);
+                    }
+                );
+
+                /* First load player objects. Then wait on them for creating ChessGame */
+                register_objects (connection, tube, "accepter");
+                fetch_objects (connection, tube);
+              }
+            );
+    }
+
+    private void tube_invalidated_cb (TelepathyGLib.Proxy tube_channel,
+        uint domain,
+        int code,
+        string message)
+    {
+        debug ("Tube has been invalidated: %s", message);
+    }
+
+    public void handle_channels (TelepathyGLib.SimpleHandler handler,
+        TelepathyGLib.Account account,
+        TelepathyGLib.Connection conn,
+        List<TelepathyGLib.Channel> channel_bundle,
+        List<TelepathyGLib.ChannelRequest> requests,
+        int64 action_time,
+        TelepathyGLib.HandleChannelsContext context)
+    {
+        Error error = new TelepathyGLib.Error.NOT_AVAILABLE ("No channel to be handled");
+
+        debug ("Handling channels");
+
+        foreach (TelepathyGLib.Channel tube_channel in channel_bundle)
+        {
+          if (! (tube_channel is TelepathyGLib.DBusTubeChannel))
+            continue;
+          if ((tube_channel as TelepathyGLib.DBusTubeChannel).service_name !=
+              TelepathyGLib.CLIENT_BUS_NAME_BASE + "Remote.Game")
+            continue;
+
+          if (tube_channel.requested)
+          {
+              /* We created this channel. Make a tube offer and wait for approval */
+              offer_tube (tube_channel as TelepathyGLib.DBusTubeChannel);
+          }
+          else
+          {
+              /* This is an incoming channel request */
+              accept_tube (tube_channel as TelepathyGLib.DBusTubeChannel);
+          }
+
+          (tube_channel as TelepathyGLib.Proxy).invalidated.connect (
+              tube_invalidated_cb);
+
+          context.accept ();
+          /* Only one of accept() or fail() can be called on context */
+          return;
+        }
+
+        debug ("Rejecting channels");
+        context.fail (error);
+
+        return;
+    }
+
+    private void ensure_legacy_channel_async (TelepathyGLib.Account account)
+    {
+        TelepathyGLib.AccountChannelRequest req;
+        var ht = new HashTable<string, Variant> (str_hash, str_equal);
+
+        req = new TelepathyGLib.AccountChannelRequest (
+            account, ht,
+            TelepathyGLib.user_action_time_from_x11 (0));
+
+        req.set_request_property (
+            TelepathyGLib.PROP_CHANNEL_CHANNEL_TYPE,
+            new Variant.string (TelepathyGLib.IFACE_CHANNEL_TYPE_TUBES));
+        req.set_request_property (
+            TelepathyGLib.PROP_CHANNEL_TARGET_HANDLE_TYPE,
+            new Variant.uint16 (TelepathyGLib.HandleType.CONTACT));
+        req.set_request_property (
+            TelepathyGLib.PROP_CHANNEL_TARGET_ID,
+            new Variant.string (remote_id));
+
+        req.ensure_channel_async.begin ("", null);
+    }
+
+    public override void startup ()
+    {
+        string account_path = TelepathyGLib.ACCOUNT_OBJECT_PATH_BASE + my_account;
+        TelepathyGLib.Account account;
+        TelepathyGLib.AutomaticClientFactory factory = new TelepathyGLib.AutomaticClientFactory (null);
+
+        var immutable_acc_props = new HashTable<string, Value?> (str_hash, str_equal);
+        Quark features[] = {};
+        features += TelepathyGLib.Account.get_feature_quark_connection ();
+        factory.add_account_features (features);
+
+        try {
+            account = factory.ensure_account (account_path, immutable_acc_props);
+        }
+        catch (Error e)
+        {
+            stderr.printf ("Unable to create account: %s", e.message);
+        }
+
+        tp_handler =  new TelepathyGLib.SimpleHandler.with_am (
+            TelepathyGLib.AccountManager.dup (),
+            true,     /* Bypass approval */
+            true,     /* Requests */
+            "Remote.Game",
+            false,    /* Uniquify name */
+            handle_channels);
+
+        var filter = new HashTable<string, Value?> (str_hash, str_equal);
+        filter.insert (
+            TelepathyGLib.PROP_CHANNEL_CHANNEL_TYPE,
+            TelepathyGLib.IFACE_CHANNEL_TYPE_DBUS_TUBE);
+        filter.insert (
+            TelepathyGLib.PROP_CHANNEL_TARGET_HANDLE_TYPE,
+            1);
+        filter.insert (
+            TelepathyGLib.PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME,
+              TelepathyGLib.CLIENT_BUS_NAME_BASE + "Remote.Game");
+
+        (tp_handler as TelepathyGLib.BaseClient).add_handler_filter (filter);
+
+        try {
+            (tp_handler as TelepathyGLib.BaseClient).register ();
+        }
+        catch (Error e) {
+            debug ("Failed to register handler: %s", e.message);
+        }
+
+        debug ("Waiting for tube offer");
+
+        /* Create a DBusTube Channel */
+
+        /* Workaround for https://bugs.freedesktop.org/show_bug.cgi?id=47760 */
+        ensure_legacy_channel_async (account);
+
+        var ht = new HashTable<string, Variant> (str_hash, str_equal);
+
+        var req = new TelepathyGLib.AccountChannelRequest (
+            account, ht,
+            TelepathyGLib.user_action_time_from_x11 (0));
+
+        req.set_request_property (
+            TelepathyGLib.PROP_CHANNEL_CHANNEL_TYPE,
+            new Variant.string (TelepathyGLib.IFACE_CHANNEL_TYPE_DBUS_TUBE));
+        req.set_request_property (
+            TelepathyGLib.PROP_CHANNEL_TARGET_HANDLE_TYPE,
+            new Variant.uint16 (TelepathyGLib.HandleType.CONTACT));
+        req.set_request_property (
+            TelepathyGLib.PROP_CHANNEL_TARGET_ID,
+            new Variant.string (remote_id));
+        req.set_request_property (
+            TelepathyGLib.PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME,
+            new Variant.string (service));
+
+        bool channel_dispatched = false;
+        req.create_channel_async.begin (service, null,
+            (obj, res)=>{
+                try
+                {
+                     channel_dispatched = req.create_channel_async.end (res);
+                }
+                catch (Error e)
+                {
+                     debug ("Failed to create channel: %s", e.message);
+                }
+
+                if (channel_dispatched)
+                  debug ("DBus channel with %s successfully dispatched.",
+                      remote_id);
+                else
+                  debug ("Unsuccessful in creating and dispatching DBus channel with %s.",
+                      remote_id);
+              }
+            );
+
+    }
+}
+
+class TestTubeApp
+{
+    public static void main (string args [])
+    {
+        RemoteGameHandler app = new RemoteGameHandler (args[1],  args[2]);
+        app.run ();
+    }
+}



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