[librest/gwagner/oauth2] oauth2: tests



commit 315a4c0a0ba000b9695d1bc832c2f600b1dd0600
Author: Günther Wagner <info gunibert de>
Date:   Wed Nov 17 07:16:46 2021 +0100

    oauth2: tests

 rest/rest-oauth2-proxy.c        |  19 ++-
 rest/rest-oauth2-proxy.h        |   9 +-
 rest/rest-pkce-code-challenge.c |  14 +++
 rest/rest-pkce-code-challenge.h |   6 +
 rest/rest-utils.c               |   8 ++
 tests/flickr.c                  |  13 ++
 tests/helper/test-server.c      | 123 +++++++++++++++++++
 tests/helper/test-server.h      |  34 ++++++
 tests/meson.build               |   3 +-
 tests/oauth2.c                  | 215 +++++++++++++++++++++++++++++++++
 tests/proxy.c                   | 260 ++++++++++++----------------------------
 11 files changed, 514 insertions(+), 190 deletions(-)
---
diff --git a/rest/rest-oauth2-proxy.c b/rest/rest-oauth2-proxy.c
index 14ecaab..7c0d222 100644
--- a/rest/rest-oauth2-proxy.c
+++ b/rest/rest-oauth2-proxy.c
@@ -40,6 +40,8 @@ typedef struct
 
 G_DEFINE_TYPE_WITH_PRIVATE (RestOAuth2Proxy, rest_oauth2_proxy, REST_TYPE_PROXY)
 
