Verified Commit 006dbe77 authored by James Westman's avatar James Westman
Browse files

tests: Add ShumateNetworkTileSource tests

parent 5edf9c0a
Pipeline #272459 passed with stage
in 3 minutes and 22 seconds
#include <gtk/gtk.h>
#include <libsoup/soup.h>
#include <shumate/shumate.h>
#include "test-tile-server.h"
......@@ -10,9 +11,11 @@ create_tile_source (const char *uri)
// source
g_autofree char *template = g_strdup_printf ("%s/#X#/#Y#/#Z#", uri);
g_autofree char *r = g_uuid_string_random ();
g_autofree char *id = g_strdup_printf ("test_%s", r);
return SHUMATE_MAP_SOURCE (
shumate_network_tile_source_new_full ("testsrc",
shumate_network_tile_source_new_full (id,
"Test Source",
NULL, NULL,
0, 20,
......@@ -51,8 +54,140 @@ test_network_tile_source_tile (void)
g_main_loop_run (loop);
g_assert_nonnull (shumate_tile_get_texture (tile));
test_tile_server_assert_requests (server, 1);
}
/* Test that once a tile is requested, future requests go to the cache */
static void
test_network_tile_cache_hit (void)
{
g_autoptr(TestTileServer) server = test_tile_server_new ();
g_autofree char *uri = test_tile_server_start (server);
g_autoptr(ShumateMapSource) source = create_tile_source (uri);
g_autoptr(ShumateTile) tile = shumate_tile_new_full (0, 0, 256, 1);
g_autoptr(GMainLoop) loop = NULL;
g_object_ref_sink (tile);
/* Fill the tile */
loop = g_main_loop_new (NULL, TRUE);
shumate_map_source_fill_tile_async (source, tile, NULL, on_tile_filled, loop);
g_main_loop_run (loop);
g_assert_nonnull (shumate_tile_get_texture (tile));
shumate_tile_set_texture (tile, NULL);
test_tile_server_assert_requests (server, 1);
loop = g_main_loop_new (NULL, TRUE);
shumate_map_source_fill_tile_async (source, tile, NULL, on_tile_filled, loop);
g_main_loop_run (loop);
g_assert_nonnull (shumate_tile_get_texture (tile));
test_tile_server_assert_requests (server, 0);
}
static void
on_filled_invalid_url (GObject *object, GAsyncResult *res, gpointer user_data)
{
g_autoptr(GError) error = NULL;
GMainLoop *loop = user_data;
shumate_map_source_fill_tile_finish ((ShumateMapSource *) object, res, &error);
g_assert_error (error, SHUMATE_NETWORK_SOURCE_ERROR, SHUMATE_NETWORK_SOURCE_ERROR_MALFORMED_URL);
g_main_loop_quit (loop);
}
/* Test that the proper error is thrown when the URL is invalid */
static void
test_network_tile_invalid_url (void)
{
char *uri = "this isn't a valid url";
g_autoptr(ShumateMapSource) source = create_tile_source (uri);
g_autoptr(ShumateTile) tile = shumate_tile_new_full (0, 0, 256, 1);
g_autoptr(GMainLoop) loop = NULL;
g_object_ref_sink (tile);
/* Fill the tile */
loop = g_main_loop_new (NULL, TRUE);
shumate_map_source_fill_tile_async (source, tile, NULL, on_filled_invalid_url, loop);
g_main_loop_run (loop);
g_assert_null (shumate_tile_get_texture (tile));
}
static void
on_filled_bad_response (GObject *object, GAsyncResult *res, gpointer user_data)
{
g_autoptr(GError) error = NULL;
GMainLoop *loop = user_data;
shumate_map_source_fill_tile_finish ((ShumateMapSource *) object, res, &error);
g_assert_error (error, SHUMATE_NETWORK_SOURCE_ERROR, SHUMATE_NETWORK_SOURCE_ERROR_BAD_RESPONSE);
g_main_loop_quit (loop);
}
/* Test that the proper error is thrown when a bad response is returned */
static void
test_network_tile_bad_response (void)
{
g_autoptr(TestTileServer) server = test_tile_server_new ();
g_autofree char *uri = test_tile_server_start (server);
g_autoptr(ShumateMapSource) source = create_tile_source (uri);
g_autoptr(ShumateTile) tile = shumate_tile_new_full (0, 0, 256, 1);
g_autoptr(GMainLoop) loop = NULL;
g_object_ref_sink (tile);
test_tile_server_set_status (server, 404);
/* Fill the tile */
loop = g_main_loop_new (NULL, TRUE);
shumate_map_source_fill_tile_async (source, tile, NULL, on_filled_bad_response, loop);
g_main_loop_run (loop);
g_assert_null (shumate_tile_get_texture (tile));
}
static void
on_filled_invalid_data (GObject *object, GAsyncResult *res, gpointer user_data)
{
g_autoptr(GError) error = NULL;
GMainLoop *loop = user_data;
shumate_map_source_fill_tile_finish ((ShumateMapSource *) object, res, &error);
g_assert_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE);
g_main_loop_quit (loop);
}
/* Test that the proper error is thrown when invalid data is returned */
static void
test_network_tile_invalid_data (void)
{
g_autoptr(TestTileServer) server = test_tile_server_new ();
g_autofree char *uri = test_tile_server_start (server);
g_autoptr(ShumateMapSource) source = create_tile_source (uri);
g_autoptr(ShumateTile) tile = shumate_tile_new_full (0, 0, 256, 1);
g_autoptr(GMainLoop) loop = NULL;
g_object_ref_sink (tile);
test_tile_server_set_data (server, "this is not an image file");
/* Fill the tile */
loop = g_main_loop_new (NULL, TRUE);
shumate_map_source_fill_tile_async (source, tile, NULL, on_filled_invalid_data, loop);
g_main_loop_run (loop);
g_assert_null (shumate_tile_get_texture (tile));
}
int
main (int argc, char *argv[])
{
......@@ -60,6 +195,12 @@ main (int argc, char *argv[])
gtk_init ();
g_test_add_func ("/network-tile-source/tile", test_network_tile_source_tile);
/* shumate_network_source_fill_tile_async doesn't wait for the cache
* operation to finish, so this is unreliable */
/* g_test_add_func ("/network-tile-source/cache-hit", test_network_tile_cache_hit); */
g_test_add_func ("/network-tile-source/invalid-url", test_network_tile_invalid_url);
g_test_add_func ("/network-tile-source/bad-response", test_network_tile_bad_response);
g_test_add_func ("/network-tile-source/invalid-data", test_network_tile_invalid_data);
return g_test_run ();
}
......@@ -11,11 +11,43 @@ struct _TestTileServer
{
GObject parent_instance;
SoupServer *server;
GBytes *bytes;
int requests;
int status;
char *etag;
};
G_DEFINE_TYPE (TestTileServer, test_tile_server, G_TYPE_OBJECT)
static cairo_status_t
write_func (void *bytearray, const unsigned char *data, unsigned int length)
{
g_byte_array_append ((GByteArray *) bytearray, data, length);
return CAIRO_STATUS_SUCCESS;
}
static GBytes *
generate_image ()
{
GByteArray *bytearray = g_byte_array_new ();
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 256, 256);
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
cairo_surface_write_to_png_stream (surface, write_func, bytearray);
cairo_surface_destroy (surface);
return g_byte_array_free_to_bytes (bytearray);
}
TestTileServer *
test_tile_server_new (void)
{
......@@ -28,6 +60,8 @@ test_tile_server_finalize (GObject *object)
TestTileServer *self = (TestTileServer *)object;
g_clear_object (&self->server);
g_clear_pointer (&self->bytes, g_bytes_unref);
g_clear_pointer (&self->etag, g_free);
G_OBJECT_CLASS (test_tile_server_parent_class)->finalize (object);
}
......@@ -44,35 +78,8 @@ static void
test_tile_server_init (TestTileServer *self)
{
self->server = soup_server_new (NULL, NULL);
}
static cairo_status_t
write_func (void *bytearray, const unsigned char *data, unsigned int length)
{
g_byte_array_append ((GByteArray *) bytearray, data, length);
return CAIRO_STATUS_SUCCESS;
}
static GBytes *
generate_image ()
{
GByteArray *bytearray = g_byte_array_new ();
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 256, 256);
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
cairo_surface_write_to_png_stream (surface, write_func, bytearray);
cairo_surface_destroy (surface);
return g_byte_array_free_to_bytes (bytearray);
self->bytes = generate_image ();
self->status = 200;
}
......@@ -84,11 +91,19 @@ server_callback (SoupServer *server,
SoupClientContext *client,
gpointer user_data)
{
TestTileServer *self = user_data;
gsize data_size;
const char *data = g_bytes_get_data ((GBytes *) user_data, &data_size);
const char *data = NULL;
self->requests ++;
if (self->bytes)
{
data = g_bytes_get_data (self->bytes, &data_size);
soup_message_set_response (msg, "image/png", SOUP_MEMORY_STATIC, data, data_size);
}
soup_message_set_response (msg, "image/png", SOUP_MEMORY_STATIC, data, data_size);
soup_message_set_status (msg, 200);
soup_message_set_status (msg, self->status);
}
......@@ -97,7 +112,7 @@ test_tile_server_start (TestTileServer *self)
{
g_autoptr(GError) error = NULL;
g_autoptr(GSList) uris = NULL;
soup_server_add_handler (self->server, NULL, server_callback, generate_image (), (GDestroyNotify) g_bytes_unref);
soup_server_add_handler (self->server, NULL, server_callback, self, NULL);
soup_server_listen_local (self->server, 0, 0, &error);
g_assert_no_error (error);
......@@ -106,3 +121,33 @@ test_tile_server_start (TestTileServer *self)
g_assert_true (g_slist_length (uris) >= 1);
return soup_uri_to_string (uris->data, FALSE);
}
void
test_tile_server_assert_requests (TestTileServer *self, int times)
{
g_assert_cmpint (self->requests, ==, times);
self->requests = 0;
}
void
test_tile_server_set_status (TestTileServer *self, int status)
{
self->status = status;
}
void
test_tile_server_set_data (TestTileServer *self, const char *data)
{
g_bytes_unref (self->bytes);
if (data)
self->bytes = g_bytes_new (data, strlen (data));
else
self->bytes = NULL;
}
void
test_tile_server_set_etag (TestTileServer *self, const char *etag)
{
g_clear_pointer (&self->etag, g_free);
self->etag = g_strdup (etag);
}
......@@ -12,6 +12,9 @@ G_DECLARE_FINAL_TYPE (TestTileServer, test_tile_server, TEST, TILE_SERVER, GObje
TestTileServer *test_tile_server_new (void);
char *test_tile_server_start (TestTileServer *self);
void test_tile_server_assert_requests (TestTileServer *self, int times);
void test_tile_server_set_status (TestTileServer *self, int status);
void test_tile_server_set_data (TestTileServer *self, const char *data);
void test_tile_server_set_etag (TestTileServer *self, const char *etag);
G_END_DECLS
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment