[libgdata: 14/22] tests: Add a dummy GDataAuthorizer implementation



commit 31c69604484a0c1a0e9913c2db760c2f63b72883
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Aug 31 00:13:59 2014 +0100

    tests: Add a dummy GDataAuthorizer implementation
    
    This will come in useful when testing services which don’t support
    ClientLogin authorisation, such as Google Tasks. Such services require
    OAuth authorisation, which requires user interaction. That puts up a big
    barrier to running the unit tests frequently, and Google seem to provide
    no ‘playground’ API key which could be used to bypass this requirement
    for testing purposes.
    
    The idea is that traces are recorded for tests using an OAuth
    authoriser (requiring user interaction), then the dummy authoriser is
    substituted when the tests are run offline against the pre-recorded
    traces. This will require custom message matching in uhttpmock to ignore
    the Authorization header, which will differ between the OAuth and dummy
    authorisers.

 docs/reference/Makefile.am           |    5 +-
 gdata/tests/Makefile.am              |    2 +
 gdata/tests/gdata-dummy-authorizer.c |  222 ++++++++++++++++++++++++++++++++++
 gdata/tests/gdata-dummy-authorizer.h |   71 +++++++++++
 4 files changed, 299 insertions(+), 1 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 5957d38..af248c7 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -66,7 +66,10 @@ IGNORE_HFILES = \
        gdata-buffer.h          \
        gdata-batch-private.h   \
        gdata-batch-feed.h      \
-       gdata-gd-feed-link.h
+       gdata-gd-feed-link.h \
+       gdata-dummy-authorizer.c \
+       gdata-dummy-authorizer.h \
+       $(NULL)
 
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/gdata/tests/Makefile.am b/gdata/tests/Makefile.am
index 0238861..c6474df 100644
--- a/gdata/tests/Makefile.am
+++ b/gdata/tests/Makefile.am
@@ -6,6 +6,8 @@ noinst_LTLIBRARIES = libgdata-test.la
 libgdata_test_la_SOURCES = \
        common.c \
        common.h \
+       gdata-dummy-authorizer.c \
+       gdata-dummy-authorizer.h \
        $(NULL)
 
 libgdata_test_la_LIBADD = \