+G_DEFINE_QUARK (rest-oauth2-proxy-error-quark, rest_oauth2_proxy_error)
+
 enum {
   PROP_0,
   PROP_AUTH_URL,
@@ -342,7 +344,7 @@ rest_oauth2_proxy_init (RestOAuth2Proxy *self)
  *
  * Since: 0.8
  */
-const gchar *
+gchar *
 rest_oauth2_proxy_build_authorization_url (RestOAuth2Proxy  *self,
                                            const gchar      *code_challenge,
                                            const gchar      *scope,
@@ -356,13 +358,15 @@ rest_oauth2_proxy_build_authorization_url (RestOAuth2Proxy  *self,
 
   g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
 
-  *state = random_string (10);
+  if (state != NULL)
+    *state = random_string (10);
   params = g_hash_table_new (g_str_hash, g_str_equal);
 
   g_hash_table_insert (params, "response_type", "code");
   g_hash_table_insert (params, "client_id", priv->client_id);
   g_hash_table_insert (params, "redirect_uri", priv->redirect_uri);
-  g_hash_table_insert (params, "state", *state);
+  if (state != NULL)
+    g_hash_table_insert (params, "state", *state);
   g_hash_table_insert (params, "code_challenge", (gchar *)code_challenge);
   g_hash_table_insert (params, "code_challenge_method", "S256");
   if (scope)
@@ -478,6 +482,15 @@ rest_oauth2_proxy_refresh_access_token_async (RestOAuth2Proxy     *self,
 
   g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
 
+  if (priv->refresh_token == NULL)
+    {
+      g_task_return_new_error (task,
+                               REST_OAUTH2_PROXY_ERROR,
+                               REST_OAUTH2_PROXY_NO_REFRESH_TOKEN,
+                               "No refresh token available");
+      return;
+    }
+
   params = g_hash_table_new (g_str_hash, g_str_equal);
 
   g_hash_table_insert (params, "client_id", priv->client_id);
diff --git a/rest/rest-oauth2-proxy.h b/rest/rest-oauth2-proxy.h
index c41884f..7ba3111 100644
--- a/rest/rest-oauth2-proxy.h
+++ b/rest/rest-oauth2-proxy.h
@@ -39,13 +39,20 @@ struct _RestOAuth2ProxyClass
   gpointer padding[8];
 };
 
+enum {
+  REST_OAUTH2_PROXY_NO_REFRESH_TOKEN,
+};
+
+#define REST_OAUTH2_PROXY_ERROR rest_oauth2_proxy_error_quark ()
+GQuark rest_oauth2_proxy_error_quark ();
+
 RestOAuth2Proxy *rest_oauth2_proxy_new                         (const gchar          *authurl,
                                                                 const gchar          *tokenurl,
                                                                 const gchar          *redirecturl,
                                                                 const gchar          *client_id,
                                                                 const gchar          *client_secret,
                                                                 const gchar          *baseurl);
-const gchar     *rest_oauth2_proxy_build_authorization_url     (RestOAuth2Proxy      *self,
+gchar           *rest_oauth2_proxy_build_authorization_url     (RestOAuth2Proxy      *self,
                                                                 const gchar          *code_challenge,
                                                                 const gchar          *scope,
                                                                 gchar               **state);
diff --git a/rest/rest-pkce-code-challenge.c b/rest/rest-pkce-code-challenge.c
index f9932ec..a235232 100644
--- a/rest/rest-pkce-code-challenge.c
+++ b/rest/rest-pkce-code-challenge.c
@@ -96,12 +96,26 @@ rest_pkce_code_challenge_free (RestPkceCodeChallenge *self)
   g_slice_free (RestPkceCodeChallenge, self);
 }
 
+/**
+ * rest_pkce_code_challenge_get_challenge:
+ *
+ * Returns the Code Challenge for the Pkce verification.
+ *
+ * Returns: the code_challenge
+ */
 const gchar *
 rest_pkce_code_challenge_get_challenge (RestPkceCodeChallenge *self)
 {
   return self->code_challenge;
 }
 
+/**
+ * rest_pkce_code_challenge_get_verifier:
+ *
+ * Returns the Code Verifier for the Pkce verification.
+ *
+ * Returns: the code_verifier
+ */
 const gchar *
 rest_pkce_code_challenge_get_verifier (RestPkceCodeChallenge *self)
 {
diff --git a/rest/rest-pkce-code-challenge.h b/rest/rest-pkce-code-challenge.h
index eba1ea6..7823861 100644
--- a/rest/rest-pkce-code-challenge.h
+++ b/rest/rest-pkce-code-challenge.h
@@ -26,6 +26,12 @@ G_BEGIN_DECLS
 
 #define REST_TYPE_PKCE_CODE_CHALLENGE (rest_pkce_code_challenge_get_type ())
 
+/**
+ * RestPkceCodeChallenge:
+ *
+ * In order to play a Pkce Code Verification during a OAuth2 authorization
+ * you need this structure which handles the algorithmic part.
+ */
 typedef struct _RestPkceCodeChallenge RestPkceCodeChallenge;
 
 GType                  rest_pkce_code_challenge_get_type      (void) G_GNUC_CONST;
diff --git a/rest/rest-utils.c b/rest/rest-utils.c
index bb5a877..385ee55 100644
--- a/rest/rest-utils.c
+++ b/rest/rest-utils.c
@@ -20,6 +20,14 @@
 
 #include "rest-utils.h"
 
+/**
+ * random_string:
+ * @length: the length of the random string
+ *
+ * Creates a random string from a given alphabeth with length @length
+ *
+ * Returns: (transfer full): a random string
+ */
 gchar *
 random_string (guint length)
 {
diff --git a/tests/flickr.c b/tests/flickr.c
index 11301fa..2d1ee99 100644
--- a/tests/flickr.c
+++ b/tests/flickr.c
@@ -108,6 +108,18 @@ test_flickr ()
 
 }
 
+static void
+test_build_login_url (void)
+{
+  RestProxy *p = flickr_proxy_new ("api", "secret");
+  g_autofree gchar *login_url = flickr_proxy_build_login_url (FLICKR_PROXY (p), NULL, "read");
+
+  g_assert_cmpstr (login_url, ==, 
"http://flickr.com/services/auth/?api_key=api&perms=read&api_sig=55e7647bc1a6e512172b8fda472a64a8";);
+
+  login_url = flickr_proxy_build_login_url (FLICKR_PROXY (p), "746563215463214621", "read");
+
+  g_assert_cmpstr (login_url, ==, 
"http://flickr.com/services/auth/?frob=746563215463214621&api_key=api&perms=read&api_sig=bcabfd22f3beb489aeb3605b8c9e0441";);
+}
 
 int
 main (int argc, char **argv)
@@ -115,6 +127,7 @@ main (int argc, char **argv)
   g_test_init (&argc, &argv, NULL);
 
   g_test_add_func ("/flickr/flickr", test_flickr);
+  g_test_add_func ("/flickr/test_build_login_url", test_build_login_url);
 
   return g_test_run ();
 }
diff --git a/tests/helper/test-server.c b/tests/helper/test-server.c
new file mode 100644
index 0000000..764ef10
--- /dev/null
+++ b/tests/helper/test-server.c
@@ -0,0 +1,123 @@
+/* test-server.c
+ *
+ * Copyright 2021 Günther Wagner <info gunibert de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "test-server.h"
+
+static GMutex server_start_mutex;
+static GCond server_start_cond;
+
+SoupServer *
+test_server_new ()
+{
+  SoupServer *server = soup_server_new ("tls-certificate", NULL, NULL);
+  return server;
+}
+
+gchar *
+test_server_get_uri (SoupServer *server,
+                     const char *scheme,
+                     const char *host)
+{
+       GSList *uris, *u;
+#ifdef WITH_SOUP_2
+  SoupURI *uri, *ret_uri = NULL;
+#else
+       GUri *uri, *ret_uri = NULL;
+#endif
+
+       uris = soup_server_get_uris (server);
+       for (u = uris; u; u = u->next) {
+               uri = u->data;
+
+#ifdef WITH_SOUP_2
+               if (scheme && strcmp (soup_uri_get_scheme (uri), scheme) != 0)
+                       continue;
+               if (host && strcmp (soup_uri_get_host (uri), host) != 0)
+                       continue;
+
+               ret_uri = soup_uri_copy (uri);
+#else
+               if (scheme && strcmp (g_uri_get_scheme (uri), scheme) != 0)
+                       continue;
+               if (host && strcmp (g_uri_get_host (uri), host) != 0)
+                       continue;
+
+               ret_uri = g_uri_ref (uri);
+#endif
+               break;
+       }
+
+#ifdef WITH_SOUP_2
+       g_slist_free_full (uris, (GDestroyNotify)soup_uri_free);
+  return soup_uri_to_string (ret_uri, FALSE);
+#else
+       g_slist_free_full (uris, (GDestroyNotify)g_uri_unref);
+  return g_uri_to_string (ret_uri);
+#endif
+}
+
+static gpointer
+run_server_thread (gpointer user_data)
+{
+       SoupServer *server = user_data;
+       GMainContext *context;
+       GMainLoop *loop;
+  GError *error = NULL;
+
+       context = g_main_context_new ();
+       g_main_context_push_thread_default (context);
+       loop = g_main_loop_new (context, FALSE);
+       g_object_set_data (G_OBJECT (server), "GMainLoop", loop);
+
+       // TODO: error handling
+       soup_server_listen_local (server, 0, 0, &error);
+  if (error != NULL)
+    g_error ("%s", error->message);
+
+       g_mutex_lock (&server_start_mutex);
+       g_cond_signal (&server_start_cond);
+       g_mutex_unlock (&server_start_mutex);
+
+       g_main_loop_run (loop);
+       g_main_loop_unref (loop);
+
+  g_print("%s\n", "Shutting down server...");
+
+       soup_server_disconnect (server);
+
+       g_main_context_pop_thread_default (context);
+       g_main_context_unref (context);
+
+       return NULL;
+}
+
+void
+test_server_run_in_thread (SoupServer *server)
+{
+       GThread *thread;
+
+       g_mutex_lock (&server_start_mutex);
+
+       thread = g_thread_new ("server_thread", run_server_thread, server);
+       g_cond_wait (&server_start_cond, &server_start_mutex);
+       g_mutex_unlock (&server_start_mutex);
+
+       g_object_set_data (G_OBJECT (server), "thread", thread);
+}
diff --git a/tests/helper/test-server.h b/tests/helper/test-server.h
new file mode 100644
index 0000000..28b5ec3
--- /dev/null
+++ b/tests/helper/test-server.h
@@ -0,0 +1,34 @@
+/* test-server.h
+ *
+ * Copyright 2021 Günther Wagner <info gunibert de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <libsoup/soup.h>
+
+G_BEGIN_DECLS
+
+SoupServer *test_server_new           (void);
+void        test_server_run_in_thread (SoupServer *server);
+gchar      *test_server_get_uri       (SoupServer *server,
+                                       const char *scheme,
+                                       const char *host);
+
+G_END_DECLS
diff --git a/tests/meson.build b/tests/meson.build
index 8a0b3d6..c7c9170 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -5,6 +5,7 @@ test_suites = {
     'threaded',
     'xml',
     'custom-serialize',
+    'oauth2',
   ],
   'rest-extras': [
     'flickr',
@@ -22,7 +23,7 @@ test_deps = [
 foreach suite, test_names : test_suites
   foreach name : test_names
     test_bin = executable(name,
-      '@0@.c'.format(name),
+      ['@0@.c'.format(name), 'helper/test-server.c'],
       dependencies: test_deps,
       include_directories: config_h_inc,
     )
diff --git a/tests/oauth2.c b/tests/oauth2.c
new file mode 100644
index 0000000..c9ba8d2
--- /dev/null
+++ b/tests/oauth2.c
@@ -0,0 +1,215 @@
+/* oauth2.c
+ *
+ * Copyright 2021 Günther Wagner <info gunibert de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <glib.h>
+#include "rest/rest.h"
+#include "helper/test-server.h"
+
+static void
+server_callback (SoupServer        *server,
+                 SoupMessage       *msg,
+                 const gchar       *path,
+                 GHashTable        *query,
+                 SoupClientContext *client,
+                 gpointer           user_data)
+{
+  g_print ("%s\n", path);
+  if (g_strcmp0 (path, "/token") == 0)
+    {
+      g_print ("%s\n", msg->request_body->data);
+      gchar *json = "{"
+           "\"access_token\":\"2YotnFZFEjr1zCsicMWpAA\","
+           "\"token_type\":\"example\","
+           "\"expires_in\":3600,"
+           "\"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\","
+           "\"example_parameter\":\"example_value\""
+         "}";
+      soup_message_set_status (msg, SOUP_STATUS_OK);
+      soup_message_set_response (msg, "application/json", SOUP_MEMORY_COPY, json, strlen(json));
+      return;
+    }
+  else if (g_strcmp0 (path, "/api/bearer") == 0)
+    {
+      const gchar *authorization = soup_message_headers_get_one (msg->request_headers, "Authorization");
+      g_print ("%s\n", authorization);
+      soup_message_set_status (msg, SOUP_STATUS_OK);
+      soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY, authorization, strlen(authorization));
+      return;
+    }
+}
+
+static void
+test_authorization_url (gconstpointer url)
+{
+  g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth";,
+                                                                  "http://www.example.com/token";,
+                                                                  "http://www.example.com";,
+                                                                  "client-id",
+                                                                  "client-secret",
+                                                                  "http://www.example.com/api";));
+  g_autoptr(RestPkceCodeChallenge) pkce = rest_pkce_code_challenge_new_random ();
+
+  gchar *authorization_url = rest_oauth2_proxy_build_authorization_url (REST_OAUTH2_PROXY (proxy),
+                                             rest_pkce_code_challenge_get_challenge (pkce),
+                                             NULL,
+                                             NULL);
+  g_autofree gchar *expected = g_strdup_printf 
("http://www.example.com/auth?code_challenge_method=S256&redirect_uri=http%%3A%%2F%%2Fwww.example.com&client_id=client-id&code_challenge=%s&response_type=code";,
 rest_pkce_code_challenge_get_challenge (pkce));
+  g_assert_cmpstr (authorization_url, ==, expected);
+}
+
+static void
+test_fetch_access_token_finished (GObject      *object,
+                                  GAsyncResult *result,
+                                  gpointer      user_data)
+{
+  g_autoptr(GError) error = NULL;
+  gboolean *finished = user_data;
+
+  g_assert (G_IS_OBJECT (object));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  rest_oauth2_proxy_fetch_access_token_finish (REST_OAUTH2_PROXY (object), result, &error);
+  g_assert_no_error (error);
+
+  *finished = TRUE;
+}
+
+static void
+test_fetch_access_token (gconstpointer url)
+{
+  GMainContext *async_context = g_main_context_ref_thread_default ();
+  g_autoptr(GError) error = NULL;
+
+  g_autofree gchar *tokenurl = g_strdup_printf ("%stoken", (gchar *)url);
+  g_autofree gchar *baseurl = g_strdup_printf ("%sapi", (gchar *)url);
+
+  gboolean finished = FALSE;
+  g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth";,
+                                                                  tokenurl,
+                                                                  "http://www.example.com";,
+                                                                  "client-id",
+                                                                  "client-secret",
+                                                                  baseurl));
+  rest_oauth2_proxy_fetch_access_token_async (REST_OAUTH2_PROXY (proxy), "1234567890", "code_verifier", 
NULL, test_fetch_access_token_finished, &finished);
+  while (!finished) {
+    g_main_context_iteration (async_context, TRUE);
+  }
+
+  g_assert_cmpstr ("2YotnFZFEjr1zCsicMWpAA", ==, rest_oauth2_proxy_get_access_token (REST_OAUTH2_PROXY 
(proxy)));
+  g_assert_cmpstr ("tGzv3JOkF0XG5Qx2TlKWIA", ==, rest_oauth2_proxy_get_refresh_token (REST_OAUTH2_PROXY 
(proxy)));
+
+  g_autoptr(RestProxyCall) call = rest_proxy_new_call (proxy);
+  rest_proxy_call_set_method (call, "GET");
+  rest_proxy_call_set_function (call, "bearer");
+  rest_proxy_call_sync (call, &error);
+  g_assert_no_error (error);
+  g_autofree gchar *payload = g_strndup (rest_proxy_call_get_payload (call), 
rest_proxy_call_get_payload_length (call));
+  g_assert_cmpstr ("Bearer 2YotnFZFEjr1zCsicMWpAA", ==, payload);
+
+  g_main_context_unref (async_context);
+}
+
+static void
+test_refresh_access_token_finished_error (GObject      *object,
+                                          GAsyncResult *result,
+                                          gpointer      user_data)
+{
+  g_autoptr(GError) error = NULL;
+  gboolean *finished = user_data;
+
+  g_assert (G_IS_OBJECT (object));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  rest_oauth2_proxy_refresh_access_token_finish (REST_OAUTH2_PROXY (object), result, &error);
+  g_assert_error (error, REST_OAUTH2_PROXY_ERROR, REST_OAUTH2_PROXY_NO_REFRESH_TOKEN);
+
+  *finished = TRUE;
+}
+
+static void
+test_refresh_access_token_finished (GObject      *object,
+                                    GAsyncResult *result,
+                                    gpointer      user_data)
+{
+  g_autoptr(GError) error = NULL;
+  gboolean *finished = user_data;
+
+  g_assert (G_IS_OBJECT (object));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  rest_oauth2_proxy_refresh_access_token_finish (REST_OAUTH2_PROXY (object), result, &error);
+  g_assert_no_error (error);
+
+  *finished = TRUE;
+}
+
+static void
+test_refresh_access_token (gconstpointer url)
+{
+  GMainContext *async_context = g_main_context_ref_thread_default ();
+  g_autoptr(GError) error = NULL;
+
+  g_autofree gchar *tokenurl = g_strdup_printf ("%stoken", (gchar *)url);
+  g_autofree gchar *baseurl = g_strdup_printf ("%sapi", (gchar *)url);
+
+  gboolean finished = FALSE;
+  g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth";,
+                                                                  tokenurl,
+                                                                  "http://www.example.com";,
+                                                                  "client-id",
+                                                                  "client-secret",
+                                                                  baseurl));
+  rest_oauth2_proxy_refresh_access_token_async (REST_OAUTH2_PROXY (proxy), NULL, 
test_refresh_access_token_finished_error, &finished);
+
+  while (!finished) {
+    g_main_context_iteration (async_context, TRUE);
+  }
+
+  rest_oauth2_proxy_set_refresh_token (REST_OAUTH2_PROXY (proxy), "refresh_token");
+  rest_oauth2_proxy_refresh_access_token_async (REST_OAUTH2_PROXY (proxy), NULL, 
test_refresh_access_token_finished, &finished);
+
+  while (!finished) {
+    g_main_context_iteration (async_context, TRUE);
+  }
+
+  g_assert_cmpstr ("2YotnFZFEjr1zCsicMWpAA", ==, rest_oauth2_proxy_get_access_token (REST_OAUTH2_PROXY 
(proxy)));
+  g_assert_cmpstr ("tGzv3JOkF0XG5Qx2TlKWIA", ==, rest_oauth2_proxy_get_refresh_token (REST_OAUTH2_PROXY 
(proxy)));
+}
+
+gint
+main (gint   argc,
+      gchar *argv[])
+{
+  SoupServer *server;
+  g_autofree gchar *url;
+
+  g_test_init (&argc, &argv, NULL);
+
+  server = test_server_new ();
+  soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+  test_server_run_in_thread (server);
+  url = test_server_get_uri (server, "http", NULL);
+
+  g_test_add_data_func ("/oauth2/authorization_url", url, test_authorization_url);
+  g_test_add_data_func ("/oauth2/fetch_access_token", url, test_fetch_access_token);
+  g_test_add_data_func ("/oauth2/refresh_access_token", url, test_refresh_access_token);
+
+  return g_test_run ();
+}
diff --git a/tests/proxy.c b/tests/proxy.c
index 3abbc1c..fc77869 100644
--- a/tests/proxy.c
+++ b/tests/proxy.c
@@ -35,19 +35,13 @@
 #include <stdlib.h>
 #include <libsoup/soup.h>
 #include <rest/rest-proxy.h>
+#include "helper/test-server.h"
 
 #if SOUP_CHECK_VERSION (2, 28, 0)
 /* Avoid deprecation warning with newer libsoup */
 #define soup_message_headers_get soup_message_headers_get_one
 #endif
 
-#define PORT 8080
-
-static int errors = 0;
-
-SoupServer *server;
-GMainLoop *server_loop;
-
 #ifdef WITH_SOUP_2
 static void
 server_callback (SoupServer        *server,
@@ -182,257 +176,153 @@ server_callback (SoupServer        *server,
 static void
 ping_test (RestProxy *proxy)
 {
-  RestProxyCall *call;
+  g_autoptr(RestProxyCall) call;
   GError *error = NULL;
 
   call = rest_proxy_new_call (proxy);
   rest_proxy_call_set_function (call, "ping");
   rest_proxy_call_set_method (call, "GET");
-
-  if (!rest_proxy_call_sync (call, &error)) {
-    g_printerr ("2: Call failed: %s\n", error->message);
-    g_error_free (error);
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_assert(error == NULL);
-
-  if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
-    g_printerr ("wrong response code\n");
-    errors++;
-    return;
-  }
-
-  if (rest_proxy_call_get_payload_length (call) != 0) {
-    g_printerr ("wrong length returned\n");
-    errors++;
-    return;
-  }
+  rest_proxy_call_sync (call, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
+  g_assert_cmpint (rest_proxy_call_get_payload_length (call), ==, 0);
 
   g_object_unref (call);
-
   call = rest_proxy_new_call (proxy);
   rest_proxy_call_set_function (call, "ping");
   rest_proxy_call_set_method (call, "POST");
-
   rest_proxy_call_sync (call, &error);
-  /* g_assert_nonnull(error); */
-
-  if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_NOT_FOUND) {
-    g_printerr ("wrong response code\n");
-    errors++;
-    return;
-  }
-
-  g_object_unref (call);
+  g_assert_error (error, REST_PROXY_ERROR, 404);
+  g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_NOT_FOUND);
 }
 
 static void
 echo_test (RestProxy *proxy)
 {
-  RestProxyCall *call;
+  g_autoptr(RestProxyCall) call;
   GError *error = NULL;
 
   call = rest_proxy_new_call (proxy);
   rest_proxy_call_set_function (call, "echo");
   rest_proxy_call_add_param (call, "value", "echome");
-
-  if (!rest_proxy_call_sync (call, &error)) {
-    g_printerr ("3: Call failed: %s\n", error->message);
-    g_error_free (error);
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_assert(error == NULL);
-
-  if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
-    g_printerr ("wrong response code\n");
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  if (rest_proxy_call_get_payload_length (call) != 6) {
-    g_printerr ("wrong length returned\n");
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  if (g_strcmp0 ("echome", rest_proxy_call_get_payload (call)) != 0) {
-    g_printerr ("wrong string returned\n");
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_object_unref (call);
+  rest_proxy_call_sync (call, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
+  g_assert_cmpint (rest_proxy_call_get_payload_length (call), ==, 6);
+  g_assert_cmpstr (rest_proxy_call_get_payload (call), ==, "echome");
 }
 
 static void
 reverse_test (RestProxy *proxy)
 {
-  RestProxyCall *call;
+  g_autoptr(RestProxyCall) call;
   GError *error = NULL;
 
   call = rest_proxy_new_call (proxy);
   rest_proxy_call_set_function (call, "reverse");
   rest_proxy_call_add_param (call, "value", "reverseme");
-
-  if (!rest_proxy_call_sync (call, &error)) {
-    g_printerr ("4: Call failed: %s\n", error->message);
-    g_error_free (error);
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_assert(error == NULL);
-
-  if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
-    g_printerr ("wrong response code\n");
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  if (rest_proxy_call_get_payload_length (call) != 9) {
-    g_printerr ("wrong length returned\n");
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  if (g_strcmp0 ("emesrever", rest_proxy_call_get_payload (call)) != 0) {
-    g_printerr ("wrong string returned\n");
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_object_unref (call);
+  rest_proxy_call_sync (call, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
+  g_assert_cmpint (rest_proxy_call_get_payload_length (call), ==, 9);
+  g_assert_cmpstr (rest_proxy_call_get_payload (call), ==, "emesrever");
 }
 
 static void
 status_ok_test (RestProxy *proxy, guint status)
 {
-  RestProxyCall *call;
+  g_autoptr(RestProxyCall) call;
+  g_autofree gchar *status_str;
   GError *error = NULL;
-  char *status_str;
 
   call = rest_proxy_new_call (proxy);
   rest_proxy_call_set_function (call, "status");
   status_str = g_strdup_printf ("%d", status);
   rest_proxy_call_add_param (call, "status", status_str);
-  g_free (status_str);
-
-  if (!rest_proxy_call_sync (call, &error)) {
-    g_printerr ("1: Call failed: %s\n", error->message);
-    g_error_free (error);
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_assert(error == NULL);
-
-  if (rest_proxy_call_get_status_code (call) != status) {
-    g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
-    errors++;
-    return;
-  }
+  rest_proxy_call_sync (call, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, status);
+}
 
-  g_object_unref (call);
+static void
+status_test (RestProxy *proxy)
+{
+  status_ok_test (proxy, SOUP_STATUS_OK);
+  status_ok_test (proxy, SOUP_STATUS_NO_CONTENT);
 }
 
 static void
 status_error_test (RestProxy *proxy, guint status)
 {
-  RestProxyCall *call;
-  GError *error = NULL;
-  char *status_str;
+  g_autoptr(RestProxyCall) call;
+  g_autoptr(GError) error = NULL;
+  g_autofree gchar *status_str;
 
   call = rest_proxy_new_call (proxy);
   rest_proxy_call_set_function (call, "status");
   status_str = g_strdup_printf ("%d", status);
   rest_proxy_call_add_param (call, "status", status_str);
-  g_free (status_str);
-
-  if (rest_proxy_call_sync (call, &error)) {
-    g_printerr ("Call succeeded should have failed");
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_error_free (error);
-
-  if (rest_proxy_call_get_status_code (call) != status) {
-    g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
-    errors++;
-    return;
-  }
+  rest_proxy_call_sync (call, &error);
+  g_assert_error (error, REST_PROXY_ERROR, status);
+  g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, status);
+}
 
-  g_object_unref (call);
+static void
+status_test_error (RestProxy *proxy)
+{
+  status_error_test (proxy, SOUP_STATUS_BAD_REQUEST);
+  status_error_test (proxy, SOUP_STATUS_NOT_IMPLEMENTED);
 }
 
 static void
 test_status_ok (RestProxy *proxy, const char *function)
 {
-  RestProxyCall *call;
-  GError *error = NULL;
+  g_autoptr(RestProxyCall) call;
+  g_autoptr(GError) error = NULL;
 
   call = rest_proxy_new_call (proxy);
   rest_proxy_call_set_function (call, function);
-
-  if (!rest_proxy_call_sync (call, &error)) {
-    g_printerr ("%s call failed: %s\n", function, error->message);
-    g_error_free (error);
-    errors++;
-    g_object_unref (call);
-    return;
-  }
-  g_assert(error == NULL);
-
-  if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
-    g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
-    errors++;
-    return;
-  }
-
-  g_object_unref (call);
+  rest_proxy_call_sync (call, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
 }
 
-static void *
-server_thread_func (gpointer data)
+static void
+test_user_agent (RestProxy *proxy)
 {
-  server_loop = g_main_loop_new (NULL, TRUE);
-  soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
-
-  soup_server_listen_local (server, PORT, 0, NULL);
-  g_main_loop_run (server_loop);
-
-  return NULL;
+  test_status_ok (proxy, "useragent/none");
+  rest_proxy_set_user_agent (proxy, "TestSuite-1.0");
+  test_status_ok (proxy, "useragent/testsuite");
 }
 
 int
-main (int argc, char **argv)
+main (int     argc,
+      gchar **argv)
 {
-  char *url;
   RestProxy *proxy;
+  SoupServer *server;
+  gint ret;
+  gchar *uri;
 
-  server = g_object_new (SOUP_TYPE_SERVER, NULL);
-  g_thread_new ("Server Thread", server_thread_func, NULL);
+  g_test_init (&argc, &argv, NULL);
 
-  url = g_strdup_printf ("http://127.0.0.1:%d/";, PORT);
-  proxy = rest_proxy_new (url, FALSE);
-  g_free (url);
+  server = test_server_new ();
+  soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+  test_server_run_in_thread (server);
+  uri = test_server_get_uri (server, "http", NULL);
 
-  ping_test (proxy);
-  echo_test (proxy);
-  reverse_test (proxy);
-  status_ok_test (proxy, SOUP_STATUS_OK);
-  status_ok_test (proxy, SOUP_STATUS_NO_CONTENT);
-  status_error_test (proxy, SOUP_STATUS_BAD_REQUEST);
-  status_error_test (proxy, SOUP_STATUS_NOT_IMPLEMENTED);
+  proxy = rest_proxy_new (uri, FALSE);
 
-  test_status_ok (proxy, "useragent/none");
-  rest_proxy_set_user_agent (proxy, "TestSuite-1.0");
-  test_status_ok (proxy, "useragent/testsuite");
+  g_test_add_data_func ("/proxy/ping", proxy, ping_test);
+  g_test_add_data_func ("/proxy/echo", proxy, echo_test);
+  g_test_add_data_func ("/proxy/reverse", proxy, reverse_test);
+  g_test_add_data_func ("/proxy/status_ok_test", proxy, status_test);
+  g_test_add_data_func ("/proxy/status_error_test", proxy, status_test_error);
+  g_test_add_data_func ("/proxy/user_agent", proxy, test_user_agent);
+
+  ret = g_test_run ();
+
+       g_main_context_unref (g_main_context_default ());
 
-  g_main_loop_quit (server_loop);
-  return errors != 0;
+  return ret;
 }


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