|
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 |
}
|