Blame tests/lib-net.c

Packit 67b98c
/*
Packit 67b98c
 * Copyright (C) 2016 Victor Toso <me@victortoso.com>
Packit 67b98c
 *
Packit 67b98c
 * This library is free software; you can redistribute it and/or
Packit 67b98c
 * modify it under the terms of the GNU Lesser General Public License
Packit 67b98c
 * as published by the Free Software Foundation; version 2.1 of
Packit 67b98c
 * the License, or (at your option) any later version.
Packit 67b98c
 *
Packit 67b98c
 * This library is distributed in the hope that it will be useful, but
Packit 67b98c
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67b98c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit 67b98c
 * Lesser General Public License for more details.
Packit 67b98c
 *
Packit 67b98c
 * You should have received a copy of the GNU Lesser General Public
Packit 67b98c
 * License along with this library; if not, write to the Free Software
Packit 67b98c
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
Packit 67b98c
 * 02110-1301 USA
Packit 67b98c
 *
Packit 67b98c
 */
Packit 67b98c
Packit 67b98c
#include <string.h>
Packit 67b98c
#include <grilo.h>
Packit 67b98c
#include <net/grl-net.h>
Packit 67b98c
#include <libsoup/soup.h>
Packit 67b98c
Packit 67b98c
typedef struct {
Packit 67b98c
  GrlRegistry *registry;
Packit 67b98c
  GMainLoop *loop;
Packit 67b98c
  SoupServer *server;
Packit 67b98c
  GCancellable *cancellable;
Packit 67b98c
  guint timeout;
Packit 67b98c
  guint num_operations;
Packit 67b98c
  gboolean timeout_is_expected;
Packit 67b98c
} Fixture;
Packit 67b98c
Packit 67b98c
typedef struct {
Packit 67b98c
  Fixture *f;
Packit 67b98c
  guint id;
Packit 67b98c
  gint64 request_time;
Packit 67b98c
  gint64 expected_time;
Packit 67b98c
} ThrottlingOperation;
Packit 67b98c
Packit 67b98c
#define NO_DELAY     0
Packit 67b98c
#define DELAY        2
Packit 67b98c
#define BIG_DELAY    15     /* Big enough for a timeout */
Packit 67b98c
Packit 67b98c
#define THRESHOLD    1      /* 1 second, see https://bugzilla.gnome.org/show_bug.cgi?id=774578 */
Packit 67b98c
Packit 67b98c
#define NUM_STRESS_TEST 100
Packit 67b98c
Packit 67b98c
static void
Packit 67b98c
fixture_setup (Fixture *fixture, gconstpointer data)
Packit 67b98c
{
Packit 67b98c
  fixture->num_operations = 0;
Packit 67b98c
  fixture->registry = grl_registry_get_default ();
Packit 67b98c
  fixture->loop = g_main_loop_new (NULL, TRUE);
Packit 67b98c
  fixture->server = soup_server_new (NULL, NULL);
Packit 67b98c
  fixture->cancellable = g_cancellable_new ();
Packit 67b98c
  fixture->timeout_is_expected = FALSE;
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
static void
Packit 67b98c
fixture_teardown (Fixture *fixture, gconstpointer data)
Packit 67b98c
{
Packit 67b98c
  g_main_loop_unref (fixture->loop);
Packit 67b98c
  g_object_unref (fixture->server);
Packit 67b98c
  g_object_unref (fixture->cancellable);
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
/* unexpected */
Packit 67b98c
static gboolean
Packit 67b98c
timeout (gpointer user_data)
Packit 67b98c
{
Packit 67b98c
  Fixture *f = user_data;
Packit 67b98c
  g_main_loop_quit (f->loop);
Packit 67b98c
Packit 67b98c
  if (!f->timeout_is_expected)
Packit 67b98c
    g_test_fail ();
Packit 67b98c
Packit 67b98c
  return G_SOURCE_REMOVE;
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
static void
Packit 67b98c
soup_server_throttling_cb (SoupServer *server,
Packit 67b98c
                           SoupMessage *message,
Packit 67b98c
                           const char *path,
Packit 67b98c
                           GHashTable *query,
Packit 67b98c
                           SoupClientContext *client,
Packit 67b98c
                           gpointer user_data)
Packit 67b98c
{
Packit 67b98c
  gchar *response = g_strdup_printf ("%" G_GINT64_FORMAT, g_get_monotonic_time());
Packit 67b98c
Packit 67b98c
  soup_message_set_response (message, "text/plain", SOUP_MEMORY_TAKE, response, strlen(response));
Packit 67b98c
  soup_message_set_status (message, SOUP_STATUS_OK);
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
static void
Packit 67b98c
test_net_wc_throttling_cb (GObject *source_object,
Packit 67b98c
                           GAsyncResult *res,
Packit 67b98c
                           gpointer user_data)
Packit 67b98c
{
Packit 67b98c
  gchar *data;
Packit 67b98c
  gsize len;
Packit 67b98c
  gboolean ret;
Packit 67b98c
  guint64 received_time;
Packit 67b98c
  GError *err = NULL;
Packit 67b98c
  ThrottlingOperation *op = user_data;
Packit 67b98c
  Fixture *f = op->f;
Packit 67b98c
Packit 67b98c
  ret = grl_net_wc_request_finish (GRL_NET_WC (source_object), res, &data, &len, &err;;
Packit 67b98c
  g_assert_no_error (err);
Packit 67b98c
  g_assert_true (ret);
Packit 67b98c
  received_time = g_ascii_strtoull (data, NULL, 0);
Packit 67b98c
  g_assert_cmpint (received_time, >=, op->expected_time);
Packit 67b98c
Packit 67b98c
  g_free (op);
Packit 67b98c
  f->num_operations--;
Packit 67b98c
Packit 67b98c
  if (f->num_operations == 0) {
Packit 67b98c
    if (f->timeout > 0)
Packit 67b98c
        g_source_remove(f->timeout);
Packit 67b98c
    g_main_loop_quit (f->loop);
Packit 67b98c
  }
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
static ThrottlingOperation *
Packit 67b98c
throttling_operation_new (Fixture *f, guint delay_in_sec)
Packit 67b98c
{
Packit 67b98c
  ThrottlingOperation *op;
Packit 67b98c
  static guint id = 0;
Packit 67b98c
Packit 67b98c
  op = g_new(ThrottlingOperation, 1);
Packit 67b98c
  op->f = f;
Packit 67b98c
  op->id = id;
Packit 67b98c
  op->request_time = g_get_monotonic_time ();
Packit 67b98c
  op->expected_time = op->request_time + (G_USEC_PER_SEC * delay_in_sec);
Packit 67b98c
Packit 67b98c
  /* Some THRESOLD seems necessary as the test time happens before the actual
Packit 67b98c
   * GrlNetWc computation. This test is more about throttling working than
Packit 67b98c
   * precision. */
Packit 67b98c
  op->expected_time -= THRESHOLD;
Packit 67b98c
Packit 67b98c
  id++;
Packit 67b98c
  f->num_operations++;
Packit 67b98c
  return op;
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
static void
Packit 67b98c
test_net_wc_small_throttling (Fixture *f,
Packit 67b98c
                              gconstpointer data)
Packit 67b98c
{
Packit 67b98c
  GSList *uris;
Packit 67b98c
  gchar *request;
Packit 67b98c
  GrlNetWc *wc;
Packit 67b98c
  ThrottlingOperation *op;
Packit 67b98c
Packit 67b98c
  g_test_bug ("769331");
Packit 67b98c
Packit 67b98c
  GError *error = NULL;
Packit 67b98c
  soup_server_add_handler (f->server, NULL, soup_server_throttling_cb, NULL, NULL);
Packit 67b98c
  soup_server_listen_local (f->server, 0, 0, &error);
Packit 67b98c
  g_assert_no_error (error);
Packit 67b98c
Packit 67b98c
  uris = soup_server_get_uris (f->server);
Packit 67b98c
  g_assert_nonnull (uris);
Packit 67b98c
  request = soup_uri_to_string (uris->data, FALSE);
Packit 67b98c
  g_slist_free_full (uris, (GDestroyNotify) soup_uri_free);
Packit 67b98c
  g_assert_nonnull (request);
Packit 67b98c
Packit 67b98c
  wc = grl_net_wc_new ();
Packit 67b98c
  grl_net_wc_set_throttling (wc, DELAY);
Packit 67b98c
Packit 67b98c
  /* The throttling is considered between requests which means that the first
Packit 67b98c
   * request is done as fast as possible */
Packit 67b98c
  op = throttling_operation_new(f, NO_DELAY);
Packit 67b98c
  grl_net_wc_request_async (wc, request, f->cancellable, test_net_wc_throttling_cb, op);
Packit 67b98c
Packit 67b98c
  op = throttling_operation_new(f, DELAY);
Packit 67b98c
  grl_net_wc_request_async (wc, request, f->cancellable, test_net_wc_throttling_cb, op);
Packit 67b98c
Packit 67b98c
  g_object_unref (wc);
Packit 67b98c
  g_free (request);
Packit 67b98c
Packit 67b98c
  f->timeout = g_timeout_add_seconds (5, timeout, f);
Packit 67b98c
  g_main_loop_run (f->loop);
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
static void
Packit 67b98c
test_net_wc_big_throttling (Fixture *f,
Packit 67b98c
                            gconstpointer data)
Packit 67b98c
{
Packit 67b98c
  GSList *uris;
Packit 67b98c
  gchar *request;
Packit 67b98c
  GrlNetWc *wc;
Packit 67b98c
  ThrottlingOperation *op;
Packit 67b98c
Packit 67b98c
  g_test_bug ("769331");
Packit 67b98c
Packit 67b98c
  GError *error = NULL;
Packit 67b98c
  soup_server_add_handler (f->server, NULL, soup_server_throttling_cb, NULL, NULL);
Packit 67b98c
  soup_server_listen_local (f->server, 0, 0, &error);
Packit 67b98c
  g_assert_no_error (error);
Packit 67b98c
Packit 67b98c
  uris = soup_server_get_uris (f->server);
Packit 67b98c
  g_assert_nonnull (uris);
Packit 67b98c
  request = soup_uri_to_string (uris->data, FALSE);
Packit 67b98c
  g_slist_free_full (uris, (GDestroyNotify) soup_uri_free);
Packit 67b98c
  g_assert_nonnull (request);
Packit 67b98c
Packit 67b98c
  wc = grl_net_wc_new ();
Packit 67b98c
  grl_net_wc_set_throttling (wc, BIG_DELAY);
Packit 67b98c
Packit 67b98c
  /* The throttling is considered between requests which means that the first
Packit 67b98c
   * request is done as fast as possible */
Packit 67b98c
  op = throttling_operation_new(f, NO_DELAY);
Packit 67b98c
  grl_net_wc_request_async (wc, request, f->cancellable, test_net_wc_throttling_cb, op);
Packit 67b98c
Packit 67b98c
  op = throttling_operation_new(f, BIG_DELAY);
Packit 67b98c
  grl_net_wc_request_async (wc, request, f->cancellable, test_net_wc_throttling_cb, op);
Packit 67b98c
Packit 67b98c
  g_object_unref (wc);
Packit 67b98c
  g_free (request);
Packit 67b98c
Packit 67b98c
  f->timeout_is_expected = TRUE;
Packit 67b98c
  g_timeout_add_seconds (5, timeout, f);
Packit 67b98c
  g_main_loop_run (f->loop);
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
static void
Packit 67b98c
test_net_wc_no_throttling_stress (Fixture *f,
Packit 67b98c
                                  gconstpointer data)
Packit 67b98c
{
Packit 67b98c
  GSList *uris;
Packit 67b98c
  gchar *request;
Packit 67b98c
  GrlNetWc *wc;
Packit 67b98c
  gint i;
Packit 67b98c
  GError *error = NULL;
Packit 67b98c
Packit 67b98c
  g_test_bug ("771338");
Packit 67b98c
Packit 67b98c
  /* Create SoupServer with simple callback to reply */
Packit 67b98c
  soup_server_add_handler (f->server, NULL, soup_server_throttling_cb, NULL, NULL);
Packit 67b98c
  soup_server_listen_local (f->server, 0, 0, &error);
Packit 67b98c
  g_assert_no_error (error);
Packit 67b98c
Packit 67b98c
  uris = soup_server_get_uris (f->server);
Packit 67b98c
  g_assert_nonnull (uris);
Packit 67b98c
  request = soup_uri_to_string (uris->data, FALSE);
Packit 67b98c
  g_slist_free_full (uris, (GDestroyNotify) soup_uri_free);
Packit 67b98c
  g_assert_nonnull (request);
Packit 67b98c
Packit 67b98c
  /* Under the same grl-net-wc, create NUM_STRESS_TEST async operations to our
Packit 67b98c
   * test SoupServer to verify if any regression can be seen */
Packit 67b98c
  wc = grl_net_wc_new ();
Packit 67b98c
  for (i = 0; i < NUM_STRESS_TEST; i++) {
Packit 67b98c
      ThrottlingOperation *op;
Packit 67b98c
Packit 67b98c
      op = throttling_operation_new(f, NO_DELAY);
Packit 67b98c
      grl_net_wc_request_async (wc, request, f->cancellable, test_net_wc_throttling_cb, op);
Packit 67b98c
  }
Packit 67b98c
  g_object_unref (wc);
Packit 67b98c
  g_free (request);
Packit 67b98c
Packit 67b98c
  f->timeout_is_expected = FALSE;
Packit 67b98c
  g_timeout_add_seconds (5, timeout, f);
Packit 67b98c
  g_main_loop_run (f->loop);
Packit 67b98c
}
Packit 67b98c
Packit 67b98c
int
Packit 67b98c
main (int argc, char **argv)
Packit 67b98c
{
Packit 67b98c
  g_test_init (&argc, &argv, NULL);
Packit 67b98c
Packit 67b98c
  g_test_bug_base ("http://bugs.gnome.org/%s");
Packit 67b98c
Packit 67b98c
  grl_init (&argc, &argv);
Packit 67b98c
Packit 67b98c
  g_test_add ("/net/throttling/small-delay",
Packit 67b98c
              Fixture, NULL,
Packit 67b98c
              fixture_setup,
Packit 67b98c
              test_net_wc_small_throttling,
Packit 67b98c
              fixture_teardown);
Packit 67b98c
Packit 67b98c
  g_test_add ("/net/throttling/big-delay",
Packit 67b98c
              Fixture, NULL,
Packit 67b98c
              fixture_setup,
Packit 67b98c
              test_net_wc_big_throttling,
Packit 67b98c
              fixture_teardown);
Packit 67b98c
Packit 67b98c
  g_test_add ("/net/throttling/disabled/stress",
Packit 67b98c
              Fixture, NULL,
Packit 67b98c
              fixture_setup,
Packit 67b98c
              test_net_wc_no_throttling_stress,
Packit 67b98c
              fixture_teardown);
Packit 67b98c
Packit 67b98c
  return g_test_run ();
Packit 67b98c
}