[libshumate] tests: Add ShumateNetworkTileSource tests



commit 006dbe774c6e16eb944cdb2aa2428cd79951efd7
Author: James Westman <james jwestman net>
Date:   Fri Mar 26 22:23:15 2021 -0500

    tests: Add ShumateNetworkTileSource tests

 tests/network-tile-source.c | 143 +++++++++++++++++++++++++++++++++++++++++++-
 tests/test-tile-server.c    | 111 ++++++++++++++++++++++++----------
 tests/test-tile-server.h    |   5 +-
 3 files changed, 224 insertions(+), 35 deletions(-)
---
diff --git a/tests/network-tile-source.c b/tests/network-tile-source.c
index fce9eeb..bceca25 100644
--- a/tests/network-tile-source.c
+++ b/tests/network-tile-source.c
@@ -1,4 +1,5 @@
 #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 ();
 }
diff --git a/tests/test-tile-server.c b/tests/test-tile-server.c
index 719be56..6820bc4 100644
--- a/tests/test-tile-server.c
+++ b/tests/test-tile-server.c
@@ -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);
+}
diff --git a/tests/test-tile-server.h b/tests/test-tile-server.h
index fe2d802..98e24f3 100644
--- a/tests/test-tile-server.h
+++ b/tests/test-tile-server.h
@@ -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


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