diff --git a/gdata/tests/gdata-dummy-authorizer.c b/gdata/tests/gdata-dummy-authorizer.c
new file mode 100644
index 0000000..6197ffb
--- /dev/null
+++ b/gdata/tests/gdata-dummy-authorizer.c
@@ -0,0 +1,222 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * GData Client
+ * Copyright (C) Philip Withnall 2014 <philip tecnocode co uk>
+ *
+ * GData Client is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GData Client 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * SECTION:gdata-dummy-authorizer
+ * @short_description: GData dummy authorization interface
+ * @stability: Unstable
+ * @include: tests/gdata-dummy-authorizer.h
+ *
+ * #GDataDummyAuthorizer is a dummy #GDataAuthorizer implementation intended for
+ * use in prototyping and testing code. It should not be used in production
+ * code.
+ *
+ * It adds a constant ‘Authorization’ header to all requests it processes whose
+ * domain is in the set of domains the authorizer was initialised with. All
+ * requests for other domains have no header added, and are considered
+ * non-authorized.
+ *
+ * Since: UNRELEASED
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include "gdata-dummy-authorizer.h"
+#include "gdata-private.h"
+
+static void authorizer_init (GDataAuthorizerInterface *iface);
+static void finalize (GObject *object);
+
+static void process_request (GDataAuthorizer *self,
+                             GDataAuthorizationDomain *domain,
+                             SoupMessage *message);
+static gboolean is_authorized_for_domain (GDataAuthorizer *self,
+                                          GDataAuthorizationDomain *domain);
+
+struct _GDataDummyAuthorizerPrivate {
+       GMutex mutex; /* mutex for authorization_domains */
+
+       /* Mapping from GDataAuthorizationDomain to itself; a set of domains
+        * which are authorised. */
+       GHashTable *authorization_domains;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GDataDummyAuthorizer, gdata_dummy_authorizer,
+                         G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GDATA_TYPE_AUTHORIZER,
+                                                authorizer_init))
+
+static void
+gdata_dummy_authorizer_class_init (GDataDummyAuthorizerClass *klass)
+{
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (GDataDummyAuthorizerPrivate));
+
+       gobject_class->finalize = finalize;
+}
+
+static void
+authorizer_init (GDataAuthorizerInterface *iface)
+{
+       iface->process_request = process_request;
+       iface->is_authorized_for_domain = is_authorized_for_domain;
+}
+
+static void
+gdata_dummy_authorizer_init (GDataDummyAuthorizer *self)
+{
+       self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                                 GDATA_TYPE_DUMMY_AUTHORIZER,
+                                                 GDataDummyAuthorizerPrivate);
+
+       /* Set up the authorizer's mutex */
+       g_mutex_init (&(self->priv->mutex));
+       self->priv->authorization_domains = g_hash_table_new_full (g_direct_hash,
+                                                                  g_direct_equal,
+                                                                  g_object_unref,
+                                                                  NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+       GDataDummyAuthorizerPrivate *priv = GDATA_DUMMY_AUTHORIZER (object)->priv;
+
+       g_hash_table_destroy (priv->authorization_domains);
+       g_mutex_clear (&(priv->mutex));
+
+       /* Chain up to the parent class */
+       G_OBJECT_CLASS (gdata_dummy_authorizer_parent_class)->finalize (object);
+}
+
+static void
+process_request (GDataAuthorizer *self, GDataAuthorizationDomain *domain,
+                 SoupMessage *message)
+{
+       GDataDummyAuthorizerPrivate *priv = GDATA_DUMMY_AUTHORIZER (self)->priv;
+
+       /* Set the authorisation header */
+       g_mutex_lock (&(priv->mutex));
+
+       if (g_hash_table_lookup (priv->authorization_domains, domain) != NULL) {
+               soup_message_headers_replace (message->request_headers,
+                                             "Authorization", "dummy");
+       }
+
+       g_mutex_unlock (&(priv->mutex));
+}
+
+static gboolean
+is_authorized_for_domain (GDataAuthorizer *self,
+                          GDataAuthorizationDomain *domain)
+{
+       GDataDummyAuthorizerPrivate *priv = GDATA_DUMMY_AUTHORIZER (self)->priv;
+       gpointer result;
+
+       g_mutex_lock (&(priv->mutex));
+       result = g_hash_table_lookup (priv->authorization_domains, domain);
+       g_mutex_unlock (&(priv->mutex));
+
+       /* Sanity check */
+       g_assert (result == NULL || result == domain);
+
+       return (result != NULL);
+}
+
+/*
+ * gdata_dummy_authorizer_new:
+ * @service_type: the #GType of a #GDataService subclass which the
+ * #GDataDummyAuthorizer will be used with
+ *
+ * Creates a new #GDataDummyAuthorizer.
+ *
+ * The #GDataAuthorizationDomain<!-- -->s for the given @service_type (i.e. as
+ * returned by gdata_service_get_authorization_domains()) will be authorized,
+ * and all others will not.
+ *
+ * Return value: (transfer full): a new #GDataDummyAuthorizer; unref with
+ * g_object_unref()
+ *
+ * Since: UNRELEASED
+ */
+GDataDummyAuthorizer *
+gdata_dummy_authorizer_new (GType service_type)
+{
+       GList/*<unowned GDataAuthorizationDomain>*/ *domains;  /* owned */
+       GDataDummyAuthorizer *retval = NULL;  /* owned */
+
+       g_return_val_if_fail (g_type_is_a (service_type, GDATA_TYPE_SERVICE),
+                             NULL);
+
+       domains = gdata_service_get_authorization_domains (service_type);
+       retval = gdata_dummy_authorizer_new_for_authorization_domains (domains);
+       g_list_free (domains);
+
+       return retval;
+}
+
+/*
+ * gdata_dummy_authorizer_new_for_authorization_domains:
+ * @authorization_domains: (element-type GDataAuthorizationDomain) (transfer none):
+ * a non-empty list of #GDataAuthorizationDomain<!-- -->s to be authorized
+ * against by the #GDataDummyAuthorizer
+ *
+ * Creates a new #GDataDummyAuthorizer. This function is intended to be used
+ * only when the default authorization domain list for a single #GDataService,
+ * as used by gdata_dummy_authorizer_new(), isn't suitable. For example, this
+ * could be because the #GDataDummyAuthorizer will be used with multiple
+ * #GDataService subclasses, or because the client requires a specific set of
+ * authorization domains.
+ *
+ * Return value: (transfer full): a new #GDataDummyAuthorizer; unref with
+ * g_object_unref()
+ *
+ * Since: UNRELEASED
+ */
+GDataDummyAuthorizer *
+gdata_dummy_authorizer_new_for_authorization_domains (GList *authorization_domains)
+{
+       GList *i;
+       GDataDummyAuthorizer *authorizer;
+
+       g_return_val_if_fail (authorization_domains != NULL, NULL);
+
+       authorizer = GDATA_DUMMY_AUTHORIZER (g_object_new (GDATA_TYPE_DUMMY_AUTHORIZER,
+                                                          NULL));
+
+       /* Register all the domains with the authorizer */
+       for (i = authorization_domains; i != NULL; i = i->next) {
+               GDataAuthorizationDomain *domain;
+
+               g_return_val_if_fail (GDATA_IS_AUTHORIZATION_DOMAIN (i->data),
+                                     NULL);
+
+               /* We don't have to lock the authoriser's mutex here as no other
+                * code has seen the authoriser yet */
+               domain = GDATA_AUTHORIZATION_DOMAIN (i->data);
+               g_hash_table_insert (authorizer->priv->authorization_domains,
+                                    g_object_ref (domain), domain);
+       }
+
+       return authorizer;
+}
diff --git a/gdata/tests/gdata-dummy-authorizer.h b/gdata/tests/gdata-dummy-authorizer.h
new file mode 100644
index 0000000..8117314
--- /dev/null
+++ b/gdata/tests/gdata-dummy-authorizer.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * GData Client
+ * Copyright (C) Philip Withnall 2014 <philip tecnocode co uk>
+ *
+ * GData Client is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GData Client 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GDATA_DUMMY_AUTHORIZER_H
+#define GDATA_DUMMY_AUTHORIZER_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "gdata-authorizer.h"
+
+G_BEGIN_DECLS
+
+#define GDATA_TYPE_DUMMY_AUTHORIZER            (gdata_dummy_authorizer_get_type ())
+#define GDATA_DUMMY_AUTHORIZER(o)              (G_TYPE_CHECK_INSTANCE_CAST ((o), 
GDATA_TYPE_DUMMY_AUTHORIZER, GDataDummyAuthorizer))
+#define GDATA_DUMMY_AUTHORIZER_CLASS(k)                (G_TYPE_CHECK_CLASS_CAST((k), 
GDATA_TYPE_DUMMY_AUTHORIZER, GDataDummyAuthorizerClass))
+#define GDATA_IS_DUMMY_AUTHORIZER(o)           (G_TYPE_CHECK_INSTANCE_TYPE ((o), 
GDATA_TYPE_DUMMY_AUTHORIZER))
+#define GDATA_IS_DUMMY_AUTHORIZER_CLASS(k)     (G_TYPE_CHECK_CLASS_TYPE ((k), GDATA_TYPE_DUMMY_AUTHORIZER))
+#define GDATA_DUMMY_AUTHORIZER_GET_CLASS(o)    (G_TYPE_INSTANCE_GET_CLASS ((o), GDATA_TYPE_DUMMY_AUTHORIZER, 
GDataDummyAuthorizerClass))
+
+typedef struct _GDataDummyAuthorizerPrivate    GDataDummyAuthorizerPrivate;
+
+/**
+ * GDataDummyAuthorizer:
+ *
+ * All the fields in the #GDataDummyAuthorizer structure are private and should never be accessed directly.
+ *
+ * Since: UNRELEASED
+ */
+typedef struct {
+       /*< private >*/
+       GObject parent;
+       GDataDummyAuthorizerPrivate *priv;
+} GDataDummyAuthorizer;
+
+/**
+ * GDataDummyAuthorizerClass:
+ *
+ * All the fields in the #GDataDummyAuthorizerClass structure are private and should never be accessed 
directly.
+ *
+ * Since: UNRELEASED
+ */
+typedef struct {
+       /*< private >*/
+       GObjectClass parent;
+} GDataDummyAuthorizerClass;
+
+GType gdata_dummy_authorizer_get_type (void) G_GNUC_CONST;
+
+GDataDummyAuthorizer *gdata_dummy_authorizer_new (GType service_type) G_GNUC_WARN_UNUSED_RESULT 
G_GNUC_MALLOC;
+GDataDummyAuthorizer *gdata_dummy_authorizer_new_for_authorization_domains (GList *authorization_domains) 
G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+
+G_END_DECLS
+
+#endif /* !GDATA_DUMMY_AUTHORIZER_H */


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