Blame gio/tests/gdbus-peer-object-manager.c

Packit ae235b
/* GLib testing framework examples and tests
Packit ae235b
 *
Packit ae235b
 * Copyright (C) 2012 Red Hat Inc.
Packit ae235b
 *
Packit ae235b
 * This library is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * This library is distributed in the hope that it will be useful,
Packit ae235b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ae235b
 * Lesser General Public License for more details.
Packit ae235b
 *
Packit ae235b
 * You should have received a copy of the GNU Lesser General
Packit ae235b
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit ae235b
 *
Packit ae235b
 * Author: Stef Walter <stefw@gnome.org>
Packit ae235b
 */
Packit ae235b
Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
#include <gio/gio.h>
Packit ae235b
Packit ae235b
#include <sys/socket.h>
Packit ae235b
Packit ae235b
#include <errno.h>
Packit ae235b
#include <string.h>
Packit ae235b
#include <unistd.h>
Packit ae235b
Packit ae235b
typedef struct {
Packit ae235b
  GDBusInterfaceSkeleton parent;
Packit ae235b
  gint number;
Packit ae235b
} MockInterface;
Packit ae235b
Packit ae235b
typedef struct {
Packit ae235b
  GDBusInterfaceSkeletonClass parent_class;
Packit ae235b
} MockInterfaceClass;
Packit ae235b
Packit ae235b
static GType mock_interface_get_type (void);
Packit ae235b
G_DEFINE_TYPE (MockInterface, mock_interface, G_TYPE_DBUS_INTERFACE_SKELETON)
Packit ae235b
Packit ae235b
static void
Packit ae235b
mock_interface_init (MockInterface *self)
Packit ae235b
{
Packit ae235b
Packit ae235b
}
Packit ae235b
Packit ae235b
static GDBusInterfaceInfo *
Packit ae235b
mock_interface_get_info (GDBusInterfaceSkeleton *skeleton)
Packit ae235b
{
Packit ae235b
  static GDBusPropertyInfo path_info = {
Packit ae235b
    -1,
Packit ae235b
    "Path",
Packit ae235b
    "o",
Packit ae235b
    G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
Packit ae235b
    NULL,
Packit ae235b
  };
Packit ae235b
Packit ae235b
  static GDBusPropertyInfo number_info = {
Packit ae235b
    -1,
Packit ae235b
    "Number",
Packit ae235b
    "i",
Packit ae235b
    G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
Packit ae235b
    NULL,
Packit ae235b
  };
Packit ae235b
Packit ae235b
  static GDBusPropertyInfo *property_info[] = {
Packit ae235b
    &path_info,
Packit ae235b
    &number_info,
Packit ae235b
    NULL
Packit ae235b
  };
Packit ae235b
Packit ae235b
  static GDBusInterfaceInfo interface_info = {
Packit ae235b
    -1,
Packit ae235b
    (gchar *) "org.mock.Interface",
Packit ae235b
    NULL,
Packit ae235b
    NULL,
Packit ae235b
    (GDBusPropertyInfo **) &property_info,
Packit ae235b
    NULL
Packit ae235b
  };
Packit ae235b
Packit ae235b
  return &interface_info;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GVariant *
Packit ae235b
mock_interface_get_property (GDBusConnection *connection,
Packit ae235b
                             const gchar *sender,
Packit ae235b
                             const gchar *object_path,
Packit ae235b
                             const gchar *interface_name,
Packit ae235b
                             const gchar *property_name,
Packit ae235b
                             GError **error,
Packit ae235b
                             gpointer user_data)
Packit ae235b
{
Packit ae235b
  MockInterface *self = user_data;
Packit ae235b
  if (g_str_equal (property_name, "Path"))
Packit ae235b
    return g_variant_new_object_path (object_path);
Packit ae235b
  else if (g_str_equal (property_name, "Number"))
Packit ae235b
    return g_variant_new_int32 (self->number);
Packit ae235b
  else
Packit ae235b
    return NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GDBusInterfaceVTable *
Packit ae235b
mock_interface_get_vtable (GDBusInterfaceSkeleton *interface)
Packit ae235b
{
Packit ae235b
  static GDBusInterfaceVTable vtable = {
Packit ae235b
    NULL,
Packit ae235b
    mock_interface_get_property,
Packit ae235b
    NULL,
Packit ae235b
  };
Packit ae235b
Packit ae235b
  return &vtable;
Packit ae235b
}
Packit ae235b
Packit ae235b
static GVariant *
Packit ae235b
mock_interface_get_properties (GDBusInterfaceSkeleton *interface)
Packit ae235b
{
Packit ae235b
  GVariantBuilder builder;
Packit ae235b
  GDBusInterfaceInfo *info;
Packit ae235b
  GDBusInterfaceVTable *vtable;
Packit ae235b
  guint n;
Packit ae235b
Packit ae235b
  /* Groan, this is completely generic code and should be in gdbus */
Packit ae235b
Packit ae235b
  info = g_dbus_interface_skeleton_get_info (interface);
Packit ae235b
  vtable = g_dbus_interface_skeleton_get_vtable (interface);
Packit ae235b
Packit ae235b
  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
Packit ae235b
  for (n = 0; info->properties[n] != NULL; n++)
Packit ae235b
    {
Packit ae235b
      if (info->properties[n]->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
Packit ae235b
        {
Packit ae235b
          GVariant *value;
Packit ae235b
          g_return_val_if_fail (vtable->get_property != NULL, NULL);
Packit ae235b
          value = (vtable->get_property) (g_dbus_interface_skeleton_get_connection (interface), NULL,
Packit ae235b
                                          g_dbus_interface_skeleton_get_object_path (interface),
Packit ae235b
                                          info->name, info->properties[n]->name,
Packit ae235b
                                          NULL, interface);
Packit ae235b
          if (value != NULL)
Packit ae235b
            {
Packit ae235b
              g_variant_take_ref (value);
Packit ae235b
              g_variant_builder_add (&builder, "{sv}", info->properties[n]->name, value);
Packit ae235b
              g_variant_unref (value);
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return g_variant_builder_end (&builder);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
mock_interface_flush (GDBusInterfaceSkeleton *skeleton)
Packit ae235b
{
Packit ae235b
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
mock_interface_class_init (MockInterfaceClass *klass)
Packit ae235b
{
Packit ae235b
  GDBusInterfaceSkeletonClass *skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
Packit ae235b
  skeleton_class->get_info = mock_interface_get_info;
Packit ae235b
  skeleton_class->get_properties = mock_interface_get_properties;
Packit ae235b
  skeleton_class->flush = mock_interface_flush;
Packit ae235b
  skeleton_class->get_vtable = mock_interface_get_vtable;
Packit ae235b
}
Packit ae235b
typedef struct {
Packit ae235b
  GDBusConnection *server;
Packit ae235b
  GDBusConnection *client;
Packit ae235b
  GMainLoop *loop;
Packit ae235b
  GAsyncResult *result;
Packit ae235b
} Test;
Packit ae235b
Packit ae235b
static void
Packit ae235b
on_server_connection (GObject *source,
Packit ae235b
                      GAsyncResult *result,
Packit ae235b
                      gpointer user_data)
Packit ae235b
{
Packit ae235b
  Test *test = user_data;
Packit ae235b
  GError *error = NULL;
Packit ae235b
Packit ae235b
  g_assert (test->server == NULL);
Packit ae235b
  test->server = g_dbus_connection_new_finish (result, &error);
Packit ae235b
  g_assert_no_error (error);
Packit ae235b
  g_assert (test->server != NULL);
Packit ae235b
Packit ae235b
  if (test->server && test->client)
Packit ae235b
    g_main_loop_quit (test->loop);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
on_client_connection (GObject *source,
Packit ae235b
                      GAsyncResult *result,
Packit ae235b
                      gpointer user_data)
Packit ae235b
{
Packit ae235b
  Test *test = user_data;
Packit ae235b
  GError *error = NULL;
Packit ae235b
Packit ae235b
  g_assert (test->client == NULL);
Packit ae235b
  test->client = g_dbus_connection_new_finish (result, &error);
Packit ae235b
  g_assert_no_error (error);
Packit ae235b
  g_assert (test->client != NULL);
Packit ae235b
Packit ae235b
  if (test->server && test->client)
Packit ae235b
    g_main_loop_quit (test->loop);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
setup (Test *test,
Packit ae235b
       gconstpointer unused)
Packit ae235b
{
Packit ae235b
  GError *error = NULL;
Packit ae235b
  GSocket *socket;
Packit ae235b
  GSocketConnection *stream;
Packit ae235b
  gchar *guid;
Packit ae235b
  int pair[2];
Packit ae235b
Packit ae235b
  test->loop = g_main_loop_new (NULL, FALSE);
Packit ae235b
Packit ae235b
  if (socketpair (AF_UNIX, SOCK_STREAM, 0, pair) < 0)
Packit ae235b
    {
Packit ae235b
      int errsv = errno;
Packit ae235b
      g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (errsv),
Packit ae235b
                   "%s", g_strerror (errsv));
Packit ae235b
      g_assert_no_error (error);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  /* Build up the server stuff */
Packit ae235b
  socket = g_socket_new_from_fd (pair[1], &error);
Packit ae235b
  g_assert_no_error (error);
Packit ae235b
Packit ae235b
  stream = g_socket_connection_factory_create_connection (socket);
Packit ae235b
  g_assert (stream != NULL);
Packit ae235b
  g_object_unref (socket);
Packit ae235b
Packit ae235b
  guid = g_dbus_generate_guid ();
Packit ae235b
  g_dbus_connection_new (G_IO_STREAM (stream), guid,
Packit ae235b
                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
Packit ae235b
                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
Packit ae235b
                         NULL, NULL, on_server_connection, test);
Packit ae235b
  g_object_unref (stream);
Packit ae235b
  g_free (guid);
Packit ae235b
Packit ae235b
  /* Build up the client stuff */
Packit ae235b
  socket = g_socket_new_from_fd (pair[0], &error);
Packit ae235b
  g_assert_no_error (error);
Packit ae235b
Packit ae235b
  stream = g_socket_connection_factory_create_connection (socket);
Packit ae235b
  g_assert (stream != NULL);
Packit ae235b
  g_object_unref (socket);
Packit ae235b
Packit ae235b
  g_dbus_connection_new (G_IO_STREAM (stream), NULL,
Packit ae235b
                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
Packit ae235b
                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS,
Packit ae235b
                         NULL, NULL, on_client_connection, test);
Packit ae235b
Packit ae235b
  g_main_loop_run (test->loop);
Packit ae235b
Packit ae235b
  g_assert (test->server);
Packit ae235b
  g_assert (test->client);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
teardown (Test *test,
Packit ae235b
          gconstpointer unused)
Packit ae235b
{
Packit ae235b
  g_clear_object (&test->client);
Packit ae235b
  g_clear_object (&test->server);
Packit ae235b
  g_main_loop_unref (test->loop);
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
on_result (GObject *source,
Packit ae235b
           GAsyncResult *result,
Packit ae235b
           gpointer user_data)
Packit ae235b
{
Packit ae235b
  Test *test = user_data;
Packit ae235b
  g_assert (test->result == NULL);
Packit ae235b
  test->result = g_object_ref (result);
Packit ae235b
  g_main_loop_quit (test->loop);
Packit ae235b
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
test_object_manager (Test *test,
Packit ae235b
                     gconstpointer test_data)
Packit ae235b
{
Packit ae235b
  GDBusObjectManager *client;
Packit ae235b
  GDBusObjectManagerServer *server;
Packit ae235b
  MockInterface *mock;
Packit ae235b
  GDBusObjectSkeleton *skeleton;
Packit ae235b
  const gchar *dbus_name;
Packit ae235b
  GError *error = NULL;
Packit ae235b
  GDBusInterface *proxy;
Packit ae235b
  GVariant *prop;
Packit ae235b
  const gchar *object_path = test_data;
Packit ae235b
  gchar *number1_path = NULL, *number2_path = NULL;
Packit ae235b
Packit ae235b
  if (g_strcmp0 (object_path, "/") == 0)
Packit ae235b
    {
Packit ae235b
      number1_path = g_strdup ("/number_1");
Packit ae235b
      number2_path = g_strdup ("/number_2");
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      number1_path = g_strdup_printf ("%s/number_1", object_path);
Packit ae235b
      number2_path = g_strdup_printf ("%s/number_2", object_path);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  server = g_dbus_object_manager_server_new (object_path);
Packit ae235b
Packit ae235b
  mock = g_object_new (mock_interface_get_type (), NULL);
Packit ae235b
  mock->number = 1;
Packit ae235b
  skeleton = g_dbus_object_skeleton_new (number1_path);
Packit ae235b
  g_dbus_object_skeleton_add_interface (skeleton, G_DBUS_INTERFACE_SKELETON (mock));
Packit ae235b
  g_dbus_object_manager_server_export (server, skeleton);
Packit ae235b
Packit ae235b
  mock = g_object_new (mock_interface_get_type (), NULL);
Packit ae235b
  mock->number = 2;
Packit ae235b
  skeleton = g_dbus_object_skeleton_new (number2_path);
Packit ae235b
  g_dbus_object_skeleton_add_interface (skeleton, G_DBUS_INTERFACE_SKELETON (mock));
Packit ae235b
  g_dbus_object_manager_server_export (server, skeleton);
Packit ae235b
Packit ae235b
  g_dbus_object_manager_server_set_connection (server, test->server);
Packit ae235b
Packit ae235b
  dbus_name = NULL;
Packit ae235b
Packit ae235b
  g_dbus_object_manager_client_new (test->client, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
Packit ae235b
                                    dbus_name, object_path, NULL, NULL, NULL, NULL, on_result, test);
Packit ae235b
Packit ae235b
  g_main_loop_run (test->loop);
Packit ae235b
  client = g_dbus_object_manager_client_new_finish (test->result, &error);
Packit ae235b
  g_assert_no_error (error);
Packit ae235b
  g_clear_object (&test->result);
Packit ae235b
Packit ae235b
  proxy = g_dbus_object_manager_get_interface (client, number1_path, "org.mock.Interface");
Packit ae235b
  g_assert (proxy != NULL);
Packit ae235b
  prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Path");
Packit ae235b
  g_assert (prop != NULL);
Packit ae235b
  g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_OBJECT_PATH);
Packit ae235b
  g_assert_cmpstr (g_variant_get_string (prop, NULL), ==, number1_path);
Packit ae235b
  g_variant_unref (prop);
Packit ae235b
  prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Number");
Packit ae235b
  g_assert (prop != NULL);
Packit ae235b
  g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_INT32);
Packit ae235b
  g_assert_cmpint (g_variant_get_int32 (prop), ==, 1);
Packit ae235b
  g_variant_unref (prop);
Packit ae235b
  g_object_unref (proxy);
Packit ae235b
Packit ae235b
  proxy = g_dbus_object_manager_get_interface (client, number2_path, "org.mock.Interface");
Packit ae235b
  g_assert (proxy != NULL);
Packit ae235b
  prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Path");
Packit ae235b
  g_assert (prop != NULL);
Packit ae235b
  g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_OBJECT_PATH);
Packit ae235b
  g_assert_cmpstr (g_variant_get_string (prop, NULL), ==, number2_path);
Packit ae235b
  g_variant_unref (prop);
Packit ae235b
  prop = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Number");
Packit ae235b
  g_assert (prop != NULL);
Packit ae235b
  g_assert_cmpstr ((gchar *)g_variant_get_type (prop), ==, (gchar *)G_VARIANT_TYPE_INT32);
Packit ae235b
  g_assert_cmpint (g_variant_get_int32 (prop), ==, 2);
Packit ae235b
  g_variant_unref (prop);
Packit ae235b
  g_object_unref (proxy);
Packit ae235b
Packit ae235b
  g_object_unref (server);
Packit ae235b
  g_object_unref (client);
Packit ae235b
Packit ae235b
  g_free (number2_path);
Packit ae235b
  g_free (number1_path);
Packit ae235b
}
Packit ae235b
Packit ae235b
int
Packit ae235b
main (int   argc,
Packit ae235b
      char *argv[])
Packit ae235b
{
Packit ae235b
  g_test_init (&argc, &argv, NULL);
Packit ae235b
Packit ae235b
  g_test_add ("/gdbus/peer-object-manager/normal", Test, "/objects",
Packit ae235b
              setup, test_object_manager, teardown);
Packit ae235b
  g_test_add ("/gdbus/peer-object-manager/root", Test, "/",
Packit ae235b
              setup, test_object_manager, teardown);
Packit ae235b
Packit ae235b
  return g_test_run();
Packit ae235b
}